Beispiel #1
0
        /**
         * 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;
                    }
                }
            }
        }
Beispiel #2
0
        /**
         * Determine whether a flagset includes any curse flags.
         */
        public static bool cursed_p(Bitflag f)
        {
            Bitflag f2 = new Bitflag(Object_Flag.SIZE);

            f2.wipe();
            create_mask(f2, false, object_flag_type.CURSE);

            return(f.is_inter(f2));
        }
Beispiel #3
0
        /**
         * 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;
        }
Beispiel #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);
        }
Beispiel #5
0
        /*
         * Process a monster
         *
         * In several cases, we directly update the monster lore
         *
         * Note that a monster is only allowed to "reproduce" if there
         * are a limited number of "reproducing" monsters on the current
         * level.  This should prevent the level from being "swamped" by
         * reproducing monsters.  It also allows a large mass of mice to
         * prevent a louse from multiplying, but this is a small price to
         * pay for a simple multiplication method.
         *
         * XXX Monster fear is slightly odd, in particular, monsters will
         * fixate on opening a door even if they cannot open it.  Actually,
         * the same thing happens to normal monsters when they hit a door
         *
         * In addition, monsters which *cannot* open or bash down a door
         * will still stand there trying to open it...  XXX XXX XXX
         *
         * Technically, need to check for monster in the way combined
         * with that monster being in a wall (or door?) XXX
         */
        public static void process_monster(Cave c, int m_idx)
        {
            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];

            int i, oy, ox, ny, nx;

            int[] mm = new int[5];

            bool woke_up = false;
            bool stagger;

            bool do_turn;
            bool do_move;
            bool do_view;

            bool did_open_door;
            bool did_bash_door;

            /* Handle "sleep" */
            if (m_ptr.m_timed[(int)Misc.MON_TMD.SLEEP] != 0)
            {
                uint notice;

                /* Aggravation */
                if (Misc.p_ptr.check_state(Object_Flag.AGGRAVATE, Misc.p_ptr.state.flags))
                {
                    /* Wake the monster */
                    mon_clear_timed(m_idx, (int)Misc.MON_TMD.SLEEP, Misc.MON_TMD_FLG_NOTIFY, false);

                    /* Notice the "waking up" */
                    if (m_ptr.ml && !m_ptr.unaware)
                    {
                        //char m_name[80];
                        string m_name;

                        /* Get the monster name */
                        m_name = m_ptr.monster_desc(0);
                        //monster_desc(m_name, sizeof(m_name), m_ptr, 0);

                        /* Dump a message */
                        Utilities.msg("%^s wakes up.", m_name);

                        /* Hack -- Update the health bar */
                        if (Misc.p_ptr.health_who == m_idx) Misc.p_ptr.redraw |= (Misc.PR_HEALTH);
                    }

                    /* Efficiency XXX XXX */
                    return;
                }

                /* Anti-stealth */
                notice = (uint)Random.randint0(1024);

                /* Hack -- See if monster "notices" player */
                if ((notice * notice * notice) <= Misc.p_ptr.state.noise)
                {
                    int d = 1;

                    /* Wake up faster near the player */
                    if (m_ptr.cdis < 50) d = (100 / m_ptr.cdis);

                    /* Still asleep */
                    if (m_ptr.m_timed[(int)Misc.MON_TMD.SLEEP] > d)
                    {
                        /* Monster wakes up "a little bit" */
                        mon_dec_timed(m_idx, (int)Misc.MON_TMD.SLEEP, d , (ushort)Misc.MON_TMD_FLG_NOMESSAGE, false);

                        /* Notice the "not waking up" */
                        if (m_ptr.ml && !m_ptr.unaware)
                        {
                            /* Hack -- Count the ignores */
                            if (l_ptr.ignore < Byte.MaxValue)
                            {
                                l_ptr.ignore++;
                            }
                        }
                    }

                    /* Just woke up */
                    else
                    {
                        /* Reset sleep counter */
                        woke_up = mon_clear_timed(m_idx, (int)Misc.MON_TMD.SLEEP, Misc.MON_TMD_FLG_NOMESSAGE, false);

                        /* Notice the "waking up" */
                        if (m_ptr.ml && !m_ptr.unaware)
                        {
                            //char m_name[80];
                            string m_name;

                            /* Get the monster name */
                            m_name = m_ptr.monster_desc(0);

                            /* Dump a message */
                            //Utilities.msg("%^s wakes up.", m_name);
                            Utilities.msg(m_name + " wakes up.");

                            /* Hack -- Update the health bar */
                            if (Misc.p_ptr.health_who == m_idx) Misc.p_ptr.redraw |= (Misc.PR_HEALTH);

                            /* Hack -- Count the wakings */
                            if (l_ptr.wake < byte.MaxValue)
                            {
                                l_ptr.wake++;
                            }
                        }
                    }
                }

                /* Still sleeping */
                if (m_ptr.m_timed[(int)Misc.MON_TMD.SLEEP] != 0) return;
            }

            /* If the monster just woke up, then it doesn't act */
            if (woke_up) return;

            if (m_ptr.m_timed[(int)Misc.MON_TMD.FAST] != 0)
                mon_dec_timed(m_idx, Misc.MON_TMD.FAST, 1, 0, false);

            if (m_ptr.m_timed[(int)Misc.MON_TMD.SLOW] != 0)
                mon_dec_timed(m_idx, Misc.MON_TMD.SLOW, 1, 0, false);

            if (m_ptr.m_timed[(int)Misc.MON_TMD.STUN] != 0)
            {
                throw new NotImplementedException();
                //int d = 1;

                ///* Make a "saving throw" against stun */
                //if (randint0(5000) <= r_ptr.level * r_ptr.level)
                //{
                //    /* Recover fully */
                //    d = m_ptr.m_timed[MON_TMD_STUN];
                //}

                ///* Hack -- Recover from stun */
                //if (m_ptr.m_timed[MON_TMD_STUN] > d)
                //    mon_dec_timed(m_idx, MON_TMD_STUN, 1, MON_TMD_FLG_NOMESSAGE, false);
                //else
                //    mon_clear_timed(m_idx, MON_TMD_STUN, MON_TMD_FLG_NOTIFY, false);

                ///* Still stunned */
                //if (m_ptr.m_timed[MON_TMD_STUN]) return;
            }

            if (m_ptr.m_timed[(int)Misc.MON_TMD.CONF] != 0)
            {
                throw new NotImplementedException();
                //int d = randint1(r_ptr.level / 10 + 1);

                ///* Still confused */
                //if (m_ptr.m_timed[MON_TMD_CONF] > d)
                //    mon_dec_timed(m_idx, MON_TMD_CONF, d , MON_TMD_FLG_NOMESSAGE,
                //        false);
                //else
                //    mon_clear_timed(m_idx, MON_TMD_CONF, MON_TMD_FLG_NOTIFY, false);
            }

            if (m_ptr.m_timed[(int)Misc.MON_TMD.FEAR] != 0)
            {
                /* Amount of "boldness" */
                int d = Random.randint1(r_ptr.level / 10 + 1);

                if (m_ptr.m_timed[(int)Misc.MON_TMD.FEAR] > d)
                    mon_dec_timed(m_idx, Misc.MON_TMD.FEAR, d, Misc.MON_TMD_FLG_NOMESSAGE, false);
                else
                    mon_clear_timed(m_idx, Misc.MON_TMD.FEAR, Misc.MON_TMD_FLG_NOTIFY, false);
            }

            /* Get the origin */
            oy = m_ptr.fy;
            ox = m_ptr.fx;

            /* Attempt to "mutiply" (all monsters are allowed an attempt for lore
             * purposes, even non-breeders)
             */
            if (Misc.num_repro < Misc.MAX_REPRO)
            {
                int k, y, x;

                /* Count the adjacent monsters */
                for (k = 0, y = oy - 1; y <= oy + 1; y++)
                {
                    for (x = ox - 1; x <= ox + 1; x++)
                    {
                        /* Count monsters */
                        if (Cave.cave.m_idx[y][x] > 0) k++;
                    }
                }

                /* Multiply slower in crowded areas */
                if ((k < 4) && (k == 0 || Random.one_in_(k * Misc.MON_MULT_ADJ)))
                {
                    /* Successful breeding attempt, learn about that now */
                    if (m_ptr.ml) l_ptr.flags.on(Monster_Flag.MULTIPLY.value);

                    /* Try to multiply (only breeders allowed) */
                    if (r_ptr.flags.has(Monster_Flag.MULTIPLY.value) && multiply_monster(m_idx))
                    {
                        /* Make a sound */
                        if (m_ptr.ml)
                        {
                            //sound(MSG_MULTIPLY); //TODO: enable sound
                        }

                        /* Multiplying takes energy */
                        return;
                    }
                }
            }

            /* Mimics lie in wait */
            if (is_mimicking(m_idx)) return;

            /* Attempt to cast a spell */
            if (make_attack_spell(m_idx)) return;

            /* Reset */
            stagger = false;

            /* Confused */
            if (m_ptr.m_timed[(int)Misc.MON_TMD.CONF] != 0)
            {
                /* Stagger */
                stagger = true;
            }

            /* Random movement - always attempt for lore purposes */
            else
            {
                int roll = Random.randint0(100);

                /* Random movement (25%) */
                if (roll < 25)
                {
                    /* Learn about small random movement */
                    if (m_ptr.ml) l_ptr.flags.on(Monster_Flag.RAND_25.value);

                    /* Stagger */
                    if (r_ptr.flags.test(Monster_Flag.RAND_25.value, Monster_Flag.RAND_50.value)) stagger = true;
                }

                /* Random movement (50%) */
                else if (roll < 50)
                {
                    /* Learn about medium random movement */
                    if (m_ptr.ml) l_ptr.flags.on(Monster_Flag.RAND_50.value);

                    /* Stagger */
                    if (r_ptr.flags.has(Monster_Flag.RAND_50.value)) stagger = true;
                }

                /* Random movement (75%) */
                else if (roll < 75)
                {
                    /* Stagger */
                    if (r_ptr.flags.test_all(Monster_Flag.RAND_25.value, Monster_Flag.RAND_50.value))
                    {
                        stagger = true;
                    }
                }
            }

            /* Normal movement */
            if (!stagger)
            {
                /* Logical moves, may do nothing */
                if (!get_moves(Cave.cave, m_idx, mm)) return;
            }

            /* Assume nothing */
            do_turn = false;
            do_move = false;
            do_view = false;

            /* Assume nothing */
            did_open_door = false;
            did_bash_door = false;

            /* Process moves */
            for (i = 0; i < 5; i++)
            {
                /* Get the direction (or stagger) */
                int d = (stagger ? Misc.ddd[Random.randint0(8)] : mm[i]);

                /* Get the destination */
                ny = oy + Misc.ddy[d];
                nx = ox + Misc.ddx[d];

                /* Floor is open? */
                if (Cave.cave_floor_bold(ny, nx))
                {
                    /* Go ahead and move */
                    do_move = true;
                }

                /* Permanent wall in the way */
                else if (Cave.cave.feat[ny][nx] >= Cave.FEAT_PERM_EXTRA)
                {
                    /* Nothing */
                }

                /* Normal wall, door, or secret door in the way */
                else
                {
                    /* There's some kind of feature in the way, so learn about
                     * kill-wall and pass-wall now
                     */
                    if (m_ptr.ml)
                    {
                        l_ptr.flags.on(Monster_Flag.PASS_WALL.value);
                        l_ptr.flags.on(Monster_Flag.KILL_WALL.value);
                    }

                    /* Monster moves through walls (and doors) */
                    if (r_ptr.flags.has(Monster_Flag.PASS_WALL.value))
                    {
                        /* Pass through walls/doors/rubble */
                        do_move = true;
                    }

                    /* Monster destroys walls (and doors) */
                    else if (r_ptr.flags.has(Monster_Flag.KILL_WALL.value))
                    {
                        /* Eat through walls/doors/rubble */
                        do_move = true;

                        /* Forget the wall */
                        Cave.cave.info[ny][nx] &= ~(Cave.CAVE_MARK);

                        /* Notice */
                        Cave.cave_set_feat(c, ny, nx, Cave.FEAT_FLOOR);

                        /* Note changes to viewable region */
                        if (Cave.player_has_los_bold(ny, nx)) do_view = true;
                    }

                    /* Handle doors and secret doors */
                    else if (((Cave.cave.feat[ny][nx] >= Cave.FEAT_DOOR_HEAD) &&
                                 (Cave.cave.feat[ny][nx] <= Cave.FEAT_DOOR_TAIL)) ||
                                (Cave.cave.feat[ny][nx] == Cave.FEAT_SECRET))
                    {
                        bool may_bash = true;

                        /* Take a turn */
                        do_turn = true;

                        /* Learn about door abilities */
                        if (m_ptr.ml)
                        {
                            l_ptr.flags.on(Monster_Flag.OPEN_DOOR.value);
                            l_ptr.flags.on(Monster_Flag.BASH_DOOR.value);
                        }

                        /* Creature can open doors. */
                        if (r_ptr.flags.has(Monster_Flag.OPEN_DOOR.value))
                        {
                            /* Closed doors and secret doors */
                            if ((Cave.cave.feat[ny][nx] == Cave.FEAT_DOOR_HEAD) ||
                                     (Cave.cave.feat[ny][nx] == Cave.FEAT_SECRET)) {
                                /* The door is open */
                                did_open_door = true;

                                /* Do not bash the door */
                                may_bash = false;
                            }

                            /* Locked doors (not jammed) */
                            else if (Cave.cave.feat[ny][nx] < Cave.FEAT_DOOR_HEAD + 0x08) {
                                int k;

                                /* Door power */
                                k = ((Cave.cave.feat[ny][nx] - Cave.FEAT_DOOR_HEAD) & 0x07);

                                /* Try to unlock it */
                                if (Random.randint0(m_ptr.hp / 10) > k) {
                                    Utilities.msg("Something fiddles with a lock.");

                                    /* Reduce the power of the door by one */
                                    Cave.cave_set_feat(c, ny, nx, Cave.cave.feat[ny][nx] - 1);

                                    /* Do not bash the door */
                                    may_bash = false;
                                }
                            }
                        }

                        /* Stuck doors -- attempt to bash them down if allowed */
                        if (may_bash && r_ptr.flags.has(Monster_Flag.BASH_DOOR.value))
                        {
                            int k;

                            /* Door power */
                            k = ((Cave.cave.feat[ny][nx] - Cave.FEAT_DOOR_HEAD) & 0x07);

                            /* Attempt to bash */
                            if (Random.randint0(m_ptr.hp / 10) > k) {
                                Utilities.msg("Something slams against a door.");

                                /* Reduce the power of the door by one */
                                Cave.cave_set_feat(c, ny, nx, Cave.cave.feat[ny][nx] - 1);

                                /* If the door is no longer jammed */
                                if (Cave.cave.feat[ny][nx] < Cave.FEAT_DOOR_HEAD + 0x09)	{
                                    Utilities.msg("You hear a door burst open!");

                                    /* Disturb (sometimes) */
                                    Cave.disturb(Misc.p_ptr, 0, 0);

                                    /* The door was bashed open */
                                    did_bash_door = true;

                                    /* Hack -- fall into doorway */
                                    do_move = true;
                                }
                            }
                        }
                    }

                    /* Deal with doors in the way */
                    if (did_open_door || did_bash_door)
                    {
                        /* Break down the door */
                        if (did_bash_door && (Random.randint0(100) < 50))
                        {
                            Cave.cave_set_feat(c, ny, nx, Cave.FEAT_BROKEN);
                        }

                        /* Open the door */
                        else
                        {
                            Cave.cave_set_feat(c, ny, nx, Cave.FEAT_OPEN);
                        }

                        /* Handle viewable doors */
                        if (Cave.player_has_los_bold(ny, nx)) do_view = true;
                    }
                }

                /* Hack -- check for Glyph of Warding */
                if (do_move && (Cave.cave.feat[ny][nx] == Cave.FEAT_GLYPH))
                {
                    /* Assume no move allowed */
                    do_move = false;

                    /* Break the ward */
                    if (Random.randint1(Misc.BREAK_GLYPH) < r_ptr.level)
                    {
                        /* Describe observable breakage */
                        if ((Cave.cave.info[ny][nx] & (Cave.CAVE_MARK)) != 0)
                        {
                            Utilities.msg("The rune of protection is broken!");
                        }

                        /* Forget the rune */
                        Cave.cave.info[ny][nx] &= ~Cave.CAVE_MARK;

                        /* Break the rune */
                        Cave.cave_set_feat(c, ny, nx, Cave.FEAT_FLOOR);

                        /* Allow movement */
                        do_move = true;
                    }
                }

                /* The player is in the way. */
                if (do_move && (Cave.cave.m_idx[ny][nx] < 0))
                {
                    /* Learn about if the monster attacks */
                    if (m_ptr.ml) l_ptr.flags.on(Monster_Flag.NEVER_BLOW.value);

                    /* Some monsters never attack */
                    if (r_ptr.flags.has(Monster_Flag.NEVER_BLOW.value))
                    {
                        /* Do not move */
                        do_move = false;
                    }

                    /* Otherwise, attack the player */
                    else
                    {
                        /* Do the attack */
                        m_ptr.make_attack_normal(Misc.p_ptr);

                        /* Do not move */
                        do_move = false;

                        /* Took a turn */
                        do_turn = true;
                    }
                }

                /* Some monsters never move */
                if (do_move && r_ptr.flags.has(Monster_Flag.NEVER_MOVE.value))
                {
                    /* Learn about lack of movement */
                    if (m_ptr.ml) l_ptr.flags.on(Monster_Flag.NEVER_MOVE.value);

                    /* Do not move */
                    do_move = false;
                }

                /* A monster is in the way */
                if (do_move && (Cave.cave.m_idx[ny][nx] > 0))
                {
                    Monster n_ptr = Cave.cave_monster(Cave.cave, Cave.cave.m_idx[ny][nx]);

                    /* Kill weaker monsters */
                    bool kill_ok = r_ptr.flags.has(Monster_Flag.KILL_BODY.value);

                    /* Move weaker monsters if they can swap places */
                    /* (not in a wall) */
                    bool move_ok = (r_ptr.flags.has(Monster_Flag.MOVE_BODY.value) &&
                                   Cave.cave_floor_bold(m_ptr.fy, m_ptr.fx));

                    /* Assume no movement */
                    do_move = false;

                    if (compare_monsters(m_ptr, n_ptr) > 0)
                    {
                        /* Learn about pushing and shoving */
                        if (m_ptr.ml)
                        {
                            l_ptr.flags.on(Monster_Flag.KILL_BODY.value);
                            l_ptr.flags.on(Monster_Flag.MOVE_BODY.value);
                        }

                        if (kill_ok || move_ok)
                        {
                            /* Get the names of the monsters involved */
                            //char m_name[80];
                            //char n_name[80];
                            string m_name;
                            string n_name;
                            m_name = m_ptr.monster_desc(Desc.IND1);
                            n_name = n_ptr.monster_desc(Desc.IND1);

                            /* Allow movement */
                            do_move = true;

                            /* Monster ate another monster */
                            if (kill_ok)
                            {
                                /* Note if visible */
                                if (m_ptr.ml && (m_ptr.mflag & (Monster_Flag.MFLAG_VIEW)) != 0)
                                {
                                    string name = Char.ToUpper(m_name[0]) + m_name.Substring(1);
                                    Utilities.msg("{0} tramples over {1}.", name, n_name);
                                }

                                throw new NotImplementedException();
                                //delete_monster(ny, nx);
                            }
                            else
                            {
                                /* Note if visible */
                                if (m_ptr.ml && (m_ptr.mflag & (Monster_Flag.MFLAG_VIEW)) != 0)
                                {
                                    string name = Char.ToUpper(m_name[0]) + m_name.Substring(1);
                                    Utilities.msg("{0} pushes past {1}.", name, n_name);
                                }
                            }
                        }
                    }
                }

                /* Creature has been allowed move */
                if (do_move)
                {
                    short this_o_idx, next_o_idx = 0;

                    /* Learn about no lack of movement */
                    if (m_ptr.ml) l_ptr.flags.on(Monster_Flag.NEVER_MOVE.value);

                    /* Take a turn */
                    do_turn = true;

                    /* Move the monster */
                    monster_swap(oy, ox, ny, nx);

                    /* Possible disturb */
                    if (m_ptr.ml && (Option.disturb_move.value ||
                                (((m_ptr.mflag & (Monster_Flag.MFLAG_VIEW)) != 0) && Option.disturb_near.value)))
                    {
                        /* Disturb */
                        Cave.disturb(Misc.p_ptr, 0, 0);
                    }

                    /* Scan all objects in the grid */
                    for (this_o_idx = Cave.cave.o_idx[ny][nx]; this_o_idx != 0; this_o_idx = next_o_idx)
                    {
                        Object.Object o_ptr;

                        /* Get the object */
                        o_ptr = Object.Object.byid(this_o_idx);
                        if(o_ptr == null)
                            continue;

                        /* Get the next object */
                        next_o_idx = o_ptr.next_o_idx;

                        /* Skip gold */
                        if (o_ptr.tval == TVal.TV_GOLD) continue;

                        /* Learn about item pickup behavior */
                        if (m_ptr.ml)
                        {
                            l_ptr.flags.on(Monster_Flag.TAKE_ITEM.value);
                            l_ptr.flags.on(Monster_Flag.KILL_ITEM.value);
                        }

                        /* Take or Kill objects on the floor */
                        if (r_ptr.flags.has(Monster_Flag.TAKE_ITEM.value) || r_ptr.flags.has(Monster_Flag.KILL_ITEM.value))
                        {
                            Bitflag obj_flags = new Bitflag(Object_Flag.SIZE);
                            Bitflag mon_flags = new Bitflag(Monster_Flag.SIZE);

                            //char m_name[80];
                            //char o_name[80];
                            string m_name;
                            string o_name = "";

                            mon_flags.wipe();

                            /* Extract some flags */
                            o_ptr.object_flags(ref obj_flags);

                            /* Get the object name */
                            o_name = o_ptr.object_desc(Object.Object.Detail.PREFIX | Object.Object.Detail.FULL);

                            /* Get the monster name */
                            m_name = m_ptr.monster_desc(Desc.IND1);

                            /* React to objects that hurt the monster */
                            throw new NotImplementedException();
                            //react_to_slay(obj_flags, mon_flags);

                            ///* The object cannot be picked up by the monster */
                            //if (o_ptr.artifact || rf_is_inter(r_ptr.flags, mon_flags))
                            //{
                            //    /* Only give a message for "take_item" */
                            //    if (rf_has(r_ptr.flags, RF_TAKE_ITEM))
                            //    {
                            //        /* Describe observable situations */
                            //        if (m_ptr.ml && Cave.player_has_los_bold(ny, nx) && !squelch_item_ok(o_ptr))
                            //        {
                            //            /* Dump a message */
                            //            msg("%^s tries to pick up %s, but fails.",
                            //                       m_name, o_name);
                            //        }
                            //    }
                            //}

                            ///* Pick up the item */
                            //else if (rf_has(r_ptr.flags, RF_TAKE_ITEM))
                            //{
                            //    Object.Object i_ptr;
                            //    //object_type object_type_body;

                            //    /* Describe observable situations */
                            //    if (player_has_los_bold(ny, nx) && !squelch_item_ok(o_ptr))
                            //    {
                            //        /* Dump a message */
                            //        msg("%^s picks up %s.", m_name, o_name);
                            //    }

                            //    /* Get local object */
                            //    i_ptr = &object_type_body;

                            //    /* Obtain local object */
                            //    object_copy(i_ptr, o_ptr);

                            //    /* Delete the object */
                            //    delete_object_idx(this_o_idx);

                            //    /* Carry the object */
                            //    monster_carry(m_ptr, i_ptr);
                            //}

                            ///* Destroy the item */
                            //else
                            //{
                            //    /* Describe observable situations */
                            //    if (player_has_los_bold(ny, nx) && !squelch_item_ok(o_ptr))
                            //    {
                            //        /* Dump a message */
                            //        msgt(MSG_DESTROY, "%^s crushes %s.", m_name, o_name);
                            //    }

                            //    /* Delete the object */
                            //    delete_object_idx(this_o_idx);
                            //}
                        }
                    }
                }

                /* Stop when done */
                if (do_turn) break;
            }

            /* If we haven't done anything, try casting a spell again */
            if (Option.birth_ai_smart.value && !do_turn && !do_move)
            {
                /* Cast spell */
                if (make_attack_spell(m_idx)) return;
            }

            if (r_ptr.flags.has(Monster_Flag.HAS_LIGHT.value)) do_view = true;

            /* Notice changes in view */
            if (do_view)
            {
                /* Update the visuals */
                Misc.p_ptr.update |= (Misc.PU_UPDATE_VIEW | Misc.PU_MONSTERS);

                /* Fully update the flow XXX XXX XXX */
                Misc.p_ptr.update |= (Misc.PU_FORGET_FLOW | Misc.PU_UPDATE_FLOW);
            }

            /* Hack -- get "bold" if out of options */
            if (!do_turn && !do_move && m_ptr.m_timed[(int)Misc.MON_TMD.FEAR] != 0)
            {
                mon_clear_timed(m_idx, Misc.MON_TMD.FEAR, Misc.MON_TMD_FLG_NOTIFY, false);
            }

            /* If we see an unaware monster do something, become aware of it */
            if(do_turn && m_ptr.unaware) {
                throw new NotImplementedException();
                //become_aware(m_idx);
            }
        }
Beispiel #6
0
        /**
         * Determine whether a flagset includes any curse flags.
         */
        public static bool cursed_p(Bitflag f)
        {
            Bitflag f2 = new Bitflag(Object_Flag.SIZE);

            f2.wipe();
            create_mask(f2, false, object_flag_type.CURSE);

            return f.is_inter(f2);
        }
Beispiel #7
0
        /**
         * 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;
        }
Beispiel #8
0
        /*
         * Obtain the flags for an item
         */
        public void object_flags(ref Bitflag flags)
        {
            flags.wipe();

            if (kind == null)
                return;

            flags.copy(this.flags);
        }
Beispiel #9
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);
        }
Beispiel #10
0
        /**
         * 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;
                }
            }
        }