#include "angband.h" #include school_book_type school_books[SCHOOL_BOOKS_SIZE]; s32b SCHOOL_AIR; s32b SCHOOL_AULE; s32b SCHOOL_CONVEYANCE; s32b SCHOOL_DEMON; s32b SCHOOL_DEVICE; s32b SCHOOL_DIVINATION; s32b SCHOOL_EARTH; s32b SCHOOL_ERU; s32b SCHOOL_FIRE; s32b SCHOOL_GEOMANCY; s32b SCHOOL_MANA; s32b SCHOOL_MANDOS; s32b SCHOOL_MANWE; s32b SCHOOL_MELKOR; s32b SCHOOL_META; s32b SCHOOL_MIND; s32b SCHOOL_MUSIC; s32b SCHOOL_NATURE; s32b SCHOOL_TEMPORAL; s32b SCHOOL_TULKAS; s32b SCHOOL_UDUN; s32b SCHOOL_ULMO; s32b SCHOOL_VARDA; s32b SCHOOL_WATER; s32b SCHOOL_YAVANNA; static int compare_spell_idx(spell_idx_list *a, spell_idx_list *b) { return SGLIB_NUMERIC_COMPARATOR(a->i, b->i); } SGLIB_DEFINE_LIST_FUNCTIONS(spell_idx_list, compare_spell_idx, next); static int compare_school_idx(school_idx *a, school_idx *b) { return SGLIB_NUMERIC_COMPARATOR(a->i, b->i); } SGLIB_DEFINE_LIST_FUNCTIONS(school_idx, compare_school_idx, next); void school_idx_init(school_idx *e, s32b i) { assert(e != NULL); e->i = i; e->next = NULL; } school_idx *school_idx_new(s32b i) { school_idx *e = malloc(sizeof(school_idx)); assert(e != NULL); school_idx_init(e, i); return e; } void school_idx_add_new(school_idx **list, s32b i) { school_idx *e = school_idx_new(i); assert(e != NULL); sglib_school_idx_add(list, e); } static bool_ uses_piety_to_cast(int s) { return spell_at(s)->casting_type == USE_PIETY; } static bool_ castable_while_blind(int s) { return spell_at(s)->castable_while_blind; } static bool_ castable_while_confused(int s) { return spell_at(s)->castable_while_confused; } /** Describe what type of energy the spell uses for casting */ cptr get_power_name(s32b s) { return uses_piety_to_cast(s) ? "piety" : "mana"; } /* Changes the amount of power(mana, piety, whatever) for the spell */ void adjust_power(s32b s, s32b amount) { if (uses_piety_to_cast(s)) { inc_piety(GOD_ALL, amount); } else { increase_mana(amount); } } /* Return the amount of power available for casting spell */ s32b get_power(s32b s) { return uses_piety_to_cast(s) ? p_ptr->grace : p_ptr->csp; } /* Output the describtion when it is used as a spell */ void print_spell_desc(int s, int y) { string_list *sl; struct sglib_string_list_iterator it; for (sl = sglib_string_list_it_init(&it, school_spells[s].description); sl != NULL; sl = sglib_string_list_it_next(&it)) { c_prt(TERM_L_BLUE, sl->s, y, 0); y++; } if (uses_piety_to_cast(s)) { c_prt(TERM_L_WHITE, "It uses piety to cast.", y, 0); y++; } if (castable_while_blind(s)) { c_prt(TERM_ORANGE, "It is castable even while blinded.", y, 0); y++; } if (castable_while_confused(s)) { c_prt(TERM_ORANGE, "It is castable even while confused.", y, 0); y++; } } school_book_type *school_books_at(int i) { assert(i >= 0); assert(i < SCHOOL_BOOKS_SIZE); return &school_books[i]; } static void school_book_init(school_book_type *school_book) { school_book->spell_idx_list = NULL; } static void spell_idx_init(spell_idx_list *p, s32b spell_idx) { assert(p != NULL); p->i = spell_idx; p->next = NULL; } static spell_idx_list *new_spell_idx(void *ctx, s32b spell_idx) { spell_idx_list *e = malloc(sizeof(spell_idx_list)); spell_idx_init(e, spell_idx); return e; } void school_book_add_spell(school_book_type *school_book, s32b spell_idx) { spell_idx_list *e; assert(school_book != NULL); e = new_spell_idx(school_book, spell_idx); sglib_spell_idx_list_add(&school_book->spell_idx_list, e); } int school_book_length(int sval) { school_book_type *school_book = school_books_at(sval); if (sval == BOOK_RANDOM) { return 1; } /* Parse all spells */ return sglib_spell_idx_list_len(school_book->spell_idx_list); } int spell_x(int sval, int pval, int i) { assert(i >= 0); if (sval == BOOK_RANDOM) { return pval; } else { school_book_type *school_book; spell_idx_list *spell_idx = NULL; struct sglib_spell_idx_list_iterator it; school_book = school_books_at(sval); for (spell_idx = sglib_spell_idx_list_it_init(&it, school_book->spell_idx_list); (spell_idx != NULL) && (i > 0); spell_idx = sglib_spell_idx_list_it_next(&it)) { i--; } assert(spell_idx != NULL); /* Went off the end of the list? */ return spell_idx->i; } } bool_ school_book_contains_spell(int sval, s32b spell_idx) { school_book_type *school_book = NULL; spell_idx_list e; random_book_setup(sval, spell_idx); school_book = school_books_at(sval); spell_idx_init(&e, spell_idx); return NULL != sglib_spell_idx_list_find_member(school_book->spell_idx_list, &e); } void push_spell(int book_idx, s32b spell_idx) { school_book_type *school_book = school_books_at(book_idx); assert(school_book != NULL); school_book_add_spell(school_book, spell_idx); } void init_school_books() { int i; /* Initialize the new school books */ for (i = 0; ispell_idx_list != NULL); school_book->spell_idx_list->i = spell_idx; } } static void spell_school_name(char *buf, spell_type *spell) { school_idx *school_idx = NULL; struct sglib_school_idx_iterator sit; bool_ first = TRUE; buf[0] = '\0'; for (school_idx = sglib_school_idx_it_init(&sit, spell->schools); school_idx != NULL; school_idx = sglib_school_idx_it_next(&sit)) { int sch = school_idx->i; school_type *school = school_at(sch); /* Add separator? */ if (!first) { strcat(buf, "/"); } first = FALSE; /* Add school name */ strcat(buf, school->name); } } int print_spell(cptr label_, byte color, int y, s32b s) { s32b level; bool_ na; spell_type *spell = spell_at(s); char sch_str[128]; cptr spell_info = get_spell_info(s); cptr label = (label_ == NULL) ? "" : label_; char level_str[8] = "n/a"; char buf[128]; get_level_school(s, 50, -50, &level, &na); spell_school_name(sch_str, spell); if (!na) { sprintf(level_str, "%3d", level); } sprintf(buf, "%s%-20s%-16s %s %4d %3d%% %s", label, school_spells[s].name, sch_str, level_str, get_mana(s), spell_chance(s), spell_info); c_prt(color, buf, y, 0); return y + 1; } int print_book(s16b sval, s32b pval, object_type *obj) { int y = 2; int i; school_book_type *school_book; spell_idx_list *spell_idx; struct sglib_spell_idx_list_iterator it; random_book_setup(sval, pval); school_book = school_books_at(sval); /* Parse all spells */ i = 0; for (spell_idx = sglib_spell_idx_list_it_init(&it, school_book->spell_idx_list); spell_idx != NULL; spell_idx = sglib_spell_idx_list_it_next(&it)) { s32b s = spell_idx->i; byte color = TERM_L_DARK; bool_ is_ok; char label[8]; is_ok = is_ok_spell(s, obj); if (is_ok) { color = (get_mana(s) > get_power(s)) ? TERM_ORANGE : TERM_L_GREEN; } sprintf(label, "%c) ", 'a' + i); y = print_spell(label, color, y, s); i++; } prt(format(" %-20s%-16s Level Cost Fail Info", "Name", "School"), 1, 0); return y; } static bool_ call_spell_function(s32b s) { spell_type *spell = spell_at(s); assert(spell->effect_func != NULL); return (spell->effect_func(-1) != NO_CAST); } void lua_cast_school_spell(s32b s, bool_ no_cost) { bool_ use = FALSE; /* No magic? */ if (p_ptr->antimagic > 0) { msg_print("Your anti-magic field disrupts any magic attempts."); return; } /* No magic? */ if (p_ptr->anti_magic) { msg_print("Your anti-magic shell disrupts any magic attempts."); return; } /* if it costs something then some condition must be met */ if (!no_cost) { /* Require lite */ if (!castable_while_blind(s) && ((p_ptr->blind > 0) || no_lite())) { msg_print("You cannot see!"); return; } /* Not when confused */ if (!castable_while_confused(s) && (p_ptr->confused > 0)) { msg_print("You are too confused!"); return; } /* Enough mana */ if (get_mana(s) > get_power(s)) { char buf[128]; sprintf(buf, "You do not have enough %s, do you want to try anyway?", get_power_name(s)); if (!get_check(buf)) { return; } } /* Invoke the spell effect */ if (!magik(spell_chance(s))) { use = call_spell_function(s); } else { use = TRUE; /* failures are dangerous; we'll flush the input buffer so it isn't missed. */ if (flush_failure) { flush(); } msg_print("You failed to get the spell off!"); } } else { call_spell_function(s); } /* Use the mana/piety */ if (use == TRUE) { /* Reduce mana */ adjust_power(s, -get_mana(s)); /* Take a turn */ energy_use = is_magestaff() ? 80 : 100; } /* Refresh player */ p_ptr->redraw |= PR_MANA; p_ptr->window |= PW_PLAYER; } void spell_description_add_line(s32b spell_idx, cptr line) { string_list_append(&school_spells[spell_idx].description, line); } void device_allocation_init(device_allocation *device_allocation, byte tval) { assert(device_allocation != NULL); device_allocation->tval = tval; device_allocation->rarity = 0; range_init(&device_allocation->base_level, 0, 0); range_init(&device_allocation->max_level, 0, 0); device_allocation->next = NULL; } device_allocation *device_allocation_new(byte tval) { device_allocation *d = malloc(sizeof(device_allocation)); device_allocation_init(d, tval); return d; } int compare_device_allocation(device_allocation *a, device_allocation *b) { return SGLIB_NUMERIC_COMPARATOR(a->tval, b->tval); } SGLIB_DEFINE_LIST_FUNCTIONS(device_allocation, compare_device_allocation, next); void dice_init(dice_type *dice, long base, long num, long sides) { assert(dice != NULL); dice->base = base; dice->num = num; dice->sides = sides; } bool_ dice_parse(dice_type *dice, cptr s) { long base, num, sides; if (sscanf(s, "%ld+%ldd%ld", &base, &num, &sides) == 3) { dice_init(dice, base, num, sides); return TRUE; } if (sscanf(s, "%ld+d%ld", &base, &sides) == 2) { dice_init(dice, base, 1, sides); return TRUE; } if (sscanf(s, "d%ld", &sides) == 1) { dice_init(dice, 0, 1, sides); return TRUE; } if (sscanf(s, "%ldd%ld", &num, &sides) == 2) { dice_init(dice, 0, num, sides); return TRUE; } if (sscanf(s, "%ld", &base) == 1) { dice_init(dice, base, 0, 0); return TRUE; } return FALSE; } void dice_parse_checked(dice_type *dice, cptr s) { bool_ result = dice_parse(dice, s); if (!result) { abort(); } } long dice_roll(dice_type *dice) { assert(dice != NULL); return dice->base + damroll(dice->num, dice->sides); } void dice_print(dice_type *dice, char *output) { char buf[16]; output[0] = '\0'; if (dice->base > 0) { sprintf(buf, "%ld", dice->base); strcat(output, buf); } if ((dice->num > 0) || (dice->sides > 0)) { if (dice->base > 0) { strcat(output, "+"); } if (dice->num > 1) { sprintf(buf, "%ld", dice->num); strcat(output, buf); } strcat(output, "d"); sprintf(buf, "%ld", dice->sides); strcat(output, buf); } }