OSDN Git Service

Leon氏の勧めに従って、Vanillaのコードと同様に各ソースファイルの頭の
[hengband/hengband.git] / src / monster2.c
index 37d2178..e38503b 100644 (file)
@@ -1,22 +1,21 @@
 /* File: monster2.c */
 
-/* Purpose: misc code for monsters */
-
 /*
- * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
+ * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
  *
- * This software may be copied and distributed for educational, research, and
- * not for profit purposes provided that this copyright and statement are
- * included in all such copies.
+ * This software may be copied and distributed for educational, research,
+ * and not for profit purposes provided that this copyright and statement
+ * are included in all such copies.  Other copyrights may also apply.
  */
 
+/* Purpose: misc code for monsters */
+
 #include "angband.h"
 
 #define HORDE_NOGOOD 0x01
 #define HORDE_NOEVIL 0x02
 
 bool is_kage = FALSE;
-u16b horde_align = 0;
 
 cptr horror_desc[MAX_SAN_HORROR] =
 {
@@ -153,6 +152,47 @@ cptr funny_comments[MAX_SAN_COMMENT] =
 
 
 /*
+ * Set the target of counter attack
+ */
+void set_target(monster_type *m_ptr, int y, int x)
+{
+       m_ptr->target_y = y;
+       m_ptr->target_x = x;
+}
+
+
+/*
+ * Reset the target of counter attack
+ */
+void reset_target(monster_type *m_ptr)
+{
+       set_target(m_ptr, 0, 0);
+}
+
+
+/*
+ *  Extract monster race pointer of a monster's true form
+ */
+monster_race *real_r_ptr(monster_type *m_ptr)
+{
+       monster_race *r_ptr = &r_info[m_ptr->r_idx];
+
+       /* Extract real race */
+       if (m_ptr->mflag2 & MFLAG_CHAMELEON)
+       {
+               if (r_ptr->flags1 & RF1_UNIQUE)
+                       return &r_info[MON_CHAMELEON_K];
+               else
+                       return &r_info[MON_CHAMELEON];
+       }
+       else
+       {
+               return r_ptr;
+       }
+}
+
+
+/*
  * Delete a monster by index.
  *
  * When a monster is deleted, all of its objects are deleted.
@@ -174,17 +214,7 @@ void delete_monster_idx(int i)
 
 
        /* Hack -- Reduce the racial counter */
-       if (m_ptr->mflag2 & MFLAG_CHAMELEON)
-       {
-               if (r_ptr->flags1 & RF1_UNIQUE)
-                       r_info[MON_CHAMELEON_K].cur_num--;
-               else
-                       r_info[MON_CHAMELEON].cur_num--;
-       }
-       else
-       {
-               r_ptr->cur_num--;
-       }
+       real_r_ptr(m_ptr)->cur_num--;
 
        /* Hack -- count the number of "reproducers" */
        if (r_ptr->flags2 & (RF2_MULTIPLY)) num_repro--;
@@ -231,6 +261,9 @@ void delete_monster_idx(int i)
 
        /* Visual update */
        lite_spot(y, x);
+
+       /* Update some things */
+       p_ptr->update |= (PU_MON_LITE);
 }
 
 
@@ -382,7 +415,7 @@ void compact_monsters(int size)
                        if (r_ptr->flags1 & (RF1_UNIQUE)) chance = 100;
 
                        /* All monsters get a saving throw */
-                       if (rand_int(100) < chance) continue;
+                       if (randint0(100) < chance) continue;
 
                        /* Delete the monster */
                        delete_monster_idx(i);
@@ -443,23 +476,11 @@ void wipe_m_list(void)
        {
                monster_type *m_ptr = &m_list[i];
 
-               monster_race *r_ptr = &r_info[m_ptr->r_idx];
-
                /* Skip dead monsters */
                if (!m_ptr->r_idx) continue;
 
-               /* Mega-Hack -- preserve Unique's XXX XXX XXX */
-
                /* Hack -- Reduce the racial counter */
-               if (m_ptr->mflag2 & MFLAG_CHAMELEON)
-               {
-                       if (r_ptr->flags1 & RF1_UNIQUE)
-                               r_info[MON_CHAMELEON_K].cur_num = 0;
-                       else
-                               r_info[MON_CHAMELEON].cur_num = 0;
-               }
-               else
-                       r_ptr->cur_num = 0;
+               real_r_ptr(m_ptr)->cur_num = 0;
 
                /* Monster is gone */
                cave[m_ptr->fy][m_ptr->fx].m_idx = 0;
@@ -564,7 +585,7 @@ static int summon_specific_who = -1;
 /*
  * Hack -- the hostility of the summoned monster
  */
-static int summon_specific_hostile = TRUE;
+static bool summon_specific_hostile = TRUE;
 
 static bool summon_unique_okay = FALSE;
 
@@ -628,8 +649,8 @@ static bool summon_specific_aux(int r_idx)
                case SUMMON_HI_UNDEAD:
                {
                        okay = ((r_ptr->d_char == 'L') ||
-                               (r_ptr->d_char == 'V') ||
-                               (r_ptr->d_char == 'W'));
+                               (r_ptr->d_char == 'V') ||
+                               (r_ptr->d_char == 'W'));
                        break;
                }
 
@@ -691,10 +712,10 @@ static bool summon_specific_aux(int r_idx)
                case SUMMON_BIZARRE6:
                {
                        okay = ((r_ptr->d_char == '!') ||
-                                (r_ptr->d_char == '?') ||
-                                (r_ptr->d_char == '=') ||
-                                (r_ptr->d_char == '$') ||
-                                (r_ptr->d_char == '|'));
+                                (r_ptr->d_char == '?') ||
+                                (r_ptr->d_char == '=') ||
+                                (r_ptr->d_char == '$') ||
+                                (r_ptr->d_char == '|'));
                        break;
                }
 
@@ -707,7 +728,7 @@ static bool summon_specific_aux(int r_idx)
                case SUMMON_CYBER:
                {
                        okay = ((r_ptr->d_char == 'U') &&
-                               (r_ptr->flags4 & RF4_ROCKET));
+                               (r_ptr->flags4 & RF4_ROCKET));
                        break;
                }
 
@@ -827,6 +848,44 @@ static bool summon_specific_aux(int r_idx)
                        okay = (r_ptr->flags7 & RF7_GUARDIAN);
                        break;
                }
+
+               case SUMMON_KNIGHTS:
+               {
+                       okay = ((r_idx == MON_NOV_PALADIN) ||
+                               (r_idx == MON_NOV_PALADIN_G) ||
+                               (r_idx == MON_PALADIN) ||
+                               (r_idx == MON_W_KNIGHT) ||
+                               (r_idx == MON_ULTRA_PALADIN) ||
+                               (r_idx == MON_KNI_TEMPLAR));
+                       break;
+               }
+
+               case SUMMON_EAGLES:
+               {
+                       okay = (r_ptr->d_char == 'B' &&
+                               (r_ptr->flags8 & RF8_WILD_MOUNTAIN) &&
+                               (r_ptr->flags8 & RF8_WILD_ONLY));
+                       break;
+               }
+
+               case SUMMON_PIRANHAS:
+               {
+                       okay = (r_idx == MON_PIRANHA);
+                       break;
+               }
+
+               case SUMMON_ARMAGE_GOOD:
+               {
+                       okay = (r_ptr->d_char == 'A' && (r_ptr->flags3 & RF3_GOOD));
+                       break;
+               }
+
+               case SUMMON_ARMAGE_EVIL:
+               {
+                       okay = ((r_ptr->flags3 & RF3_DEMON) ||
+                               (r_ptr->d_char == 'A' && (r_ptr->flags3 & RF3_EVIL)));
+                       break;
+               }
        }
 
        /* Result */
@@ -835,7 +894,7 @@ static bool summon_specific_aux(int r_idx)
 }
 
 
-static bool chameleon_change = FALSE;
+static int chameleon_change_m_idx = 0;
 
 
 /*
@@ -846,18 +905,20 @@ static bool restrict_monster_to_dungeon(int r_idx)
 {
        dungeon_info_type *d_ptr = &d_info[dungeon_type];
        monster_race *r_ptr = &r_info[r_idx];
-        byte a;
+       byte a;
 
        if (d_ptr->flags1 & DF1_CHAMELEON)
        {
-               if (chameleon_change) return TRUE;
+               if (chameleon_change_m_idx) return TRUE;
        }
        if (d_ptr->flags1 & DF1_NO_MAGIC)
        {
-               if (r_idx == MON_CHAMELEON) return TRUE;
-               if (r_ptr->freq_spell && !(r_ptr->flags4 & RF4_NOMAGIC_MASK) && !(r_ptr->flags5 & RF5_NOMAGIC_MASK) && !(r_ptr->flags6 & RF6_NOMAGIC_MASK))
+               if (r_idx != MON_CHAMELEON &&
+                   r_ptr->freq_spell && 
+                   !(r_ptr->flags4 & RF4_NOMAGIC_MASK) &&
+                   !(r_ptr->flags5 & RF5_NOMAGIC_MASK) &&
+                   !(r_ptr->flags6 & RF6_NOMAGIC_MASK))
                        return FALSE;
-               else return TRUE;
        }
        if (d_ptr->flags1 & DF1_NO_MELEE)
        {
@@ -866,219 +927,217 @@ static bool restrict_monster_to_dungeon(int r_idx)
                    !(r_ptr->flags5 & (RF5_BOLT_MASK | RF5_BEAM_MASK | RF5_BALL_MASK | RF5_CAUSE_1 | RF5_CAUSE_2 | RF5_CAUSE_3 | RF5_CAUSE_4 | RF5_MIND_BLAST | RF5_BRAIN_SMASH)) &&
                    !(r_ptr->flags6 & (RF6_BOLT_MASK | RF6_BEAM_MASK | RF6_BALL_MASK)))
                        return FALSE;
-               else return TRUE;
        }
        if (d_ptr->flags1 & DF1_BEGINNER)
        {
                if (r_ptr->level > dun_level)
                        return FALSE;
-               else return TRUE;
        }
 
        if (d_ptr->special_div == 64) return TRUE;
        if (summon_specific_type && !(d_ptr->flags1 & DF1_CHAMELEON)) return TRUE;
 
-        if(d_ptr->mode == DUNGEON_MODE_AND)
-        {
-                if (d_ptr->mflags1)
+       if(d_ptr->mode == DUNGEON_MODE_AND)
+       {
+               if (d_ptr->mflags1)
                {
-                        if((d_ptr->mflags1 & r_ptr->flags1) != d_ptr->mflags1)
-                                return FALSE;
+                       if((d_ptr->mflags1 & r_ptr->flags1) != d_ptr->mflags1)
+                               return FALSE;
                }
-                if (d_ptr->mflags2)
+               if (d_ptr->mflags2)
                {
-                        if((d_ptr->mflags2 & r_ptr->flags2) != d_ptr->mflags2)
-                                return FALSE;
+                       if((d_ptr->mflags2 & r_ptr->flags2) != d_ptr->mflags2)
+                               return FALSE;
                }
-                if (d_ptr->mflags3)
+               if (d_ptr->mflags3)
                {
-                        if((d_ptr->mflags3 & r_ptr->flags3) != d_ptr->mflags3)
-                                return FALSE;
+                       if((d_ptr->mflags3 & r_ptr->flags3) != d_ptr->mflags3)
+                               return FALSE;
                }
-                if (d_ptr->mflags4)
+               if (d_ptr->mflags4)
                {
-                        if((d_ptr->mflags4 & r_ptr->flags4) != d_ptr->mflags4)
-                                return FALSE;
+                       if((d_ptr->mflags4 & r_ptr->flags4) != d_ptr->mflags4)
+                               return FALSE;
                }
-                if (d_ptr->mflags5)
+               if (d_ptr->mflags5)
                {
-                        if((d_ptr->mflags5 & r_ptr->flags5) != d_ptr->mflags5)
-                                return FALSE;
+                       if((d_ptr->mflags5 & r_ptr->flags5) != d_ptr->mflags5)
+                               return FALSE;
                }
-                if (d_ptr->mflags6)
+               if (d_ptr->mflags6)
                {
-                        if((d_ptr->mflags6 & r_ptr->flags6) != d_ptr->mflags6)
-                                return FALSE;
+                       if((d_ptr->mflags6 & r_ptr->flags6) != d_ptr->mflags6)
+                               return FALSE;
                }
-                if (d_ptr->mflags7)
+               if (d_ptr->mflags7)
                {
-                        if((d_ptr->mflags7 & r_ptr->flags7) != d_ptr->mflags7)
-                                return FALSE;
+                       if((d_ptr->mflags7 & r_ptr->flags7) != d_ptr->mflags7)
+                               return FALSE;
                }
-                if (d_ptr->mflags8)
+               if (d_ptr->mflags8)
                {
-                        if((d_ptr->mflags8 & r_ptr->flags8) != d_ptr->mflags8)
-                                return FALSE;
+                       if((d_ptr->mflags8 & r_ptr->flags8) != d_ptr->mflags8)
+                               return FALSE;
                }
-                if (d_ptr->mflags9)
+               if (d_ptr->mflags9)
                {
-                        if((d_ptr->mflags9 & r_ptr->flags9) != d_ptr->mflags9)
-                                return FALSE;
+                       if((d_ptr->mflags9 & r_ptr->flags9) != d_ptr->mflags9)
+                               return FALSE;
                }
-                for(a = 0; a < 5; a++)
-                        if(d_ptr->r_char[a] && (d_ptr->r_char[a] != r_ptr->d_char)) return FALSE;
-        }
-        else if(d_ptr->mode == DUNGEON_MODE_NAND)
-        {
-                byte ok[9 + 5], i = 0, j = 0;
+               for(a = 0; a < 5; a++)
+                       if(d_ptr->r_char[a] && (d_ptr->r_char[a] != r_ptr->d_char)) return FALSE;
+       }
+       else if(d_ptr->mode == DUNGEON_MODE_NAND)
+       {
+               byte ok[9 + 5], i = 0, j = 0;
 
-                if (d_ptr->mflags1)
+               if (d_ptr->mflags1)
                {
-                        i++;
-                        if(d_ptr->mflags1 & r_ptr->flags1)
-                                ok[0] = 1;
+                       i++;
+                       if(d_ptr->mflags1 & r_ptr->flags1)
+                               ok[0] = 1;
                }
-                if (d_ptr->mflags2)
+               if (d_ptr->mflags2)
                {
-                        i++;
-                        if(d_ptr->mflags2 & r_ptr->flags2)
-                                ok[1] = 1;
+                       i++;
+                       if(d_ptr->mflags2 & r_ptr->flags2)
+                               ok[1] = 1;
                }
-                if (d_ptr->mflags3)
+               if (d_ptr->mflags3)
                {
-                        i++;
-                        if(d_ptr->mflags3 & r_ptr->flags3)
-                                ok[2] = 1;
+                       i++;
+                       if(d_ptr->mflags3 & r_ptr->flags3)
+                               ok[2] = 1;
                }
-                if (d_ptr->mflags4)
+               if (d_ptr->mflags4)
                {
-                        i++;
-                        if(d_ptr->mflags4 & r_ptr->flags4)
-                                ok[3] = 1;
+                       i++;
+                       if(d_ptr->mflags4 & r_ptr->flags4)
+                               ok[3] = 1;
                }
-                if (d_ptr->mflags5)
+               if (d_ptr->mflags5)
                {
-                        i++;
-                        if(d_ptr->mflags5 & r_ptr->flags5)
-                                ok[4] = 1;
+                       i++;
+                       if(d_ptr->mflags5 & r_ptr->flags5)
+                               ok[4] = 1;
                }
-                if (d_ptr->mflags6)
+               if (d_ptr->mflags6)
                {
-                        i++;
-                        if(d_ptr->mflags6 & r_ptr->flags6)
-                                ok[5] = 1;
+                       i++;
+                       if(d_ptr->mflags6 & r_ptr->flags6)
+                               ok[5] = 1;
                }
-                if (d_ptr->mflags7)
+               if (d_ptr->mflags7)
                {
-                        i++;
-                        if(d_ptr->mflags7 & r_ptr->flags7)
-                                ok[6] = 1;
+                       i++;
+                       if(d_ptr->mflags7 & r_ptr->flags7)
+                               ok[6] = 1;
                }
-                if (d_ptr->mflags8)
+               if (d_ptr->mflags8)
                {
-                        i++;
-                        if(d_ptr->mflags8 & r_ptr->flags8)
-                                ok[7] = 1;
+                       i++;
+                       if(d_ptr->mflags8 & r_ptr->flags8)
+                               ok[7] = 1;
                }
-                if (d_ptr->mflags9)
+               if (d_ptr->mflags9)
                {
-                        i++;
-                        if(d_ptr->mflags9 & r_ptr->flags9)
-                                ok[8] = 1;
+                       i++;
+                       if(d_ptr->mflags9 & r_ptr->flags9)
+                               ok[8] = 1;
                }
 
-                for(a = 0; a < 5; a++)
-                {
-                        if(d_ptr->r_char[a])
-                        {
-                                i++;
-                                if (d_ptr->r_char[a] != r_ptr->d_char) ok[9 + a] = 1;
-                        }
-                }
+               for(a = 0; a < 5; a++)
+               {
+                       if(d_ptr->r_char[a])
+                       {
+                               i++;
+                               if (d_ptr->r_char[a] != r_ptr->d_char) ok[9 + a] = 1;
+                       }
+               }
 
-                j = ok[0] + ok[1] + ok[2] + ok[3] + ok[4] + ok[5] + ok[6] + ok[7] + ok[8] + ok[9] + ok[10] + ok[11] + ok[12] + ok[13];
+               j = ok[0] + ok[1] + ok[2] + ok[3] + ok[4] + ok[5] + ok[6] + ok[7] + ok[8] + ok[9] + ok[10] + ok[11] + ok[12] + ok[13];
 
-                if(i == j) return FALSE;
-        }
-        else if(d_ptr->mode == DUNGEON_MODE_OR)
-        {
-                byte ok = FALSE, i;
-                s32b flag;
+               if(i == j) return FALSE;
+       }
+       else if(d_ptr->mode == DUNGEON_MODE_OR)
+       {
+               byte ok = FALSE, i;
+               s32b flag;
 
-                for(i = 0; i < 32; i++)
-                {
-                        flag = d_ptr->mflags1 & (1 << i);
-                        if(r_ptr->flags1 & flag) ok = TRUE;
+               for(i = 0; i < 32; i++)
+               {
+                       flag = d_ptr->mflags1 & (1 << i);
+                       if(r_ptr->flags1 & flag) ok = TRUE;
 
-                        flag = d_ptr->mflags2 & (1 << i);
-                        if(r_ptr->flags2 & flag) ok = TRUE;
+                       flag = d_ptr->mflags2 & (1 << i);
+                       if(r_ptr->flags2 & flag) ok = TRUE;
 
-                        flag = d_ptr->mflags3 & (1 << i);
-                        if(r_ptr->flags3 & flag) ok = TRUE;
+                       flag = d_ptr->mflags3 & (1 << i);
+                       if(r_ptr->flags3 & flag) ok = TRUE;
 
-                        flag = d_ptr->mflags4 & (1 << i);
-                        if(r_ptr->flags4 & flag) ok = TRUE;
+                       flag = d_ptr->mflags4 & (1 << i);
+                       if(r_ptr->flags4 & flag) ok = TRUE;
 
-                        flag = d_ptr->mflags5 & (1 << i);
-                        if(r_ptr->flags5 & flag) ok = TRUE;
+                       flag = d_ptr->mflags5 & (1 << i);
+                       if(r_ptr->flags5 & flag) ok = TRUE;
 
-                        flag = d_ptr->mflags6 & (1 << i);
-                        if(r_ptr->flags6 & flag) ok = TRUE;
+                       flag = d_ptr->mflags6 & (1 << i);
+                       if(r_ptr->flags6 & flag) ok = TRUE;
 
-                        flag = d_ptr->mflags7 & (1 << i);
-                        if(r_ptr->flags7 & flag) ok = TRUE;
+                       flag = d_ptr->mflags7 & (1 << i);
+                       if(r_ptr->flags7 & flag) ok = TRUE;
 
-                        flag = d_ptr->mflags8 & (1 << i);
-                        if(r_ptr->flags8 & flag) ok = TRUE;
+                       flag = d_ptr->mflags8 & (1 << i);
+                       if(r_ptr->flags8 & flag) ok = TRUE;
 
-                        flag = d_ptr->mflags9 & (1 << i);
-                        if(r_ptr->flags9 & flag) ok = TRUE;
-                }
-                for(a = 0; a < 5; a++)
-                        if(d_ptr->r_char[a] == r_ptr->d_char) ok = TRUE;
+                       flag = d_ptr->mflags9 & (1 << i);
+                       if(r_ptr->flags9 & flag) ok = TRUE;
+               }
+               for(a = 0; a < 5; a++)
+                       if(d_ptr->r_char[a] == r_ptr->d_char) ok = TRUE;
 
-                return ok;
-        }
-        else if(d_ptr->mode == DUNGEON_MODE_NOR)
-        {
-                byte ok = TRUE, i;
-                s32b flag;
+               return ok;
+       }
+       else if(d_ptr->mode == DUNGEON_MODE_NOR)
+       {
+               byte ok = TRUE, i;
+               s32b flag;
 
-                for(i = 0; i < 32; i++)
-                {
-                        flag = d_ptr->mflags1 & (1 << i);
-                        if(r_ptr->flags1 & flag) ok = FALSE;
+               for(i = 0; i < 32; i++)
+               {
+                       flag = d_ptr->mflags1 & (1 << i);
+                       if(r_ptr->flags1 & flag) ok = FALSE;
 
-                        flag = d_ptr->mflags2 & (1 << i);
-                        if(r_ptr->flags2 & flag) ok = FALSE;
+                       flag = d_ptr->mflags2 & (1 << i);
+                       if(r_ptr->flags2 & flag) ok = FALSE;
 
-                        flag = d_ptr->mflags3 & (1 << i);
-                        if(r_ptr->flags3 & flag) ok = FALSE;
+                       flag = d_ptr->mflags3 & (1 << i);
+                       if(r_ptr->flags3 & flag) ok = FALSE;
 
-                        flag = d_ptr->mflags4 & (1 << i);
-                        if(r_ptr->flags4 & flag) ok = FALSE;
+                       flag = d_ptr->mflags4 & (1 << i);
+                       if(r_ptr->flags4 & flag) ok = FALSE;
 
-                        flag = d_ptr->mflags5 & (1 << i);
-                        if(r_ptr->flags5 & flag) ok = FALSE;
+                       flag = d_ptr->mflags5 & (1 << i);
+                       if(r_ptr->flags5 & flag) ok = FALSE;
 
-                        flag = d_ptr->mflags6 & (1 << i);
-                        if(r_ptr->flags6 & flag) ok = FALSE;
+                       flag = d_ptr->mflags6 & (1 << i);
+                       if(r_ptr->flags6 & flag) ok = FALSE;
 
-                        flag = d_ptr->mflags7 & (1 << i);
-                        if(r_ptr->flags7 & flag) ok = FALSE;
+                       flag = d_ptr->mflags7 & (1 << i);
+                       if(r_ptr->flags7 & flag) ok = FALSE;
 
-                        flag = d_ptr->mflags8 & (1 << i);
-                        if(r_ptr->flags8 & flag) ok = FALSE;
+                       flag = d_ptr->mflags8 & (1 << i);
+                       if(r_ptr->flags8 & flag) ok = FALSE;
 
-                        flag = d_ptr->mflags9 & (1 << i);
-                        if(r_ptr->flags9 & flag) ok = FALSE;
-                }
-                for(a = 0; a < 5; a++)
-                        if(d_ptr->r_char[a] == r_ptr->d_char) ok = FALSE;
-                return ok;
-        }
+                       flag = d_ptr->mflags9 & (1 << i);
+                       if(r_ptr->flags9 & flag) ok = FALSE;
+               }
+               for(a = 0; a < 5; a++)
+                       if(d_ptr->r_char[a] == r_ptr->d_char) ok = FALSE;
+               return ok;
+       }
 
-        return TRUE;
+       return TRUE;
 }
 
 /*
@@ -1111,7 +1170,7 @@ errr get_mon_num_prep(monster_hook_type monster_hook,
                    (get_mon_num2_hook && !((*get_mon_num2_hook)(entry->index))))
                        continue;
 
-               if (!p_ptr->inside_battle && !chameleon_change &&
+               if (!p_ptr->inside_battle && !chameleon_change_m_idx &&
                    summon_specific_type != SUMMON_GUARDIANS)
                {
                        /* Hack -- don't create questors */
@@ -1134,7 +1193,7 @@ errr get_mon_num_prep(monster_hook_type monster_hook,
                {
                        int hoge = entry->prob2 * d_info[dungeon_type].special_div;
                        entry->prob2 = hoge / 64;
-                       if (rand_int(64) < (hoge & 0x3f)) entry->prob2++;
+                       if (randint0(64) < (hoge & 0x3f)) entry->prob2++;
                }
        }
 
@@ -1219,10 +1278,10 @@ s16b get_mon_num(int level)
 
        if (level > MAX_DEPTH - 1) level = MAX_DEPTH - 1;
 
-       if ((dungeon_turn > hoge*10000L) && !level)
+       if ((dungeon_turn > hoge*(TURNS_PER_TICK*500L)) && !level)
        {
-               pls_kakuritu = MAX(2, NASTY_MON-((dungeon_turn/50000L-hoge/10)));
-               pls_level = MIN(8,3 + dungeon_turn/400000L-hoge/40);
+               pls_kakuritu = MAX(2, NASTY_MON-((dungeon_turn/(TURNS_PER_TICK*2500L)-hoge/10)));
+               pls_level = MIN(8,3 + dungeon_turn/(TURNS_PER_TICK*20000L)-hoge/40);
        }
        else
        {
@@ -1242,15 +1301,15 @@ s16b get_mon_num(int level)
        if ((level > 0) && !p_ptr->inside_battle && !(d_info[dungeon_type].flags1 & DF1_BEGINNER))
        {
                /* Nightmare mode allows more out-of depth monsters */
-               if (ironman_nightmare && !rand_int(pls_kakuritu))
+               if (ironman_nightmare && !randint0(pls_kakuritu))
                {
                        /* What a bizarre calculation */
-                       level = 1 + (level * MAX_DEPTH / randint(MAX_DEPTH));
+                       level = 1 + (level * MAX_DEPTH / randint1(MAX_DEPTH));
                }
                else
                {
                        /* Occasional "nasty" monster */
-                       if (!rand_int(pls_kakuritu))
+                       if (!randint0(pls_kakuritu))
                        {
                                /* Pick a level bonus */
                                int d = MIN(5, level/10) + pls_level;
@@ -1260,7 +1319,7 @@ s16b get_mon_num(int level)
                        }
 
                        /* Occasional "nasty" monster */
-                       if (!rand_int(pls_kakuritu))
+                       if (!randint0(pls_kakuritu))
                        {
                                /* Pick a level bonus */
                                int d = MIN(5, level/10) + pls_level;
@@ -1290,7 +1349,7 @@ s16b get_mon_num(int level)
                /* Access the actual race */
                r_ptr = &r_info[r_idx];
 
-               if (!p_ptr->inside_battle && !chameleon_change)
+               if (!p_ptr->inside_battle && !chameleon_change_m_idx)
                {
                        /* Hack -- "unique" monsters must be "unique" */
                        if (((r_ptr->flags1 & (RF1_UNIQUE)) ||
@@ -1312,13 +1371,6 @@ s16b get_mon_num(int level)
                                if (r_info[MON_LUPART].cur_num > 0) continue;
                        }
                }
-               else if (!p_ptr->inside_battle && chameleon_change
-                        && (r_ptr->flags1 & (RF1_UNIQUE)))
-               {
-                       /* Hack -- Chameleon Lord must be "unique" */
-                       if (r_info[MON_CHAMELEON_K].cur_num >= r_ptr->max_num)
-                               continue;
-               }
 
                /* Accept */
                table[i].prob3 = table[i].prob2;
@@ -1332,7 +1384,7 @@ s16b get_mon_num(int level)
 
 
        /* Pick a monster */
-       value = rand_int(total);
+       value = randint0(total);
 
        /* Find the monster */
        for (i = 0; i < alloc_race_size; i++)
@@ -1346,7 +1398,7 @@ s16b get_mon_num(int level)
 
 
        /* Power boost */
-       p = rand_int(100);
+       p = randint0(100);
 
        /* Try for a "harder" monster once (50%) or twice (10%) */
        if (p < 60)
@@ -1355,7 +1407,7 @@ s16b get_mon_num(int level)
                j = i;
 
                /* Pick a monster */
-               value = rand_int(total);
+               value = randint0(total);
 
                /* Find the monster */
                for (i = 0; i < alloc_race_size; i++)
@@ -1378,7 +1430,7 @@ s16b get_mon_num(int level)
                j = i;
 
                /* Pick a monster */
-               value = rand_int(total);
+               value = randint0(total);
 
                /* Find the monster */
                for (i = 0; i < alloc_race_size; i++)
@@ -1438,6 +1490,8 @@ s16b get_mon_num(int level)
  *   0x20 --> Pronominalize visible monsters
  *   0x40 --> Assume the monster is hidden
  *   0x80 --> Assume the monster is visible
+ *  0x100 --> Chameleon's true name
+ *  0x200 --> Ignore hallucination, and penetrate shape change
  *
  * Useful Modes:
  *   0x00 --> Full nominative name ("the kobold") or "it"
@@ -1458,20 +1512,16 @@ void monster_desc(char *desc, monster_type *m_ptr, int mode)
        bool            seen, pron;
        bool            named = FALSE;
 
-       if (m_ptr->mflag2 & MFLAG_KAGE) r_ptr = &r_info[MON_KAGE];
-       else r_ptr = &r_info[m_ptr->r_idx];
+       r_ptr = &r_info[m_ptr->ap_r_idx];
 
-       if ((mode & 0x100) && (m_ptr->mflag2 & MFLAG_CHAMELEON))
-       {
-               if (r_ptr->flags1 & RF1_UNIQUE) name = (r_name + r_info[MON_CHAMELEON_K].name);
-               else name = (r_name + r_info[MON_CHAMELEON].name);
-       }
+       /* Mode of 0x100 will reveal Chameleon's true name */
+       if (mode & 0x100) name = (r_name + real_r_ptr(m_ptr)->name);
        else name = (r_name + r_ptr->name);
 
        /* Are we hallucinating? (Idea from Nethack...) */
-       if (p_ptr->image)
+       if (p_ptr->image && !(mode & 0x200))
        {
-               if (randint(2) == 1)
+               if (one_in_(2))
                {
 #ifdef JP
 if (!get_rnd_line("silly_j.txt", m_ptr->r_idx, silly_name))
@@ -1488,7 +1538,7 @@ if (!get_rnd_line("silly_j.txt", m_ptr->r_idx, silly_name))
 
                        do
                        {
-                               hallu_race = &r_info[randint(max_r_idx - 1)];
+                               hallu_race = &r_info[randint1(max_r_idx - 1)];
                        }
                        while (hallu_race->flags1 & RF1_UNIQUE);
 
@@ -1608,9 +1658,9 @@ if (!get_rnd_line("silly_j.txt", m_ptr->r_idx, silly_name))
        {
                /* The monster is visible, so use its gender */
 #ifdef JP
-                if (r_ptr->flags1 & (RF1_FEMALE)) strcpy(desc, "Èà½÷¼«¿È");
-                else if (r_ptr->flags1 & (RF1_MALE)) strcpy(desc, "È༫¿È");
-                else strcpy(desc, "¤½¤ì¼«¿È");
+               if (r_ptr->flags1 & (RF1_FEMALE)) strcpy(desc, "Èà½÷¼«¿È");
+               else if (r_ptr->flags1 & (RF1_MALE)) strcpy(desc, "È༫¿È");
+               else strcpy(desc, "¤½¤ì¼«¿È");
 #else
                if (r_ptr->flags1 & RF1_FEMALE) strcpy(desc, "herself");
                else if (r_ptr->flags1 & RF1_MALE) strcpy(desc, "himself");
@@ -1623,8 +1673,29 @@ if (!get_rnd_line("silly_j.txt", m_ptr->r_idx, silly_name))
        /* Handle all other visible monster requests */
        else
        {
+               /* Tanuki? */
+               if (is_pet(m_ptr) && m_ptr->ap_r_idx != m_ptr->r_idx)
+               {
+#ifdef JP
+                               char *t;
+                               strcpy(buf, name);
+                               t = buf;
+                               while(strncmp(t, "¡Ù", 2) && *t) t++;
+                               if (*t)
+                               {
+                                       *t = '\0';
+                                       (void)sprintf(desc, "%s¡©¡Ù", buf);
+                               }
+                               else
+                                       (void)sprintf(desc, "%s¡©", name);
+#else
+                               (void)sprintf(desc, "%s?", name);
+#endif
+               }
+               else
+
                /* It could be a Unique */
-               if ((r_ptr->flags1 & RF1_UNIQUE) && !p_ptr->image)
+               if ((r_ptr->flags1 & RF1_UNIQUE) && !(p_ptr->image && !(mode & 0x200)))
                {
                        /* Start with the name (thus nominative and objective) */
                        if ((m_ptr->mflag2 & MFLAG_CHAMELEON) && !(mode & 0x100))
@@ -1668,16 +1739,6 @@ if (!get_rnd_line("silly_j.txt", m_ptr->r_idx, silly_name))
 #endif
 
                        (void)strcat(desc, name);
-
-                       if (m_ptr->nickname)
-                       {
-#ifdef JP
-                               sprintf(buf,"¡Ö%s¡×",quark_str(m_ptr->nickname));
-#else
-                               sprintf(buf," called %s",quark_str(m_ptr->nickname));
-#endif
-                               strcat(desc,buf);
-                       }
                }
 
                /* It could be a normal, definite, monster */
@@ -1699,45 +1760,57 @@ if (!get_rnd_line("silly_j.txt", m_ptr->r_idx, silly_name))
 #endif
 
                        (void)strcat(desc, name);
+               }
 
-                       if (m_ptr->nickname)
-                       {
+               if (m_ptr->nickname)
+               {
 #ifdef JP
-                               sprintf(buf,"¡Ö%s¡×",quark_str(m_ptr->nickname));
+                       sprintf(buf,"¡Ö%s¡×",quark_str(m_ptr->nickname));
 #else
-                               sprintf(buf," called %s",quark_str(m_ptr->nickname));
+                       sprintf(buf," called %s",quark_str(m_ptr->nickname));
 #endif
-                               strcat(desc,buf);
-                       }
+                       strcat(desc,buf);
+               }
 
-                       if ((m_ptr->fy == py) && (m_ptr->fx == px))
+               if ((m_ptr->fy == py) && (m_ptr->fx == px))
+               {
 #ifdef JP
-                               strcat(desc,"(¾èÇÏÃæ)");
+                       strcat(desc,"(¾èÇÏÃæ)");
 #else
-                               strcat(desc,"(riding)");
+                       strcat(desc,"(riding)");
 #endif
-                       if ((mode & 0x200) && (m_ptr->mflag2 & MFLAG_CHAMELEON))
+               }
+
+               if ((mode & 0x200) && (m_ptr->mflag2 & MFLAG_CHAMELEON))
+               {
+                       if (r_ptr->flags1 & RF1_UNIQUE)
                        {
-                               if (r_ptr->flags1 & RF1_UNIQUE)
 #ifdef JP
-                                       strcat(desc,"(¥«¥á¥ì¥ª¥ó¤Î²¦)");
+                               strcat(desc,"(¥«¥á¥ì¥ª¥ó¤Î²¦)");
 #else
-                                       strcat(desc,"(Chameleon Lord)");
+                               strcat(desc,"(Chameleon Lord)");
 #endif
-                               else
+                       }
+                       else
+                       {
 #ifdef JP
-                                       strcat(desc,"(¥«¥á¥ì¥ª¥ó)");
+                               strcat(desc,"(¥«¥á¥ì¥ª¥ó)");
 #else
-                                       strcat(desc,"(Chameleon)");
+                               strcat(desc,"(Chameleon)");
 #endif
                        }
                }
 
+               if ((mode & 0x200) && m_ptr->ap_r_idx != m_ptr->r_idx)
+               {
+                       strcat(desc, format("(%s)", r_name + r_info[m_ptr->r_idx].name));
+               }
+
                /* Handle the Possessive as a special afterthought */
                if (mode & 0x02)
                {
                        /* XXX Check for trailing "s" */
-
+                       
                        /* Simply append "apostrophe" and "s" */
 #ifdef JP
                        (void)strcat(desc, "¤Î");
@@ -1754,24 +1827,104 @@ if (!get_rnd_line("silly_j.txt", m_ptr->r_idx, silly_name))
 
 /*
  * Learn about a monster (by "probing" it)
+ *
+ * Return the number of new flags learnt.  -Mogami-
  */
-void lore_do_probe(int m_idx)
+int lore_do_probe(int r_idx)
 {
-       monster_type *m_ptr = &m_list[m_idx];
-
-       monster_race *r_ptr = &r_info[m_ptr->r_idx];
+       monster_race *r_ptr = &r_info[r_idx];
+       int i, n = 0;
+       byte tmp_byte;
+
+       /* Maximal info about awareness */
+       if (r_ptr->r_wake != MAX_UCHAR) n++;
+       if (r_ptr->r_ignore != MAX_UCHAR) n++;
+       r_ptr->r_wake = r_ptr->r_ignore = MAX_UCHAR;
+                               
+       /* Observe "maximal" attacks */
+       for (i = 0; i < 4; i++)
+       {
+               /* Examine "actual" blows */
+               if (r_ptr->blow[i].effect || r_ptr->blow[i].method)
+               {
+                       /* Maximal observations */
+                       if (r_ptr->r_blows[i] != MAX_UCHAR) n++;
+                       r_ptr->r_blows[i] = MAX_UCHAR;
+               }
+       }
+                               
+       /* Maximal drops */
+       tmp_byte = 
+               (((r_ptr->flags1 & RF1_DROP_4D2) ? 8 : 0) +
+                ((r_ptr->flags1 & RF1_DROP_3D2) ? 6 : 0) +
+                ((r_ptr->flags1 & RF1_DROP_2D2) ? 4 : 0) +
+                ((r_ptr->flags1 & RF1_DROP_1D2) ? 2 : 0) +
+                ((r_ptr->flags1 & RF1_DROP_90)  ? 1 : 0) +
+                ((r_ptr->flags1 & RF1_DROP_60)  ? 1 : 0));
+
+       /* Only "valid" drops */
+       if (!(r_ptr->flags1 & RF1_ONLY_GOLD))
+       {
+               if (r_ptr->r_drop_item != tmp_byte) n++;
+               r_ptr->r_drop_item = tmp_byte;
+       }
+       if (!(r_ptr->flags1 & RF1_ONLY_ITEM))
+       {
+               if (r_ptr->r_drop_gold != tmp_byte) n++;
+               r_ptr->r_drop_gold = tmp_byte;
+       }
+                               
+       /* Observe many spells */
+       if (r_ptr->r_cast_spell != MAX_UCHAR) n++;
+       r_ptr->r_cast_spell = MAX_UCHAR;
+                               
+       /* Count unknown flags */
+       for (i = 0; i < 32; i++)
+       {
+               if (!(r_ptr->r_flags1 & (1L << i)) &&
+                   (r_ptr->flags1 & (1L << i))) n++;
+               if (!(r_ptr->r_flags2 & (1L << i)) &&
+                   (r_ptr->flags2 & (1L << i))) n++;
+               if (!(r_ptr->r_flags3 & (1L << i)) &&
+                   (r_ptr->flags3 & (1L << i))) n++;
+               if (!(r_ptr->r_flags4 & (1L << i)) &&
+                   (r_ptr->flags4 & (1L << i))) n++;
+               if (!(r_ptr->r_flags5 & (1L << i)) &&
+                   (r_ptr->flags5 & (1L << i))) n++;
+               if (!(r_ptr->r_flags6 & (1L << i)) &&
+                   (r_ptr->flags6 & (1L << i))) n++;
+
+               /* r_flags7 is actually unused */
+#if 0
+               if (!(r_ptr->r_flags7 & (1L << i)) &&
+                   (r_ptr->flags7 & (1L << i))) n++;
+#endif
+       }
 
-       /* Hack -- Memorize some flags */
+       /* Know all the flags */
        r_ptr->r_flags1 = r_ptr->flags1;
        r_ptr->r_flags2 = r_ptr->flags2;
        r_ptr->r_flags3 = r_ptr->flags3;
+       r_ptr->r_flags4 = r_ptr->flags4;
+       r_ptr->r_flags5 = r_ptr->flags5;
+       r_ptr->r_flags6 = r_ptr->flags6;
+
+       /* r_flags7 is actually unused */
+       /* r_ptr->r_flags7 = r_ptr->flags7; */
+
+       /* Know about evolution */
+       if (!(r_ptr->r_xtra1 & MR1_SINKA)) n++;
+       r_ptr->r_xtra1 |= MR1_SINKA;
 
        /* Update monster recall window */
-       if (p_ptr->monster_race_idx == m_ptr->r_idx)
+       if (p_ptr->monster_race_idx == r_idx)
        {
                /* Window stuff */
                p_ptr->window |= (PW_MONSTER);
        }
+
+       /* Return the number of new flags learnt */
+       return n;
 }
 
 
@@ -1849,7 +2002,7 @@ void sanity_blast(monster_type *m_ptr, bool necro)
                if (is_pet(m_ptr))
                        return; /* Pet eldritch horrors are safe most of the time */
 
-               if (randint(100) > power) return;
+               if (randint1(100) > power) return;
 
                if (saving_throw(p_ptr->skill_sav - power))
                {
@@ -1860,17 +2013,18 @@ void sanity_blast(monster_type *m_ptr, bool necro)
                {
                        /* Something silly happens... */
 #ifdef JP
-msg_format("%s%s¤Î´é¤ò¸«¤Æ¤·¤Þ¤Ã¤¿¡ª",
+                       msg_format("%s%s¤Î´é¤ò¸«¤Æ¤·¤Þ¤Ã¤¿¡ª",
+                               funny_desc[randint0(MAX_SAN_FUNNY)], m_name);
 #else
                        msg_format("You behold the %s visage of %s!",
+                               funny_desc[randint0(MAX_SAN_FUNNY)], m_name);
 #endif
 
-                               funny_desc[rand_int(MAX_SAN_FUNNY)], m_name);
 
-                       if (randint(3) == 1)
+                       if (one_in_(3))
                        {
-                               msg_print(funny_comments[rand_int(MAX_SAN_COMMENT)]);
-                               p_ptr->image = p_ptr->image + randint(r_ptr->level);
+                               msg_print(funny_comments[randint0(MAX_SAN_COMMENT)]);
+                               p_ptr->image = p_ptr->image + randint1(r_ptr->level);
                        }
 
                        return; /* Never mind; we can't see it clearly enough */
@@ -1878,18 +2032,18 @@ msg_format("%s%s
 
                /* Something frightening happens... */
 #ifdef JP
-msg_format("%s%s¤Î´é¤ò¸«¤Æ¤·¤Þ¤Ã¤¿¡ª",
+               msg_format("%s%s¤Î´é¤ò¸«¤Æ¤·¤Þ¤Ã¤¿¡ª",
+                       horror_desc[randint0(MAX_SAN_HORROR)], m_name);
 #else
                msg_format("You behold the %s visage of %s!",
+                       horror_desc[randint0(MAX_SAN_HORROR)], m_name);
 #endif
 
-                       horror_desc[rand_int(MAX_SAN_HORROR)], m_name);
-
                r_ptr->r_flags2 |= RF2_ELDRITCH_HORROR;
 
                /* Demon characters are unaffected */
                if ((p_ptr->prace == RACE_IMP) || (p_ptr->prace == RACE_DEMON) || (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_DEMON)) return;
-               if (wizard) return;
+               if (p_ptr->wizard) return;
 
                /* Undead characters are 50% likely to be unaffected */
                if ((p_ptr->prace == RACE_SKELETON) || (p_ptr->prace == RACE_ZOMBIE)
@@ -1913,11 +2067,11 @@ msg_print("
        {
                if (!p_ptr->resist_conf)
                {
-                       (void)set_confused(p_ptr->confused + rand_int(4) + 4);
+                       (void)set_confused(p_ptr->confused + randint0(4) + 4);
                }
                if (!p_ptr->resist_chaos && one_in_(3))
                {
-                       (void)set_image(p_ptr->image + rand_int(250) + 150);
+                       (void)set_image(p_ptr->image + randint0(250) + 150);
                }
                return;
        }
@@ -1933,19 +2087,19 @@ msg_print("
        {
                if (!p_ptr->resist_conf)
                {
-                       (void)set_confused(p_ptr->confused + rand_int(4) + 4);
+                       (void)set_confused(p_ptr->confused + randint0(4) + 4);
                }
                if (!p_ptr->free_act)
                {
-                       (void)set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4);
+                       (void)set_paralyzed(p_ptr->paralyzed + randint0(4) + 4);
                }
-               while (rand_int(100) > p_ptr->skill_sav)
+               while (randint0(100) > p_ptr->skill_sav)
                        (void)do_dec_stat(A_INT);
-               while (rand_int(100) > p_ptr->skill_sav)
+               while (randint0(100) > p_ptr->skill_sav)
                        (void)do_dec_stat(A_WIS);
                if (!p_ptr->resist_chaos)
                {
-                       (void)set_image(p_ptr->image + rand_int(250) + 150);
+                       (void)set_image(p_ptr->image + randint0(250) + 150);
                }
                return;
        }
@@ -1979,7 +2133,7 @@ msg_print("
 
        while (!happened)
        {
-               switch (randint(21))
+               switch (randint1(21))
                {
                        case 1:
                                if (!(p_ptr->muta3 & MUT3_MORONIC) && one_in_(5))
@@ -2158,6 +2312,8 @@ void update_mon(int m_idx, bool full)
 
        monster_race *r_ptr = &r_info[m_ptr->r_idx];
 
+       bool do_disturb = disturb_move;
+
        int d;
 
        /* Current location */
@@ -2170,6 +2326,14 @@ void update_mon(int m_idx, bool full)
        /* Seen by vision */
        bool easy = FALSE;
 
+       /* Do disturb? */
+       if (disturb_high)
+       {
+               monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
+
+               if (ap_r_ptr->r_tkills && ap_r_ptr->level >= p_ptr->lev)
+                       do_disturb = TRUE;
+       }
 
        /* Compute distance */
        if (full)
@@ -2256,6 +2420,105 @@ void update_mon(int m_idx, bool full)
                                        if (r_ptr->flags2 & (RF2_STUPID)) r_ptr->r_flags2 |= (RF2_STUPID);
                                }
                        }
+
+                       /* Magical sensing */
+                       if ((p_ptr->esp_animal) && (r_ptr->flags3 & (RF3_ANIMAL)))
+                       {
+                               flag = TRUE;
+                               r_ptr->r_flags3 |= (RF3_ANIMAL);
+
+                       }
+
+                       /* Magical sensing */
+                       if ((p_ptr->esp_undead) && (r_ptr->flags3 & (RF3_UNDEAD)))
+                       {
+                               flag = TRUE;
+                               r_ptr->r_flags3 |= (RF3_UNDEAD);
+
+                       }
+
+                       /* Magical sensing */
+                       if ((p_ptr->esp_demon) && (r_ptr->flags3 & (RF3_DEMON)))
+                       {
+                               flag = TRUE;
+                               r_ptr->r_flags3 |= (RF3_DEMON);
+
+                       }
+
+                       /* Magical sensing */
+                       if ((p_ptr->esp_orc) && (r_ptr->flags3 & (RF3_ORC)))
+                       {
+                               flag = TRUE;
+                               r_ptr->r_flags3 |= (RF3_ORC);
+
+                       }
+
+                       /* Magical sensing */
+                       if ((p_ptr->esp_troll) && (r_ptr->flags3 & (RF3_TROLL)))
+                       {
+                               flag = TRUE;
+                               r_ptr->r_flags3 |= (RF3_TROLL);
+
+                       }
+
+                       /* Magical sensing */
+                       if ((p_ptr->esp_giant) && (r_ptr->flags3 & (RF3_GIANT)))
+                       {
+                               flag = TRUE;
+                               r_ptr->r_flags3 |= (RF3_GIANT);
+
+                       }
+
+                       /* Magical sensing */
+                       if ((p_ptr->esp_dragon) && (r_ptr->flags3 & (RF3_DRAGON)))
+                       {
+                               flag = TRUE;
+                               r_ptr->r_flags3 |= (RF3_DRAGON);
+
+                       }
+
+                       /* Magical sensing */
+                       if ((p_ptr->esp_human) && (r_ptr->flags2 & (RF2_HUMAN)))
+                       {
+                               flag = TRUE;
+                               r_ptr->r_flags2 |= (RF2_HUMAN);
+
+                       }
+
+                       /* Magical sensing */
+                       if ((p_ptr->esp_evil) && (r_ptr->flags3 & (RF3_EVIL)))
+                       {
+                               flag = TRUE;
+                               r_ptr->r_flags3 |= (RF3_EVIL);
+
+                       }
+
+                       /* Magical sensing */
+                       if ((p_ptr->esp_good) && (r_ptr->flags3 & (RF3_GOOD)))
+                       {
+                               flag = TRUE;
+                               r_ptr->r_flags3 |= (RF3_GOOD);
+
+                       }
+
+                       /* Magical sensing */
+                       if ((p_ptr->esp_nonliving) && 
+                           (r_ptr->flags3 & (RF3_NONLIVING)) &&
+                           !(r_ptr->flags3 & (RF3_DEMON)) &&
+                           !(r_ptr->flags3 & (RF3_UNDEAD)))
+                       {
+                               flag = TRUE;
+                               r_ptr->r_flags3 |= (RF3_NONLIVING);
+
+                       }
+
+                       /* Magical sensing */
+                       if ((p_ptr->esp_unique) && (r_ptr->flags1 & (RF1_UNIQUE)))
+                       {
+                               flag = TRUE;
+                               r_ptr->r_flags1 |= (RF1_UNIQUE);
+
+                       }
                }
 
                /* Normal line of sight, and not blind */
@@ -2335,9 +2598,10 @@ void update_mon(int m_idx, bool full)
                        if (p_ptr->riding == m_idx) p_ptr->redraw |= (PR_UHEALTH);
 
                        /* Hack -- Count "fresh" sightings */
-                       if ((m_ptr->mflag2 & MFLAG_KAGE) && (r_info[MON_KAGE].r_sights < MAX_SHORT))
+                       if ((m_ptr->ap_r_idx == MON_KAGE) && (r_info[MON_KAGE].r_sights < MAX_SHORT))
                                r_info[MON_KAGE].r_sights++;
-                       else if (r_ptr->r_sights < MAX_SHORT) r_ptr->r_sights++;
+                       else if (m_ptr->ap_r_idx == m_ptr->r_idx && 
+                                r_ptr->r_sights < MAX_SHORT) r_ptr->r_sights++;
 
                        /* Eldritch Horror */
                        if (r_ptr->flags2 & RF2_ELDRITCH_HORROR)
@@ -2371,7 +2635,7 @@ void update_mon(int m_idx, bool full)
                        if (p_ptr->riding == m_idx) p_ptr->redraw |= (PR_UHEALTH);
 
                        /* Disturb on disappearance */
-                       if (disturb_move)
+                       if (do_disturb)
                        {
                                if (disturb_pets || is_hostile(m_ptr))
                                        disturb(1, 0);
@@ -2390,7 +2654,7 @@ void update_mon(int m_idx, bool full)
                        m_ptr->mflag |= (MFLAG_VIEW);
 
                        /* Disturb on appearance */
-                       if (disturb_move)
+                       if (do_disturb)
                        {
                                if (disturb_pets || is_hostile(m_ptr))
                                        disturb(1, 0);
@@ -2408,7 +2672,7 @@ void update_mon(int m_idx, bool full)
                        m_ptr->mflag &= ~(MFLAG_VIEW);
 
                        /* Disturb on disappearance */
-                       if (disturb_move)
+                       if (do_disturb)
                        {
                                if (disturb_pets || is_hostile(m_ptr))
                                        disturb(1, 0);
@@ -2439,9 +2703,14 @@ void update_monsters(bool full)
 }
 
 
+/*
+ * Hack -- the index of the summoning monster
+ */
 static bool monster_hook_chameleon_lord(int r_idx)
 {
        monster_race *r_ptr = &r_info[r_idx];
+       monster_type *m_ptr = &m_list[chameleon_change_m_idx];
+       monster_race *old_r_ptr = &r_info[m_ptr->r_idx];
 
        if (!(r_ptr->flags1 & (RF1_UNIQUE))) return FALSE;
        if (r_ptr->flags7 & (RF7_FRIENDLY | RF7_CHAMELEON)) return FALSE;
@@ -2451,12 +2720,32 @@ static bool monster_hook_chameleon_lord(int r_idx)
        if ((r_ptr->blow[0].method == RBM_EXPLODE) || (r_ptr->blow[1].method == RBM_EXPLODE) || (r_ptr->blow[2].method == RBM_EXPLODE) || (r_ptr->blow[3].method == RBM_EXPLODE))
                return FALSE;
 
+       if (!monster_can_cross_terrain(cave[m_ptr->fy][m_ptr->fx].feat, r_ptr)) return FALSE;
+
+       /* Not born */
+       if (!(old_r_ptr->flags7 & RF7_CHAMELEON))
+       {
+               if ((m_ptr->sub_align & SUB_ALIGN_EVIL) && (r_ptr->flags3 & RF3_GOOD)) return FALSE;
+               if ((m_ptr->sub_align & SUB_ALIGN_GOOD) && (r_ptr->flags3 & RF3_EVIL)) return FALSE;
+       }
+
+       /* Born now */
+       else if (summon_specific_who > 0)
+       {
+               monster_type *sm_ptr = &m_list[summon_specific_who];
+
+               if ((sm_ptr->sub_align & SUB_ALIGN_EVIL) && (r_ptr->flags3 & RF3_GOOD)) return FALSE;
+               if ((sm_ptr->sub_align & SUB_ALIGN_GOOD) && (r_ptr->flags3 & RF3_EVIL)) return FALSE;
+       }
+
        return TRUE;
 }
 
 static bool monster_hook_chameleon(int r_idx)
 {
        monster_race *r_ptr = &r_info[r_idx];
+       monster_type *m_ptr = &m_list[chameleon_change_m_idx];
+       monster_race *old_r_ptr = &r_info[m_ptr->r_idx];
 
        if (r_ptr->flags1 & (RF1_UNIQUE)) return FALSE;
        if (r_ptr->flags2 & RF2_MULTIPLY) return FALSE;
@@ -2465,21 +2754,39 @@ static bool monster_hook_chameleon(int r_idx)
        if ((r_ptr->blow[0].method == RBM_EXPLODE) || (r_ptr->blow[1].method == RBM_EXPLODE) || (r_ptr->blow[2].method == RBM_EXPLODE) || (r_ptr->blow[3].method == RBM_EXPLODE))
                return FALSE;
 
+       if (!monster_can_cross_terrain(cave[m_ptr->fy][m_ptr->fx].feat, r_ptr)) return FALSE;
+
+       /* Not born */
+       if (!(old_r_ptr->flags7 & RF7_CHAMELEON))
+       {
+               if ((old_r_ptr->flags3 & RF3_GOOD) && !(r_ptr->flags3 & RF3_GOOD)) return FALSE;
+               if ((old_r_ptr->flags3 & RF3_EVIL) && !(r_ptr->flags3 & RF3_EVIL)) return FALSE;
+               if (!(old_r_ptr->flags3 & (RF3_GOOD | RF3_EVIL)) && (r_ptr->flags3 & (RF3_GOOD | RF3_EVIL))) return FALSE;
+       }
+
+       /* Born now */
+       else if (summon_specific_who > 0)
+       {
+               monster_type *sm_ptr = &m_list[summon_specific_who];
+
+               if ((sm_ptr->sub_align & SUB_ALIGN_EVIL) && (r_ptr->flags3 & RF3_GOOD)) return FALSE;
+               if ((sm_ptr->sub_align & SUB_ALIGN_GOOD) && (r_ptr->flags3 & RF3_EVIL)) return FALSE;
+       }
+
        return (*(get_monster_hook()))(r_idx);
 }
 
 
 void choose_new_monster(int m_idx, bool born, int r_idx)
 {
-       int attempt = 5000;
        int oldmaxhp, i;
        monster_type *m_ptr = &m_list[m_idx];
        monster_race *r_ptr;
        char old_m_name[80];
-       int old_r_idx = m_ptr->r_idx;
        bool old_unique = FALSE;
 
-       if (r_info[m_ptr->r_idx].flags1 & RF1_UNIQUE) old_unique = TRUE;
+       if (r_info[m_ptr->r_idx].flags1 & RF1_UNIQUE)
+               old_unique = TRUE;
        if (old_unique && (r_idx == MON_CHAMELEON)) r_idx = MON_CHAMELEON_K;
        r_ptr = &r_info[r_idx];
 
@@ -2487,44 +2794,47 @@ void choose_new_monster(int m_idx, bool born, int r_idx)
 
        if (!r_idx)
        {
-               chameleon_change = TRUE;
+               int level;
+
+               chameleon_change_m_idx = m_idx;
                if (old_unique)
                        get_mon_num_prep(monster_hook_chameleon_lord, NULL);
                else
                        get_mon_num_prep(monster_hook_chameleon, NULL);
 
-               while (attempt--)
-               {
-                       int level;
+               if (old_unique)
+                       level = r_info[MON_CHAMELEON_K].level;
+               else if (!dun_level)
+                       level = wilderness[p_ptr->wilderness_y][p_ptr->wilderness_x].level;
+               else
+                       level = dun_level;
 
-                       if (old_unique)
-                               level = r_info[MON_CHAMELEON_K].level;
-                       else if (!dun_level)
-                               level = wilderness[p_ptr->wilderness_y][p_ptr->wilderness_x].level;
-                       else
-                               level = dun_level;
+               if (d_info[dungeon_type].flags1 & DF1_CHAMELEON) level+= 2+randint1(3);
+
+               r_idx = get_mon_num(level);
+               r_ptr = &r_info[r_idx];
 
-                       if (d_info[dungeon_type].flags1 & DF1_CHAMELEON) level+= 2+randint(3);
-                       r_idx = get_mon_num(level);
-                       r_ptr = &r_info[r_idx];
+               chameleon_change_m_idx = 0;
 
-                       if (!monster_can_cross_terrain(cave[m_ptr->fy][m_ptr->fx].feat, r_ptr)) continue;
-                       if (!born && !old_unique)
-                       {
-                               if ((r_info[old_r_idx].flags3 & RF3_GOOD) && !(r_ptr->flags3 & RF3_GOOD)) continue;
-                               if ((r_info[old_r_idx].flags3 & RF3_EVIL) && !(r_ptr->flags3 & RF3_EVIL)) continue;
-                               if (!(r_info[old_r_idx].flags3 & (RF3_GOOD | RF3_EVIL)) && (r_ptr->flags3 & (RF3_GOOD | RF3_EVIL))) continue;
-                       }
-                       break;
-               }
-               chameleon_change = FALSE;
-               if (!attempt) return;
+               /* Paranoia */
+               if (!r_idx) return;
        }
 
        m_ptr->r_idx = r_idx;
+       m_ptr->ap_r_idx = r_idx;
        update_mon(m_idx, FALSE);
        lite_spot(m_ptr->fy, m_ptr->fx);
-       if (born) return;
+       if (born)
+       {
+               /* Sub-alignment of a chameleon */
+               if (r_ptr->flags3 & (RF3_EVIL | RF3_GOOD))
+               {
+                       m_ptr->sub_align = SUB_ALIGN_NEUTRAL;
+                       if (r_ptr->flags3 & RF3_EVIL) m_ptr->sub_align |= SUB_ALIGN_EVIL;
+                       if (r_ptr->flags3 & RF3_GOOD) m_ptr->sub_align |= SUB_ALIGN_GOOD;
+               }
+               return;
+       }
 
        if (m_idx == p_ptr->riding)
        {
@@ -2547,7 +2857,7 @@ void choose_new_monster(int m_idx, bool born, int r_idx)
        m_ptr->mspeed = r_ptr->speed;
        /* Hack -- small racial variety */
        /* Allow some small variation per monster */
-       if(rand_int(4) == 1){
+       if(one_in_(4)){
                i = extract_energy[r_ptr->speed] / 3;
                if (i) m_ptr->mspeed += rand_spread(0, i);
        }
@@ -2572,6 +2882,50 @@ void choose_new_monster(int m_idx, bool born, int r_idx)
 
 
 /*
+ *  Hook for Tanuki
+ */
+static bool monster_hook_tanuki(int r_idx)
+{
+       monster_race *r_ptr = &r_info[r_idx];
+
+       if (r_ptr->flags1 & (RF1_UNIQUE)) return FALSE;
+       if (r_ptr->flags2 & RF2_MULTIPLY) return FALSE;
+       if (r_ptr->flags7 & (RF7_FRIENDLY | RF7_CHAMELEON)) return FALSE;
+       if (r_ptr->flags7 & RF7_AQUATIC) return FALSE;
+       
+       if ((r_ptr->blow[0].method == RBM_EXPLODE) || (r_ptr->blow[1].method == RBM_EXPLODE) || (r_ptr->blow[2].method == RBM_EXPLODE) || (r_ptr->blow[3].method == RBM_EXPLODE))
+               return FALSE;
+
+       return (*(get_monster_hook()))(r_idx);
+}
+
+
+/*
+ *  Set initial racial appearance of a monster
+ */
+static int initial_r_appearance(int r_idx)
+{
+       int attempts = 1000;
+
+       int ap_r_idx;
+       int min = MIN(base_level-5, 50);
+
+       if (!(r_info[r_idx].flags7 & RF7_TANUKI))
+               return r_idx;
+
+       get_mon_num_prep(monster_hook_tanuki, NULL);
+
+       while (--attempts)
+       {
+               ap_r_idx = get_mon_num(base_level + 10);
+               if (r_info[ap_r_idx].level >= min) return ap_r_idx;
+       }
+
+       return r_idx;
+}
+
+
+/*
  * Attempt to place a monster of the given race at the given location.
  *
  * To give the player a sporting chance, any monster that appears in
@@ -2590,7 +2944,7 @@ void choose_new_monster(int m_idx, bool born, int r_idx)
  * This is the only function which may place a monster in the dungeon,
  * except for the savefile loading code.
  */
-bool place_monster_one(int y, int x, int r_idx, bool slp, bool friendly, bool pet, bool no_pet)
+bool place_monster_one(int who, int y, int x, int r_idx, u32b mode)
 {
        int                     i;
        int rune_dam = 0;
@@ -2603,18 +2957,18 @@ bool place_monster_one(int y, int x, int r_idx, bool slp, bool friendly, bool pe
 
        cptr            name = (r_name + r_ptr->name);
 
-        /* DO NOT PLACE A MONSTER IN THE SMALL SCALE WILDERNESS !!! */
-        if(p_ptr->wild_mode) return FALSE;
+       /* DO NOT PLACE A MONSTER IN THE SMALL SCALE WILDERNESS !!! */
+       if(p_ptr->wild_mode) return FALSE;
 
        /* Verify location */
        if (!in_bounds(y, x)) return (FALSE);
 
        /* Require empty space (if not ghostly) */
        if (!(!dun_level && (cave[y][x].feat == FEAT_MOUNTAIN) && ((r_ptr->flags8 & RF8_WILD_MOUNTAIN) || (r_ptr->flags7 & RF7_CAN_FLY))) &&
-           !cave_empty_bold2(y, x) &&
+           !(cave_empty_bold2(y, x) || (mode & PM_IGNORE_TERRAIN)) &&
            !((r_ptr->flags2 & RF2_PASS_WALL) &&
-           !(cave_perma_bold(y, x) || cave[y][x].m_idx ||
-           ((y == py) && (x == px))))) return (FALSE);
+             !(cave_perma_bold(y, x) || cave[y][x].m_idx ||
+               ((y == py) && (x == px))))) return (FALSE);
 
        /* Paranoia */
        if (!r_idx) return (FALSE);
@@ -2622,18 +2976,12 @@ bool place_monster_one(int y, int x, int r_idx, bool slp, bool friendly, bool pe
        /* Paranoia */
        if (!r_ptr->name) return (FALSE);
 
-#if 0
-       /* Hack -- no creation on glyph of warding */
-       if (cave[y][x].feat == FEAT_GLYPH) return (FALSE);
-       if (cave[y][x].feat == FEAT_MINOR_GLYPH) return (FALSE);
-#endif
-
        /* Nor on the Pattern */
        if ((cave[y][x].feat >= FEAT_PATTERN_START)
         && (cave[y][x].feat <= FEAT_PATTERN_XTRA2))
                return (FALSE);
 
-       if (monster_terrain_sensitive &&
+       if (!(mode & PM_IGNORE_TERRAIN) &&
            !monster_can_cross_terrain(cave[y][x].feat, r_ptr))
        {
                return FALSE;
@@ -2696,9 +3044,9 @@ bool place_monster_one(int y, int x, int r_idx, bool slp, bool friendly, bool pe
        /* Access the location */
        c_ptr = &cave[y][x];
 
-       if (c_ptr->feat == FEAT_GLYPH)
+       if (is_glyph_grid(c_ptr))
        {
-               if (randint(BREAK_GLYPH) < (r_ptr->level+20))
+               if (randint1(BREAK_GLYPH) < (r_ptr->level+20))
                {
                        /* Describe observable breakage */
                        if (c_ptr->info & CAVE_MARK)
@@ -2715,9 +3063,8 @@ msg_print("
                        c_ptr->info &= ~(CAVE_MARK);
 
                        /* Break the rune */
-                       c_ptr->feat = floor_type[rand_int(100)];
-                       c_ptr->info &= ~(CAVE_MASK);
-                       c_ptr->info |= CAVE_FLOOR;
+                       c_ptr->info &= ~(CAVE_OBJECT);
+                       c_ptr->mimic = 0;
 
                        /* Notice */
                        note_spot(y, x);
@@ -2787,6 +3134,17 @@ msg_print("
 
        /* Save the race */
        m_ptr->r_idx = r_idx;
+       m_ptr->ap_r_idx = initial_r_appearance(r_idx);
+
+       /* Sub-alignment of a monster */
+       if ((who > 0) && !(r_ptr->flags3 & (RF3_EVIL | RF3_GOOD)))
+               m_ptr->sub_align = m_list[who].sub_align;
+       else
+       {
+               m_ptr->sub_align = SUB_ALIGN_NEUTRAL;
+               if (r_ptr->flags3 & RF3_EVIL) m_ptr->sub_align |= SUB_ALIGN_EVIL;
+               if (r_ptr->flags3 & RF3_GOOD) m_ptr->sub_align |= SUB_ALIGN_GOOD;
+       }
 
        /* Place the monster at the location */
        m_ptr->fy = y;
@@ -2801,8 +3159,7 @@ msg_print("
        /* Unknown distance */
        m_ptr->cdis = 0;
 
-       m_ptr->target_y = 0;
-       m_ptr->target_x = 0;
+       reset_target(m_ptr);
 
        m_ptr->nickname = 0;
 
@@ -2818,34 +3175,46 @@ msg_print("
                r_ptr = &r_info[m_ptr->r_idx];
                m_ptr->mflag2 |= MFLAG_CHAMELEON;
                rating++;
+
+               /* Hack - Set sub_align to neutral when the Chameleon Lord is generated as "GUARDIAN" */
+               if ((r_ptr->flags1 & RF1_UNIQUE) && (who <= 0))
+                       m_ptr->sub_align = SUB_ALIGN_NEUTRAL;
        }
-       else if (is_kage) m_ptr->mflag2 |= MFLAG_KAGE;
-       if (no_pet) m_ptr->mflag2 |= MFLAG_NOPET;
+       else if (is_kage)
+       {
+               m_ptr->ap_r_idx = MON_KAGE;
+               m_ptr->mflag2 |= MFLAG_KAGE;
+       }
+
+       if (mode & PM_NO_PET) m_ptr->mflag2 |= MFLAG_NOPET;
 
        /* Not visible */
        m_ptr->ml = FALSE;
 
        /* Pet? */
-       if (pet)
+       if (mode & PM_FORCE_PET)
        {
                set_pet(m_ptr);
        }
        /* Friendly? */
-       else if ((friendly || (r_ptr->flags7 & RF7_FRIENDLY)) &&
-                !(p_ptr->align >= 0 && (r_ptr->flags3 & RF3_EVIL)) &&
-                !(p_ptr->align < 0 && (r_ptr->flags3 & RF3_GOOD)))
+       else if ((r_ptr->flags7 & RF7_FRIENDLY) ||
+                (mode & PM_FORCE_FRIENDLY) || is_friendly_idx(who))
        {
-               set_friendly(m_ptr);
+               if (!(p_ptr->align >= 0 && (r_ptr->flags3 & RF3_EVIL)) &&
+                   !(p_ptr->align < 0 && (r_ptr->flags3 & RF3_GOOD)))
+               {
+                       set_friendly(m_ptr);
+               }
        }
 
        /* Assume no sleeping */
        m_ptr->csleep = 0;
 
        /* Enforce sleeping if needed */
-       if (slp && r_ptr->sleep && !ironman_nightmare)
+       if ((mode & PM_ALLOW_SLEEP) && r_ptr->sleep && !ironman_nightmare)
        {
                int val = r_ptr->sleep;
-               m_ptr->csleep = ((val * 2) + randint(val * 10));
+               m_ptr->csleep = ((val * 2) + randint1(val * 10));
        }
 
        /* Assign maximal hitpoints */
@@ -2881,7 +3250,7 @@ msg_print("
        if (!(r_ptr->flags1 & RF1_UNIQUE) && !p_ptr->inside_arena)
        {
                /* Allow some small variation per monster */
-         if(rand_int(4) == 1){
+         if(one_in_(4)){
                i = extract_energy[r_ptr->speed] / 3;
                if (i) m_ptr->mspeed += rand_spread(0, i);
          }
@@ -2891,15 +3260,19 @@ msg_print("
          }
        }
 
+       if (mode & PM_HASTE) m_ptr->fast = 100;
+
        if (m_ptr->mspeed > 199) m_ptr->mspeed = 199;
 
        /* Give a random starting energy */
-       m_ptr->energy = (byte)rand_int(100);
-
-       /* Nightmare monsters are more prepared */
-       if (ironman_nightmare)
+       if (!ironman_nightmare)
        {
-               m_ptr->energy *= 2;
+               m_ptr->energy_need = ENERGY_NEED() - (s16b)randint0(100);
+       }
+       else
+       {
+               /* Nightmare monsters are more prepared */
+               m_ptr->energy_need = ENERGY_NEED() - (s16b)randint0(100) * 2;
        }
 
        /* Force monster to wait for player, unless in Nightmare mode */
@@ -2924,12 +3297,16 @@ msg_print("
        update_mon(c_ptr->m_idx, TRUE);
 
 
-       /* Hack -- Count the monsters on the level */
-       if (m_ptr->mflag2 & MFLAG_CHAMELEON)
-               r_info[r_idx].cur_num++;
-       else
-               r_ptr->cur_num++;
+       /* Count the monsters on the level */
+       real_r_ptr(m_ptr)->cur_num++;
 
+       /*
+        * Memorize location of the unique monster in saved floors.
+        * A unique monster move from old saved floor.
+        */
+       if (character_dungeon &&
+           ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_UNIQUE_7)))
+               real_r_ptr(m_ptr)->floor_id = p_ptr->floor_id;
 
        /* Hack -- Count the number of "reproducers" */
        if (r_ptr->flags2 & RF2_MULTIPLY) num_repro++;
@@ -2940,9 +3317,12 @@ msg_print("
 
        if (p_ptr->warning && character_dungeon)
        {
-               cptr color;
                if (r_ptr->flags1 & RF1_UNIQUE)
                {
+                       cptr color;
+                       object_type *o_ptr;
+                       char o_name[MAX_NLEN];
+
                        if (r_ptr->level > p_ptr->lev + 30)
 #ifdef JP
                                color = "¹õ¤¯";
@@ -2953,7 +3333,7 @@ msg_print("
 #ifdef JP
                                color = "»ç¿§¤Ë";
 #else
-                               color = "perple";
+                               color = "purple";
 #endif
                        else if (r_ptr->level > p_ptr->lev + 5)
 #ifdef JP
@@ -2979,18 +3359,21 @@ msg_print("
 #else
                                color = "white";
 #endif
+
+                       o_ptr = choose_warning_item();
+                       object_desc(o_name, o_ptr, FALSE, 0);
 #ifdef JP
-                       msg_format("»ØÎؤÏ%s¸÷¤Ã¤¿¡£",color);
+                       msg_format("%s¤Ï%s¸÷¤Ã¤¿¡£",o_name, color);
 #else
-                       msg_format("Your ring glows %s.",color);
+                       msg_format("%s glows %s.",o_name, color);
 #endif
                }
        }
 
-       if (c_ptr->feat == FEAT_MINOR_GLYPH)
+       if (is_explosive_rune_grid(c_ptr))
        {
                /* Break the ward */
-               if (randint(BREAK_MINOR_GLYPH) > r_ptr->level)
+               if (randint1(BREAK_MINOR_GLYPH) > r_ptr->level)
                {
                        /* Describe observable breakage */
                        if (c_ptr->info & CAVE_MARK)
@@ -3001,7 +3384,7 @@ msg_print("
                                msg_print("The rune explodes!");
 #endif
 
-                               project(0, 2, y, x, 2 * (p_ptr->lev + damroll(7, 7)), GF_MANA, (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP | PROJECT_NO_REF | PROJECT_NO_HANGEKI), -1);
+                               project(0, 2, y, x, 2 * (p_ptr->lev + damroll(7, 7)), GF_MANA, (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP | PROJECT_NO_HANGEKI), -1);
                        }
                }
                else
@@ -3017,9 +3400,9 @@ msg_print("
                c_ptr->info &= ~(CAVE_MARK);
 
                /* Break the rune */
-               c_ptr->feat = floor_type[rand_int(100)];
-               c_ptr->info &= ~(CAVE_MASK);
-               c_ptr->info |= CAVE_FLOOR;
+               c_ptr->info &= ~(CAVE_OBJECT);
+               c_ptr->mimic = 0;
+
                note_spot(y, x);
                lite_spot(y, x);
        }
@@ -3062,13 +3445,7 @@ static bool mon_scatter(int *yp, int *xp, int y, int x, int max_dist)
                        if (!cave_empty_bold2(ny, nx)) continue;
                        if (cave[ny][nx].m_idx) continue;
                        if ((ny == py) && (nx == px)) continue;
-                       
-#if 0
-                       /* Hack -- no summon on glyph of warding */
-                       if (cave[ny][nx].feat == FEAT_GLYPH) continue;
-                       if (cave[ny][nx].feat == FEAT_MINOR_GLYPH) continue;
-#endif
-                       
+                                               
                        /* ... nor on the Pattern */
                        if ((cave[ny][nx].feat >= FEAT_PATTERN_START) &&
                            (cave[ny][nx].feat <= FEAT_PATTERN_XTRA2))
@@ -3112,7 +3489,7 @@ static bool mon_scatter(int *yp, int *xp, int y, int x, int max_dist)
 /*
  * Attempt to place a "group" of monsters around the given location
  */
-static bool place_monster_group(int y, int x, int r_idx, bool slp, bool friendly, bool pet, bool no_pet)
+static bool place_monster_group(int who, int y, int x, int r_idx, u32b mode)
 {
        monster_race *r_ptr = &r_info[r_idx];
 
@@ -3126,20 +3503,20 @@ static bool place_monster_group(int y, int x, int r_idx, bool slp, bool friendly
 
 
        /* Pick a group size */
-       total = randint(10);
+       total = randint1(10);
 
        /* Hard monsters, small groups */
        if (r_ptr->level > dun_level)
        {
                extra = r_ptr->level - dun_level;
-               extra = 0 - randint(extra);
+               extra = 0 - randint1(extra);
        }
 
        /* Easy monsters, large groups */
        else if (r_ptr->level < dun_level)
        {
                extra = dun_level - r_ptr->level;
-               extra = randint(extra);
+               extra = randint1(extra);
        }
 
        /* Hack -- limit group reduction */
@@ -3181,7 +3558,7 @@ static bool place_monster_group(int y, int x, int r_idx, bool slp, bool friendly
                        if (!cave_empty_bold2(my, mx)) continue;
 
                        /* Attempt to place another monster */
-                       if (place_monster_one(my, mx, r_idx, slp, friendly, pet, no_pet))
+                       if (place_monster_one(who, my, mx, r_idx, mode))
                        {
                                /* Add it to the "hack" set */
                                hack_y[hack_n] = my;
@@ -3204,6 +3581,7 @@ static bool place_monster_group(int y, int x, int r_idx, bool slp, bool friendly
  * Hack -- help pick an escort type
  */
 static int place_monster_idx = 0;
+static int place_monster_m_idx = 0;
 
 /*
  * Hack -- help pick an escort type
@@ -3211,6 +3589,7 @@ static int place_monster_idx = 0;
 static bool place_monster_okay(int r_idx)
 {
        monster_race *r_ptr = &r_info[place_monster_idx];
+       monster_type *m_ptr = &m_list[place_monster_m_idx];
 
        monster_race *z_ptr = &r_info[r_idx];
 
@@ -3230,8 +3609,8 @@ static bool place_monster_okay(int r_idx)
        if (place_monster_idx == r_idx) return (FALSE);
 
        /* Skip different alignment */
-       if (((r_ptr->flags3 & RF3_EVIL) && (z_ptr->flags3 & RF3_GOOD)) ||
-           ((r_ptr->flags3 & RF3_GOOD) && (r_ptr->flags3 & RF3_EVIL)))
+       if (((m_ptr->sub_align & SUB_ALIGN_EVIL) && (z_ptr->flags3 & RF3_GOOD)) ||
+           ((m_ptr->sub_align & SUB_ALIGN_GOOD) && (z_ptr->flags3 & RF3_EVIL)))
                return FALSE;
 
        if (r_ptr->flags7 & RF7_FRIENDLY)
@@ -3241,6 +3620,9 @@ static bool place_monster_okay(int r_idx)
                        return FALSE;
        }
 
+       if ((r_ptr->flags7 & RF7_CHAMELEON) && !(z_ptr->flags7 & RF7_CHAMELEON))
+               return FALSE;
+
        /* Okay */
        return (TRUE);
 }
@@ -3264,27 +3646,30 @@ static bool place_monster_okay(int r_idx)
  * Note the use of the new "monster allocation table" code to restrict
  * the "get_mon_num()" function to "legal" escort types.
  */
-bool place_monster_aux(int y, int x, int r_idx, bool slp, bool grp, bool friendly, bool pet, bool no_kage, bool no_pet)
+bool place_monster_aux(int who, int y, int x, int r_idx, u32b mode)
 {
        int             i;
        monster_race    *r_ptr = &r_info[r_idx];
 
-       if (one_in_(333) && !no_kage && !pet) is_kage = TRUE;
-       else is_kage = FALSE;
+       if (one_in_(333) && !(mode & PM_NO_KAGE) && !(mode & PM_FORCE_PET))
+               is_kage = TRUE;
+       else
+               is_kage = FALSE;
 
        /* Place one monster, or fail */
-       if (!place_monster_one(y, x, r_idx, slp, friendly, pet, no_pet)) return (FALSE);
+       if (!place_monster_one(who, y, x, r_idx, mode)) return (FALSE);
 
 
        /* Require the "group" flag */
-       if (!grp) return (TRUE);
+       if (!(mode & PM_ALLOW_GROUP)) return (TRUE);
 
+       place_monster_m_idx = hack_m_idx_ii;
 
        /* Friends for certain monsters */
        if (r_ptr->flags1 & (RF1_FRIENDS))
        {
                /* Attempt to place a group */
-               (void)place_monster_group(y, x, r_idx, slp, friendly, pet, no_pet);
+               (void)place_monster_group(who, y, x, r_idx, mode);
        }
 
 
@@ -3315,14 +3700,14 @@ bool place_monster_aux(int y, int x, int r_idx, bool slp, bool grp, bool friendl
                        if (!z) break;
 
                        /* Place a single escort */
-                       (void)place_monster_one(ny, nx, z, slp, friendly, pet, no_pet);
+                       (void)place_monster_one(place_monster_m_idx, ny, nx, z, mode);
 
                        /* Place a "group" of escorts if needed */
                        if ((r_info[z].flags1 & RF1_FRIENDS) ||
                            (r_ptr->flags1 & RF1_ESCORTS))
                        {
                                /* Place a group of monsters */
-                               (void)place_monster_group(ny, nx, z, slp, friendly, pet, no_pet);
+                               (void)place_monster_group(place_monster_m_idx, ny, nx, z, mode);
                        }
                }
        }
@@ -3337,7 +3722,7 @@ bool place_monster_aux(int y, int x, int r_idx, bool slp, bool grp, bool friendl
  *
  * Attempt to find a monster appropriate to the "monster_level"
  */
-bool place_monster(int y, int x, bool slp, bool grp)
+bool place_monster(int y, int x, u32b mode)
 {
        int r_idx;
 
@@ -3351,7 +3736,7 @@ bool place_monster(int y, int x, bool slp, bool grp)
        if (!r_idx) return (FALSE);
 
        /* Attempt to place the monster */
-       if (place_monster_aux(y, x, r_idx, slp, grp, FALSE, FALSE, FALSE, FALSE)) return (TRUE);
+       if (place_monster_aux(0, y, x, r_idx, mode)) return (TRUE);
 
        /* Oops */
        return (FALSE);
@@ -3389,35 +3774,31 @@ bool alloc_horde(int y, int x)
        }
        if (attempts < 1) return FALSE;
 
-       if (r_ptr->flags3 & RF3_GOOD) horde_align |= HORDE_NOEVIL;
-       if (r_ptr->flags3 & RF3_EVIL) horde_align |= HORDE_NOGOOD;
-
        attempts = 1000;
 
        while (--attempts)
        {
                /* Attempt to place the monster */
-               if (place_monster_aux(y, x, r_idx, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE)) break;
+               if (place_monster_aux(0, y, x, r_idx, 0L)) break;
        }
 
-       if (attempts < 1) {horde_align = 0;return FALSE;}
+       if (attempts < 1) return FALSE;
 
        m_idx = cave[y][x].m_idx;
 
        if (m_list[m_idx].mflag2 & MFLAG_CHAMELEON) r_ptr = &r_info[m_list[m_idx].r_idx];
        summon_kin_type = r_ptr->d_char;
 
-       for (attempts = randint(10) + 5; attempts; attempts--)
+       for (attempts = randint1(10) + 5; attempts; attempts--)
        {
                scatter(&cy, &cx, y, x, 5, 0);
 
-               (void)summon_specific(m_idx, cy, cx, dun_level + 5, SUMMON_KIN, TRUE, FALSE, FALSE, FALSE, FALSE);
+               (void)summon_specific(m_idx, cy, cx, dun_level + 5, SUMMON_KIN, PM_ALLOW_GROUP);
 
                y = cy;
                x = cx;
        }
 
-       horde_align = 0;
        return TRUE;
 }
 
@@ -3434,17 +3815,44 @@ bool alloc_horde(int y, int x)
  *
  * Use "monster_level" for the monster level
  */
-bool alloc_monster(int dis, bool slp)
+bool alloc_monster(int dis, u32b mode)
 {
        int                     y = 0, x = 0;
        int         attempts_left = 10000;
+       int guardian = d_info[dungeon_type].final_guardian;
+
+       /* Put an Guardian */
+       if(guardian && d_info[dungeon_type].maxdepth == dun_level && r_info[guardian].cur_num < r_info[guardian].max_num )
+       {
+               int oy;
+               int ox;
+               int try = 4000;
+
+               /* Find a good position */
+               while(try)
+               {
+                       /* Get a random spot */
+                       oy = randint1(cur_hgt - 4) + 2;
+                       ox = randint1(cur_wid - 4) + 2;
+
+                       /* Is it a good spot ? */
+                       if (cave_empty_bold2(oy, ox) && monster_can_cross_terrain(cave[oy][ox].feat, &r_info[guardian]))
+                       {
+                               /* Place the guardian */
+                               if (place_monster_aux(0, oy, ox, guardian, (PM_ALLOW_GROUP | PM_NO_KAGE | PM_NO_PET))) break;
+                       }
+                       /* One less try */
+                       try--;
+               }
+       }
+
 
        /* Find a legal, distant, unoccupied, space */
        while (attempts_left--)
        {
                /* Pick a location */
-               y = rand_int(cur_hgt);
-               x = rand_int(cur_wid);
+               y = randint0(cur_hgt);
+               x = randint0(cur_wid);
 
                /* Require empty floor grid (was "naked") */
                if (dun_level || (wilderness[p_ptr->wilderness_y][p_ptr->wilderness_x].terrain != TERRAIN_MOUNTAIN))
@@ -3477,7 +3885,7 @@ msg_print("
 
 
 #ifdef MONSTER_HORDES
-       if (randint(5000) <= dun_level)
+       if (randint1(5000) <= dun_level)
        {
                if (alloc_horde(y, x))
                {
@@ -3495,7 +3903,7 @@ if (cheat_hear) msg_print("
 #endif /* MONSTER_HORDES */
 
                /* Attempt to place the monster, allow groups */
-               if (place_monster(y, x, slp, TRUE)) return (TRUE);
+               if (place_monster(y, x, (mode | PM_ALLOW_GROUP))) return (TRUE);
 
 #ifdef MONSTER_HORDES
        }
@@ -3522,15 +3930,14 @@ static bool summon_specific_okay(int r_idx)
        if (summon_specific_who > 0)
        {
                monster_type *m_ptr = &m_list[summon_specific_who];
-               monster_race *s_ptr = &r_info[m_ptr->r_idx];
 
                /* Do not summon enemies */
 
                /* Friendly vs. opposite aligned normal or pet */
                if (((r_ptr->flags3 & RF3_EVIL) &&
-                         (s_ptr->flags3 & RF3_GOOD)) ||
+                         (m_ptr->sub_align & SUB_ALIGN_GOOD)) ||
                         ((r_ptr->flags3 & RF3_GOOD) &&
-                         (s_ptr->flags3 & RF3_EVIL)))
+                         (m_ptr->sub_align & SUB_ALIGN_EVIL)))
                {
                        return FALSE;
                }
@@ -3547,11 +3954,11 @@ static bool summon_specific_okay(int r_idx)
                /* Do not summon enemies of the pets */
                if ((p_ptr->align < -9) && (r_ptr->flags3 & RF3_GOOD))
                {
-                       if (!(one_in_((0-p_ptr->align)/2+1))) return FALSE;
+                       if (!one_in_((0-p_ptr->align)/2+1)) return FALSE;
                }
                else if ((p_ptr->align > 9) && (r_ptr->flags3 & RF3_EVIL))
                {
-                       if (!(one_in_(p_ptr->align/2+1))) return FALSE;
+                       if (!one_in_(p_ptr->align/2+1)) return FALSE;
                }
        }
 
@@ -3566,9 +3973,6 @@ static bool summon_specific_okay(int r_idx)
             ((p_ptr->align < -9) && (r_ptr->flags3 & RF3_GOOD))))
                return FALSE;
 
-       if ((horde_align & HORDE_NOGOOD) && (r_ptr->flags3 & RF3_GOOD)) return FALSE;
-       if ((horde_align & HORDE_NOEVIL) && (r_ptr->flags3 & RF3_EVIL)) return FALSE;
-
        if ((r_ptr->flags7 & RF7_CHAMELEON) && (d_info[dungeon_type].flags1 & DF1_CHAMELEON)) return TRUE;
 
        return (summon_specific_aux(r_idx));
@@ -3599,12 +4003,10 @@ static bool summon_specific_okay(int r_idx)
  *
  * Note that this function may not succeed, though this is very rare.
  */
-bool summon_specific(int who, int y1, int x1, int lev, int type, bool group, bool friendly, bool pet, bool unique_okay, bool no_pet)
+bool summon_specific(int who, int y1, int x1, int lev, int type, u32b mode)
 {
        int x, y, r_idx;
 
-       bool no_kage = FALSE;
-
        if (p_ptr->inside_arena) return (FALSE);
 
        if (!mon_scatter(&y, &x, y1, x1, 2)) return FALSE;
@@ -3615,10 +4017,10 @@ bool summon_specific(int who, int y1, int x1, int lev, int type, bool group, boo
        /* Save the "summon" type */
        summon_specific_type = type;
 
-       summon_unique_okay = unique_okay;
+       summon_unique_okay = (mode & PM_ALLOW_UNIQUE) ? TRUE : FALSE;
 
        /* Save the hostility */
-       summon_specific_hostile = (!friendly && !pet);
+       summon_specific_hostile = (!(mode & PM_FORCE_FRIENDLY) && !(is_friendly_idx(who)) && !(mode & PM_FORCE_PET));
 
        /* Prepare allocation table */
        get_mon_num_prep(summon_specific_okay, get_monster_hook2(y, x));
@@ -3633,10 +4035,10 @@ bool summon_specific(int who, int y1, int x1, int lev, int type, bool group, boo
                return (FALSE);
        }
 
-       if ((type == SUMMON_BLUE_HORROR) || (type == SUMMON_DAWN)) no_kage = TRUE;
+       if ((type == SUMMON_BLUE_HORROR) || (type == SUMMON_DAWN)) mode |= PM_NO_KAGE;
 
        /* Attempt to place the monster (awake, allow groups) */
-       if (!place_monster_aux(y, x, r_idx, FALSE, group, friendly, pet, no_kage, no_pet))
+       if (!place_monster_aux(who, y, x, r_idx, mode))
        {
                summon_specific_type = 0;
                return (FALSE);
@@ -3648,7 +4050,7 @@ bool summon_specific(int who, int y1, int x1, int lev, int type, bool group, boo
 }
 
 /* A "dangerous" function, creates a pet of the specified type */
-bool summon_named_creature (int oy, int ox, int r_idx, bool slp, bool group_ok, bool friendly, bool pet)
+bool summon_named_creature (int who, int oy, int ox, int r_idx, u32b mode)
 {
        int x, y;
 
@@ -3663,7 +4065,7 @@ bool summon_named_creature (int oy, int ox, int r_idx, bool slp, bool group_ok,
        if (!mon_scatter(&y, &x, oy, ox, 2)) return FALSE;
 
        /* Place it (allow groups) */
-       return place_monster_aux(y, x, r_idx, slp, group_ok, friendly, pet, TRUE, FALSE);
+       return place_monster_aux(who, y, x, r_idx, (mode | PM_NO_KAGE));
 }
 
 
@@ -3672,7 +4074,7 @@ bool summon_named_creature (int oy, int ox, int r_idx, bool slp, bool group_ok,
  *
  * Note that "reproduction" REQUIRES empty space.
  */
-bool multiply_monster(int m_idx, bool clone, bool friendly, bool pet)
+bool multiply_monster(int m_idx, bool clone, u32b mode)
 {
        monster_type    *m_ptr = &m_list[m_idx];
 
@@ -3681,8 +4083,10 @@ bool multiply_monster(int m_idx, bool clone, bool friendly, bool pet)
        if (!mon_scatter(&y, &x, m_ptr->fy, m_ptr->fx, 1))
                return FALSE;
 
+       if (m_ptr->mflag2 & MFLAG_NOPET) mode |= PM_NO_PET;
+
        /* Create a new monster (awake, no groups) */
-       if (!place_monster_aux(y, x, m_ptr->r_idx, FALSE, FALSE, friendly, pet, TRUE, (bool)(m_ptr->mflag2 & MFLAG_NOPET)))
+       if (!place_monster_aux(m_idx, y, x, m_ptr->r_idx, (mode | PM_NO_KAGE)))
                return FALSE;
 
        if (clone)
@@ -4428,7 +4832,7 @@ void update_smart_learn(int m_idx, int what)
        if (r_ptr->flags2 & (RF2_STUPID)) return;
 
        /* Not intelligent, only learn sometimes */
-       if (!(r_ptr->flags2 & (RF2_SMART)) && (rand_int(100) < 50)) return;
+       if (!(r_ptr->flags2 & (RF2_SMART)) && (randint0(100) < 50)) return;
 
 
        /* XXX XXX XXX */