OSDN Git Service

[Refactor] #40581 Separated special-death-switcher.c/h from monster-death.c
authorHourier <hourier@users.sourceforge.jp>
Fri, 21 Aug 2020 06:50:59 +0000 (15:50 +0900)
committerHourier <hourier@users.sourceforge.jp>
Fri, 21 Aug 2020 06:50:59 +0000 (15:50 +0900)
Hengband/Hengband/Hengband.vcxproj
Hengband/Hengband/Hengband.vcxproj.filters
src/Makefile.am
src/monster-floor/monster-death-util.c
src/monster-floor/monster-death-util.h
src/monster-floor/monster-death.c
src/monster-floor/special-death-switcher.c [new file with mode: 0644]
src/monster-floor/special-death-switcher.h [new file with mode: 0644]

index cbc547f..729d516 100644 (file)
     <ClCompile Include="..\..\src\monster-floor\monster-death-util.c" />\r
     <ClCompile Include="..\..\src\monster-floor\monster-lite-util.c" />\r
     <ClCompile Include="..\..\src\monster-floor\monster-lite.c" />\r
+    <ClCompile Include="..\..\src\monster-floor\special-death-switcher.c" />\r
     <ClCompile Include="..\..\src\monster\monster-status-setter.c" />\r
     <ClCompile Include="..\..\src\mspell\element-resistance-checker.c" />\r
     <ClCompile Include="..\..\src\mspell\high-resistance-checker.c" />\r
     <ClInclude Include="..\..\src\monster-floor\monster-death-util.h" />\r
     <ClInclude Include="..\..\src\monster-floor\monster-lite-util.h" />\r
     <ClInclude Include="..\..\src\monster-floor\monster-lite.h" />\r
+    <ClInclude Include="..\..\src\monster-floor\special-death-switcher.h" />\r
     <ClInclude Include="..\..\src\monster\monster-status-setter.h" />\r
     <ClInclude Include="..\..\src\mspell\element-resistance-checker.h" />\r
     <ClInclude Include="..\..\src\mspell\high-resistance-checker.h" />\r
index 3e79dfa..0ec0c4e 100644 (file)
     <ClCompile Include="..\..\src\monster-floor\monster-death-util.c">
       <Filter>monster-floor</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\monster-floor\special-death-switcher.c">
+      <Filter>monster-floor</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\src\combat\shoot.h">
     <ClInclude Include="..\..\src\monster-floor\monster-death-util.h">
       <Filter>monster-floor</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\monster-floor\special-death-switcher.h">
+      <Filter>monster-floor</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\..\src\wall.bmp" />
index edfebc0..3df32da 100644 (file)
@@ -492,6 +492,7 @@ hengband_SOURCES = \
        monster-floor/one-monster-placer.c monster-floor/one-monster-placer.h \
        monster-floor/place-monster-types.h \
        monster-floor/quantum-effect.c monster-floor/quantum-effect.h \
+       monster-floor/special-death-switcher.c monster-floor/special-death-switcher.h \
        \
        monster-race/monster-race.c monster-race/monster-race.h \
        monster-race/monster-race-hook.c monster-race/monster-race-hook.h \
index 04f67e0..4809a58 100644 (file)
@@ -38,6 +38,7 @@ static OBJECT_SUBTYPE_VALUE get_coin_type(MONRACE_IDX r_idx)
 monster_death_type *initialize_monster_death_type(player_type *player_ptr, monster_death_type *md_ptr, MONSTER_IDX m_idx, bool drop_item)
 {
     floor_type *floor_ptr = player_ptr->current_floor_ptr;
+    md_ptr->m_idx = m_idx;
     md_ptr->m_ptr = &floor_ptr->m_list[m_idx];
     md_ptr->r_ptr = &r_info[md_ptr->m_ptr->r_idx];
     md_ptr->do_gold = (!(md_ptr->r_ptr->flags1 & RF1_ONLY_ITEM));
index f24b467..b00d327 100644 (file)
@@ -5,6 +5,7 @@
 typedef struct monster_type monster_type;
 typedef struct monster_race monster_race;
 typedef struct monster_death_type {
+    MONSTER_IDX m_idx;
     monster_type *m_ptr;
     monster_race *r_ptr;
     bool do_gold;
@@ -14,6 +15,7 @@ typedef struct monster_death_type {
     bool drop_chosen_item;
     POSITION md_y;
     POSITION md_x;
+    u32b mo_mode;
 } monster_death_type;
 
 monster_death_type *initialize_monster_death_type(player_type *player_ptr, monster_death_type *md_ptr, MONSTER_IDX m_idx, bool drop_item);
index 727bf72..2275330 100644 (file)
@@ -22,6 +22,7 @@
 #include "main/music-definitions-table.h"
 #include "main/sound-of-music.h"
 #include "market/arena-info-table.h"
+#include "monster-floor/special-death-switcher.h"
 #include "monster-floor/monster-death-util.h"
 #include "monster-floor/monster-object.h"
 #include "monster-floor/monster-summon.h"
@@ -175,291 +176,13 @@ void monster_death(player_type *player_ptr, MONSTER_IDX m_idx, bool drop_item)
 
     monster_drop_carried_objects(player_ptr, md_ptr->m_ptr);
 
-    u32b mo_mode = 0L;
+    md_ptr->mo_mode = 0L;
     if (md_ptr->r_ptr->flags1 & RF1_DROP_GOOD)
-        mo_mode |= AM_GOOD;
+        md_ptr->mo_mode |= AM_GOOD;
     if (md_ptr->r_ptr->flags1 & RF1_DROP_GREAT)
-        mo_mode |= AM_GREAT;
-
-    switch (md_ptr->m_ptr->r_idx) {
-    case MON_PINK_HORROR: {
-        if (floor_ptr->inside_arena || player_ptr->phase_out)
-            break;
-
-        bool notice = FALSE;
-        for (int i = 0; i < 2; i++) {
-            POSITION wy = md_ptr->md_y, wx = md_ptr->md_x;
-            bool pet = is_pet(md_ptr->m_ptr);
-            BIT_FLAGS mode = 0L;
-
-            if (pet) {
-                mode |= PM_FORCE_PET;
-            }
-
-            if (summon_specific(player_ptr, (pet ? -1 : m_idx), wy, wx, 100, SUMMON_BLUE_HORROR, mode)) {
-                if (player_can_see_bold(player_ptr, wy, wx))
-                    notice = TRUE;
-            }
-        }
-
-        if (notice) {
-            msg_print(_("ピンク・ホラーは分裂した!", "The Pink horror divides!"));
-        }
-
-        break;
-    }
-    case MON_BLOODLETTER: {
-        if (!md_ptr->drop_chosen_item || (randint1(100) >= 15))
-            break;
-
-        q_ptr = &forge;
-        object_prep(player_ptr, q_ptr, lookup_kind(TV_SWORD, SV_BLADE_OF_CHAOS));
-        apply_magic(player_ptr, q_ptr, floor_ptr->object_level, AM_NO_FIXED_ART | mo_mode);
-        (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
-        break;
-    }
-    case MON_RAAL: {
-        if (!md_ptr->drop_chosen_item || (floor_ptr->dun_level <= 9))
-            break;
-
-        q_ptr = &forge;
-        object_wipe(q_ptr);
-        if ((floor_ptr->dun_level > 49) && one_in_(5))
-            get_obj_num_hook = kind_is_good_book;
-        else
-            get_obj_num_hook = kind_is_book;
-
-        make_object(player_ptr, q_ptr, mo_mode);
-        (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
-        break;
-    }
-    case MON_DAWN: {
-        if (floor_ptr->inside_arena || player_ptr->phase_out)
-            break;
-        if (one_in_(7))
-            break;
-
-        POSITION wy = md_ptr->md_y, wx = md_ptr->md_x;
-        int attempts = 100;
-        bool pet = is_pet(md_ptr->m_ptr);
-        do {
-            scatter(player_ptr, &wy, &wx, md_ptr->md_y, md_ptr->md_x, 20, 0);
-        } while (!(in_bounds(floor_ptr, wy, wx) && is_cave_empty_bold2(player_ptr, wy, wx)) && --attempts);
-
-        if (attempts <= 0)
-            break;
-
-        BIT_FLAGS mode = 0L;
-        if (pet)
-            mode |= PM_FORCE_PET;
-
-        if (summon_specific(player_ptr, (pet ? -1 : m_idx), wy, wx, 100, SUMMON_DAWN, mode)) {
-            if (player_can_see_bold(player_ptr, wy, wx))
-                msg_print(_("新たな戦士が現れた!", "A new warrior steps forth!"));
-        }
-
-        break;
-    }
-    case MON_UNMAKER: {
-        BIT_FLAGS flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
-        (void)project(player_ptr, m_idx, 6, md_ptr->md_y, md_ptr->md_x, 100, GF_CHAOS, flg, -1);
-        break;
-    }
-    case MON_UNICORN_ORD:
-    case MON_MORGOTH:
-    case MON_ONE_RING: {
-        if (player_ptr->pseikaku != PERSONALITY_LAZY)
-            break;
-        if (!md_ptr->drop_chosen_item)
-            break;
-
-        ARTIFACT_IDX a_idx = 0;
-        artifact_type *a_ptr = NULL;
-        do {
-            switch (randint0(3)) {
-            case 0:
-                a_idx = ART_NAMAKE_HAMMER;
-                break;
-            case 1:
-                a_idx = ART_NAMAKE_BOW;
-                break;
-            case 2:
-                a_idx = ART_NAMAKE_ARMOR;
-                break;
-            }
-
-            a_ptr = &a_info[a_idx];
-        } while (a_ptr->cur_num);
-
-        if (create_named_art(player_ptr, a_idx, md_ptr->md_y, md_ptr->md_x)) {
-            a_ptr->cur_num = 1;
-            if (current_world_ptr->character_dungeon)
-                a_ptr->floor_id = player_ptr->floor_id;
-        } else if (!preserve_mode)
-            a_ptr->cur_num = 1;
-
-        break;
-    }
-    case MON_SERPENT: {
-        if (!md_ptr->drop_chosen_item)
-            break;
-
-        q_ptr = &forge;
-        object_prep(player_ptr, q_ptr, lookup_kind(TV_HAFTED, SV_GROND));
-        q_ptr->name1 = ART_GROND;
-        apply_magic(player_ptr, q_ptr, -1, AM_GOOD | AM_GREAT);
-        (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
-        q_ptr = &forge;
-        object_prep(player_ptr, q_ptr, lookup_kind(TV_CROWN, SV_CHAOS));
-        q_ptr->name1 = ART_CHAOS;
-        apply_magic(player_ptr, q_ptr, -1, AM_GOOD | AM_GREAT);
-        (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
-        break;
-    }
-    case MON_B_DEATH_SWORD: {
-        if (!md_ptr->drop_chosen_item)
-            break;
-
-        q_ptr = &forge;
-        object_prep(player_ptr, q_ptr, lookup_kind(TV_SWORD, randint1(2)));
-        (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
-        break;
-    }
-    case MON_A_GOLD:
-    case MON_A_SILVER: {
-        bool is_drop_can = md_ptr->drop_chosen_item;
-        bool is_silver = md_ptr->m_ptr->r_idx == MON_A_SILVER;
-        is_silver &= md_ptr->r_ptr->r_akills % 5 == 0;
-        is_drop_can &= (md_ptr->m_ptr->r_idx == MON_A_GOLD) || is_silver;
-        if (!is_drop_can)
-            break;
-
-        q_ptr = &forge;
-        object_prep(player_ptr, q_ptr, lookup_kind(TV_CHEST, SV_CHEST_KANDUME));
-        apply_magic(player_ptr, q_ptr, floor_ptr->object_level, AM_NO_FIXED_ART);
-        (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
-        break;
-    }
-    case MON_ROLENTO: {
-        BIT_FLAGS flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
-        (void)project(player_ptr, m_idx, 3, md_ptr->md_y, md_ptr->md_x, damroll(20, 10), GF_FIRE, flg, -1);
-        break;
-    }
-    case MON_MIDDLE_AQUA_FIRST:
-    case MON_LARGE_AQUA_FIRST:
-    case MON_EXTRA_LARGE_AQUA_FIRST:
-    case MON_MIDDLE_AQUA_SECOND:
-    case MON_LARGE_AQUA_SECOND:
-    case MON_EXTRA_LARGE_AQUA_SECOND: {
-        if (floor_ptr->inside_arena || player_ptr->phase_out)
-            break;
-
-        bool notice = FALSE;
-        const int popped_bubbles = 4;
-        for (int i = 0; i < popped_bubbles; i++) {
-            POSITION wy = md_ptr->md_y, wx = md_ptr->md_x;
-            bool pet = is_pet(md_ptr->m_ptr);
-            BIT_FLAGS mode = PM_NONE;
-
-            if (pet)
-                mode |= PM_FORCE_PET;
-
-            MONSTER_IDX smaller_bubblle = md_ptr->m_ptr->r_idx - 1;
-            if (summon_named_creature(player_ptr, (pet ? -1 : m_idx), wy, wx, smaller_bubblle, mode) && player_can_see_bold(player_ptr, wy, wx))
-                notice = TRUE;
-        }
-
-        if (notice)
-            msg_print(_("泡が弾けた!", "The bubble pops!"));
-
-        break;
-    }
-    case MON_TOTEM_MOAI: {
-        if (floor_ptr->inside_arena || player_ptr->phase_out || one_in_(8))
-            break;
-
-        POSITION wy = md_ptr->md_y, wx = md_ptr->md_x;
-        int attempts = 100;
-        bool pet = is_pet(md_ptr->m_ptr);
-        do {
-            scatter(player_ptr, &wy, &wx, md_ptr->md_y, md_ptr->md_x, 20, 0);
-        } while (!(in_bounds(floor_ptr, wy, wx) && is_cave_empty_bold2(player_ptr, wy, wx)) && --attempts);
-
-        if (attempts <= 0)
-            break;
-
-        BIT_FLAGS mode = PM_NONE;
-        if (pet)
-            mode |= PM_FORCE_PET;
-
-        if (summon_named_creature(player_ptr, (pet ? -1 : m_idx), wy, wx, MON_TOTEM_MOAI, mode) && player_can_see_bold(player_ptr, wy, wx))
-            msg_print(_("新たなモアイが現れた!", "A new moai steps forth!"));
-
-        break;
-    }
-    default: {
-        if (!md_ptr->drop_chosen_item)
-            break;
-
-        switch (md_ptr->r_ptr->d_char) {
-        case '(': {
-            if (floor_ptr->dun_level <= 0)
-                break;
-
-            q_ptr = &forge;
-            object_wipe(q_ptr);
-            get_obj_num_hook = kind_is_cloak;
-            make_object(player_ptr, q_ptr, mo_mode);
-            (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
-            break;
-        }
-        case '/': {
-            if (floor_ptr->dun_level <= 4)
-                break;
-
-            q_ptr = &forge;
-            object_wipe(q_ptr);
-            get_obj_num_hook = kind_is_polearm;
-            make_object(player_ptr, q_ptr, mo_mode);
-            (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
-            break;
-        }
-        case '[': {
-            if (floor_ptr->dun_level <= 19)
-                break;
-
-            q_ptr = &forge;
-            object_wipe(q_ptr);
-            get_obj_num_hook = kind_is_armor;
-            make_object(player_ptr, q_ptr, mo_mode);
-            (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
-            break;
-        }
-        case '\\': {
-            if (floor_ptr->dun_level <= 4)
-                break;
-            q_ptr = &forge;
-            object_wipe(q_ptr);
-            get_obj_num_hook = kind_is_hafted;
-            make_object(player_ptr, q_ptr, mo_mode);
-            (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
-            break;
-        }
-        case '|': {
-            if (md_ptr->m_ptr->r_idx == MON_STORMBRINGER)
-                break;
-
-            q_ptr = &forge;
-            object_wipe(q_ptr);
-            get_obj_num_hook = kind_is_sword;
-            make_object(player_ptr, q_ptr, mo_mode);
-            (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
-            break;
-        }
-        }
-    }
-    }
+        md_ptr->mo_mode |= AM_GREAT;
 
+    switch_special_death(player_ptr, md_ptr);
     if (md_ptr->drop_chosen_item) {
         ARTIFACT_IDX a_idx = 0;
         PERCENTAGE chance = 0;
@@ -559,7 +282,7 @@ void monster_death(player_type *player_ptr, MONSTER_IDX m_idx, bool drop_item)
                 continue;
             dump_gold++;
         } else {
-            if (!make_object(player_ptr, q_ptr, mo_mode))
+            if (!make_object(player_ptr, q_ptr, md_ptr->mo_mode))
                 continue;
             dump_item++;
         }
diff --git a/src/monster-floor/special-death-switcher.c b/src/monster-floor/special-death-switcher.c
new file mode 100644 (file)
index 0000000..6d15ba5
--- /dev/null
@@ -0,0 +1,309 @@
+#include "monster-floor/special-death-switcher.h"
+#include "art-definition/art-armor-types.h"
+#include "art-definition/art-bow-types.h"
+#include "art-definition/art-protector-types.h"
+#include "art-definition/art-weapon-types.h"
+#include "artifact/fixed-art-generator.h"
+#include "effect/effect-characteristics.h"
+#include "effect/effect-processor.h"
+#include "floor/cave.h"
+#include "floor/floor-object.h"
+#include "floor/floor-util.h"
+#include "game-option/birth-options.h"
+#include "grid/grid.h"
+#include "monster-floor/monster-death-util.h"
+#include "monster-floor/monster-summon.h"
+#include "monster-floor/place-monster-types.h"
+#include "monster-race/monster-race.h"
+#include "monster-race/race-indice-types.h"
+#include "monster/monster-info.h"
+#include "object-enchant/apply-magic.h"
+#include "object-enchant/item-apply-magic.h"
+#include "object/object-generator.h"
+#include "object/object-kind-hook.h"
+#include "spell/spell-types.h"
+#include "spell/spells-summon.h"
+#include "sv-definition/sv-other-types.h"
+#include "sv-definition/sv-protector-types.h"
+#include "sv-definition/sv-weapon-types.h"
+#include "system/artifact-type-definition.h"
+#include "system/floor-type-definition.h"
+#include "system/monster-type-definition.h"
+#include "system/object-type-definition.h"
+#include "system/system-variables.h"
+#include "view/display-messages.h"
+#include "world/world.h"
+
+void switch_special_death(player_type *player_ptr, monster_death_type *md_ptr)
+{
+    floor_type *floor_ptr = player_ptr->current_floor_ptr;
+    switch (md_ptr->m_ptr->r_idx) {
+    case MON_PINK_HORROR: {
+        if (floor_ptr->inside_arena || player_ptr->phase_out)
+            break;
+
+        bool notice = FALSE;
+        for (int i = 0; i < 2; i++) {
+            POSITION wy = md_ptr->md_y;
+            POSITION wx = md_ptr->md_x;
+            bool pet = is_pet(md_ptr->m_ptr);
+            BIT_FLAGS mode = pet ? PM_FORCE_PET : PM_NONE;
+            if (summon_specific(player_ptr, (pet ? -1 : md_ptr->m_idx), wy, wx, 100, SUMMON_BLUE_HORROR, mode) && player_can_see_bold(player_ptr, wy, wx))
+                notice = TRUE;
+        }
+
+        if (notice)
+            msg_print(_("\83s\83\93\83N\81E\83z\83\89\81[\82Í\95ª\97ô\82µ\82½\81I", "The Pink horror divides!"));
+
+        break;
+    }
+    case MON_BLOODLETTER: {
+        if (!md_ptr->drop_chosen_item || (randint1(100) >= 15))
+            break;
+
+        object_type forge;
+        object_type *q_ptr = &forge;
+        object_prep(player_ptr, q_ptr, lookup_kind(TV_SWORD, SV_BLADE_OF_CHAOS));
+        apply_magic(player_ptr, q_ptr, floor_ptr->object_level, AM_NO_FIXED_ART | md_ptr->mo_mode);
+        (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
+        break;
+    }
+    case MON_RAAL: {
+        if (!md_ptr->drop_chosen_item || (floor_ptr->dun_level <= 9))
+            break;
+
+        object_type forge;
+        object_type *q_ptr = &forge;
+        object_wipe(q_ptr);
+        if ((floor_ptr->dun_level > 49) && one_in_(5))
+            get_obj_num_hook = kind_is_good_book;
+        else
+            get_obj_num_hook = kind_is_book;
+
+        make_object(player_ptr, q_ptr, md_ptr->mo_mode);
+        (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
+        break;
+    }
+    case MON_DAWN: {
+        if (floor_ptr->inside_arena || player_ptr->phase_out || one_in_(7))
+            break;
+
+        POSITION wy = md_ptr->md_y;
+        POSITION wx = md_ptr->md_x;
+        int attempts = 100;
+        bool pet = is_pet(md_ptr->m_ptr);
+        do {
+            scatter(player_ptr, &wy, &wx, md_ptr->md_y, md_ptr->md_x, 20, 0);
+        } while (!(in_bounds(floor_ptr, wy, wx) && is_cave_empty_bold2(player_ptr, wy, wx)) && --attempts);
+
+        if (attempts <= 0)
+            break;
+
+        BIT_FLAGS mode = pet ? PM_FORCE_PET : PM_NONE;
+        if (summon_specific(player_ptr, (pet ? -1 : md_ptr->m_idx), wy, wx, 100, SUMMON_DAWN, mode) && player_can_see_bold(player_ptr, wy, wx))
+            msg_print(_("\90V\82½\82È\90í\8em\82ª\8c»\82ê\82½\81I", "A new warrior steps forth!"));
+
+        break;
+    }
+    case MON_UNMAKER: {
+        BIT_FLAGS flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
+        (void)project(player_ptr, md_ptr->m_idx, 6, md_ptr->md_y, md_ptr->md_x, 100, GF_CHAOS, flg, -1);
+        break;
+    }
+    case MON_UNICORN_ORD:
+    case MON_MORGOTH:
+    case MON_ONE_RING: {
+        if ((player_ptr->pseikaku != PERSONALITY_LAZY) || !md_ptr->drop_chosen_item)
+            break;
+
+        ARTIFACT_IDX a_idx = 0;
+        artifact_type *a_ptr = NULL;
+        do {
+            switch (randint0(3)) {
+            case 0:
+                a_idx = ART_NAMAKE_HAMMER;
+                break;
+            case 1:
+                a_idx = ART_NAMAKE_BOW;
+                break;
+            case 2:
+                a_idx = ART_NAMAKE_ARMOR;
+                break;
+            }
+
+            a_ptr = &a_info[a_idx];
+        } while (a_ptr->cur_num > 0);
+
+        if (create_named_art(player_ptr, a_idx, md_ptr->md_y, md_ptr->md_x)) {
+            a_ptr->cur_num = 1;
+            if (current_world_ptr->character_dungeon)
+                a_ptr->floor_id = player_ptr->floor_id;
+        } else if (!preserve_mode)
+            a_ptr->cur_num = 1;
+
+        break;
+    }
+    case MON_SERPENT: {
+        if (!md_ptr->drop_chosen_item)
+            break;
+
+        object_type forge;
+        object_type *q_ptr = &forge;
+        object_prep(player_ptr, q_ptr, lookup_kind(TV_HAFTED, SV_GROND));
+        q_ptr->name1 = ART_GROND;
+        apply_magic(player_ptr, q_ptr, -1, AM_GOOD | AM_GREAT);
+        (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
+        q_ptr = &forge;
+        object_prep(player_ptr, q_ptr, lookup_kind(TV_CROWN, SV_CHAOS));
+        q_ptr->name1 = ART_CHAOS;
+        apply_magic(player_ptr, q_ptr, -1, AM_GOOD | AM_GREAT);
+        (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
+        break;
+    }
+    case MON_B_DEATH_SWORD: {
+        if (!md_ptr->drop_chosen_item)
+            break;
+
+        object_type forge;
+        object_type *q_ptr = &forge;
+        object_prep(player_ptr, q_ptr, lookup_kind(TV_SWORD, randint1(2)));
+        (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
+        break;
+    }
+    case MON_A_GOLD:
+    case MON_A_SILVER: {
+        bool is_drop_can = md_ptr->drop_chosen_item;
+        bool is_silver = md_ptr->m_ptr->r_idx == MON_A_SILVER;
+        is_silver &= md_ptr->r_ptr->r_akills % 5 == 0;
+        is_drop_can &= (md_ptr->m_ptr->r_idx == MON_A_GOLD) || is_silver;
+        if (!is_drop_can)
+            break;
+
+        object_type forge;
+        object_type *q_ptr = &forge;
+        object_prep(player_ptr, q_ptr, lookup_kind(TV_CHEST, SV_CHEST_KANDUME));
+        apply_magic(player_ptr, q_ptr, floor_ptr->object_level, AM_NO_FIXED_ART);
+        (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
+        break;
+    }
+    case MON_ROLENTO: {
+        BIT_FLAGS flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
+        (void)project(player_ptr, md_ptr->m_idx, 3, md_ptr->md_y, md_ptr->md_x, damroll(20, 10), GF_FIRE, flg, -1);
+        break;
+    }
+    case MON_MIDDLE_AQUA_FIRST:
+    case MON_LARGE_AQUA_FIRST:
+    case MON_EXTRA_LARGE_AQUA_FIRST:
+    case MON_MIDDLE_AQUA_SECOND:
+    case MON_LARGE_AQUA_SECOND:
+    case MON_EXTRA_LARGE_AQUA_SECOND: {
+        if (floor_ptr->inside_arena || player_ptr->phase_out)
+            break;
+
+        bool notice = FALSE;
+        const int popped_bubbles = 4;
+        for (int i = 0; i < popped_bubbles; i++) {
+            POSITION wy = md_ptr->md_y;
+            POSITION wx = md_ptr->md_x;
+            bool pet = is_pet(md_ptr->m_ptr);
+            BIT_FLAGS mode = pet ? PM_FORCE_PET : PM_NONE;
+            MONSTER_IDX smaller_bubblle = md_ptr->m_ptr->r_idx - 1;
+            if (summon_named_creature(player_ptr, (pet ? -1 : md_ptr->m_idx), wy, wx, smaller_bubblle, mode) && player_can_see_bold(player_ptr, wy, wx))
+                notice = TRUE;
+        }
+
+        if (notice)
+            msg_print(_("\96A\82ª\92e\82¯\82½\81I", "The bubble pops!"));
+
+        break;
+    }
+    case MON_TOTEM_MOAI: {
+        if (floor_ptr->inside_arena || player_ptr->phase_out || one_in_(8))
+            break;
+
+        POSITION wy = md_ptr->md_y;
+        POSITION wx = md_ptr->md_x;
+        int attempts = 100;
+        bool pet = is_pet(md_ptr->m_ptr);
+        do {
+            scatter(player_ptr, &wy, &wx, md_ptr->md_y, md_ptr->md_x, 20, 0);
+        } while (!(in_bounds(floor_ptr, wy, wx) && is_cave_empty_bold2(player_ptr, wy, wx)) && --attempts);
+
+        if (attempts <= 0)
+            break;
+
+        BIT_FLAGS mode = pet ? PM_FORCE_PET : PM_NONE;
+        if (summon_named_creature(player_ptr, (pet ? -1 : md_ptr->m_idx), wy, wx, MON_TOTEM_MOAI, mode) && player_can_see_bold(player_ptr, wy, wx))
+            msg_print(_("\90V\82½\82È\83\82\83A\83C\82ª\8c»\82ê\82½\81I", "A new moai steps forth!"));
+
+        break;
+    }
+    default: {
+        if (!md_ptr->drop_chosen_item)
+            break;
+
+        switch (md_ptr->r_ptr->d_char) {
+        case '(': {
+            if (floor_ptr->dun_level <= 0)
+                break;
+
+            object_type forge;
+            object_type *q_ptr = &forge;
+            object_wipe(q_ptr);
+            get_obj_num_hook = kind_is_cloak;
+            make_object(player_ptr, q_ptr, md_ptr->mo_mode);
+            (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
+            break;
+        }
+        case '/': {
+            if (floor_ptr->dun_level <= 4)
+                break;
+
+            object_type forge;
+            object_type *q_ptr = &forge;
+            object_wipe(q_ptr);
+            get_obj_num_hook = kind_is_polearm;
+            make_object(player_ptr, q_ptr, md_ptr->mo_mode);
+            (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
+            break;
+        }
+        case '[': {
+            if (floor_ptr->dun_level <= 19)
+                break;
+
+            object_type forge;
+            object_type *q_ptr = &forge;
+            object_wipe(q_ptr);
+            get_obj_num_hook = kind_is_armor;
+            make_object(player_ptr, q_ptr, md_ptr->mo_mode);
+            (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
+            break;
+        }
+        case '\\': {
+            if (floor_ptr->dun_level <= 4)
+                break;
+
+            object_type forge;
+            object_type *q_ptr = &forge;
+            object_wipe(q_ptr);
+            get_obj_num_hook = kind_is_hafted;
+            make_object(player_ptr, q_ptr, md_ptr->mo_mode);
+            (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
+            break;
+        }
+        case '|': {
+            if (md_ptr->m_ptr->r_idx == MON_STORMBRINGER)
+                break;
+
+            object_type forge;
+            object_type *q_ptr = &forge;
+            object_wipe(q_ptr);
+            get_obj_num_hook = kind_is_sword;
+            make_object(player_ptr, q_ptr, md_ptr->mo_mode);
+            (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
+            break;
+        }
+        }
+    }
+    }
+}
diff --git a/src/monster-floor/special-death-switcher.h b/src/monster-floor/special-death-switcher.h
new file mode 100644 (file)
index 0000000..f10aba8
--- /dev/null
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "system/angband.h"
+
+typedef struct monster_death_type monster_death_type;
+void switch_special_death(player_type *player_ptr, monster_death_type *md_ptr);