Esempio n. 1
0
        public Bitflag spell_flags = new Bitflag(Monster_Spell_Flag.SIZE); /* Observed racial spell flags */

        /*
         * Take note that the given monster just dropped some treasure
         *
         * Note that learning the "GOOD"/"GREAT" flags gives information
         * about the treasure (even when the monster is killed for the first
         * time, such as uniques, and the treasure has not been examined yet).
         *
         * This "indirect" method is used to prevent the player from learning
         * exactly how much treasure a monster can drop from observing only
         * a single example of a drop.  This method actually observes how much
         * gold and items are dropped, and remembers that information to be
         * described later by the monster recall code.
         */
        public static void lore_treasure(int m_idx, int num_item, int num_gold)
        {
            Monster      m_ptr = Cave.cave_monster(Cave.cave, m_idx);
            Monster_Lore l_ptr = Misc.l_list[m_ptr.r_idx];


            /* Note the number of things dropped */
            if (num_item > l_ptr.drop_item)
            {
                l_ptr.drop_item = (byte)num_item;
            }
            if (num_gold > l_ptr.drop_gold)
            {
                l_ptr.drop_gold = (byte)num_gold;
            }

            /* Learn about drop quality */
            l_ptr.flags.on(Monster_Flag.DROP_GOOD.value);
            l_ptr.flags.on(Monster_Flag.DROP_GREAT.value);

            /* Update monster recall window */
            if (Misc.p_ptr.monster_race_idx == m_ptr.r_idx)
            {
                /* Window stuff */
                Misc.p_ptr.redraw |= (Misc.PR_MONSTER);
            }
        }
Esempio n. 2
0
        public static void wr_monster_memory()
        {
            int i;
            int r_idx;

            wr_u16b(Misc.z_info.r_max);
            for (r_idx = 0; r_idx < Misc.z_info.r_max; r_idx++) {
                Monster_Race r_ptr = Misc.r_info[r_idx];
                Monster_Lore l_ptr = Misc.l_list[r_idx];

                if (r_ptr == null) {
                    r_ptr = new Monster_Race();
                }

                if (l_ptr == null) {
                    l_ptr = new Monster_Lore();
                }

                /* Count sights/deaths/kills */
                wr_s16b(l_ptr.sights);
                wr_s16b(l_ptr.deaths);
                wr_s16b(l_ptr.pkills);
                wr_s16b(l_ptr.tkills);

                /* Count wakes and ignores */
                wr_byte(l_ptr.wake);
                wr_byte(l_ptr.ignore);

                /* Count drops */
                wr_byte(l_ptr.drop_gold);
                wr_byte(l_ptr.drop_item);

                /* Count spells */
                wr_byte(l_ptr.cast_innate);
                wr_byte(l_ptr.cast_spell);

                /* Count blows of each type */
                for (i = 0; i < Monster_Blow.MONSTER_BLOW_MAX; i++)
                    wr_byte(l_ptr.blows[i]);

                /* Memorize flags */
                for (i = 0; i < Monster_Flag.BYTES && i < Monster_Flag.SIZE; i++)
                    wr_byte(l_ptr.flags.data[i]);
                if (i < Monster_Flag.BYTES) Savefile.pad_bytes(Monster_Flag.BYTES - i);

                for (i = 0; i < Monster_Flag.BYTES && i < Monster_Spell_Flag.SIZE; i++)
                    wr_byte(l_ptr.spell_flags[i]);
                if (i < Monster_Flag.BYTES) Savefile.pad_bytes(Monster_Flag.BYTES - i);

                /* Monster limit per level */
                wr_byte(r_ptr.max_num);

                /* XXX */
                wr_byte(0);
                wr_byte(0);
                wr_byte(0);
            }
        }
Esempio n. 3
0
        /*
         * This function updates the monster record of the given monster
         *
         * This involves extracting the distance to the player (if requested),
         * and then checking for visibility (natural, infravision, see-invis,
         * telepathy), updating the monster visibility flag, redrawing (or
         * erasing) the monster when its visibility changes, and taking note
         * of any interesting monster flags (cold-blooded, invisible, etc).
         *
         * Note the new "mflag" field which encodes several monster state flags,
         * including "view" for when the monster is currently in line of sight,
         * and "mark" for when the monster is currently visible via detection.
         *
         * The only monster fields that are changed here are "cdis" (the
         * distance from the player), "ml" (visible to the player), and
         * "mflag" (to maintain the "MFLAG_VIEW" flag).
         *
         * Note the special "update_monsters()" function which can be used to
         * call this function once for every monster.
         *
         * Note the "full" flag which requests that the "cdis" field be updated,
         * this is only needed when the monster (or the player) has moved.
         *
         * Every time a monster moves, we must call this function for that
         * monster, and update the distance, and the visibility.  Every time
         * the player moves, we must call this function for every monster, and
         * update the distance, and the visibility.  Whenever the player "state"
         * changes in certain ways ("blindness", "infravision", "telepathy",
         * and "see invisible"), we must call this function for every monster,
         * and update the visibility.
         *
         * Routines that change the "illumination" of a grid must also call this
         * function for any monster in that grid, since the "visibility" of some
         * monsters may be based on the illumination of their grid.
         *
         * Note that this function is called once per monster every time the
         * player moves.  When the player is running, this function is one
         * of the primary bottlenecks, along with "update_view()" and the
         * "process_monsters()" code, so efficiency is important.
         *
         * Note the optimized "inline" version of the "distance()" function.
         *
         * A monster is "visible" to the player if (1) it has been detected
         * by the player, (2) it is close to the player and the player has
         * telepathy, or (3) it is close to the player, and in line of sight
         * of the player, and it is "illuminated" by some combination of
         * infravision, torch light, or permanent light (invisible monsters
         * are only affected by "light" if the player can see invisible).
         *
         * Monsters which are not on the current panel may be "visible" to
         * the player, and their descriptions will include an "offscreen"
         * reference.  Currently, offscreen monsters cannot be targeted
         * or viewed directly, but old targets will remain set.  XXX XXX
         *
         * The player can choose to be disturbed by several things, including
         * "OPT(disturb_move)" (monster which is viewable moves in some way), and
         * "OPT(disturb_near)" (monster which is "easily" viewable moves in some
         * way).  Note that "moves" includes "appears" and "disappears".
         */
        public static void update_mon(int m_idx, bool full)
        {
            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];

            if (l_ptr == null)
            {
                l_ptr = Misc.l_list[m_ptr.r_idx] = new Monster_Lore();
            }

            int d;

            /* Current location */
            int fy = m_ptr.fy;
            int fx = m_ptr.fx;

            /* Seen at all */
            bool flag = false;

            /* Seen by vision */
            bool easy = false;


            /* Compute distance */
            if (full)
            {
                int py = Misc.p_ptr.py;
                int px = Misc.p_ptr.px;

                /* Distance components */
                int dy = (py > fy) ? (py - fy) : (fy - py);
                int dx = (px > fx) ? (px - fx) : (fx - px);

                /* Approximate distance */
                d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));

                /* Restrict distance */
                if (d > 255)
                {
                    d = 255;
                }

                /* Save the distance */
                m_ptr.cdis = (byte)d;
            }

            /* Extract distance */
            else
            {
                /* Extract the distance */
                d = m_ptr.cdis;
            }


            /* Detected */
            if ((m_ptr.mflag & (Monster_Flag.MFLAG_MARK)) != 0)
            {
                flag = true;
            }


            /* Nearby */
            if (d <= Misc.MAX_SIGHT)
            {
                /* Basic telepathy */
                if (Misc.p_ptr.check_state(Object_Flag.TELEPATHY, Misc.p_ptr.state.flags))
                {
                    /* Empty mind, no telepathy */
                    if (r_ptr.flags.has(Monster_Flag.EMPTY_MIND.value))
                    {
                        /* Nothing! */
                    }

                    /* Weird mind, occasional telepathy */
                    else if (r_ptr.flags.has(Monster_Flag.WEIRD_MIND.value))
                    {
                        throw new NotImplementedException();
                        ///* One in ten individuals are detectable */
                        //if ((m_idx % 10) == 5)
                        //{
                        //    /* Detectable */
                        //    flag = true;

                        //    /* Check for LOS so that MFLAG_VIEW is set later */
                        //    if (player_has_los_bold(fy, fx)) easy = true;
                        //}
                    }

                    /* Normal mind, allow telepathy */
                    else
                    {
                        throw new NotImplementedException();
                        ///* Detectable */
                        //flag = true;

                        ///* Check for LOS to that MFLAG_VIEW is set later */
                        //if (player_has_los_bold(fy, fx)) easy = true;
                    }
                }

                /* Normal line of sight and player is not blind */
                if (Cave.player_has_los_bold(fy, fx) && Misc.p_ptr.timed[(int)Timed_Effect.BLIND] == 0)
                {
                    /* Use "infravision" */
                    if (d <= Misc.p_ptr.state.see_infra)
                    {
                        /* Learn about warm/cold blood */
                        l_ptr.flags.on(Monster_Flag.COLD_BLOOD.value);

                        /* Handle "warm blooded" monsters */
                        if (!r_ptr.flags.has(Monster_Flag.COLD_BLOOD.value))
                        {
                            /* Easy to see */
                            easy = flag = true;
                        }
                    }

                    /* See if the monster is emitting light */
                    /*if (rf_has(r_ptr.flags, RF_HAS_LIGHT)) easy = flag = true;*/

                    /* Use "illumination" */
                    if (Cave.player_can_see_bold(fy, fx))
                    {
                        /* Learn it emits light */
                        l_ptr.flags.on(Monster_Flag.HAS_LIGHT.value);

                        /* Learn about invisibility */
                        l_ptr.flags.on(Monster_Flag.INVISIBLE.value);

                        /* Handle "invisible" monsters */
                        if (r_ptr.flags.has(Monster_Flag.INVISIBLE.value))
                        {
                            /* See invisible */
                            if (Misc.p_ptr.check_state(Object_Flag.SEE_INVIS, Misc.p_ptr.state.flags))
                            {
                                /* Easy to see */
                                easy = flag = true;
                            }
                        }

                        /* Handle "normal" monsters */
                        else
                        {
                            /* Easy to see */
                            easy = flag = true;
                        }
                    }
                }
            }

            /* If a mimic looks like a squelched item, it's not seen */
            if (is_mimicking(m_idx))
            {
                throw new NotImplementedException();
                //object_type *o_ptr = object_byid(m_ptr.mimicked_o_idx);
                //if (squelch_item_ok(o_ptr))
                //    easy = flag = false;
            }

            /* The monster is now visible */
            if (flag)
            {
                /* Learn about the monster's mind */
                if (Misc.p_ptr.check_state(Object_Flag.TELEPATHY, Misc.p_ptr.state.flags))
                {
                    l_ptr.flags.set(Monster_Flag.EMPTY_MIND.value, Monster_Flag.WEIRD_MIND.value,
                                    Monster_Flag.SMART.value, Monster_Flag.STUPID.value);
                }

                /* It was previously unseen */
                if (!m_ptr.ml)
                {
                    /* Mark as visible */
                    m_ptr.ml = true;

                    /* Draw the monster */
                    Cave.cave_light_spot(Cave.cave, fy, fx);

                    /* Update health bar as needed */
                    if (Misc.p_ptr.health_who == m_idx)
                    {
                        Misc.p_ptr.redraw |= (Misc.PR_HEALTH);
                    }

                    /* Hack -- Count "fresh" sightings */
                    if (l_ptr.sights < short.MaxValue)
                    {
                        l_ptr.sights++;
                    }

                    /* Disturb on appearance */
                    if (Option.disturb_move.value)
                    {
                        Cave.disturb(Misc.p_ptr, 1, 0);
                    }

                    /* Window stuff */
                    Misc.p_ptr.redraw |= Misc.PR_MONLIST;
                }
            }

            /* The monster is not visible */
            else
            {
                /* It was previously seen */
                if (m_ptr.ml)
                {
                    /* Treat mimics differently */
                    if (m_ptr.mimicked_o_idx == 0 || Squelch.item_ok(Object.Object.byid(m_ptr.mimicked_o_idx)))
                    {
                        /* Mark as not visible */
                        m_ptr.ml = false;

                        /* Erase the monster */
                        Cave.cave_light_spot(Cave.cave, fy, fx);

                        /* Update health bar as needed */
                        if (Misc.p_ptr.health_who == m_idx)
                        {
                            Misc.p_ptr.redraw |= (Misc.PR_HEALTH);
                        }

                        /* Disturb on disappearance */
                        if (Option.disturb_move.value)
                        {
                            Cave.disturb(Misc.p_ptr, 1, 0);
                        }

                        /* Window stuff */
                        Misc.p_ptr.redraw |= Misc.PR_MONLIST;
                    }
                }
            }


            /* The monster is now easily visible */
            if (easy)
            {
                /* Change */
                if ((m_ptr.mflag & (Monster_Flag.MFLAG_VIEW)) == 0)
                {
                    /* Mark as easily visible */
                    m_ptr.mflag |= (Monster_Flag.MFLAG_VIEW);

                    /* Disturb on appearance */
                    if (Option.disturb_near.value)
                    {
                        Cave.disturb(Misc.p_ptr, 1, 0);
                    }

                    /* Re-draw monster window */
                    Misc.p_ptr.redraw |= Misc.PR_MONLIST;
                }
            }

            /* The monster is not easily visible */
            else
            {
                /* Change */
                if ((m_ptr.mflag & (Monster_Flag.MFLAG_VIEW)) != 0)
                {
                    /* Mark as not easily visible */
                    m_ptr.mflag &= ~(Monster_Flag.MFLAG_VIEW);

                    /* Disturb on disappearance */
                    if (Option.disturb_near.value)
                    {
                        Cave.disturb(Misc.p_ptr, 1, 0);
                    }

                    /* Re-draw monster list window */
                    Misc.p_ptr.redraw |= Misc.PR_MONLIST;
                }
            }
        }
Esempio n. 4
0
        /*
         * Attack the player via physical attacks.
         */
        //TODO: Submit this function to the Guiness book of world records for "Longest f*****g function"
        //TODO: Refactor this. Refactor this so f*****g hard.
        public bool make_attack_normal(Player.Player p)
        {
            Monster_Race r_ptr = Misc.r_info[r_idx];

            Monster_Lore l_ptr = Misc.l_list[r_idx];

            int i, tmp;

            short gold;

            string o_name;


            // Not allowed to attack
            if (r_ptr.flags.has(Monster_Flag.NEVER_BLOW.value))
            {
                return(false);
            }

            // Total armor
            int ac = p.state.ac + p.state.to_a;

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


            // Get the monster name (or "it")
            string m_name = monster_desc(0);

            // Get the "died from" information (i.e. "a kobold")
            string ddesc = monster_desc(Desc.SHOW | Desc.IND2);

            // Assume no blink
            bool blinked = false;

            // Scan through all blows
            for (int ap_cnt = 0; ap_cnt < Monster_Blow.MONSTER_BLOW_MAX; ap_cnt++)
            {
                bool visible  = false;
                bool obvious  = false;
                bool do_break = false;

                int power  = 0;
                int damage = 0;

                string act = null;

                if (r_ptr.blow[ap_cnt] == null)
                {
                    continue;
                }

                // Extract the attack infomation
                RBE effect = r_ptr.blow[ap_cnt].effect;
                RBM method = r_ptr.blow[ap_cnt].method;
                int d_dice = r_ptr.blow[ap_cnt].d_dice;
                int d_side = r_ptr.blow[ap_cnt].d_side;


                // Hack -- no more attacks
                if (method == RBM.NONE)
                {
                    break;
                }

                // Handle "leaving"
                if (p.leaving)
                {
                    break;
                }

                // Extract visibility (before blink)
                if (ml)
                {
                    visible = true;
                }

                // Extract visibility from carrying light
                if (r_ptr.flags.has(Monster_Flag.HAS_LIGHT.value))
                {
                    visible = true;
                }

                power = effect.power;

                // Monster hits player
                if (effect == null || check_hit(p, power, rlev))
                {
                    // Always disturbing
                    Cave.disturb(p, 1, 0);

                    // Hack -- Apply "protection from evil"
                    if (p.timed[(int)Timed_Effect.PROTEVIL] > 0)
                    {
                        // Learn about the evil flag
                        if (ml)
                        {
                            l_ptr.flags.on(Monster_Flag.EVIL.value);
                        }

                        if (r_ptr.flags.has(Monster_Flag.EVIL.value) && p.lev >= rlev && Random.randint0(100) + p.lev > 50)
                        {
                            // Message
                            Utilities.msg("%^s is repelled.", m_name);

                            // Hack -- Next attack
                            continue;
                        }
                    }


                    // Assume no cut or stun
                    bool do_cut  = method.do_cut;
                    bool do_stun = method.do_stun;

                    // Assume no sound
                    Message_Type sound_msg = method.sound_msg;

                    act = method.action;

                    // Describe the attack method
                    if (method == RBM.INSULT)
                    {
                        throw new NotImplementedException();
                        //act = desc_insult[Random.randint0(Misc.MAX_DESC_INSULT)];
                    }
                    else if (method == RBM.MOAN)
                    {
                        throw new NotImplementedException();
                        //act = desc_moan[Random.randint0(Misc.MAX_DESC_MOAN)];
                    }

                    // Message
                    if (act != null)
                    {
                        string name = Char.ToUpper(m_name[0]) + m_name.Substring(1);
                        Utilities.msgt(sound_msg, "{0} {1}", name, act);
                    }


                    // Hack -- assume all attacks are obvious
                    obvious = true;

                    // Roll out the damage
                    if (d_dice > 0 && d_side > 0)
                    {
                        damage = Random.damroll(d_dice, d_side);
                    }
                    else
                    {
                        damage = 0;
                    }

                    // Apply appropriate damage
                    if (effect.value == 0)
                    {
                        // Hack -- Assume obvious
                        obvious = true;

                        // Hack -- No damage
                        damage = 0;
                    }
                    else if (effect.value == RBE.HURT.value)
                    {
                        // Obvious
                        obvious = true;

                        // Hack -- Player armor reduces total damage
                        damage -= (damage * ((ac < 240) ? ac : 240) / 400);

                        // Take damage
                        Spell.take_hit(p, damage, ddesc);
                    }
                    else if (effect.value == RBE.POISON.value)
                    {
                        damage = Spell.adjust_dam(p, GF.POIS, damage, aspect.RANDOMISE,
                                                  Spell.check_for_resist(p, GF.POIS, p.state.flags, true));

                        // Take damage
                        Spell.take_hit(p, damage, ddesc);

                        // Take "poison" effect
                        if (p.inc_timed(Timed_Effect.POISONED, Random.randint1(rlev) + 5, true, true))
                        {
                            obvious = true;
                        }

                        // Learn about the player
                        monster_learn_resists(p, GF.POIS);
                    }
                    else if (effect.value == RBE.UN_BONUS.value)
                    {
                        throw new NotImplementedException();
                        //// Take damage
                        //take_hit(p, damage, ddesc);

                        //// Allow complete resist
                        //if (!check_state(p, OF_RES_DISEN, p.state.flags))
                        //{
                        //    // Apply disenchantment
                        //    if (apply_disenchant(0)) obvious = true;
                        //}

                        //// Learn about the player
                        //monster_learn_resists(m_ptr, p, GF_DISEN);
                    }
                    else if (effect.value == RBE.UN_POWER.value)
                    {
                        throw new NotImplementedException();
                        //int unpower = 0, newcharge;

                        //// Take damage
                        //take_hit(p, damage, ddesc);

                        //// Find an item
                        //for (k = 0; k < 10; k++)
                        //{
                        //    // Pick an item
                        //    i = randint0(INVEN_PACK);

                        //    // Obtain the item
                        //    o_ptr = &p.inventory[i];

                        //    // Skip non-objects
                        //    if (!o_ptr.kind) continue;

                        //    // Drain charged wands/staves
                        //    if ((o_ptr.tval == TV_STAFF) ||
                        //        (o_ptr.tval == TV_WAND))
                        //    {
                        //        // Charged?
                        //        if (o_ptr.pval[DEFAULT_PVAL])
                        //        {
                        //            // Get number of charge to drain
                        //            unpower = (rlev / (o_ptr.kind.level + 2)) + 1;

                        //            // Get new charge value, don't allow negative
                        //            newcharge = MAX((o_ptr.pval[DEFAULT_PVAL]
                        //                    - unpower),0);

                        //            // Remove the charges
                        //            o_ptr.pval[DEFAULT_PVAL] = newcharge;
                        //        }
                        //    }

                        //    if (unpower)
                        //    {
                        //        int heal = rlev * unpower;

                        //        msg("Energy drains from your pack!");

                        //        obvious = true;

                        //        // Don't heal more than max hp
                        //        heal = MIN(heal, maxhp - hp);

                        //        // Heal
                        //        hp += heal;

                        //        // Redraw (later) if needed
                        //        if (cave_monster(cave, p.health_who) == m_ptr)
                        //            p.redraw |= (PR_HEALTH);

                        //        // Combine / Reorder the pack
                        //        p.notice |= (PN_COMBINE | PN_REORDER);

                        //        // Redraw stuff
                        //        p.redraw |= (PR_INVEN);

                        //        // Affect only a single inventory slot
                        //        break;
                        //    }
                        //}
                    }
                    else if (effect.value == RBE.EAT_GOLD.value)
                    {
                        // Take damage
                        Spell.take_hit(p, damage, ddesc);

                        // Obvious
                        obvious = true;

                        // Saving throw (unless paralyzed) based on dex and level
                        if (p.timed[(int)Timed_Effect.PARALYZED] == 0 &&
                            (Random.randint0(100) < (Player.Player.adj_dex_safe[p.state.stat_ind[(int)Stat.Dex]] + p.lev)))
                        {
                            // Saving throw message
                            Utilities.msg("You quickly protect your money pouch!");

                            // Occasional blink anyway
                            if (Random.randint0(3) != 0)
                            {
                                blinked = true;
                            }
                        }

                        // Eat gold
                        else
                        {
                            gold = (short)((p.au / 10) + Random.randint1(25));
                            if (gold < 2)
                            {
                                gold = 2;
                            }
                            if (gold > 5000)
                            {
                                gold = (short)((p.au / 20) + Random.randint1(3000));
                            }
                            if (gold > p.au)
                            {
                                gold = (short)p.au;
                            }
                            p.au -= gold;
                            if (gold <= 0)
                            {
                                Utilities.msg("Nothing was stolen.");
                                break;
                            }
                            // Let the player know they were robbed
                            Utilities.msg("Your purse feels lighter.");
                            if (p.au != 0)
                            {
                                Utilities.msg("{0} coins were stolen!", (long)gold);
                            }
                            else
                            {
                                Utilities.msg("All of your coins were stolen!");
                            }

                            // While we have gold, put it in objects
                            while (gold > 0)
                            {
                                int amt;

                                // Create a new temporary object
                                //object_type o;
                                //object_wipe(&o);
                                Object.Object o = new Object.Object();
                                o.prep(Object.Object_Kind.objkind_get(TVal.TV_GOLD, (int)SVal.sval_gold.SV_GOLD), 0, aspect.MINIMISE);

                                // Amount of gold to put in this object
                                amt = gold > Misc.MAX_PVAL ? Misc.MAX_PVAL : gold;
                                o.pval[Misc.DEFAULT_PVAL] = (short)amt;
                                gold -= (short)amt;

                                // Set origin to stolen, so it is not confused with
                                // dropped treasure in monster_death
                                o.origin = Origin.STOLEN;

                                // Give the gold to the monster
                                carry(o);
                            }

                            // Redraw gold
                            p.redraw |= (Misc.PR_GOLD);

                            // Blink away
                            blinked = true;
                        }
                    }
                    else if (effect.value == RBE.EAT_ITEM.value)
                    {
                        // Take damage
                        Spell.take_hit(p, damage, ddesc);

                        // Saving throw (unless paralyzed) based on dex and level
                        if (p.timed[(int)Timed_Effect.PARALYZED] == 0 &&
                            (Random.randint0(100) < (Player.Player.adj_dex_safe[p.state.stat_ind[(int)Stat.Dex]] +
                                                     p.lev)))
                        {
                            // Saving throw message
                            Utilities.msg("You grab hold of your backpack!");

                            // Occasional "blink" anyway
                            blinked = true;

                            // Obvious
                            obvious = true;

                            // Done
                            break;
                        }

                        // Find an item
                        for (int k = 0; k < 10; k++)
                        {
                            Object.Object i_ptr;
                            //object_type object_type_body;

                            // Pick an item
                            i = Random.randint0(Misc.INVEN_PACK);

                            // Obtain the item
                            Object.Object o_ptr = p.inventory[i];

                            // Skip non-objects
                            if (o_ptr.kind == null)
                            {
                                continue;
                            }

                            // Skip artifacts
                            if (o_ptr.artifact != null)
                            {
                                continue;
                            }

                            // Get a description
                            o_name = o_ptr.object_desc(Object.Object.Detail.FULL);

                            // Message
                            Utilities.msg("{0}our {1} ({2}) was stolen!",
                                          ((o_ptr.number > 1) ? "One of y" : "Y"),
                                          o_name, Object.Object.index_to_label(i));

                            // Get local object
                            i_ptr = new Object.Object();                        //&object_type_body;

                            // Obtain local object
                            i_ptr = o_ptr.copy();

                            // Modify number
                            i_ptr.number = 1;

                            // Hack -- If a rod, staff, or wand, allocate total
                            // maximum timeouts or charges between those
                            // stolen and those missed. -LM-
                            o_ptr.distribute_charges(i_ptr, 1);

                            // Carry the object
                            carry(i_ptr);

                            // Steal the items
                            Object.Object.inven_item_increase(i, -1);
                            Object.Object.inven_item_optimize(i);

                            // Obvious
                            obvious = true;

                            // Blink away
                            blinked = true;

                            // Done
                            break;
                        }
                    }
                    else if (effect.value == RBE.EAT_FOOD.value)
                    {
                        throw new NotImplementedException();
                        //// Take damage
                        //take_hit(p, damage, ddesc);

                        //// Steal some food
                        //for (k = 0; k < 10; k++)
                        //{
                        //    // Pick an item from the pack
                        //    i = randint0(INVEN_PACK);

                        //    // Get the item
                        //    o_ptr = &p.inventory[i];

                        //    // Skip non-objects
                        //    if (!o_ptr.kind) continue;

                        //    // Skip non-food objects
                        //    if (o_ptr.tval != TV_FOOD) continue;

                        //    // Get a description
                        //    object_desc(o_name, sizeof(o_name), o_ptr,
                        //                ODESC_PREFIX | ODESC_BASE);

                        //    // Message
                        //    msg("%sour %s (%c) was eaten!",
                        //                ((o_ptr.number > 1) ? "One of y" : "Y"),
                        //                o_name, index_to_label(i));

                        //    // Steal the items
                        //    inven_item_increase(i, -1);
                        //    inven_item_optimize(i);

                        //    // Obvious
                        //    obvious = true;

                        //    // Done
                        //    break;
                        //}
                    }
                    else if (effect.value == RBE.EAT_LIGHT.value)
                    {
                        throw new NotImplementedException();
                        //bitflag f[OF_SIZE];

                        //// Take damage
                        //take_hit(p, damage, ddesc);

                        //// Get the light, and its flags
                        //o_ptr = &p.inventory[INVEN_LIGHT];
                        //object_flags(o_ptr, f);

                        //// Drain fuel where applicable
                        //if (!of_has(f, OF_NO_FUEL) && (o_ptr.timeout > 0))
                        //{
                        //    // Reduce fuel
                        //    o_ptr.timeout -= (250 + randint1(250));
                        //    if (o_ptr.timeout < 1) o_ptr.timeout = 1;

                        //    // Notice
                        //    if (!p.timed[TMD_BLIND])
                        //    {
                        //        msg("Your light dims.");
                        //        obvious = true;
                        //    }

                        //    // Redraw stuff
                        //    p.redraw |= (PR_EQUIP);
                        //}
                    }
                    else if (effect.value == RBE.ACID.value)
                    {
                        throw new NotImplementedException();
                        //// Obvious
                        //obvious = true;

                        //// Message
                        //msg("You are covered in acid!");

                        //// Special damage
                        //damage = adjust_dam(p, GF_ACID, damage, RANDOMISE,
                        //    check_for_resist(p, GF_ACID, p.state.flags, true));
                        //if (damage) {
                        //    take_hit(p, damage, ddesc);
                        //    inven_damage(p, GF_ACID, MIN(damage * 5, 300));
                        //}

                        //// Learn about the player
                        //monster_learn_resists(m_ptr, p, GF_ACID);
                    }
                    else if (effect.value == RBE.ELEC.value)
                    {
                        throw new NotImplementedException();
                        //// Obvious
                        //obvious = true;

                        //// Message
                        //msg("You are struck by electricity!");

                        //// Take damage (special)
                        //damage = adjust_dam(p, GF_ELEC, damage, RANDOMISE,
                        //    check_for_resist(p, GF_ELEC, p.state.flags, true));
                        //if (damage) {
                        //    take_hit(p, damage, ddesc);
                        //    inven_damage(p, GF_ELEC, MIN(damage * 5, 300));
                        //}

                        //// Learn about the player
                        //monster_learn_resists(m_ptr, p, GF_ELEC);
                    }
                    else if (effect.value == RBE.FIRE.value)
                    {
                        throw new NotImplementedException();
                        //// Obvious
                        //obvious = true;

                        //// Message
                        //msg("You are enveloped in flames!");

                        //// Take damage (special)
                        //damage = adjust_dam(p, GF_FIRE, damage, RANDOMISE,
                        //    check_for_resist(p, GF_FIRE, p.state.flags, true));
                        //if (damage) {
                        //    take_hit(p, damage, ddesc);
                        //    inven_damage(p, GF_FIRE, MIN(damage * 5, 300));
                        //}

                        //// Learn about the player
                        //monster_learn_resists(m_ptr, p, GF_FIRE);
                    }
                    else if (effect.value == RBE.COLD.value)
                    {
                        throw new NotImplementedException();
                        //// Obvious
                        //obvious = true;

                        //// Message
                        //msg("You are covered with frost!");

                        //// Take damage (special)
                        //damage = adjust_dam(p, GF_COLD, damage, RANDOMISE,
                        //    check_for_resist(p, GF_COLD, p.state.flags, true));
                        //if (damage) {
                        //    take_hit(p, damage, ddesc);
                        //    inven_damage(p, GF_COLD, MIN(damage * 5, 300));
                        //}

                        //// Learn about the player
                        //monster_learn_resists(m_ptr, p, GF_COLD);
                    }
                    else if (effect.value == RBE.BLIND.value)
                    {
                        throw new NotImplementedException();
                        //// Take damage
                        //take_hit(p, damage, ddesc);

                        //// Increase "blind"
                        //if (player_inc_timed(p, TMD_BLIND, 10 + randint1(rlev), true, true))
                        //    obvious = true;

                        //// Learn about the player
                        //update_smart_learn(m_ptr, p, OF_RES_BLIND);
                    }
                    else if (effect.value == RBE.CONFUSE.value)
                    {
                        // Take damage
                        Spell.take_hit(p, damage, ddesc);

                        // Increase "confused"
                        if (p.inc_timed(Timed_Effect.CONFUSED, 3 + Random.randint1(rlev), true, true))
                        {
                            obvious = true;
                        }

                        // Learn about the player
                        update_smart_learn(p, Object.Object_Flag.RES_CONFU);
                    }
                    else if (effect.value == RBE.TERRIFY.value)
                    {
                        throw new NotImplementedException();
                        //// Take damage
                        //take_hit(p, damage, ddesc);

                        //// Increase "afraid"
                        //if (randint0(100) < p.state.skills[SKILL_SAVE])
                        //{
                        //    msg("You stand your ground!");
                        //    obvious = true;
                        //}
                        //else
                        //{
                        //    if (player_inc_timed(p, TMD_AFRAID, 3 + randint1(rlev), true,
                        //            true))
                        //        obvious = true;
                        //}

                        //// Learn about the player
                        //update_smart_learn(m_ptr, p, OF_RES_FEAR);
                    }
                    else if (effect.value == RBE.PARALYZE.value)
                    {
                        // Hack -- Prevent perma-paralysis via damage
                        if (p.timed[(int)Timed_Effect.PARALYZED] != 0 && (damage < 1))
                        {
                            damage = 1;
                        }

                        // Take damage
                        Spell.take_hit(p, damage, ddesc);

                        // Increase "paralyzed"
                        if (Random.randint0(100) < p.state.skills[(int)Skill.SAVE])
                        {
                            Utilities.msg("You resist the effects!");
                            obvious = true;
                        }
                        else
                        {
                            if (p.inc_timed(Timed_Effect.PARALYZED, 3 + Random.randint1(rlev), true, true))
                            {
                                obvious = true;
                            }
                        }

                        // Learn about the player
                        update_smart_learn(p, Object_Flag.FREE_ACT);
                    }
                    else if (effect.value == RBE.LOSE_STR.value)
                    {
                        throw new NotImplementedException();
                        //// Take damage
                        //take_hit(p, damage, ddesc);

                        //// Damage (stat)
                        //if (do_dec_stat(A_STR, false)) obvious = true;
                    }
                    else if (effect.value == RBE.LOSE_INT.value)
                    {
                        throw new NotImplementedException();
                        //// Take damage
                        //take_hit(p, damage, ddesc);

                        //// Damage (stat)
                        //if (do_dec_stat(A_INT, false)) obvious = true;
                    }
                    else if (effect.value == RBE.LOSE_WIS.value)
                    {
                        throw new NotImplementedException();
                        //// Take damage
                        //take_hit(p, damage, ddesc);

                        //// Damage (stat)
                        //if (do_dec_stat(A_WIS, false)) obvious = true;
                    }
                    else if (effect.value == RBE.LOSE_DEX.value)
                    {
                        throw new NotImplementedException();
                        //// Take damage
                        //take_hit(p, damage, ddesc);

                        //// Damage (stat)
                        //if (do_dec_stat(A_DEX, false)) obvious = true;
                    }
                    else if (effect.value == RBE.LOSE_CON.value)
                    {
                        throw new NotImplementedException();
                        //// Take damage
                        //take_hit(p, damage, ddesc);

                        //// Damage (stat)
                        //if (do_dec_stat(A_CON, false)) obvious = true;
                    }
                    else if (effect.value == RBE.LOSE_CHR.value)
                    {
                        throw new NotImplementedException();
                        //// Take damage
                        //take_hit(p, damage, ddesc);

                        //// Damage (stat)
                        //if (do_dec_stat(A_CHR, false)) obvious = true;
                    }
                    else if (effect.value == RBE.LOSE_ALL.value)
                    {
                        throw new NotImplementedException();
                        //// Take damage
                        //take_hit(p, damage, ddesc);

                        //// Damage (stats)
                        //if (do_dec_stat(A_STR, false)) obvious = true;
                        //if (do_dec_stat(A_DEX, false)) obvious = true;
                        //if (do_dec_stat(A_CON, false)) obvious = true;
                        //if (do_dec_stat(A_INT, false)) obvious = true;
                        //if (do_dec_stat(A_WIS, false)) obvious = true;
                        //if (do_dec_stat(A_CHR, false)) obvious = true;
                    }
                    else if (effect.value == RBE.SHATTER.value)
                    {
                        throw new NotImplementedException();
                        //// Obvious
                        //obvious = true;

                        //// Hack -- Reduce damage based on the player armor class
                        //damage -= (damage * ((ac < 240) ? ac : 240) / 400);

                        //// Take damage
                        //take_hit(p, damage, ddesc);

                        //// Radius 8 earthquake centered at the monster
                        //if (damage > 23)
                        //{
                        //    int px_old = p.px;
                        //    int py_old = p.py;

                        //    earthquake(fy, fx, 8);

                        //    // Stop the blows if the player is pushed away
                        //    if ((px_old != p.px) ||
                        //        (py_old != p.py))
                        //        do_break = true;
                        //}
                    }
                    else if (effect.value == RBE.EXP_10.value)
                    {
                        throw new NotImplementedException();
                        //// Obvious
                        //obvious = true;

                        //// Take damage
                        //take_hit(p, damage, ddesc);
                        //update_smart_learn(m_ptr, p_ptr, OF_HOLD_LIFE);

                        //if (check_state(p, OF_HOLD_LIFE, p.state.flags) && (randint0(100) < 95))
                        //{
                        //    msg("You keep hold of your life force!");
                        //}
                        //else
                        //{
                        //    s32b d = damroll(10, 6) + (p.exp/100) * MON_DRAIN_LIFE;
                        //    if (check_state(p, OF_HOLD_LIFE, p.state.flags))
                        //    {
                        //        msg("You feel your life slipping away!");
                        //        player_exp_lose(p, d / 10, false);
                        //    }
                        //    else
                        //    {
                        //        msg("You feel your life draining away!");
                        //        player_exp_lose(p, d, false);
                        //    }
                        //}
                    }
                    else if (effect.value == RBE.EXP_20.value)
                    {
                        throw new NotImplementedException();
                        //// Obvious
                        //obvious = true;

                        //// Take damage
                        //take_hit(p, damage, ddesc);
                        //update_smart_learn(m_ptr, p_ptr, OF_HOLD_LIFE);

                        //if (check_state(p, OF_HOLD_LIFE, p.state.flags) && (randint0(100) < 90))
                        //{
                        //    msg("You keep hold of your life force!");
                        //}
                        //else
                        //{
                        //    s32b d = damroll(20, 6) + (p.exp / 100) * MON_DRAIN_LIFE;

                        //    if (check_state(p, OF_HOLD_LIFE, p.state.flags))
                        //    {
                        //        msg("You feel your life slipping away!");
                        //        player_exp_lose(p, d / 10, false);
                        //    }
                        //    else
                        //    {
                        //        msg("You feel your life draining away!");
                        //        player_exp_lose(p, d, false);
                        //    }
                        //}
                    }
                    else if (effect.value == RBE.EXP_40.value)
                    {
                        throw new NotImplementedException();
                        //// Obvious
                        //obvious = true;

                        //// Take damage
                        //take_hit(p, damage, ddesc);
                        //update_smart_learn(m_ptr, p_ptr, OF_HOLD_LIFE);

                        //if (check_state(p, OF_HOLD_LIFE, p.state.flags) && (randint0(100) < 75))
                        //{
                        //    msg("You keep hold of your life force!");
                        //}
                        //else
                        //{
                        //    s32b d = damroll(40, 6) + (p.exp / 100) * MON_DRAIN_LIFE;

                        //    if (check_state(p, OF_HOLD_LIFE, p.state.flags))
                        //    {
                        //        msg("You feel your life slipping away!");
                        //        player_exp_lose(p, d / 10, false);
                        //    }
                        //    else
                        //    {
                        //        msg("You feel your life draining away!");
                        //        player_exp_lose(p, d, false);
                        //    }
                        //}
                    }
                    else if (effect.value == RBE.EXP_80.value)
                    {
                        throw new NotImplementedException();
                        //// Obvious
                        //obvious = true;

                        //// Take damage
                        //take_hit(p, damage, ddesc);
                        //update_smart_learn(m_ptr, p_ptr, OF_HOLD_LIFE);

                        //if (check_state(p, OF_HOLD_LIFE, p.state.flags) && (randint0(100) < 50))
                        //{
                        //    msg("You keep hold of your life force!");
                        //}
                        //else
                        //{
                        //    s32b d = damroll(80, 6) + (p.exp / 100) * MON_DRAIN_LIFE;

                        //    if (check_state(p, OF_HOLD_LIFE, p.state.flags))
                        //    {
                        //        msg("You feel your life slipping away!");
                        //        player_exp_lose(p, d / 10, false);
                        //    }
                        //    else
                        //    {
                        //        msg("You feel your life draining away!");
                        //        player_exp_lose(p, d, false);
                        //    }
                        //}
                    }
                    else if (effect.value == RBE.HALLU.value)
                    {
                        throw new NotImplementedException();
                        //// Take damage
                        //take_hit(p, damage, ddesc);

                        //// Increase "image"
                        //if (player_inc_timed(p, TMD_IMAGE, 3 + randint1(rlev / 2), true, true))
                        //    obvious = true;

                        //// Learn about the player
                        //monster_learn_resists(m_ptr, p, GF_CHAOS);
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }


                    // Hack -- only one of cut or stun
                    if (do_cut && do_stun)
                    {
                        // Cancel cut
                        if (Random.randint0(100) < 50)
                        {
                            do_cut = false;
                        }

                        // Cancel stun
                        else
                        {
                            do_stun = false;
                        }
                    }

                    // Handle cut
                    if (do_cut)
                    {
                        int k = 0;

                        // Critical hit (zero if non-critical)
                        tmp = monster_critical(d_dice, d_side, damage);

                        // Roll for damage
                        switch (tmp)
                        {
                        case 0: k = 0; break;

                        case 1: k = Random.randint1(5); break;

                        case 2: k = Random.randint1(5) + 5; break;

                        case 3: k = Random.randint1(20) + 20; break;

                        case 4: k = Random.randint1(50) + 50; break;

                        case 5: k = Random.randint1(100) + 100; break;

                        case 6: k = 300; break;

                        default: k = 500; break;
                        }

                        // Apply the cut
                        if (k != 0)
                        {
                            p.inc_timed(Timed_Effect.CUT, k, true, true);
                        }
                    }

                    // Handle stun
                    if (do_stun)
                    {
                        int k;

                        // Critical hit (zero if non-critical)
                        tmp = monster_critical(d_dice, d_side, damage);

                        // Roll for damage
                        switch (tmp)
                        {
                        case 0: k = 0; break;

                        case 1: k = Random.randint1(5); break;

                        case 2: k = Random.randint1(10) + 10; break;

                        case 3: k = Random.randint1(20) + 20; break;

                        case 4: k = Random.randint1(30) + 30; break;

                        case 5: k = Random.randint1(40) + 40; break;

                        case 6: k = 100; break;

                        default: k = 200; break;
                        }

                        // Apply the stun
                        if (k != 0)
                        {
                            p.inc_timed(Timed_Effect.STUN, k, true, true);
                        }
                    }
                }

                // Monster missed player
                else
                {
                    // Analyze failed attacks
                    if (method == RBM.HIT ||
                        method == RBM.TOUCH ||
                        method == RBM.PUNCH ||
                        method == RBM.KICK ||
                        method == RBM.CLAW ||
                        method == RBM.BITE ||
                        method == RBM.STING ||
                        method == RBM.BUTT ||
                        method == RBM.CRUSH ||
                        method == RBM.ENGULF)
                    {
                        // Visible monsters
                        if (ml)
                        {
                            // Disturbing
                            Cave.disturb(p, 1, 0);

                            // Message
                            //Utilities.msg("%^s misses you.", m_name);
                            Utilities.msg("{0} misses you.", m_name);
                        }
                    }
                }


                // Analyze "visible" monsters only
                if (visible)
                {
                    // Count "obvious" attacks (and ones that cause damage)
                    if (obvious || damage != 0 || (l_ptr.blows[ap_cnt] > 10))
                    {
                        // Count attacks of this type
                        if (l_ptr.blows[ap_cnt] < byte.MaxValue)
                        {
                            l_ptr.blows[ap_cnt]++;
                        }
                    }
                }

                // Skip the other blows if necessary
                if (do_break)
                {
                    break;
                }
            }


            // Blink away
            if (blinked)
            {
                Utilities.msg("There is a puff of smoke!");
                throw new NotImplementedException();
                //teleport_away(m_ptr, MAX_SIGHT * 2 + 5);
            }


            // Always notice cause of death
            if (p.is_dead && (l_ptr.deaths < short.MaxValue))
            {
                l_ptr.deaths++;
            }


            // Assume we attacked
            // Nick: Because, based on the length of this function,
            // literally a million other things could have happened
            return(true);
        }