OSDN Git Service

大鷲を強化。SPECIALの行動として、「@を掴んで空中から落す(=引き戻し+ダメージ2d8)」
[hengbandforosx/hengbandosx.git] / src / spells2.c
index 33b70f5..cbc0fe1 100644 (file)
@@ -51,7 +51,7 @@ void self_knowledge(void)
 
        strcpy(Dummy, "");
 
-       percent = (int)(((long)player_hp[PY_MAX_LEVEL - 1] * 200L) /
+       percent = (int)(((long)p_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
                (2 * p_ptr->hitdie +
                ((PY_MAX_LEVEL - 1+3) * (p_ptr->hitdie + 1))));
 
@@ -598,7 +598,7 @@ info[i++] = "
                        }
                        break;
                case CLASS_PRIEST:
-                       if (p_ptr->realm1 == REALM_LIFE)
+                       if (is_good_realm(p_ptr->realm1))
                        {
                                if (plev > 34)
                                {
@@ -642,7 +642,7 @@ info[i++] = "
                        }
                        break;
                case CLASS_PALADIN:
-                       if (p_ptr->realm1 == REALM_LIFE)
+                       if (is_good_realm(p_ptr->realm1))
                        {
                                if (plev > 29)
                                {
@@ -841,7 +841,7 @@ info[i++] = "
 #endif
                        break;
                case CLASS_NINJA:
-                       if (plev > 7)
+                       if (plev > 19)
                        {
 #ifdef JP
 info[i++] = "¤¢¤Ê¤¿¤ÏÁÇÁ᤯°ÜÆ°¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡£";
@@ -1778,7 +1778,7 @@ info[i++] = "
 #ifdef JP
 info[i++] = "¤¢¤Ê¤¿¤Ï¼Ù°­¤Ê±åÇ°¤ËÊñ¤Þ¤ì¤Æ¤¤¤ë¡£";
 #else
-               info[i++] = "You nanka.";
+               info[i++] = "You carry an ancient foul curse.";
 #endif
 
        }
@@ -1796,7 +1796,7 @@ info[i++] = "
 #ifdef JP
 info[i++] = "¤¢¤Ê¤¿¤Ï·Ð¸³ÃͤòµÛ¤ï¤ì¤Æ¤¤¤ë¡£";
 #else
-               info[i++] = "You nanka.";
+               info[i++] = "You are drained.";
 #endif
 
        }
@@ -1805,25 +1805,25 @@ info[i++] = "
 #ifdef JP
 info[i++] = "¤¢¤Ê¤¿¤Î²óÉüÎϤÏÈó¾ï¤ËÃÙ¤¤¡£";
 #else
-               info[i++] = "You nanka.";
+               info[i++] = "You regenerate slowly.";
 #endif
 
        }
        if (p_ptr->cursed & TRC_ADD_L_CURSE)
        {
 #ifdef JP
-info[i++] = "¤¢¤Ê¤¿¤Ï..."; /* nanka */
+info[i++] = "¤¢¤Ê¤¿¤Î¼å¤¤¼ö¤¤¤ÏÁý¤¨¤ë¡£"; /* »ÃÄêŪ -- henkma */
 #else
-               info[i++] = "You nanka.";
+               info[i++] = "Your weak curses multiply.";
 #endif
 
        }
        if (p_ptr->cursed & TRC_ADD_H_CURSE)
        {
 #ifdef JP
-info[i++] = "¤¢¤Ê¤¿¤Ï..."; /* nanka */
+info[i++] = "¤¢¤Ê¤¿¤Î¶¯¤¤¼ö¤¤¤ÏÁý¤¨¤ë¡£"; /* »ÃÄêŪ -- henkma */
 #else
-               info[i++] = "You nanka.";
+               info[i++] = "Your heavy curses multiply.";
 #endif
 
        }
@@ -1832,7 +1832,7 @@ info[i++] = "
 #ifdef JP
 info[i++] = "¤¢¤Ê¤¿¤Ïưʪ¤ËÁÀ¤ï¤ì¤Æ¤¤¤ë¡£";
 #else
-               info[i++] = "You nanka.";
+               info[i++] = "You attract animals.";
 #endif
 
        }
@@ -1841,7 +1841,7 @@ info[i++] = "
 #ifdef JP
 info[i++] = "¤¢¤Ê¤¿¤Ï°­Ëâ¤ËÁÀ¤ï¤ì¤Æ¤¤¤ë¡£";
 #else
-               info[i++] = "You nanka.";
+               info[i++] = "You attract demons.";
 #endif
 
        }
@@ -1850,7 +1850,7 @@ info[i++] = "
 #ifdef JP
 info[i++] = "¤¢¤Ê¤¿¤Ï¥É¥é¥´¥ó¤ËÁÀ¤ï¤ì¤Æ¤¤¤ë¡£";
 #else
-               info[i++] = "You nanka.";
+               info[i++] = "You attract dragons.";
 #endif
 
        }
@@ -1877,7 +1877,7 @@ info[i++] = "
 #ifdef JP
 info[i++] = "¤¢¤Ê¤¿¤ÎÉð´ï¤Ï¹¶·â¤ò³°¤·¤ä¤¹¤¤¡£";
 #else
-               info[i++] = "You nanka.";
+               info[i++] = "Your weapon causes you miss blows.";
 #endif
 
        }
@@ -1886,7 +1886,7 @@ info[i++] = "
 #ifdef JP
 info[i++] = "¤¢¤Ê¤¿¤Ï¹¶·â¤ò¼õ¤±¤ä¤¹¤¤¡£";
 #else
-               info[i++] = "You nanka.";
+               info[i++] = "You are subject to be hit.";
 #endif
 
        }
@@ -1895,7 +1895,7 @@ info[i++] = "
 #ifdef JP
 info[i++] = "¤¢¤Ê¤¿¤ÏËâË¡¤ò¼ºÇÔ¤·¤ä¤¹¤¤¡£";
 #else
-               info[i++] = "You nanka.";
+               info[i++] = "You are subject to fail spellcasting.";
 #endif
 
        }
@@ -1904,7 +1904,7 @@ info[i++] = "
 #ifdef JP
 info[i++] = "¤¢¤Ê¤¿¤Ï¤¹¤°¤ªÊ¢¤¬¤Ø¤ë¡£";
 #else
-               info[i++] = "You nanka.";
+               info[i++] = "You have a good appetite.";
 #endif
 
        }
@@ -1913,7 +1913,7 @@ info[i++] = "
 #ifdef JP
 info[i++] = "¤¢¤Ê¤¿¤ÏÂÎÎϤòµÛ¤ï¤ì¤Æ¤¤¤ë¡£";
 #else
-               info[i++] = "You nanka.";
+               info[i++] = "You are drained.";
 #endif
 
        }
@@ -1922,7 +1922,7 @@ info[i++] = "
 #ifdef JP
 info[i++] = "¤¢¤Ê¤¿¤ÏËâÎϤòµÛ¤ï¤ì¤Æ¤¤¤ë¡£";
 #else
-               info[i++] = "You nanka.";
+               info[i++] = "You brain is drained.";
 #endif
 
        }
@@ -2043,24 +2043,6 @@ info[i++] = "
 #endif
 
        }
-       if (p_ptr->special_attack & ATTACK_CONFUSE)
-       {
-#ifdef JP
-info[i++] = "¤¢¤Ê¤¿¤Î¼ê¤ÏÀÖ¤¯µ±¤¤¤Æ¤¤¤ë¡£";
-#else
-               info[i++] = "Your hands are glowing dull red.";
-#endif
-
-       }
-       if (p_ptr->special_attack & ATTACK_CONFUSE)
-       {
-#ifdef JP
-info[i++] = "¤¢¤Ê¤¿¤Î¼ê¤ÏÀÖ¤¯µ±¤¤¤Æ¤¤¤ë¡£";
-#else
-               info[i++] = "Your hands are glowing dull red.";
-#endif
-
-       }
        switch (p_ptr->action)
        {
                case ACTION_SEARCH:
@@ -2146,7 +2128,7 @@ info[i++] = "
        if (p_ptr->telepathy)
        {
 #ifdef JP
-info[i++] = "¤¢¤Ê¤¿¤ÏĶǽÎϤò»ý¤Ã¤Æ¤¤¤ë¡£";
+info[i++] = "¤¢¤Ê¤¿¤Ï¥Æ¥ì¥Ñ¥·¡¼Ç½ÎϤò»ý¤Ã¤Æ¤¤¤ë¡£";
 #else
                info[i++] = "You have ESP.";
 #endif
@@ -2197,6 +2179,24 @@ info[i++] = "
 #endif
 
        }
+       if (p_ptr->tim_sh_holy)
+       {
+#ifdef JP
+info[i++] = "¤¢¤Ê¤¿¤ÏÀ»¤Ê¤ë¥ª¡¼¥é¤ËÊñ¤Þ¤ì¤Æ¤¤¤ë¡£";
+#else
+               info[i++] = "You are surrounded with a holy aura.";
+#endif
+
+       }
+       if (p_ptr->tim_sh_touki)
+       {
+#ifdef JP
+info[i++] = "¤¢¤Ê¤¿¤ÏÆ®µ¤¤Î¥ª¡¼¥é¤ËÊñ¤Þ¤ì¤Æ¤¤¤ë¡£";
+#else
+               info[i++] = "You are surrounded with a energy aura.";
+#endif
+
+       }
        if (p_ptr->anti_magic)
        {
 #ifdef JP
@@ -2850,6 +2850,15 @@ info[i++] = "
 #endif
 
                }
+               if (f3 & (TR3_SLAY_HUMAN))
+               {
+#ifdef JP
+info[i++] = "¤¢¤Ê¤¿¤ÎÉð´ï¤Ï¿Í´Ö¤ËÂФ·¤ÆÆä˶¯¤¤ÎϤòȯ´ø¤¹¤ë¡£";
+#else
+                       info[i++] = "Your weapon is especially deadly against humans.";
+#endif
+
+               }
                if (f1 & (TR1_SLAY_UNDEAD))
                {
 #ifdef JP
@@ -3314,11 +3323,24 @@ bool detect_traps(int range)
        {
                for (x = 1; x <= cur_wid - 1; x++)
                {
-                       if (distance(py, px, y, x) > range) continue;
+                       int dist = distance(py, px, y, x);
+                       if (dist > range) continue;
 
                        /* Access the grid */
                        c_ptr = &cave[y][x];
 
+                       /* Mark as detected */
+                       if (dist <= range)
+                       {
+                               if (dist <= range - 1)
+                                       c_ptr->info |= (CAVE_IN_DETECT);
+
+                               c_ptr->info &= ~(CAVE_UNSAFE);
+
+                               /* Redraw */
+                               lite_spot(y, x);
+                       }
+
                        /* Detect invisible traps */
                        if (c_ptr->info & CAVE_TRAP)
                        {
@@ -3341,6 +3363,8 @@ bool detect_traps(int range)
                }
        }
 
+       p_ptr->dtrap = TRUE;
+
        if ((p_ptr->pclass == CLASS_BARD) && (p_ptr->magic_num1[0] > MUSIC_DETECT)) detect = FALSE;
 
        /* Describe */
@@ -3743,6 +3767,7 @@ bool detect_objects_magic(int range)
                        (tv == TV_ARCANE_BOOK) ||
                        (tv == TV_ENCHANT_BOOK) ||
                        (tv == TV_DAEMON_BOOK) ||
+                       (tv == TV_CRUSADE_BOOK) ||
                        (tv == TV_MUSIC_BOOK) ||
                        (tv == TV_HISSATSU_BOOK) ||
                    ((o_ptr->to_a > 0) || (o_ptr->to_h + o_ptr->to_d > 0)))
@@ -4458,6 +4483,15 @@ bool dispel_demons(int dam)
 
 
 /*
+ * Crusade
+ */
+bool crusade(void)
+{
+       return (project_hack(GF_CRUSADE, p_ptr->lev*4));
+}
+
+
+/*
  * Wake up all monsters, and speed up "los" monsters.
  */
 void aggravate_monsters(int who)
@@ -4924,6 +4958,7 @@ bool probing(void)
        int cu, cv;
        bool    probe = FALSE;
        char buf[256];
+       cptr align;
 
        cu = Term->scr->cu;
        cv = Term->scr->cv;
@@ -4954,9 +4989,12 @@ bool probing(void)
                        if (!probe) {msg_print("Probing...");msg_print(NULL);}
 #endif
 
-                       if (m_ptr->mflag2 & MFLAG_KAGE)
+                       if (m_ptr->ap_r_idx != m_ptr->r_idx)
                        {
-                               m_ptr->mflag2 &= ~(MFLAG_KAGE);
+                               if (m_ptr->mflag2 & MFLAG_KAGE)
+                                       m_ptr->mflag2 &= ~(MFLAG_KAGE);
+
+                               m_ptr->ap_r_idx = m_ptr->r_idx;
                                lite_spot(m_ptr->fy, m_ptr->fx);
                        }
                        /* Get "the monster" or "something" */
@@ -4965,11 +5003,31 @@ bool probing(void)
                        speed = m_ptr->mspeed - 110;
                        if(m_ptr->fast) speed += 10;
                        if(m_ptr->slow) speed -= 10;
+
+                       /* Get the monster's alignment */
+#ifdef JP
+                       if ((r_ptr->flags3 & RF3_EVIL) && (r_ptr->flags3 & RF3_GOOD)) align = "Á±°­";
+                       else if (r_ptr->flags3 & RF3_EVIL) align = "¼Ù°­";
+                       else if (r_ptr->flags3 & RF3_GOOD) align = "Á±ÎÉ";
+                       else if ((m_ptr->sub_align & SUB_ALIGN_EVIL) && (m_ptr->sub_align & SUB_ALIGN_GOOD)) align = "ÃæΩ(Á±°­)";
+                       else if (m_ptr->sub_align & SUB_ALIGN_EVIL) align = "ÃæΩ(¼Ù°­)";
+                       else if (m_ptr->sub_align & SUB_ALIGN_GOOD) align = "ÃæΩ(Á±ÎÉ)";
+                       else align = "ÃæΩ";
+#else
+                       if ((r_ptr->flags3 & RF3_EVIL) && (r_ptr->flags3 & RF3_GOOD)) align = "good&evil";
+                       else if (r_ptr->flags3 & RF3_EVIL) align = "evil";
+                       else if (r_ptr->flags3 & RF3_GOOD) align = "good";
+                       else if ((m_ptr->sub_align & SUB_ALIGN_EVIL) && (m_ptr->sub_align & SUB_ALIGN_GOOD)) align = "neutral(good&evil)";
+                       else if (m_ptr->sub_align & SUB_ALIGN_EVIL) align = "neutral(evil)";
+                       else if (m_ptr->sub_align & SUB_ALIGN_GOOD) align = "neutral(good)";
+                       else align = "neutral";
+#endif
+
                        /* Describe the monster */
 #ifdef JP
-sprintf(buf,"%s ... HP:%d/%d AC:%d Â®ÅÙ:%s%d ·Ð¸³:", m_name, m_ptr->hp, m_ptr->maxhp, r_ptr->ac, (speed > 0) ? "+" : "", speed);
+sprintf(buf,"%s ... Â°À­:%s HP:%d/%d AC:%d Â®ÅÙ:%s%d ·Ð¸³:", m_name, align, m_ptr->hp, m_ptr->maxhp, r_ptr->ac, (speed > 0) ? "+" : "", speed);
 #else
-sprintf(buf, "%s ... HP:%d/%d AC:%d speed:%s%d exp:", m_name, m_ptr->hp, m_ptr->maxhp, r_ptr->ac, (speed > 0) ? "+" : "", speed);
+sprintf(buf, "%s ... align:%s HP:%d/%d AC:%d speed:%s%d exp:", m_name, align, m_ptr->hp, m_ptr->maxhp, r_ptr->ac, (speed > 0) ? "+" : "", speed);
 #endif
                        if (r_ptr->next_r_idx)
                        {
@@ -5081,7 +5139,7 @@ bool destroy_area(int y1, int x1, int r, int full)
                        r_ptr = &r_info[m_ptr->r_idx];
 
                        /* Lose room and vault */
-                       c_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY | CAVE_TRAP);
+                       c_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY | CAVE_TRAP | CAVE_UNSAFE | CAVE_IN_MIRROR);
 
                        /* Lose light and knowledge */
                        c_ptr->info &= ~(CAVE_MARK | CAVE_GLOW);
@@ -5184,8 +5242,6 @@ bool destroy_area(int y1, int x1, int r, int full)
                                {
                                        /* Create floor */
                                        c_ptr->feat = floor_type[randint0(100)];
-                                       c_ptr->info &= ~(CAVE_MASK);
-                                       c_ptr->info |= CAVE_FLOOR;
                                }
                        }
                }
@@ -5298,7 +5354,7 @@ bool earthquake(int cy, int cx, int r)
                        c_ptr = &cave[yy][xx];
 
                        /* Lose room and vault */
-                       c_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY | CAVE_TRAP);
+                       c_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY | CAVE_TRAP | CAVE_UNSAFE | CAVE_IN_MIRROR );
 
                        /* Lose light and knowledge */
                        c_ptr->info &= ~(CAVE_GLOW | CAVE_MARK);
@@ -5691,8 +5747,6 @@ msg_format("%^s
                                {
                                        /* Create floor */
                                        c_ptr->feat = floor_type[randint0(100)];
-                                       c_ptr->info &= ~(CAVE_MASK);
-                                       c_ptr->info |= CAVE_FLOOR;
                                }
                        }
                }
@@ -5898,7 +5952,7 @@ static void cave_temp_room_unlite(void)
                c_ptr->info &= ~(CAVE_TEMP);
 
                /* Darken the grid */
-               c_ptr->info &= ~(CAVE_GLOW);
+               if (!(c_ptr->info & CAVE_IN_MIRROR ))c_ptr->info &= ~(CAVE_GLOW);
 
                /* Hack -- Forget "boring" grids */
                if ((c_ptr->feat <= FEAT_INVIS) || (c_ptr->feat == FEAT_DIRT) || (c_ptr->feat == FEAT_GRASS))
@@ -5928,15 +5982,70 @@ static void cave_temp_room_unlite(void)
 
 
 /*
+ * Determine how much contiguous open space this grid is next to
+ */
+static int next_to_open(int cy, int cx)
+{
+       int i;
+
+       int y, x;
+
+       int len = 0;
+       int blen = 0;
+
+       for (i = 0; i < 16; i++)
+       {
+               y = cy + ddy_cdd[i % 8];
+               x = cx + ddx_cdd[i % 8];
+
+               /* Found a wall, break the length */
+               if (!cave_floor_bold(y, x))
+               {
+                       /* Track best length */
+                       if (len > blen)
+                       {
+                               blen = len;
+                       }
+
+                       len = 0;
+               }
+               else
+               {
+                       len++;
+               }
+       }
+
+       return (MAX(len, blen));
+}
+
+
+static int next_to_walls_adj(int cy, int cx)
+{
+       int i;
+
+       int y, x;
+
+       int c = 0;
+
+       for (i = 0; i < 8; i++)
+       {
+               y = cy + ddy_ddd[i];
+               x = cx + ddx_ddd[i];
+
+               if (!cave_floor_bold(y, x)) c++;
+       }
+
+       return c;
+}
+
+
+/*
  * Aux function -- see below
  */
-static void cave_temp_room_aux(int y, int x)
+static void cave_temp_room_aux(int y, int x, bool only_room)
 {
        cave_type *c_ptr;
 
-       /* Verify */
-/*     if (!in_bounds(y, x)) return; */
-
        /* Get the grid */
        c_ptr = &cave[y][x];
 
@@ -5944,7 +6053,30 @@ static void cave_temp_room_aux(int y, int x)
        if (c_ptr->info & (CAVE_TEMP)) return;
 
        /* Do not "leave" the current room */
-       if (!(c_ptr->info & (CAVE_ROOM))) return;
+       if (!(c_ptr->info & (CAVE_ROOM)))
+       {
+               if (only_room) return;
+
+               /* Verify */
+               if (!in_bounds(y, x)) return;
+
+               /* If a wall, exit */
+               if (!cave_floor_bold(y, x)) return;
+
+               /* Do not exceed the maximum spell range */
+               if (distance(py, px, y, x) > MAX_RANGE) return;
+
+               /* Verify this grid */
+               /*
+                * The reason why it is ==6 instead of >5 is that 8 is impossible
+                * due to the check for cave_bold above.
+                * 7 lights dead-end corridors (you need to do this for the
+                * checkboard interesting rooms, so that the boundary is lit
+                * properly.
+                * This leaves only a check for 6 bounding walls!
+                */
+               if ((next_to_walls_adj(y, x) == 6) && (next_to_open(y, x) <= 1)) return;
+       }
 
        /* Paranoia -- verify space */
        if (temp_n == TEMP_MAX) return;
@@ -5958,6 +6090,22 @@ static void cave_temp_room_aux(int y, int x)
        temp_n++;
 }
 
+/*
+ * Aux function -- see below
+ */
+static void cave_temp_lite_room_aux(int y, int x)
+{
+       cave_temp_room_aux(y, x, FALSE);
+}
+
+/*
+ * Aux function -- see below
+ */
+static void cave_temp_unlite_room_aux(int y, int x)
+{
+       cave_temp_room_aux(y, x, TRUE);
+}
+
 
 
 
@@ -5969,7 +6117,7 @@ void lite_room(int y1, int x1)
        int i, x, y;
 
        /* Add the initial grid */
-       cave_temp_room_aux(y1, x1);
+       cave_temp_lite_room_aux(y1, x1);
 
        /* While grids are in the queue, add their neighbors */
        for (i = 0; i < temp_n; i++)
@@ -5980,16 +6128,16 @@ void lite_room(int y1, int x1)
                if (!cave_floor_bold(y, x)) continue;
 
                /* Spread adjacent */
-               cave_temp_room_aux(y + 1, x);
-               cave_temp_room_aux(y - 1, x);
-               cave_temp_room_aux(y, x + 1);
-               cave_temp_room_aux(y, x - 1);
+               cave_temp_lite_room_aux(y + 1, x);
+               cave_temp_lite_room_aux(y - 1, x);
+               cave_temp_lite_room_aux(y, x + 1);
+               cave_temp_lite_room_aux(y, x - 1);
 
                /* Spread diagonal */
-               cave_temp_room_aux(y + 1, x + 1);
-               cave_temp_room_aux(y - 1, x - 1);
-               cave_temp_room_aux(y - 1, x + 1);
-               cave_temp_room_aux(y + 1, x - 1);
+               cave_temp_lite_room_aux(y + 1, x + 1);
+               cave_temp_lite_room_aux(y - 1, x - 1);
+               cave_temp_lite_room_aux(y - 1, x + 1);
+               cave_temp_lite_room_aux(y + 1, x - 1);
        }
 
        /* Now, lite them all up at once */
@@ -6005,7 +6153,7 @@ void unlite_room(int y1, int x1)
        int i, x, y;
 
        /* Add the initial grid */
-       cave_temp_room_aux(y1, x1);
+       cave_temp_unlite_room_aux(y1, x1);
 
        /* Spread, breadth first */
        for (i = 0; i < temp_n; i++)
@@ -6016,16 +6164,16 @@ void unlite_room(int y1, int x1)
                if (!cave_floor_bold(y, x)) continue;
 
                /* Spread adjacent */
-               cave_temp_room_aux(y + 1, x);
-               cave_temp_room_aux(y - 1, x);
-               cave_temp_room_aux(y, x + 1);
-               cave_temp_room_aux(y, x - 1);
+               cave_temp_unlite_room_aux(y + 1, x);
+               cave_temp_unlite_room_aux(y - 1, x);
+               cave_temp_unlite_room_aux(y, x + 1);
+               cave_temp_unlite_room_aux(y, x - 1);
 
                /* Spread diagonal */
-               cave_temp_room_aux(y + 1, x + 1);
-               cave_temp_room_aux(y - 1, x - 1);
-               cave_temp_room_aux(y - 1, x + 1);
-               cave_temp_room_aux(y + 1, x - 1);
+               cave_temp_unlite_room_aux(y + 1, x + 1);
+               cave_temp_unlite_room_aux(y - 1, x - 1);
+               cave_temp_unlite_room_aux(y - 1, x + 1);
+               cave_temp_unlite_room_aux(y + 1, x - 1);
        }
 
        /* Now, darken them all at once */
@@ -6214,6 +6362,59 @@ bool fire_meteor(int who, int typ, int y, int x, int dam, int rad)
 }
 
 
+bool fire_blast(int typ, int dir, int dd, int ds, int num, int dev)
+{
+       int ly, lx, ld;
+       int ty, tx, y, x;
+       int i;
+
+       int flg = PROJECT_FAST | PROJECT_THRU | PROJECT_STOP | PROJECT_KILL | PROJECT_GRID;
+
+       /* Assume okay */
+       bool result = TRUE;
+
+       /* Use the given direction */
+       if (dir != 5)
+       {
+               ly = ty = py + 20 * ddy[dir];
+               lx = tx = px + 20 * ddx[dir];
+       }
+
+       /* Use an actual "target" */
+       else if (dir == 5)
+       {
+               tx = target_col;
+               ty = target_row;
+
+               lx = 20 * (tx - px) + px;
+               ly = 20 * (ty - py) + py;
+       }
+
+       ld = distance(py, px, ly, lx);
+
+       /* Blast */
+       for (i = 0; i < num; i++)
+       {
+               while (1)
+               {
+                       /* Get targets for some bolts */
+                       y = rand_spread(ly, ld * dev / 20);
+                       x = rand_spread(lx, ld * dev / 20);
+
+                       if (distance(ly, lx, y, x) <= ld * dev / 20) break;
+               }
+
+               /* Analyze the "dir" and the "target". */
+               if (!project(0, 0, y, x, damroll(dd, ds), typ, flg, -1))
+               {
+                       result = FALSE;
+               }
+       }
+
+       return (result);
+}
+
+
 /*
  * Switch position with a monster.
  */
@@ -6503,6 +6704,12 @@ bool stasis_monster(int dir)
 }
 
 
+bool stasis_evil(int dir)
+{
+       return (fire_ball_hide(GF_STASIS_EVIL, dir, p_ptr->lev*2, 0));
+}
+
+
 bool confuse_monster(int dir, int plev)
 {
        int flg = PROJECT_STOP | PROJECT_KILL;
@@ -6760,7 +6967,7 @@ msg_print("
                        (*count) += activate_hi_summon(py, px, FALSE);
                        if (!one_in_(6)) break;
                case 7: case 8: case 9: case 18:
-                       (*count) += summon_specific(0, py, px, dun_level, 0, TRUE, FALSE, FALSE, TRUE, TRUE);
+                       (*count) += summon_specific(0, py, px, dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET));
                        if (!one_in_(6)) break;
                case 10: case 11: case 12:
 #ifdef JP
@@ -6837,21 +7044,24 @@ int activate_hi_summon(int y, int x, bool can_pet)
 {
        int i;
        int count = 0;
-       bool pet = FALSE, friendly = FALSE, not_pet;
        int summon_lev;
+       u32b mode = PM_ALLOW_GROUP;
+       bool pet = FALSE;
 
        if (can_pet)
        {
                if (one_in_(4))
                {
-                       friendly = TRUE;
+                       mode |= PM_FORCE_FRIENDLY;
                }
                else
                {
+                       mode |= PM_FORCE_PET;
                        pet = TRUE;
                }
        }
-       not_pet = (bool)(!pet);
+
+       if (!pet) mode |= PM_NO_PET;
 
        summon_lev = (pet ? p_ptr->lev * 2 / 3 + randint1(p_ptr->lev / 2) : dun_level);
 
@@ -6860,48 +7070,51 @@ int activate_hi_summon(int y, int x, bool can_pet)
                switch (randint1(25) + (dun_level / 20))
                {
                        case 1: case 2:
-                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_ANT, TRUE, friendly, pet, FALSE, not_pet);
+                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_ANT, mode);
                                break;
                        case 3: case 4:
-                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_SPIDER, TRUE, friendly, pet, FALSE, not_pet);
+                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_SPIDER, mode);
                                break;
                        case 5: case 6:
-                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_HOUND, TRUE, friendly, pet, FALSE, not_pet);
+                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_HOUND, mode);
                                break;
                        case 7: case 8:
-                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_HYDRA, TRUE, friendly, pet, FALSE, not_pet);
+                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_HYDRA, mode);
                                break;
                        case 9: case 10:
-                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_ANGEL, TRUE, friendly, pet, FALSE, not_pet);
+                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_ANGEL, mode);
                                break;
                        case 11: case 12:
-                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_UNDEAD, TRUE, friendly, pet, FALSE, not_pet);
+                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_UNDEAD, mode);
                                break;
                        case 13: case 14:
-                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_DRAGON, TRUE, friendly, pet, FALSE, not_pet);
+                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_DRAGON, mode);
                                break;
                        case 15: case 16:
-                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_DEMON, TRUE, friendly, pet, FALSE, not_pet);
+                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_DEMON, mode);
                                break;
                        case 17:
-                               if (pet || friendly) break;
-                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_AMBERITES, TRUE, friendly, pet, TRUE, not_pet);
+                               if (can_pet) break;
+                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_AMBERITES, (mode | PM_ALLOW_UNIQUE));
                                break;
                        case 18: case 19:
-                               if (pet || friendly) break;
-                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_UNIQUE, TRUE, friendly, pet, TRUE, not_pet);
+                               if (can_pet) break;
+                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_UNIQUE, (mode | PM_ALLOW_UNIQUE));
                                break;
                        case 20: case 21:
-                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_HI_UNDEAD, TRUE, friendly, pet, (bool)(!friendly && !pet), not_pet);
+                               if (!can_pet) mode |= PM_ALLOW_UNIQUE;
+                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_HI_UNDEAD, mode);
                                break;
                        case 22: case 23:
-                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_HI_DRAGON, TRUE, friendly, pet, (bool)(!friendly && !pet), not_pet);
+                               if (!can_pet) mode |= PM_ALLOW_UNIQUE;
+                               count += summon_specific((pet ? -1 : 0), y, x, summon_lev, SUMMON_HI_DRAGON, mode);
                                break;
                        case 24:
-                               count += summon_specific((pet ? -1 : 0), y, x, 100, SUMMON_CYBER, TRUE, friendly, pet, FALSE, not_pet);
+                               count += summon_specific((pet ? -1 : 0), y, x, 100, SUMMON_CYBER, mode);
                                break;
                        default:
-                               count += summon_specific((pet ? -1 : 0), y, x,pet ? summon_lev : (((summon_lev * 3) / 2) + 5), 0, TRUE, friendly, pet, (bool)(!friendly && !pet), not_pet);
+                               if (!can_pet) mode |= PM_ALLOW_UNIQUE;
+                               count += summon_specific((pet ? -1 : 0), y, x,pet ? summon_lev : (((summon_lev * 3) / 2) + 5), 0, mode);
                }
        }
 
@@ -6915,23 +7128,20 @@ int summon_cyber(int who, int y, int x)
        int i;
        int max_cyber = (easy_band ? 1 : (dun_level / 50) + randint1(2));
        int count = 0;
-
-       bool friendly = FALSE;
-       bool pet = FALSE;
+       u32b mode = PM_ALLOW_GROUP;
 
        /* Summoned by a monster */
        if (who > 0)
        {
                monster_type *m_ptr = &m_list[who];
-               friendly = is_friendly(m_ptr);
-               pet = is_pet(m_ptr);
+               if (is_pet(m_ptr)) mode |= PM_FORCE_PET;
        }
 
        if (max_cyber > 4) max_cyber = 4;
 
        for (i = 0; i < max_cyber; i++)
        {
-               count += summon_specific(who, y, x, 100, SUMMON_CYBER, TRUE, friendly, pet, FALSE, FALSE);
+               count += summon_specific(who, y, x, 100, SUMMON_CYBER, mode);
        }
 
        return count;