예제 #1
0
        /**
         * Apply generation magic to an ego-item.
         */
        void ego_apply_magic(int level)
        {
            int i, flag, x;

            Bitflag flags = new Bitflag(Object_Flag.SIZE);
            Bitflag newf  = new Bitflag(Object_Flag.SIZE);

            object_flags(ref flags);

            /* Extra powers */
            if (ego.xtra == Object_Flag.OBJECT_XTRA_TYPE_SUSTAIN)
            {
                Object_Flag.create_mask(newf, false, Object_Flag.object_flag_type.SUST);
            }
            else if (ego.xtra == Object_Flag.OBJECT_XTRA_TYPE_RESIST)
            {
                Object_Flag.create_mask(newf, false, Object_Flag.object_flag_type.HRES);
            }
            else if (ego.xtra == Object_Flag.OBJECT_XTRA_TYPE_POWER)
            {
                Object_Flag.create_mask(newf, false, Object_Flag.object_flag_type.PROT, Object_Flag.object_flag_type.MISC);
            }

            if (ego.xtra != 0)
            {
                this.flags.on(get_new_attr(flags, newf));
            }

            /* Apply extra ego bonuses */
            to_h += (short)Random.randcalc(ego.to_h, level, aspect.RANDOMISE);
            to_d += (short)Random.randcalc(ego.to_d, level, aspect.RANDOMISE);
            to_a += (short)Random.randcalc(ego.to_a, level, aspect.RANDOMISE);

            /* Apply pvals */
            for (i = 0; i < ego.num_pvals; i++)
            {
                flags.copy(ego.pval_flags[i]);
                x = Random.randcalc(ego.pval[i], level, aspect.RANDOMISE);
                for (flag = flags.next(Bitflag.FLAG_START); flag != Bitflag.FLAG_null; flag = flags.next(flag + 1))
                {
                    add_pval(x, flag);
                }
            }

            /* Apply flags */
            this.flags.union(ego.flags);

            return;
        }
예제 #2
0
        public Player_State(Player_State state)
        {
            speed = state.speed;

            num_blows = state.num_blows;
            num_shots = state.num_shots;

            ammo_mult = state.ammo_mult;
            ammo_tval = state.ammo_tval;

            state.stat_add.CopyTo(stat_add, 0);
            state.stat_ind.CopyTo(stat_ind, 0);
            state.stat_use.CopyTo(stat_use, 0);
            state.stat_top.CopyTo(stat_top, 0);

            dis_ac = state.dis_ac;
            ac     = state.ac;

            dis_to_a = state.dis_to_a;
            to_a     = state.to_a;

            to_h     = state.to_h;
            dis_to_h = state.dis_to_h;

            to_d     = state.to_d;
            dis_to_d = state.dis_to_d;

            see_infra = state.see_infra;

            state.skills.CopyTo(skills, 0);

            noise = state.noise;

            heavy_wield = state.heavy_wield;            /* Heavy weapon */
            heavy_shoot = state.heavy_shoot;            /* Heavy shooter */
            icky_wield  = state.icky_wield;             /* Icky weapon shooter */

            flags.copy(state.flags);
        }
예제 #3
0
        /**
         * Match slays in flags against a chosen flag mask
         *
         * count is the number of matches
         * \param flags is the flagset to analyse for matches
         * \param mask is the flagset against which to test
         * \param desc[] is the array of descriptions of matching slays - can be null
         * \param brand[] is the array of descriptions of brands - can be null
         * \param mult[] is the array of multipliers of those slays - can be null
         * \param dedup is whether or not to remove duplicates
         *
         * desc[], brand[] and mult[] must be >= SL_MAX in size
         */
        //Bitflags were size Object_Flag.SIZE, might be an out param
        public static int list_slays(Bitflag flags, Bitflag mask, string[] desc, string[] brand, int[] mult, bool dedup)
        {
            int     i, count = 0;
            Bitflag f = new Bitflag(Object_Flag.SIZE);

            /* We are only interested in the flags specified in mask */
            f.copy(flags);
            f.inter(mask);

            /* Remove "duplicate" flags if desired */
            if (dedup)
            {
                dedup_slays(ref f);
            }

            /* Collect slays */
            for (i = 0; i < list.Count(); i++)
            {
                Slay s_ptr = list[i];
                if (f.has(s_ptr.object_flag.value))
                {
                    if (mult != null)
                    {
                        mult[count] = s_ptr.mult;
                    }
                    if (brand != null)
                    {
                        brand[count] = s_ptr.brand;
                    }
                    if (desc != null)
                    {
                        desc[count] = s_ptr.desc;
                    }
                    count++;
                }
            }

            return(count);
        }
예제 #4
0
        /*
         * 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);
        }
예제 #5
0
        /*
         * Creatures can cast spells, shoot missiles, and breathe.
         *
         * Returns "true" if a spell (or whatever) was (successfully) cast.
         *
         * XXX XXX XXX This function could use some work, but remember to
         * keep it as optimized as possible, while retaining generic code.
         *
         * Verify the various "blind-ness" checks in the code.
         *
         * XXX XXX XXX Note that several effects should really not be "seen"
         * if the player is blind.
         *
         * Perhaps monsters should breathe at locations *near* the player,
         * since this would allow them to inflict "partial" damage.
         *
         * Perhaps smart monsters should decline to use "bolt" spells if
         * there is a monster in the way, unless they wish to kill it.
         *
         * It will not be possible to "correctly" handle the case in which a
         * monster attempts to attack a location which is thought to contain
         * the player, but which in fact is nowhere near the player, since this
         * might induce all sorts of messages about the attack itself, and about
         * the effects of the attack, which the player might or might not be in
         * a position to observe.  Thus, for simplicity, it is probably best to
         * only allow "faulty" attacks by a monster if one of the important grids
         * (probably the initial or final grid) is in fact in view of the player.
         * It may be necessary to actually prevent spell attacks except when the
         * monster actually has line of sight to the player.  Note that a monster
         * could be left in a bizarre situation after the player ducked behind a
         * pillar and then teleported away, for example.
         *
         * Note that this function attempts to optimize the use of spells for the
         * cases in which the monster has no spells, or has spells but cannot use
         * them, or has spells but they will have no "useful" effect.  Note that
         * this function has been an efficiency bottleneck in the past.
         *
         * Note the special "MFLAG_NICE" flag, which prevents a monster from using
         * any spell attacks until the player has had a single chance to move.
         */
        static bool make_attack_spell(int m_idx)
        {
            int chance, thrown_spell, rlev, failrate;

            Bitflag f = new Bitflag(Monster_Spell_Flag.SIZE);

            Monster m_ptr = Cave.cave_monster(Cave.cave, m_idx);
            Monster_Race r_ptr = Misc.r_info[m_ptr.r_idx];
            Monster_Lore l_ptr = Misc.l_list[m_ptr.r_idx];

            //char m_name[80], m_poss[80], ddesc[80];
            string m_name, m_poss, ddesc;

            /* Player position */
            int px = Misc.p_ptr.px;
            int py = Misc.p_ptr.py;

            /* Extract the blind-ness */
            bool blind = (Misc.p_ptr.timed[(int)Timed_Effect.BLIND] != 0 ? true : false);

            /* Extract the "see-able-ness" */
            bool seen = (!blind && m_ptr.ml);

            /* Assume "normal" target */
            bool normal = true;

            /* Handle "leaving" */
            if (Misc.p_ptr.leaving) return false;

            /* Cannot cast spells when confused */
            if (m_ptr.m_timed[(int)Misc.MON_TMD.CONF] != 0) return (false);

            /* Cannot cast spells when nice */
            if ((m_ptr.mflag & Monster_Flag.MFLAG_NICE) != 0) return false;

            /* Hack -- Extract the spell probability */
            chance = (r_ptr.freq_innate + r_ptr.freq_spell) / 2;

            /* Not allowed to cast spells */
            if (chance == 0) return false;

            /* Only do spells occasionally */
            if (Random.randint0(100) >= chance) return false;

            /* Hack -- require projectable player */
            if (normal)
            {
                /* Check range */
                if (m_ptr.cdis > Misc.MAX_RANGE) return false;

                /* Check path */
                if (!Cave.projectable(m_ptr.fy, m_ptr.fx, py, px, Spell.PROJECT_NONE))
                    return false;
            }

            /* Extract the monster level */
            rlev = ((r_ptr.level >= 1) ? r_ptr.level : 1);

            /* Extract the racial spell flags */
            f.copy(r_ptr.spell_flags);

            /* Allow "desperate" spells */
            if (r_ptr.flags.has(Monster_Flag.SMART.value) &&
                m_ptr.hp < m_ptr.maxhp / 10 &&
                Random.randint0(100) < 50){

                throw new NotImplementedException();

                ///* Require intelligent spells */
                //set_spells(f, RST_HASTE | RST_ANNOY | RST_ESCAPE | RST_HEAL | RST_TACTIC | RST_SUMMON);
            }

            /* Remove the "ineffective" spells */
            remove_bad_spells(m_idx, f);

            /* Check whether summons and bolts are worth it. */
            if (!r_ptr.flags.has(Monster_Flag.STUPID.value))
            {
                /* Check for a clean bolt shot */
                if (Monster_Spell_Flag.test_spells(f, Monster_Spell_Flag.mon_spell_type.RST_BOLT) &&
                    !clean_shot(m_ptr.fy, m_ptr.fx, py, px))

                    /* Remove spells that will only hurt friends */
                    Monster_Spell_Flag.set_spells(f, ~Monster_Spell_Flag.mon_spell_type.RST_BOLT);

                /* Check for a possible summon */
                if (!(summon_possible(m_ptr.fy, m_ptr.fx)))

                    /* Remove summoning spells */
                    Monster_Spell_Flag.set_spells(f, ~Monster_Spell_Flag.mon_spell_type.RST_SUMMON);
            }

            /* No spells left */
            if (f.is_empty()) return false;

            /* Get the monster name (or "it") */
            m_name = m_ptr.monster_desc(0x00);
            //Nick: Capatilize the first letter.
            m_name = Char.ToUpper(m_name[0]) + m_name.Substring(1);

            /* Get the monster possessive ("his"/"her"/"its") */
            m_poss = m_ptr.monster_desc(Desc.PRO2 | Desc.POSS);

            /* Get the "died from" name */
            ddesc = m_ptr.monster_desc(Desc.SHOW | Desc.IND2);

            /* Choose a spell to cast */
            thrown_spell = choose_attack_spell(m_idx, f);

            /* Abort if no spell was chosen */
            if (thrown_spell == 0) return false;

            /* If we see an unaware monster try to cast a spell, become aware of it */
            if (m_ptr.unaware)
                become_aware(m_idx);

            /* Calculate spell failure rate */
            failrate = 25 - (rlev + 3) / 4;
            if (m_ptr.m_timed[(int)Misc.MON_TMD.FEAR] != 0)
                failrate += 20;

            /* Stupid monsters will never fail (for jellies and such) */
            if (Option.birth_ai_smart.value || r_ptr.flags.has(Monster_Flag.STUPID.value))
                failrate = 0;

            /* Check for spell failure (innate attacks never fail) */
            if ((thrown_spell >= Monster_Spell_Flag.MIN_NONINNATE_SPELL) && (Random.randint0(100) < failrate))
            {
                /* Message */
                Utilities.msg("{0} tries to cast a spell, but fails.", m_name);

                return true;
            }

            /* Cast the spell. */
            Cave.disturb(Misc.p_ptr, 1, 0);

            /* Special case RSF_HASTE until TMD_* and MON_TMD_* are rationalised */
            if (thrown_spell == Monster_Spell_Flag.HASTE.value) {
                if (blind)
                    Utilities.msg("{0} mumbles.", m_name);
                else
                    Utilities.msg("{0} concentrates on {1} body.", m_name, m_poss);

                mon_inc_timed(m_idx, Misc.MON_TMD.FAST, 50, 0, false);
            } else
                Monster_Spell_Flag.do_mon_spell(thrown_spell, m_idx, seen);

            /* Remember what the monster did to us */
            if (seen) {
                l_ptr.spell_flags.on(thrown_spell);

                /* Innate spell */
                if (thrown_spell < Monster_Spell_Flag.MIN_NONINNATE_SPELL) {
                    if (l_ptr.cast_innate < byte.MaxValue)
                        l_ptr.cast_innate++;
                } else {
                /* Bolt or Ball, or Special spell */
                    if (l_ptr.cast_spell < byte.MaxValue)
                        l_ptr.cast_spell++;
                }
            }
            /* Always take note of monsters that kill you */
            if (Misc.p_ptr.is_dead && (l_ptr.deaths < short.MaxValue)) {
                l_ptr.deaths++;
            }

            /* A spell was cast */
            return true;
        }
예제 #6
0
        /**
         * Wipe an object clean and make it a standard object of the specified kind.
         * Was previous "object_prep", is now a constructor for Object
         */
        public void prep(Object_Kind k, int lev, aspect rand_aspect)
        {
            int flag, x;
            Bitflag flags = new Bitflag(Object_Flag.SIZE);

            // Assign the kind and copy across data
            this.kind = k;
            this.tval = k.tval;
            this.sval = k.sval;
            this.ac = k.ac;
            this.dd = k.dd;
            this.ds = k.ds;
            this.weight = k.weight;

            // Default number
            this.number = 1;

            for(int i = 0; i < pval_flags.Length; i++) {
                pval_flags[i] = new Bitflag(Object_Flag.SIZE);
            }

            // Apply pvals and then copy flags
            for (int i = 0; i < k.num_pvals; i++) {
                flags.copy(k.pval_flags[i]);
                flags.copy(k.pval_flags[i]);
                x = Random.randcalc(k.pval[i], lev, rand_aspect);
                for (flag = flags.next(Bitflag.FLAG_START); flag != Bitflag.FLAG_null; flag = flags.next(flag + 1))
                    add_pval(x, flag);
            }
            if(k.Base != null) {
                flags.copy(k.Base.flags);
            }
            flags.union(k.flags);

            // Assign charges (wands/staves only)
            if (tval == TVal.TV_WAND || tval == TVal.TV_STAFF)
                pval[Misc.DEFAULT_PVAL] = (short)Random.randcalc(k.charge, lev, rand_aspect);

            // Assign flagless pval for food or oil
            if (tval == TVal.TV_FOOD || tval == TVal.TV_POTION || tval == TVal.TV_FLASK)
                pval[Misc.DEFAULT_PVAL] = (short)Random.randcalc(k.pval[Misc.DEFAULT_PVAL], lev, rand_aspect);

            // Default fuel for lamps
            if (tval == TVal.TV_LIGHT) {
                if(sval == SVal.SV_LIGHT_TORCH)
                    timeout = Misc.DEFAULT_TORCH;
                else if(sval == SVal.SV_LIGHT_LANTERN)
                    timeout = Misc.DEFAULT_LAMP;
            }

            // Default magic
            to_h = (short)Random.randcalc(k.to_h, lev, rand_aspect);
            to_d = (short)Random.randcalc(k.to_d, lev, rand_aspect);
            to_a = (short)Random.randcalc(k.to_a, lev, rand_aspect);
        }
예제 #7
0
        /*
         * Obtain the flags for an item
         */
        public void object_flags(ref Bitflag flags)
        {
            flags.wipe();

            if (kind == null)
                return;

            flags.copy(this.flags);
        }
예제 #8
0
        /**
         * Calculate the rating for a given slay combination
         */
        int slay_power(bool verbose, StreamWriter log_file, bool known)
        {
            Bitflag      s_index = new Bitflag(Object_Flag.SIZE);
            Bitflag      f = new Bitflag(Object_Flag.SIZE);
            Bitflag      f2 = new Bitflag(Object_Flag.SIZE);
            int          sv = 0;    //uint
            int          i, j;
            int          mult;
            Slay         best_s_ptr = null;
            Monster_Race r_ptr;

            Monster.Monster m_ptr;
            //monster_type monster_type_body;
            string[] desc   = new string[Slay.MAX.value];      // = { 0 }, *
            string[] brand  = new string[Slay.MAX.value];      // = { 0 };
            int[]    s_mult = new int[Slay.MAX.value];         // = { 0 };

            if (known)
            {
                object_flags(ref f);
            }
            else
            {
                object_flags_known(ref f);
            }

            /* Combine the slay bytes into an index value, return if there are none */
            s_index.copy(f);
            Object_Flag.create_mask(f2, false, Object_Flag.object_flag_type.SLAY,
                                    Object_Flag.object_flag_type.KILL, Object_Flag.object_flag_type.BRAND);

            if (!s_index.is_inter(f2))
            {
                return(Eval.tot_mon_power);
            }
            else
            {
                s_index.inter(f2);
            }

            /* Look in the cache to see if we know this one yet */
            sv = Slay.check_slay_cache(s_index);

            /* If it's cached (or there are no slays), return the value */
            if (sv != 0)
            {
                //file_putf(log_file, "Slay cache hit\n");
                return(sv);
            }

            /*
             * Otherwise we need to calculate the expected average multiplier
             * for this combination (multiplied by the total number of
             * monsters, which we'll divide out later).
             */
            for (i = 0; i < Misc.z_info.r_max; i++)
            {
                best_s_ptr = null;
                mult       = 1;
                r_ptr      = Misc.r_info[i];
                if (r_ptr == null)
                {
                    continue;
                }
                m_ptr       = new Monster.Monster();
                m_ptr.r_idx = (short)i;

                /* Find the best multiplier against this monster */
                Slay.improve_attack_modifier(this, m_ptr, ref best_s_ptr, false, !known);
                if (best_s_ptr != null)
                {
                    mult = best_s_ptr.mult;
                }

                /* Add the multiple to sv */
                sv += (int)(mult * r_ptr.scaled_power);
            }

            /*
             * To get the expected damage for this weapon, multiply the
             * average damage from base dice by sv, and divide by the
             * total number of monsters.
             */
            if (verbose)
            {
                /* Write info about the slay combination and multiplier */
                //file_putf(log_file, "Slay multiplier for: ");

                j = Slay.list_slays(s_index, s_index, desc, brand, s_mult, false);

                //for (i = 0; i < j; i++) {
                //    if (brand[i]) {
                //        file_putf(log_file, brand[i]);
                //    } else {
                //        file_putf(log_file, desc[i]);
                //    }
                //    file_putf(log_file, "x%d ", s_mult[i]);
                //}
                //file_putf(log_file, "\nsv is: %d\n", sv);
                //file_putf(log_file, " and t_m_p is: %d \n", tot_mon_power);
                //file_putf(log_file, "times 1000 is: %d\n", (1000 * sv) / tot_mon_power);
            }

            /* Add to the cache */
            if (Slay.fill_slay_cache(s_index, sv))
            {
                //file_putf(log_file, "Added to slay cache\n");
            }

            return(sv);
        }
예제 #9
0
        /**
         * Create a cache of slay combinations found on ego items, and the values of
         * these combinations. This is to speed up slay_power(), which will be called
         * many times for ego items during the game.
         *
         * \param items is the set of ego types from which we are extracting slay
         * combinations
         */
        public static int create_slay_cache(Ego_Item[] items)
        {
            int     count     = 0;
            Bitflag cacheme   = new Bitflag(Object_Flag.SIZE);
            Bitflag slay_mask = new Bitflag(Object_Flag.SIZE);

            /* Build the slay mask */
            Object_Flag.create_mask(slay_mask, false, Object_Flag.object_flag_type.SLAY,
                                    Object_Flag.object_flag_type.KILL, Object_Flag.object_flag_type.BRAND);

            /* Calculate necessary size of slay_cache */
            Bitflag[] dupcheck = new Bitflag[Misc.z_info.e_max];

            for (int i = 0; i < Misc.z_info.e_max; i++)
            {
                dupcheck[i] = new Bitflag(Object_Flag.SIZE);
                Ego_Item e_ptr = items[i];

                //Some items are null... I guess we should just skip them...?
                //TODO: Find out why they are null, and see if we actually should just skip them...
                if (e_ptr == null)
                {
                    continue;
                }

                /* Find the slay flags on this ego */
                cacheme.copy(e_ptr.flags);
                cacheme.inter(slay_mask);

                /* Only consider non-empty combinations of slay flags */
                if (!cacheme.is_empty())
                {
                    /* Skip previously scanned combinations */
                    for (int j = 0; j < i; j++)
                    {
                        if (cacheme.is_equal(dupcheck[j]))
                        {
                            continue;
                        }
                    }

                    /* msg("Found a new slay combo on an ego item"); */
                    count++;
                    dupcheck[i].copy(cacheme);
                }
            }

            /* Allocate slay_cache with an extra empty element for an iteration stop */
            slay_cache = new flag_cache[count + 1];
            count      = 0;

            /* Populate the slay_cache */
            for (int i = 0; i < Misc.z_info.e_max; i++)
            {
                if (!dupcheck[i].is_empty())
                {
                    slay_cache[count] = new flag_cache();
                    slay_cache[count].flags.copy(dupcheck[i]);
                    slay_cache[count].value = 0;
                    count++;
                    /*msg("Cached a slay combination");*/
                }
            }

            //From a time without garbage collection...

            /*for (i = 0; i < z_info.e_max; i++)
             *  FREE(dupcheck[i]);
             * FREE(dupcheck);*/

            /* Success */
            return(0);
        }
예제 #10
0
        /*
         * 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);
        }
예제 #11
0
        /**
         * Apply generation magic to an ego-item.
         */
        void ego_apply_magic(int level)
        {
            int i, flag, x;

            Bitflag flags = new Bitflag(Object_Flag.SIZE);
            Bitflag newf = new Bitflag(Object_Flag.SIZE);
            object_flags(ref flags);

            /* Extra powers */
            if (ego.xtra == Object_Flag.OBJECT_XTRA_TYPE_SUSTAIN)
                Object_Flag.create_mask(newf, false, Object_Flag.object_flag_type.SUST);
            else if (ego.xtra == Object_Flag.OBJECT_XTRA_TYPE_RESIST)
                Object_Flag.create_mask(newf, false, Object_Flag.object_flag_type.HRES);
            else if (ego.xtra == Object_Flag.OBJECT_XTRA_TYPE_POWER)
                Object_Flag.create_mask(newf, false, Object_Flag.object_flag_type.PROT, Object_Flag.object_flag_type.MISC);

            if (ego.xtra != 0)
                this.flags.on(get_new_attr(flags, newf));

            /* Apply extra ego bonuses */
            to_h += (short)Random.randcalc(ego.to_h, level, aspect.RANDOMISE);
            to_d += (short)Random.randcalc(ego.to_d, level, aspect.RANDOMISE);
            to_a += (short)Random.randcalc(ego.to_a, level, aspect.RANDOMISE);

            /* Apply pvals */
            for (i = 0; i < ego.num_pvals; i++) {
                flags.copy(ego.pval_flags[i]);
                x = Random.randcalc(ego.pval[i], level, aspect.RANDOMISE);
                for (flag = flags.next(Bitflag.FLAG_START); flag != Bitflag.FLAG_null; flag = flags.next(flag + 1))
                    add_pval(x, flag);
            }

            /* Apply flags */
            this.flags.union(ego.flags);

            return;
        }
예제 #12
0
        /**
         * Calculate the rating for a given slay combination
         */
        int slay_power(bool verbose, StreamWriter log_file, bool known)
        {
            Bitflag s_index = new Bitflag(Object_Flag.SIZE);
            Bitflag f = new Bitflag(Object_Flag.SIZE);
            Bitflag f2 = new Bitflag(Object_Flag.SIZE);
            int sv = 0; //uint
            int i, j;
            int mult;
            Slay best_s_ptr = null;
            Monster_Race r_ptr;
            Monster.Monster m_ptr;
            //monster_type monster_type_body;
            string[] desc = new string[Slay.MAX.value];// = { 0 }, *
            string[] brand = new string[Slay.MAX.value];// = { 0 };
            int[] s_mult = new int[Slay.MAX.value];// = { 0 };

            if (known)
                object_flags(ref f);
            else
                object_flags_known(ref f);

            /* Combine the slay bytes into an index value, return if there are none */
            s_index.copy(f);
            Object_Flag.create_mask(f2, false, Object_Flag.object_flag_type.SLAY,
                Object_Flag.object_flag_type.KILL, Object_Flag.object_flag_type.BRAND);

            if (!s_index.is_inter(f2))
                return Eval.tot_mon_power;
            else
                s_index.inter(f2);

            /* Look in the cache to see if we know this one yet */
            sv = Slay.check_slay_cache(s_index);

            /* If it's cached (or there are no slays), return the value */
            if (sv != 0)	{
                //file_putf(log_file, "Slay cache hit\n");
                return sv;
            }

            /*
             * Otherwise we need to calculate the expected average multiplier
             * for this combination (multiplied by the total number of
             * monsters, which we'll divide out later).
             */
            for (i = 0; i < Misc.z_info.r_max; i++)	{
                best_s_ptr = null;
                mult = 1;
                r_ptr = Misc.r_info[i];
                if(r_ptr == null)
                    continue;
                m_ptr = new Monster.Monster();
                m_ptr.r_idx = (short)i;

                /* Find the best multiplier against this monster */
                Slay.improve_attack_modifier(this, m_ptr, ref best_s_ptr, false, !known);
                if (best_s_ptr != null)
                    mult = best_s_ptr.mult;

                /* Add the multiple to sv */
                sv += (int)(mult * r_ptr.scaled_power);
            }

            /*
             * To get the expected damage for this weapon, multiply the
             * average damage from base dice by sv, and divide by the
             * total number of monsters.
             */
            if (verbose) {
                /* Write info about the slay combination and multiplier */
                //file_putf(log_file, "Slay multiplier for: ");

                j = Slay.list_slays(s_index, s_index, desc, brand, s_mult, false);

                //for (i = 0; i < j; i++) {
                //    if (brand[i]) {
                //        file_putf(log_file, brand[i]);
                //    } else {
                //        file_putf(log_file, desc[i]);
                //    }
                //    file_putf(log_file, "x%d ", s_mult[i]);
                //}
                //file_putf(log_file, "\nsv is: %d\n", sv);
                //file_putf(log_file, " and t_m_p is: %d \n", tot_mon_power);
                //file_putf(log_file, "times 1000 is: %d\n", (1000 * sv) / tot_mon_power);
            }

            /* Add to the cache */
            if(Slay.fill_slay_cache(s_index, sv)) {
                //file_putf(log_file, "Added to slay cache\n");
            }

            return sv;
        }
예제 #13
0
파일: Slay.cs 프로젝트: jobjingjo/csangband
        /**
         * Match slays in flags against a chosen flag mask
         *
         * count is the number of matches
         * \param flags is the flagset to analyse for matches
         * \param mask is the flagset against which to test
         * \param desc[] is the array of descriptions of matching slays - can be null
         * \param brand[] is the array of descriptions of brands - can be null
         * \param mult[] is the array of multipliers of those slays - can be null
         * \param dedup is whether or not to remove duplicates
         *
         * desc[], brand[] and mult[] must be >= SL_MAX in size
         */
        //Bitflags were size Object_Flag.SIZE, might be an out param
        public static int list_slays(Bitflag flags, Bitflag mask, string[] desc, string[] brand,int[] mult, bool dedup)
        {
            int i, count = 0;
            Bitflag f = new Bitflag(Object_Flag.SIZE);

            /* We are only interested in the flags specified in mask */
            f.copy(flags);
            f.inter(mask);

            /* Remove "duplicate" flags if desired */
            if (dedup) dedup_slays(ref f);

            /* Collect slays */
            for (i = 0; i < list.Count(); i++) {
                Slay s_ptr = list[i];
                if (f.has(s_ptr.object_flag.value)) {
                    if (mult != null)
                        mult[count] = s_ptr.mult;
                    if (brand != null)
                        brand[count] = s_ptr.brand;
                    if (desc != null)
                        desc[count] = s_ptr.desc;
                    count++;
                }
            }

            return count;
        }
예제 #14
0
파일: Slay.cs 프로젝트: jobjingjo/csangband
        /**
         * Create a cache of slay combinations found on ego items, and the values of
         * these combinations. This is to speed up slay_power(), which will be called
         * many times for ego items during the game.
         *
         * \param items is the set of ego types from which we are extracting slay
         * combinations
         */
        public static int create_slay_cache(Ego_Item[] items)
        {
            int count = 0;
            Bitflag cacheme = new Bitflag(Object_Flag.SIZE);
            Bitflag slay_mask = new Bitflag(Object_Flag.SIZE);

            /* Build the slay mask */
            Object_Flag.create_mask(slay_mask, false, Object_Flag.object_flag_type.SLAY,
                Object_Flag.object_flag_type.KILL, Object_Flag.object_flag_type.BRAND);

            /* Calculate necessary size of slay_cache */
            Bitflag[] dupcheck = new Bitflag[Misc.z_info.e_max];

            for (int i = 0; i < Misc.z_info.e_max; i++) {
                dupcheck[i] = new Bitflag(Object_Flag.SIZE);
                Ego_Item e_ptr = items[i];

                //Some items are null... I guess we should just skip them...?
                //TODO: Find out why they are null, and see if we actually should just skip them...
                if(e_ptr == null) {
                    continue;
                }

                /* Find the slay flags on this ego */
                cacheme.copy(e_ptr.flags);
                cacheme.inter(slay_mask);

                /* Only consider non-empty combinations of slay flags */
                if (!cacheme.is_empty()) {
                    /* Skip previously scanned combinations */
                    for (int j = 0; j < i; j++)
                        if (cacheme.is_equal(dupcheck[j])) continue;

                    /* msg("Found a new slay combo on an ego item"); */
                    count++;
                    dupcheck[i].copy(cacheme);
                }
            }

            /* Allocate slay_cache with an extra empty element for an iteration stop */
            slay_cache = new flag_cache[count + 1];
            count = 0;

            /* Populate the slay_cache */
            for (int i = 0; i < Misc.z_info.e_max; i++) {
                if (!dupcheck[i].is_empty()) {
                    slay_cache[count] = new flag_cache();
                    slay_cache[count].flags.copy(dupcheck[i]);
                    slay_cache[count].value = 0;
                    count++;
                    /*msg("Cached a slay combination");*/
                }
            }

            //From a time without garbage collection...
            /*for (i = 0; i < z_info.e_max; i++)
                FREE(dupcheck[i]);
            FREE(dupcheck);*/

            /* Success */
            return 0;
        }