/** * 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 */ //Best_s_ptr was slay** public static void improve_attack_modifier(Object o_ptr, Monster.Monster m_ptr, ref Slay best_s_ptr, bool real, bool known_only) { Monster_Race r_ptr = Misc.r_info[m_ptr.r_idx]; Monster_Lore l_ptr = Misc.l_list[m_ptr.r_idx]; Bitflag f = new Bitflag(Object_Flag.SIZE); Bitflag known_f = new Bitflag(Object_Flag.SIZE); Bitflag note_f = new Bitflag(Object_Flag.SIZE); int i; o_ptr.object_flags(ref f); o_ptr.object_flags_known(ref known_f); for (i = 0; i < Slay.MAX.value; i++) { Slay s_ptr = list[i]; if ((known_only && !known_f.has(s_ptr.object_flag.value)) || (!known_only && !f.has(s_ptr.object_flag.value))) { 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 && (known_f.has(s_ptr.object_flag.value) || (s_ptr.monster_flag != Monster_Flag.NONE && r_ptr.flags.has(s_ptr.monster_flag.value)) || (s_ptr.resist_flag != Monster_Flag.NONE && !r_ptr.flags.has(s_ptr.resist_flag.value)))) { /* notice any brand or slay that would affect monster */ note_f.wipe(); note_f.on(s_ptr.object_flag.value); object_notice_slays(o_ptr, note_f); if (m_ptr.ml && s_ptr.monster_flag != Monster_Flag.NONE) { l_ptr.flags.on(s_ptr.monster_flag.value); } if (m_ptr.ml && s_ptr.resist_flag != Monster_Flag.NONE) { l_ptr.flags.on(s_ptr.resist_flag.value); } } /* If the monster doesn't resist or the slay flag matches */ if ((s_ptr.brand != null && s_ptr.brand.Length != 0 && !r_ptr.flags.has(s_ptr.resist_flag.value)) || (s_ptr.monster_flag != Monster_Flag.NONE && r_ptr.flags.has(s_ptr.monster_flag.value))) { /* 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 */ public static void create_mask(Bitflag f, bool id, params object[] vals) { f.wipe(); /* Process each type in the va_args */ for (int i = 0; i < vals.Length; i++) { int value = (int)vals[i]; foreach (Object_Flag of in list) { if ((id && of.value == value) || (!id && of.type == (object_flag_type)vals[i])) { f.on(of.value); } } /*for (Object_Flag 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);*/ } return; }
/* * Remove the "bad" spells from a spell list */ static void remove_bad_spells(int m_idx, Bitflag f) { Monster m_ptr = Cave.cave_monster(Cave.cave, m_idx); Monster_Race r_ptr = Misc.r_info[m_ptr.r_idx]; Bitflag f2 = new Bitflag(Monster_Spell_Flag.SIZE); Bitflag ai_flags = new Bitflag(Object_Flag.SIZE); int i; uint smart = 0; /* Stupid monsters act randomly */ if (r_ptr.flags.has(Monster_Flag.STUPID.value)) { return; } /* Take working copy of spell flags */ f2.copy(f); /* Don't heal if full */ if (m_ptr.hp >= m_ptr.maxhp) { f2.off(Monster_Spell_Flag.HEAL.value); } /* Don't haste if hasted with time remaining */ if (m_ptr.m_timed[(int)Misc.MON_TMD.FAST] > 10) { f2.off(Monster_Spell_Flag.HASTE.value); } /* Don't teleport to if the player is already next to us */ if (m_ptr.cdis == 1) { f2.off(Monster_Spell_Flag.TELE_TO.value); } /* Update acquired knowledge */ ai_flags.wipe(); if (Option.birth_ai_learn.value) { /* Occasionally forget player status */ if (Random.one_in_(100)) { m_ptr.known_pflags.wipe(); } /* Use the memorized flags */ smart = m_ptr.smart; ai_flags.copy(m_ptr.known_pflags); } /* Cheat if requested */ if (Option.birth_ai_cheat.value) { for (i = 0; i < Object_Flag.MAX.value; i++) { if (Misc.p_ptr.check_state(Object_Flag.list[i], Misc.p_ptr.state.flags)) { ai_flags.on(i); } } if (Misc.p_ptr.msp == 0) { smart |= Misc.SM_IMM_MANA; } } /* Cancel out certain flags based on knowledge */ if (!ai_flags.is_empty()) { throw new NotImplementedException(); //unset_spells(f2, ai_flags, r_ptr); } if ((smart & Misc.SM_IMM_MANA) != 0 && Random.randint0(100) < 50 * (r_ptr.flags.has(Monster_Flag.SMART.value) ? 2 : 1)) { f2.off(Monster_Spell_Flag.DRAIN_MANA.value); } /* use working copy of spell flags */ f.copy(f2); }
/** * 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 */ public static void create_mask(Bitflag f, bool id, params object[] vals) { f.wipe(); /* Process each type in the va_args */ for (int i = 0; i < vals.Length; i++) { int value = (int)vals[i]; foreach(Object_Flag of in list) { if ((id && of.value == value) || (!id && of.type == (object_flag_type)vals[i])) f.on(of.value); } /*for (Object_Flag 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);*/ } return; }
/* * Determine whether a weapon or missile weapon is obviously {excellent} when * worn. * * XXX Eddie should messages be adhoc all over the place? perhaps the main * loop should check for change in inventory/wieldeds and all messages be * printed from one place */ public void notice_on_wield() { Bitflag f = new Bitflag(Object_Flag.SIZE); Bitflag f2 = new Bitflag(Object_Flag.SIZE); Bitflag obvious_mask = new Bitflag(Object_Flag.SIZE); bool obvious = false; Object_Flag.create_mask(obvious_mask, true, Object_Flag.object_flag_id.WIELD); /* Save time of wield for later */ object_last_wield = Misc.turn; /* Only deal with un-ID'd items */ if (is_known()) return; /* Wear it */ flavor_tried(); if (add_ident_flags(IDENT_WORN)) check_for_ident(); /* CC: may wish to be more subtle about this once we have ego lights * with multiple pvals */ if (is_light() && ego != null) notice_ego(); if (flavor_is_aware() && easy_know()) { notice_everything(); return; } /* Automatically sense artifacts upon wield */ sense_artifact(); /* Note artifacts when found */ if (artifact != null) History.add_artifact(artifact, is_known(), true); /* special case FA, needed at least for mages wielding gloves */ if (FA_would_be_obvious()) obvious_mask.on(Object_Flag.FREE_ACT.value); /* Extract the flags */ object_flags(ref f); /* Find obvious things (disregarding curses) - why do we remove the curses?? */ Object_Flag.create_mask(f2, false, Object_Flag.object_flag_type.CURSE); obvious_mask.diff(f2); if (f.is_inter(obvious_mask)) obvious = true; Object_Flag.create_mask(obvious_mask, true, Object_Flag.object_flag_id.WIELD); /* Notice any obvious brands or slays */ Slay.object_notice_slays(this, obvious_mask); /* Learn about obvious flags */ known_flags.union(obvious_mask); /* XXX Eddie should these next NOT call object_check_for_ident due to worries about repairing? */ /* XXX Eddie this is a small hack, but jewelry with anything noticeable really is obvious */ /* XXX Eddie learn =soulkeeping vs =bodykeeping when notice sustain_str */ if (is_jewelry()) { /* Learn the flavor of jewelry with obvious flags */ if (EASY_LEARN && obvious) flavor_aware(); /* Learn all flags on any aware non-artifact jewelry */ if (flavor_is_aware() && artifact == null) know_all_flags(); } check_for_ident(); if (!obvious) return; /* XXX Eddie need to add stealth here, also need to assert/double-check everything is covered */ /* CC: also need to add FA! */ if (f.has(Object_Flag.STR.value)) Utilities.msg("You feel %s!", pval[which_pval( Object_Flag.STR.value)] > 0 ? "stronger" : "weaker"); if (f.has(Object_Flag.INT.value)) Utilities.msg("You feel %s!", pval[which_pval( Object_Flag.INT.value)] > 0 ? "smarter" : "more stupid"); if (f.has(Object_Flag.WIS.value)) Utilities.msg("You feel %s!", pval[which_pval( Object_Flag.WIS.value)] > 0 ? "wiser" : "more naive"); if (f.has(Object_Flag.DEX.value)) Utilities.msg("You feel %s!", pval[which_pval( Object_Flag.DEX.value)] > 0 ? "more dextrous" : "clumsier"); if (f.has(Object_Flag.CON.value)) Utilities.msg("You feel %s!", pval[which_pval( Object_Flag.CON.value)] > 0 ? "healthier" : "sicklier"); if (f.has(Object_Flag.CHR.value)) Utilities.msg("You feel %s!", pval[which_pval( Object_Flag.CHR.value)] > 0 ? "cuter" : "uglier"); if (f.has(Object_Flag.SPEED.value)) Utilities.msg("You feel strangely %s.", pval[which_pval( Object_Flag.SPEED.value)] > 0 ? "quick" : "sluggish"); if (f.has(Object_Flag.BLOWS.value)) Utilities.msg("Your weapon %s in your hands.", pval[which_pval(Object_Flag.BLOWS.value)] > 0 ? "tingles" : "aches"); if (f.has(Object_Flag.SHOTS.value)) Utilities.msg("Your bow %s in your hands.", pval[which_pval(Object_Flag.SHOTS.value)] > 0 ? "tingles" : "aches"); if (f.has(Object_Flag.INFRA.value)) Utilities.msg("Your eyes tingle."); if (f.has(Object_Flag.LIGHT.value)) Utilities.msg("It glows!"); if (f.has(Object_Flag.TELEPATHY.value)) Utilities.msg("Your mind feels strangely sharper!"); /* WARNING -- masking f by obvious mask -- this should be at the end of this function */ /* CC: I think this can safely go, but just in case ... */ /*flags_mask(f, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END); */ /* Remember the flags */ notice_sensing(); /* XXX Eddie should we check_for_ident here? */ }
/* * Given an object, return a short identifier which gives some idea of what * the item is. */ public obj_pseudo_t pseudo() { Bitflag flags = new Bitflag(Object_Flag.SIZE); Bitflag f2 = new Bitflag(Object_Flag.SIZE); /* Get the known and obvious flags on the object, * not including curses or properties of the kind. */ object_flags_known(ref flags); Object_Flag.create_mask(f2, true, Object_Flag.object_flag_id.WIELD); /* FA on gloves is obvious to mage casters */ if (FA_would_be_obvious()) f2.on(Object_Flag.FREE_ACT.value); /* Now we remove the non-obvious known flags */ flags.inter(f2); /* Now we remove the cursed flags and the kind flags */ Object_Flag.create_mask(f2, false, Object_Flag.object_flag_type.CURSE); flags.diff(f2); flags.diff(kind.flags); if ((ident & IDENT_INDESTRUCT) != 0) return obj_pseudo_t.INSCRIP_SPECIAL; if ((was_sensed() || was_worn()) && artifact != null) return obj_pseudo_t.INSCRIP_SPECIAL; /* jewelry does not pseudo */ if (is_jewelry()) return obj_pseudo_t.INSCRIP_null; /* XXX Eddie should also check for flags with pvals where the pval exceeds * the base pval for things like picks of digging, though for now acid brand gets those */ if (!flags.is_empty()) return obj_pseudo_t.INSCRIP_SPLENDID; if (!is_known() && !was_sensed()) return obj_pseudo_t.INSCRIP_null; if (ego != null) { /* uncursed bad egos are not excellent */ if (ego.flags.is_inter(f2)) return obj_pseudo_t.INSCRIP_STRANGE; /* XXX Eddie need something worse */ else return obj_pseudo_t.INSCRIP_EXCELLENT; } if (to_a == Random.randcalc(kind.to_a, 0, aspect.MINIMISE) && to_h == Random.randcalc(kind.to_h, 0, aspect.MINIMISE) && to_d == Random.randcalc(kind.to_d, 0, aspect.MINIMISE)) return obj_pseudo_t.INSCRIP_AVERAGE; if (to_a >= Random.randcalc(kind.to_a, 0, aspect.MINIMISE) && to_h >= Random.randcalc(kind.to_h, 0, aspect.MINIMISE) && to_d >= Random.randcalc(kind.to_d, 0, aspect.MINIMISE)) return obj_pseudo_t.INSCRIP_MAGICAL; if (to_a <= Random.randcalc(kind.to_a, 0, aspect.MINIMISE) && to_h <= Random.randcalc(kind.to_h, 0, aspect.MINIMISE) && to_d <= Random.randcalc(kind.to_d, 0, aspect.MINIMISE)) return obj_pseudo_t.INSCRIP_MAGICAL; return obj_pseudo_t.INSCRIP_STRANGE; }
/* * Remove the "bad" spells from a spell list */ static void remove_bad_spells(int m_idx, Bitflag f) { Monster m_ptr = Cave.cave_monster(Cave.cave, m_idx); Monster_Race r_ptr = Misc.r_info[m_ptr.r_idx]; Bitflag f2 = new Bitflag(Monster_Spell_Flag.SIZE); Bitflag ai_flags = new Bitflag(Object_Flag.SIZE); int i; uint smart = 0; /* Stupid monsters act randomly */ if (r_ptr.flags.has(Monster_Flag.STUPID.value)) return; /* Take working copy of spell flags */ f2.copy(f); /* Don't heal if full */ if (m_ptr.hp >= m_ptr.maxhp) f2.off(Monster_Spell_Flag.HEAL.value); /* Don't haste if hasted with time remaining */ if (m_ptr.m_timed[(int)Misc.MON_TMD.FAST] > 10) f2.off(Monster_Spell_Flag.HASTE.value); /* Don't teleport to if the player is already next to us */ if (m_ptr.cdis == 1) f2.off(Monster_Spell_Flag.TELE_TO.value); /* Update acquired knowledge */ ai_flags.wipe(); if (Option.birth_ai_learn.value) { /* Occasionally forget player status */ if (Random.one_in_(100)) m_ptr.known_pflags.wipe(); /* Use the memorized flags */ smart = m_ptr.smart; ai_flags.copy(m_ptr.known_pflags); } /* Cheat if requested */ if (Option.birth_ai_cheat.value) { for (i = 0; i < Object_Flag.MAX.value; i++) if (Misc.p_ptr.check_state(Object_Flag.list[i], Misc.p_ptr.state.flags)) ai_flags.on(i); if (Misc.p_ptr.msp == 0) smart |= Misc.SM_IMM_MANA; } /* Cancel out certain flags based on knowledge */ if(!ai_flags.is_empty()) { throw new NotImplementedException(); //unset_spells(f2, ai_flags, r_ptr); } if ((smart & Misc.SM_IMM_MANA) != 0 && Random.randint0(100) < 50 * (r_ptr.flags.has(Monster_Flag.SMART.value) ? 2 : 1)) f2.off(Monster_Spell_Flag.DRAIN_MANA.value); /* use working copy of spell flags */ f.copy(f2); }
/* * Determine whether a weapon or missile weapon is obviously {excellent} when * worn. * * XXX Eddie should messages be adhoc all over the place? perhaps the main * loop should check for change in inventory/wieldeds and all messages be * printed from one place */ public void notice_on_wield() { Bitflag f = new Bitflag(Object_Flag.SIZE); Bitflag f2 = new Bitflag(Object_Flag.SIZE); Bitflag obvious_mask = new Bitflag(Object_Flag.SIZE); bool obvious = false; Object_Flag.create_mask(obvious_mask, true, Object_Flag.object_flag_id.WIELD); /* Save time of wield for later */ object_last_wield = Misc.turn; /* Only deal with un-ID'd items */ if (is_known()) { return; } /* Wear it */ flavor_tried(); if (add_ident_flags(IDENT_WORN)) { check_for_ident(); } /* CC: may wish to be more subtle about this once we have ego lights * with multiple pvals */ if (is_light() && ego != null) { notice_ego(); } if (flavor_is_aware() && easy_know()) { notice_everything(); return; } /* Automatically sense artifacts upon wield */ sense_artifact(); /* Note artifacts when found */ if (artifact != null) { History.add_artifact(artifact, is_known(), true); } /* special case FA, needed at least for mages wielding gloves */ if (FA_would_be_obvious()) { obvious_mask.on(Object_Flag.FREE_ACT.value); } /* Extract the flags */ object_flags(ref f); /* Find obvious things (disregarding curses) - why do we remove the curses?? */ Object_Flag.create_mask(f2, false, Object_Flag.object_flag_type.CURSE); obvious_mask.diff(f2); if (f.is_inter(obvious_mask)) { obvious = true; } Object_Flag.create_mask(obvious_mask, true, Object_Flag.object_flag_id.WIELD); /* Notice any obvious brands or slays */ Slay.object_notice_slays(this, obvious_mask); /* Learn about obvious flags */ known_flags.union(obvious_mask); /* XXX Eddie should these next NOT call object_check_for_ident due to worries about repairing? */ /* XXX Eddie this is a small hack, but jewelry with anything noticeable really is obvious */ /* XXX Eddie learn =soulkeeping vs =bodykeeping when notice sustain_str */ if (is_jewelry()) { /* Learn the flavor of jewelry with obvious flags */ if (EASY_LEARN && obvious) { flavor_aware(); } /* Learn all flags on any aware non-artifact jewelry */ if (flavor_is_aware() && artifact == null) { know_all_flags(); } } check_for_ident(); if (!obvious) { return; } /* XXX Eddie need to add stealth here, also need to assert/double-check everything is covered */ /* CC: also need to add FA! */ if (f.has(Object_Flag.STR.value)) { Utilities.msg("You feel %s!", pval[which_pval( Object_Flag.STR.value)] > 0 ? "stronger" : "weaker"); } if (f.has(Object_Flag.INT.value)) { Utilities.msg("You feel %s!", pval[which_pval( Object_Flag.INT.value)] > 0 ? "smarter" : "more stupid"); } if (f.has(Object_Flag.WIS.value)) { Utilities.msg("You feel %s!", pval[which_pval( Object_Flag.WIS.value)] > 0 ? "wiser" : "more naive"); } if (f.has(Object_Flag.DEX.value)) { Utilities.msg("You feel %s!", pval[which_pval( Object_Flag.DEX.value)] > 0 ? "more dextrous" : "clumsier"); } if (f.has(Object_Flag.CON.value)) { Utilities.msg("You feel %s!", pval[which_pval( Object_Flag.CON.value)] > 0 ? "healthier" : "sicklier"); } if (f.has(Object_Flag.CHR.value)) { Utilities.msg("You feel %s!", pval[which_pval( Object_Flag.CHR.value)] > 0 ? "cuter" : "uglier"); } if (f.has(Object_Flag.SPEED.value)) { Utilities.msg("You feel strangely %s.", pval[which_pval( Object_Flag.SPEED.value)] > 0 ? "quick" : "sluggish"); } if (f.has(Object_Flag.BLOWS.value)) { Utilities.msg("Your weapon %s in your hands.", pval[which_pval(Object_Flag.BLOWS.value)] > 0 ? "tingles" : "aches"); } if (f.has(Object_Flag.SHOTS.value)) { Utilities.msg("Your bow %s in your hands.", pval[which_pval(Object_Flag.SHOTS.value)] > 0 ? "tingles" : "aches"); } if (f.has(Object_Flag.INFRA.value)) { Utilities.msg("Your eyes tingle."); } if (f.has(Object_Flag.LIGHT.value)) { Utilities.msg("It glows!"); } if (f.has(Object_Flag.TELEPATHY.value)) { Utilities.msg("Your mind feels strangely sharper!"); } /* WARNING -- masking f by obvious mask -- this should be at the end of this function */ /* CC: I think this can safely go, but just in case ... */ /*flags_mask(f, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END); */ /* Remember the flags */ notice_sensing(); /* XXX Eddie should we check_for_ident here? */ }
/** * 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 */ //Best_s_ptr was slay** public static void improve_attack_modifier(Object o_ptr, Monster.Monster m_ptr, ref Slay best_s_ptr, bool real, bool known_only) { Monster_Race r_ptr = Misc.r_info[m_ptr.r_idx]; Monster_Lore l_ptr = Misc.l_list[m_ptr.r_idx]; Bitflag f = new Bitflag(Object_Flag.SIZE); Bitflag known_f = new Bitflag(Object_Flag.SIZE); Bitflag note_f = new Bitflag(Object_Flag.SIZE); int i; o_ptr.object_flags(ref f); o_ptr.object_flags_known(ref known_f); for (i = 0; i < Slay.MAX.value; i++) { Slay s_ptr = list[i]; if ((known_only && !known_f.has(s_ptr.object_flag.value)) || (!known_only && !f.has(s_ptr.object_flag.value))) 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 && (known_f.has(s_ptr.object_flag.value) || (s_ptr.monster_flag != Monster_Flag.NONE && r_ptr.flags.has(s_ptr.monster_flag.value)) || (s_ptr.resist_flag != Monster_Flag.NONE && !r_ptr.flags.has(s_ptr.resist_flag.value)))) { /* notice any brand or slay that would affect monster */ note_f.wipe(); note_f.on(s_ptr.object_flag.value); object_notice_slays(o_ptr, note_f); if (m_ptr.ml && s_ptr.monster_flag != Monster_Flag.NONE) l_ptr.flags.on(s_ptr.monster_flag.value); if (m_ptr.ml && s_ptr.resist_flag != Monster_Flag.NONE) l_ptr.flags.on(s_ptr.resist_flag.value); } /* If the monster doesn't resist or the slay flag matches */ if ((s_ptr.brand != null && s_ptr.brand.Length != 0 && !r_ptr.flags.has(s_ptr.resist_flag.value)) || (s_ptr.monster_flag != Monster_Flag.NONE && r_ptr.flags.has(s_ptr.monster_flag.value))) { /* compare multipliers to determine best attack */ if ((best_s_ptr == null) || ((best_s_ptr).mult < s_ptr.mult)) best_s_ptr = s_ptr; } } }