/** * Remove the "bad" spells from a spell list */ static void remove_bad_spells(struct monster *mon, bitflag f[RSF_SIZE]) { bitflag f2[RSF_SIZE], ai_flags[OF_SIZE], ai_pflags[PF_SIZE]; struct element_info el[ELEM_MAX]; bool know_something = false; /* Stupid monsters act randomly */ if (rf_has(mon->race->flags, RF_STUPID)) return; /* Take working copy of spell flags */ rsf_copy(f2, f); /* Don't heal if full */ if (mon->hp >= mon->maxhp) rsf_off(f2, RSF_HEAL); /* Don't haste if hasted with time remaining */ if (mon->m_timed[MON_TMD_FAST] > 10) rsf_off(f2, RSF_HASTE); /* Don't teleport to if the player is already next to us */ if (mon->cdis == 1) rsf_off(f2, RSF_TELE_TO); /* Update acquired knowledge */ of_wipe(ai_flags); pf_wipe(ai_pflags); if (OPT(birth_ai_learn)) { size_t i; /* Occasionally forget player status */ if (one_in_(100)) { of_wipe(mon->known_pstate.flags); pf_wipe(mon->known_pstate.pflags); for (i = 0; i < ELEM_MAX; i++) mon->known_pstate.el_info[i].res_level = 0; } /* Use the memorized info */ of_copy(ai_flags, mon->known_pstate.flags); pf_copy(ai_pflags, mon->known_pstate.pflags); if (!of_is_empty(ai_flags) || !pf_is_empty(ai_pflags)) know_something = true; for (i = 0; i < ELEM_MAX; i++) { el[i].res_level = mon->known_pstate.el_info[i].res_level; if (el[i].res_level != 0) know_something = true; } } /* Cancel out certain flags based on knowledge */ if (know_something) unset_spells(f2, ai_flags, ai_pflags, el, mon->race); /* use working copy of spell flags */ rsf_copy(f, f2); }
/* * Describe miscellaneous powers. */ static bool describe_misc_magic(textblock * tb, const object_type * o_ptr, oinfo_detail_t mode) { bool full = mode & OINFO_FULL; size_t i; bool printed = FALSE; bitflag objflags[OF_SIZE]; of_wipe(objflags); of_copy(objflags, o_ptr->flags_obj); if (!full) of_inter(objflags, o_ptr->id_obj); for (i = 0; i < N_ELEMENTS(misc_flags); i++) { if (of_has(objflags, misc_flags[i].flag)) { if (!printed) textblock_append(tb, "\nPowers: "); textblock_append(tb, "%s. ", misc_flags[i].name); printed = TRUE; } } if (printed) textblock_append(tb, "\n"); return printed; }
/** * Determine whether a flagset includes any curse flags. */ bool cursed_p(bitflag *f) { bitflag f2[OF_SIZE]; of_wipe(f2); create_mask(f2, FALSE, OFT_CURSE, OFT_MAX); return of_is_inter(f, f2); }
void set_ego_xtra_sustain(bitflag flags[OF_SIZE]) { size_t i; of_wipe(flags); for (i = 0; i < N_ELEMENTS(ego_sustains); i++) of_on(flags, ego_sustains[i]); }
/** * Extract the multiplier from a given object hitting a given monster. * * \param o_ptr is the object being used to attack * \param m_ptr is the monster being attacked * \param best_s_ptr is the best applicable slay_table entry, or NULL if no * slay already known * \param real is whether this is a real attack (where we update lore) or a * simulation (where we don't) * \param known_only is whether we are using all the object flags, or only * the ones we *already* know about */ void improve_attack_modifier(object_type *o_ptr, const monster_type *m_ptr, const struct slay **best_s_ptr, bool real, bool known_only) { monster_race *r_ptr = &r_info[m_ptr->r_idx]; monster_lore *l_ptr = &l_list[m_ptr->r_idx]; bitflag f[OF_SIZE], known_f[OF_SIZE], note_f[OF_SIZE]; int i; object_flags(o_ptr, f); object_flags_known(o_ptr, known_f); for (i = 0; i < SL_MAX; i++) { const struct slay *s_ptr = &slay_table[i]; if ((known_only && !of_has(known_f, s_ptr->object_flag)) || (!known_only && !of_has(f, s_ptr->object_flag))) continue; /* Disallow forbidden off-weapon slays/brands */ if (wield_slot(o_ptr) > INVEN_BOW && wield_slot(o_ptr) < INVEN_TOTAL && !s_ptr->nonweap) continue; /* In a real attack, learn about monster resistance or slay match if: * EITHER the slay flag on the object is known, * OR the monster is vulnerable to the slay/brand */ if (real && (of_has(known_f, s_ptr->object_flag) || (s_ptr->monster_flag && rf_has(r_ptr->flags, s_ptr->monster_flag)) || (s_ptr->resist_flag && !rf_has(r_ptr->flags, s_ptr->resist_flag)) || (s_ptr->vuln_flag && rf_has(r_ptr->flags, s_ptr->vuln_flag)))) { /* notice any brand or slay that would affect monster */ of_wipe(note_f); of_on(note_f, s_ptr->object_flag); object_notice_slays(o_ptr, note_f); if (m_ptr->ml && s_ptr->monster_flag) rf_on(l_ptr->flags, s_ptr->monster_flag); if (m_ptr->ml && s_ptr->resist_flag) rf_on(l_ptr->flags, s_ptr->resist_flag); if (m_ptr->ml && s_ptr->vuln_flag) rf_on(l_ptr->flags, s_ptr->vuln_flag); } /* If the monster doesn't resist or the slay flag matches */ if ((s_ptr->brand && !rf_has(r_ptr->flags, s_ptr->resist_flag)) || (s_ptr->monster_flag && rf_has(r_ptr->flags, s_ptr->monster_flag)) || (s_ptr->vuln_flag && rf_has(r_ptr->flags, s_ptr->vuln_flag))) { /* compare multipliers to determine best attack */ if ((*best_s_ptr == NULL) || ((*best_s_ptr)->mult < s_ptr->mult)) *best_s_ptr = s_ptr; } } }
/** * Create a "mask" of flags of a specific type or ID threshold. * * \param f is the flag array we're filling * \param id is whether we're masking by ID level * \param ... is the list of flags or ID types we're looking for * * N.B. OFT_MAX must be the last item in the ... list */ void create_mask(bitflag *f, bool id, ...) { const struct object_flag *of_ptr; int i; va_list args; of_wipe(f); va_start(args, id); /* Process each type in the va_args */ for (i = va_arg(args, int); i != OFT_MAX; i = va_arg(args, int)) { for (of_ptr = object_flag_table; of_ptr->index < OF_MAX; of_ptr++) if ((id && of_ptr->id == i) || (!id && of_ptr->type == i)) of_on(f, of_ptr->index); } va_end(args); return; }
/** * Check item flags for legality. This function currently does three things: * - checks slay_table for slay & brand contradictions (dedup_slays) * - checks gf_table for imm/res/vuln contradictions (dedup_gf_flags) * - removes all attrs from ammo except slays/brands/ignore/hates */ void check_flags(object_type *o_ptr) { bitflag f[OF_SIZE]; int i; dedup_slays(o_ptr->flags); dedup_gf_flags(o_ptr->flags); if (kind_is_ammo(o_ptr->tval)) { create_mask(f, FALSE, OFT_SLAY, OFT_BRAND, OFT_KILL, OFT_IGNORE, OFT_HATES, OFT_INT, OFT_MAX); of_inter(o_ptr->flags, f); for (i = 0; i < MAX_PVALS; i++) of_wipe(o_ptr->pval_flags[i]); o_ptr->num_pvals = 0; o_ptr->ac = 0; o_ptr->to_a = 0; } return; }
/** * Create a "mask" of object flags of a specific type or ID threshold. * * \param f is the flag array we're filling * \param id is whether we're masking by ID level * \param ... is the list of flags or ID types we're looking for * * N.B. OFT_MAX must be the last item in the ... list */ void create_obj_flag_mask(bitflag *f, bool id, ...) { int i, j; va_list args; of_wipe(f); va_start(args, id); /* Process each type in the va_args */ for (i = va_arg(args, int); i != OFT_MAX; i = va_arg(args, int)) { for (j = 1; j < z_info->property_max; j++) { struct obj_property *prop = &obj_properties[j]; if (prop->type != OBJ_PROPERTY_FLAG) continue; if ((id && prop->id_type == i) || (!id && prop->subtype == i)) { of_on(f, prop->index); } } } va_end(args); return; }
static void display_resistance_panel(const struct player_flag_record *rec, size_t size, const region *bounds) { size_t i; int j; int col = bounds->col; int row = bounds->row; int res_cols = 5 + 2 + player->body.count; Term_putstr(col, row++, res_cols, COLOUR_WHITE, " abcdefghijkl@"); for (i = 0; i < size - 3; i++, row++) { byte name_attr = COLOUR_WHITE; Term_gotoxy(col + 6, row); /* Repeated extraction of flags is inefficient but more natural */ for (j = 0; j <= player->body.count; j++) { bitflag f[OF_SIZE]; byte attr = COLOUR_WHITE | (j % 2) * 8; /* alternating columns */ char sym = '.'; bool res = false, imm = false, vul = false, rune = false; bool timed = false; bool known = false; /* Object or player info? */ if (j < player->body.count) { int index = 0; struct object *obj = slot_object(player, j); struct curse_data *curse = obj ? obj->curses : NULL; while (obj) { /* Wipe flagset */ of_wipe(f); /* Get known properties */ object_flags_known(obj, f); if (rec[i].element != -1) { known = object_element_is_known(obj, rec[i].element); } else if (rec[i].flag != -1) { known = object_flag_is_known(obj, rec[i].flag); } else { known = true; } /* Get resistance, immunity and vulnerability info */ if (rec[i].mod != -1) { if (obj->modifiers[rec[i].mod] != 0) { res = true; } rune = (player->obj_k->modifiers[rec[i].mod] == 1); } else if (rec[i].flag != -1) { if (of_has(f, rec[i].flag)) { res = true; } rune = of_has(player->obj_k->flags, rec[i].flag); } else if (rec[i].element != -1) { if (known) { if (obj->el_info[rec[i].element].res_level == 3) { imm = true; } if (obj->el_info[rec[i].element].res_level == 1) { res = true; } if (obj->el_info[rec[i].element].res_level == -1) { vul = true; } } rune = (player->obj_k->el_info[rec[i].element].res_level == 1); } /* Move to any unprocessed curse object */ if (curse) { index++; obj = NULL; while (index < z_info->curse_max) { if (curse[index].power) { obj = curses[index].obj; break; } else { index++; } } } else { obj = NULL; } } } else { player_flags(player, f); known = true; /* Timed flags only in the player column */ if (rec[i].tmd_flag >= 0) { timed = player->timed[rec[i].tmd_flag] ? true : false; /* There has to be one special case... */ if ((rec[i].tmd_flag == TMD_AFRAID) && (player->timed[TMD_TERROR])) timed = true; } /* Set which (if any) symbol and color are used */ if (rec[i].mod != -1) { int k; /* Shape modifiers */ for (k = 0; k < OBJ_MOD_MAX; k++) { res = (player->shape->modifiers[i] > 0); vul = (player->shape->modifiers[i] > 0); } /* Messy special cases */ if (rec[i].mod == OBJ_MOD_INFRA) res |= (player->race->infra > 0); if (rec[i].mod == OBJ_MOD_TUNNEL) res |= (player->race->r_skills[SKILL_DIGGING] > 0); } else if (rec[i].flag != -1) { res = of_has(f, rec[i].flag); res |= (of_has(player->shape->flags, rec[i].flag) && of_has(player->obj_k->flags, rec[i].flag)); } else if (rec[i].element != -1) { int el = rec[i].element; imm = (player->race->el_info[el].res_level == 3) || ((player->shape->el_info[el].res_level == 3) && (player->obj_k->el_info[el].res_level)); res = (player->race->el_info[el].res_level == 1) || ((player->shape->el_info[el].res_level == 1) && (player->obj_k->el_info[el].res_level)); vul = (player->race->el_info[el].res_level == -1) || ((player->shape->el_info[el].res_level == -1) && (player->obj_k->el_info[el].res_level)); } } /* Colour the name appropriately */ if (imm) { name_attr = COLOUR_GREEN; } else if (res && (name_attr != COLOUR_GREEN)) { name_attr = COLOUR_L_BLUE; } else if (vul && (name_attr != COLOUR_GREEN)) { name_attr = COLOUR_RED; } /* Set the symbols and print them */ if (vul) { sym = '-'; } else if (imm) { sym = '*'; } else if (res) { sym = '+'; } else if (timed) { sym = '!'; attr = COLOUR_L_GREEN; } else if ((j < player->body.count) && slot_object(player, j) && !known && !rune) { sym = '?'; } Term_addch(attr, sym); } /* Check if the rune is known */ if (((rec[i].mod >= 0) && (player->obj_k->modifiers[rec[i].mod] == 0)) || ((rec[i].flag >= 0) && !of_has(player->obj_k->flags, rec[i].flag)) || ((rec[i].element >= 0) && (player->obj_k->el_info[rec[i].element].res_level == 0))) { name_attr = COLOUR_SLATE; } Term_putstr(col, row, 6, name_attr, format("%5s:", rec[i].name)); } Term_putstr(col, row++, res_cols, COLOUR_WHITE, " abcdefghijkl@"); /* Equippy */ display_player_equippy(row++, col + 6); }
static void display_resistance_panel(const struct player_flag_record *rec, size_t size, const region *bounds) { size_t i; int j; int col = bounds->col; int row = bounds->row; int res_cols = 5 + 2 + player->body.count; Term_putstr(col, row++, res_cols, COLOUR_WHITE, " abcdefghijkl@"); for (i = 0; i < size - 3; i++, row++) { byte name_attr = COLOUR_WHITE; Term_gotoxy(col + 6, row); /* Repeated extraction of flags is inefficient but more natural */ for (j = 0; j <= player->body.count; j++) { struct object *obj; bitflag f[OF_SIZE]; byte attr = COLOUR_WHITE | (j % 2) * 8; /* alternating columns */ char sym = '.'; bool res = false, imm = false, vul = false, rune = false; bool timed = false; bool known = false; /* Wipe flagset */ of_wipe(f); /* Get the object or player info */ obj = j < player->body.count ? slot_object(player, j) : NULL; if (j < player->body.count && obj) { /* Get known properties */ object_flags_known(obj, f); if (rec[i].element != -1) known = object_element_is_known(obj, rec[i].element); else if (rec[i].flag != -1) known = object_flag_is_known(obj, rec[i].flag); else known = true; } else if (j == player->body.count) { player_flags(player, f); known = true; /* Timed flags only in the player column */ if (rec[i].tmd_flag >= 0) { timed = player->timed[rec[i].tmd_flag] ? true : false; /* There has to be one special case... */ if ((rec[i].tmd_flag == TMD_AFRAID) && (player->timed[TMD_TERROR])) timed = true; } } /* Set which (if any) symbol and color are used */ if (rec[i].mod != -1) { if (j != player->body.count) res = (obj && (obj->modifiers[rec[i].mod] != 0)); else { /* Messy special cases */ if (rec[i].mod == OBJ_MOD_INFRA) res = (player->race->infra > 0); if (rec[i].mod == OBJ_MOD_TUNNEL) res = (player->race->r_skills[SKILL_DIGGING] > 0); } rune = (player->obj_k->modifiers[rec[i].mod] == 1); } else if (rec[i].flag != -1) { res = of_has(f, rec[i].flag); rune = of_has(player->obj_k->flags, rec[i].flag); } else if (rec[i].element != -1) { if (j != player->body.count) { imm = obj && known && (obj->el_info[rec[i].element].res_level == 3); res = obj && known && (obj->el_info[rec[i].element].res_level == 1); vul = obj && known && (obj->el_info[rec[i].element].res_level == -1); } else { imm = player->race->el_info[rec[i].element].res_level == 3; res = player->race->el_info[rec[i].element].res_level == 1; vul = player->race->el_info[rec[i].element].res_level == -1; } rune = (player->obj_k->el_info[rec[i].element].res_level == 1); } /* Set the symbols and print them */ if (imm) name_attr = COLOUR_GREEN; else if (!rune) name_attr = COLOUR_SLATE; else if (res && (name_attr != COLOUR_GREEN)) name_attr = COLOUR_L_BLUE; if (vul) sym = '-'; else if (imm) sym = '*'; else if (res) sym = '+'; else if (timed) { sym = '!'; attr = COLOUR_L_GREEN; } else if ((j < player->body.count) && obj && !known && !rune) sym = '?'; Term_addch(attr, sym); } Term_putstr(col, row, 6, name_attr, format("%5s:", rec[i].name)); } Term_putstr(col, row++, res_cols, COLOUR_WHITE, " abcdefghijkl@"); /* Equippy */ display_player_equippy(row++, col + 6); }
static void display_resistance_panel(const struct player_flag_record *resists, size_t size, const region *bounds) { size_t i, j; int col = bounds->col; int row = bounds->row; Term_putstr(col, row++, RES_COLS, TERM_WHITE, " abcdefghijkl@"); for (i = 0; i < size-3; i++, row++) { byte name_attr = TERM_WHITE; Term_gotoxy(col+6, row); /* repeated extraction of flags is inefficient but more natural */ for (j = INVEN_WIELD; j <= INVEN_TOTAL; j++) { object_type *o_ptr = &p_ptr->inventory[j]; bitflag f[OF_SIZE]; byte attr = TERM_WHITE | (j % 2) * 8; /* alternating columns */ char sym = '.'; bool res, imm, vuln; /* Wipe flagset */ of_wipe(f); if (j < INVEN_TOTAL && o_ptr->kind) { object_flags_known(o_ptr, f); } else if (j == INVEN_TOTAL) { player_flags(f); /* If the race has innate infravision/digging, force the corresponding flag here. If we set it in player_flags(), then all callers of that function will think the infravision is caused by equipment. */ if (p_ptr->race->infra > 0) of_on(f, OF_INFRA); if (p_ptr->race->r_skills[SKILL_DIGGING] > 0) of_on(f, OF_TUNNEL); } res = of_has(f, resists[i].res_flag); imm = of_has(f, resists[i].im_flag); vuln = of_has(f, resists[i].vuln_flag); if (imm) name_attr = TERM_GREEN; else if (res && name_attr == TERM_WHITE) name_attr = TERM_L_BLUE; if (vuln) sym = '-'; else if (imm) sym = '*'; else if (res) sym = '+'; else if ((j < INVEN_TOTAL) && o_ptr->kind && !object_flag_is_known(o_ptr, resists[i].res_flag)) sym = '?'; Term_addch(attr, sym); } Term_putstr(col, row, 6, name_attr, format("%5s:", resists[i].name)); } Term_putstr(col, row++, RES_COLS, TERM_WHITE, " abcdefghijkl@"); /* Equippy */ display_player_equippy(row++, col+6); }
static void display_resistance_panel(const struct player_flag_record *resists, size_t size, const region *bounds) { size_t i; int j; int col = bounds->col; int row = bounds->row; Term_putstr(col, row++, RES_COLS, TERM_WHITE, " @abcdefghijklmnopqrstuvwxyz{|}"); for (i = 0; i < size-3; i++, row++) { byte name_attr = TERM_WHITE; Term_gotoxy(col+6, row); /* repeated extraction of flags is inefficient but more natural */ for (j = INVEN_WIELD - 1; j < INVEN_TOTAL; j++) { if (((j >= INVEN_WIELD) && (j < INVEN_WIELD + rp_ptr->melee_slots)) || ((j >= INVEN_BOW) && (j < INVEN_BOW + rp_ptr->range_slots)) || ((j >= INVEN_FINGER) && (j < INVEN_FINGER + rp_ptr->ring_slots)) || ((j >= INVEN_NECK) && (j < INVEN_NECK + rp_ptr->amulet_slots)) || ((j >= INVEN_LIGHT) && (j < INVEN_LIGHT + rp_ptr->light_slots)) || ((j >= INVEN_BODY) && (j < INVEN_BODY + rp_ptr->body_slots)) || ((j >= INVEN_OUTER) && (j < INVEN_OUTER + rp_ptr->cloak_slots)) || ((j >= INVEN_ARM) && (j < INVEN_ARM + rp_ptr->shield_slots)) || ((j >= INVEN_HEAD) && (j < INVEN_HEAD + rp_ptr->helm_slots)) || ((j >= INVEN_HANDS) && (j < INVEN_HANDS + rp_ptr->glove_slots)) || ((j >= INVEN_FEET) && (j < INVEN_FEET + rp_ptr->boot_slots)) || (j == INVEN_WIELD - 1)) { object_type *o_ptr = &p_ptr->inventory[j]; bitflag f[OF_SIZE]; byte attr = TERM_WHITE | (j % 2) * 8; /* alternating columns */ char sym = '.'; bool res, imm, vuln; /* Wipe flagset */ of_wipe(f); if (j < INVEN_WIELD) { player_flags(f); /* If the race has innate infravision/digging, force the corresponding flag here. If we set it in player_flags(), then all callers of that function will think the infravision is caused by equipment. */ if (rp_ptr->infra > 0) of_on(f, OF_INFRA); if (rp_ptr->r_skills[SKILL_DIGGING] > 0) of_on(f, OF_TUNNEL); } else if (j < INVEN_TOTAL && o_ptr->k_idx) { object_flags_known(o_ptr, f); } res = of_has(f, resists[i].res_flag); imm = of_has(f, resists[i].im_flag); vuln = of_has(f, resists[i].vuln_flag); if (imm) name_attr = TERM_GREEN; else if (res && name_attr == TERM_WHITE) name_attr = TERM_L_BLUE; if (vuln) sym = '-'; else if (imm) sym = '*'; else if (res) sym = '+'; else if ((j < INVEN_TOTAL) && o_ptr->k_idx && !object_flag_is_known(o_ptr, resists[i].res_flag)) sym = '?'; Term_addch(attr, sym); } } Term_putstr(col, row, 6, name_attr, format("%5s:", resists[i].name)); } Term_putstr(col, row++, RES_COLS, TERM_WHITE, " @abcdefghijklmnopqrstuvwxyz{|}"); /* Equippy */ display_player_equippy(row++, col+7); }