• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

変愚蛮怒のメインリポジトリです


Commit MetaInfo

Révision4fab351a44340ad8bdd82cd1c622fb78b83c74cc (tree)
l'heure2020-03-08 14:44:10
Auteurdeskull <deskull@user...>
Commiterdeskull

Message de Log

Merge remote-tracking branch 'remotes/origin/For2.2.2-Fix-Hourier' into For2.2.2-Refactoring

Change Summary

Modification

--- a/Hengband_vcs2017/Hengband/Hengband.vcxproj
+++ b/Hengband_vcs2017/Hengband/Hengband.vcxproj
@@ -195,13 +195,25 @@
195195 <ClCompile Include="..\..\src\init.c" />
196196 <ClCompile Include="..\..\src\io\gf-descriptions.c" />
197197 <ClCompile Include="..\..\src\io\interpret-pref-file.c" />
198+ <ClCompile Include="..\..\src\io\player-status-dump.c" />
198199 <ClCompile Include="..\..\src\io\read-pref-file.c" />
200+ <ClCompile Include="..\..\src\io\special-class-dump.c" />
199201 <ClCompile Include="..\..\src\io\tokenizer.c" />
200202 <ClCompile Include="..\..\src\monster-dist-offsets.c" />
201203 <ClCompile Include="..\..\src\monster-process.c" />
202204 <ClCompile Include="..\..\src\monster-status.c" />
203205 <ClCompile Include="..\..\src\monsterrace-hook.c" />
204206 <ClCompile Include="..\..\src\monsterrace.c" />
207+ <ClCompile Include="..\..\src\monster\monster-attack.c" />
208+ <ClCompile Include="..\..\src\monster\monster-direction.c" />
209+ <ClCompile Include="..\..\src\monster\monster-move.c" />
210+ <ClCompile Include="..\..\src\monster\monster-object.c" />
211+ <ClCompile Include="..\..\src\monster\monster-runaway.c" />
212+ <ClCompile Include="..\..\src\monster\monster-safety-hiding.c" />
213+ <ClCompile Include="..\..\src\monster\monster-sweep-grid.c" />
214+ <ClCompile Include="..\..\src\monster\monster-update.c" />
215+ <ClCompile Include="..\..\src\monster\monster-util.c" />
216+ <ClCompile Include="..\..\src\monster\quantum-effect.c" />
205217 <ClCompile Include="..\..\src\object-boost.c" />
206218 <ClCompile Include="..\..\src\object-curse.c" />
207219 <ClCompile Include="..\..\src\object-ego.c" />
@@ -343,9 +355,21 @@
343355 <ClInclude Include="..\..\src\horror-descriptions.h" />
344356 <ClInclude Include="..\..\src\io\gf-descriptions.h" />
345357 <ClInclude Include="..\..\src\io\interpret-pref-file.h" />
358+ <ClInclude Include="..\..\src\io\player-status-dump.h" />
346359 <ClInclude Include="..\..\src\io\read-pref-file.h" />
360+ <ClInclude Include="..\..\src\io\special-class-dump.h" />
347361 <ClInclude Include="..\..\src\io\tokenizer.h" />
348362 <ClInclude Include="..\..\src\monster-dist-offsets.h" />
363+ <ClInclude Include="..\..\src\monster\monster-attack.h" />
364+ <ClInclude Include="..\..\src\monster\monster-direction.h" />
365+ <ClInclude Include="..\..\src\monster\monster-move.h" />
366+ <ClInclude Include="..\..\src\monster\monster-object.h" />
367+ <ClInclude Include="..\..\src\monster\monster-runaway.h" />
368+ <ClInclude Include="..\..\src\monster\monster-safety-hiding.h" />
369+ <ClInclude Include="..\..\src\monster\monster-sweep-grid.h" />
370+ <ClInclude Include="..\..\src\monster\monster-update.h" />
371+ <ClInclude Include="..\..\src\monster\monster-util.h" />
372+ <ClInclude Include="..\..\src\monster\quantum-effect.h" />
349373 <ClInclude Include="..\..\src\object-flavor.h" />
350374 <ClInclude Include="..\..\src\player-inventory.h" />
351375 <ClInclude Include="..\..\src\player\permanent-resistances.h" />
--- a/Hengband_vcs2017/Hengband/Hengband.vcxproj.filters
+++ b/Hengband_vcs2017/Hengband/Hengband.vcxproj.filters
@@ -472,6 +472,42 @@
472472 <ClCompile Include="..\..\src\io\interpret-pref-file.c">
473473 <Filter>io</Filter>
474474 </ClCompile>
475+ <ClCompile Include="..\..\src\monster\quantum-effect.c">
476+ <Filter>monster</Filter>
477+ </ClCompile>
478+ <ClCompile Include="..\..\src\io\special-class-dump.c">
479+ <Filter>io</Filter>
480+ </ClCompile>
481+ <ClCompile Include="..\..\src\io\player-status-dump.c">
482+ <Filter>io</Filter>
483+ </ClCompile>
484+ <ClCompile Include="..\..\src\monster\monster-util.c">
485+ <Filter>monster</Filter>
486+ </ClCompile>
487+ <ClCompile Include="..\..\src\monster\monster-object.c">
488+ <Filter>monster</Filter>
489+ </ClCompile>
490+ <ClCompile Include="..\..\src\monster\monster-attack.c">
491+ <Filter>monster</Filter>
492+ </ClCompile>
493+ <ClCompile Include="..\..\src\monster\monster-move.c">
494+ <Filter>monster</Filter>
495+ </ClCompile>
496+ <ClCompile Include="..\..\src\monster\monster-update.c">
497+ <Filter>monster</Filter>
498+ </ClCompile>
499+ <ClCompile Include="..\..\src\monster\monster-safety-hiding.c">
500+ <Filter>monster</Filter>
501+ </ClCompile>
502+ <ClCompile Include="..\..\src\monster\monster-direction.c">
503+ <Filter>monster</Filter>
504+ </ClCompile>
505+ <ClCompile Include="..\..\src\monster\monster-runaway.c">
506+ <Filter>monster</Filter>
507+ </ClCompile>
508+ <ClCompile Include="..\..\src\monster\monster-sweep-grid.c">
509+ <Filter>monster</Filter>
510+ </ClCompile>
475511 </ItemGroup>
476512 <ItemGroup>
477513 <ClInclude Include="..\..\src\gamevalue.h" />
@@ -926,6 +962,42 @@
926962 <ClInclude Include="..\..\src\io\interpret-pref-file.h">
927963 <Filter>io</Filter>
928964 </ClInclude>
965+ <ClInclude Include="..\..\src\monster\quantum-effect.h">
966+ <Filter>monster</Filter>
967+ </ClInclude>
968+ <ClInclude Include="..\..\src\io\special-class-dump.h">
969+ <Filter>io</Filter>
970+ </ClInclude>
971+ <ClInclude Include="..\..\src\io\player-status-dump.h">
972+ <Filter>io</Filter>
973+ </ClInclude>
974+ <ClInclude Include="..\..\src\monster\monster-util.h">
975+ <Filter>monster</Filter>
976+ </ClInclude>
977+ <ClInclude Include="..\..\src\monster\monster-object.h">
978+ <Filter>monster</Filter>
979+ </ClInclude>
980+ <ClInclude Include="..\..\src\monster\monster-attack.h">
981+ <Filter>monster</Filter>
982+ </ClInclude>
983+ <ClInclude Include="..\..\src\monster\monster-move.h">
984+ <Filter>monster</Filter>
985+ </ClInclude>
986+ <ClInclude Include="..\..\src\monster\monster-update.h">
987+ <Filter>monster</Filter>
988+ </ClInclude>
989+ <ClInclude Include="..\..\src\monster\monster-safety-hiding.h">
990+ <Filter>monster</Filter>
991+ </ClInclude>
992+ <ClInclude Include="..\..\src\monster\monster-direction.h">
993+ <Filter>monster</Filter>
994+ </ClInclude>
995+ <ClInclude Include="..\..\src\monster\monster-runaway.h">
996+ <Filter>monster</Filter>
997+ </ClInclude>
998+ <ClInclude Include="..\..\src\monster\monster-sweep-grid.h">
999+ <Filter>monster</Filter>
1000+ </ClInclude>
9291001 </ItemGroup>
9301002 <ItemGroup>
9311003 <None Include="..\..\src\wall.bmp" />
--- a/lib/edit/misc.txt
+++ b/lib/edit/misc.txt
@@ -13,7 +13,7 @@ M:WX:99
1313 M:WY:66
1414
1515 # Maximum number of monsters in r_info.txt
16-M:R:1140
16+M:R:1141
1717
1818 # Maximum number of items in k_info.txt
1919 M:K:672
--- a/lib/edit/r_info.txt
+++ b/lib/edit/r_info.txt
@@ -2270,7 +2270,7 @@ S:SHOOT | HEAL | TRAPS
22702270 A:221:1:5
22712271 V:75
22722272 D:$The legendary archer steals from the rich (you qualify).
2273-D:この伝説の射手は金持ち(あなたは合格)から金を盗む
2273+D:この伝説の射手は金持ち(あなたは合格)から金を盗む。
22742274
22752275 #JZ#
22762276 N:139:ナーグリング
@@ -22604,7 +22604,7 @@ F:DROP_1D2
2260422604 F:OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE
2260522605 F:EVIL | IM_POIS | EAT_POISONOUS | CAN_SWIM
2260622606 D:$Be aware!
22607-D:$This kobold's poison can change a tough guy to a frail kid!
22607+D:$ This kobold's poison can change a tough guy to a frail kid!
2260822608 D:気をつけろ!
2260922609 D:やつの毒は大の大人を無力な子供に変えてしまう!
2261022610
@@ -22622,7 +22622,7 @@ F:EVIL | IM_POIS | EAT_POISONOUS
2262222622 F:ESCORT | ESCORTS | RES_SOUN | CAN_FLY
2262322623 F:NO_CONF
2262422624 D:$"Hey Nobita, I regret to say, but the capacity of this dungeon is 3."
22625-D:$However, there are clearly more than three money mongers around him!
22625+D:$ However, there are clearly more than three money mongers around him!
2262622626 D:「悪いなのび太、このダンジョンは3人用なんだ」
2262722627 D:しかし、彼に群がる金の亡者は明らかに3人よりも多い!
2262822628
@@ -22637,11 +22637,12 @@ B:HIT:FIRE:8d4
2263722637 F:MALE |
2263822638 F:FORCE_MAXHP | FRIENDS | DROP_60 |
2263922639 F:OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE | EAT_POISONOUS |
22640-F:EVIL | ORC | IM_POIS | RES_DARK | IM_FIRE | RES_CHAO | DEMON | WILD_VOLCANO | AURA_FIRE
22640+F:EVIL | ORC | IM_POIS | RES_DARK | IM_FIRE | RES_CHAO
22641+F:DEMON | WILD_VOLCANO | AURA_FIRE
2264122642 S:1_IN_8
2264222643 S:SHOOT | BO_FIRE |
22643-D:$Cloaked in black flame, this orc must be the descendant of a demon. Such
22644-D:$ creatures are often seen among the foulest orcs.
22644+D:$Cloaked in black flame, this orc must be the descendant of a demon.
22645+D:$ Such creatures are often seen among the foulest orcs.
2264522646 D:このオークの体にはデーモンの血が流れており、そこから来る暗黒の炎をまとっている。
2264622647 D:この不浄な結合は、暗き風習を持つ生き物の中でしばしば育まれる。
2264722648
@@ -22662,8 +22663,10 @@ S:1_IN_5 | S_KIN | SHOOT | BO_ELEC
2266222663 D:$The leader of this family, worried about the death of his homeland
2266322664 D:$ after the death of Isshin Ashina,
2266422665 D:$ seeks to obtain it without regard to any monstrous power.
22665-D:$ Therefore, it will also be inevitable that he sought them and went to Angband.
22666-D:葦名一心亡き後の故国の存亡を憂うこの一門の将は、いかなる異形の力をも顧みず手に入れようとする。
22666+D:$ Therefore, it will also be inevitable that
22667+D:$ he sought them and went to Angband.
22668+D:葦名一心亡き後の故国の存亡を憂うこの一門の将は、
22669+D:いかなる異形の力をも顧みず手に入れようとする。
2266722670 D:ゆえにそれらを求め鉄獄に至ったこともまた必然であるだろう。
2266822671
2266922672 N:1124:撲殺の天使
@@ -22888,7 +22891,8 @@ F:NO_FEAR | NO_CONF | NO_SLEEP
2288822891 S:1_IN_2 | BA_NETH | BA_WATE | BA_DARK | BA_NUKE | BA_CHAO
2288922892 S:S_HI_UNDEAD | S_DEMON | DISPEL
2289022893 D:$Undoubtedly, it was this man who unleashed the cursed artifacts
22891-D:$ and called upon the great old ones who came from the outside world and settled in Llouis.
22894+D:$ and called upon the great old ones who came from the outside world
22895+D:$ and settled in Llouis.
2289222896 D:$ It is told that his book, Necronomicon, namely stargate to the abyss,
2289322897 D:$ is still slept somewhere in the land.
2289422898 D:呪われしアーティファクトを世に解き放ち、
@@ -22906,8 +22910,10 @@ B:BITE:HURT:6d2
2290622910 F:MALE | WILD_SWAMP | WILD_WASTE
2290722911 F:OPEN_DOOR | BASH_DOOR | DROP_CORPSE | DROP_SKELETON
2290822912 F:ANIMAL | EVIL | DROP_90
22909-D:$A warrior of skaven mess around with the power of chaos and slaughter their prey from one end.
22910-D:スケイヴン族の戦士は混沌の力をいたずらに振り回し、目についた獲物を片っ端から屠っていく。
22913+D:$A warrior of skaven mess around with the power of chaos
22914+D:$ and slaughter their prey from one end.
22915+D:スケイヴン族の戦士は混沌の力をいたずらに振り回し、
22916+D:目についた獲物を片っ端から屠っていく。
2291122917
2291222918 N:1137:殺人イタチ
2291322919 E:Killer weasel
@@ -22966,3 +22972,22 @@ D:$She recognizes you as a bug that appears to be
2296622972 D:$ a myriad of connected consciousness in the Wired.
2296722973 D:あなたは、相互に結合している無数の意識達に表れたちっぽけなバグだと
2296822974 D:認識されている。
22975+
22976+N:1140:ウェンディゴ
22977+E:Wendigo
22978+G:Y:v
22979+I:120:30d19:30:55:10
22980+W:30:3:0:500:0:0
22981+B:BITE:LOSE_WIS:3d4
22982+B:CLAW:COLD:3d4
22983+B:TOUCH:TERRIFY:3d4
22984+B:WAIL:CONFUSE:3d4
22985+F:ONLY_GOLD | DROP_2D2 |
22986+F:COLD_BLOOD | OPEN_DOOR | BASH_DOOR | CAN_FLY | WEIRD_MIND | ELDRITCH_HORROR
22987+F:EVIL | DEMON | IM_COLD | IM_POIS | RES_NETH | NO_CONF | NO_SLEEP | HURT_FIRE
22988+S:1_IN_6 |
22989+S:MIND_BLAST
22990+D:$It looks like a skinny large humanoid.
22991+D:$ Folklore has it that those who commit cannibalism are brought to cognate
22992+D:それは痩せこけた巨人の姿をしていて、人食いの罪を犯した者を
22993+D:同族にすると言われている。
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,6 +30,8 @@ hengband_SOURCES = \
3030 io/gf-descriptions.c io/gf-descriptions.h \
3131 io/tokenizer.c io/tokenizer.h \
3232 io/interpret-pref-file.c io/interpret-pref-file.h \
33+ io/player-status-dump.c io/player-status-dump.h \
34+ io/special-class-dump.c io/special-class-dump.h \
3335 io/read-pref-file.c io/read-pref-file.h \
3436 io/exit-panic.c io/exit-panic.h \
3537 signal-handlers.c signal-handlers.h uid-checker.c uid-checker.h \
@@ -56,6 +58,16 @@ hengband_SOURCES = \
5658 mind.c mind.h \
5759 \
5860 monster.h monsterrace.c monsterrace.h \
61+ monster/monster-util.c monster/monster-util.h \
62+ monster/monster-direction.c monster/monster-direction.h \
63+ monster/monster-attack.c monster/monster-attack.h \
64+ monster/monster-move.c monster/monster-move.h \
65+ monster/monster-object.c monster/monster-object.h \
66+ monster/monster-runaway.c monster/monster-runaway.h \
67+ monster/monster-safety-hiding.c monster/monster-safety-hiding.h \
68+ monster/monster-sweep-grid.c monster/monster-sweep-grid.h \
69+ monster/monster-update.c monster/monster-update.h \
70+ monster/quantum-effect.c monster/quantum-effect.h \
5971 monsterrace-hook.c monsterrace-hook.h \
6072 monster-dist-offsets.c monster-dist-offsets.h \
6173 monster-process.c monster-process.h \
@@ -142,7 +154,7 @@ EXTRA_DIST = \
142154 CFLAGS += $(XFT_CFLAGS)
143155 LIBS += $(XFT_LIBS)
144156 COMPILE = $(srcdir)/gcc-wrap $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
145- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -Icmd -Icombat -Iio -Iplayer -Iview
157+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -Icmd -Icombat -Icore -Iio -Imonster -Iplayer -Iview
146158
147159 install-exec-hook:
148160 if SET_GID
--- a/src/character-dump.c
+++ b/src/character-dump.c
@@ -5,9 +5,6 @@
55 #include "dungeon.h"
66 #include "store.h"
77 #include "cmd/cmd-pet.h"
8-#include "cmd/cmd-magiceat.h"
9-#include "objectkind.h"
10-#include "monster-spell.h"
118 #include "monster-status.h"
129 #include "sort.h"
1310 #include "quest.h"
@@ -15,101 +12,11 @@
1512 #include "mutation.h"
1613 #include "object-flavor.h"
1714 #include "cmd/cmd-dump.h"
15+#include "io/special-class-dump.h"
16+#include "io/player-status-dump.h"
1817 #include "avatar.h"
1918
2019 /*!
21- * @brief プレイヤーのステータス表示をファイルにダンプする
22- * @param creature_ptr プレーヤーへの参照ポインタ
23- * @param fff ファイルポインタ
24- * @return なし
25- */
26-static void dump_aux_display_player(player_type *creature_ptr, FILE *fff, display_player_pf display_player, map_name_pf map_name)
27-{
28- TERM_COLOR a;
29- char c;
30- char buf[1024];
31- display_player(creature_ptr, 0, map_name);
32-
33- for (TERM_LEN y = 1; y < 22; y++)
34- {
35- TERM_LEN x;
36- for (x = 0; x < 79; x++)
37- {
38- (void)(Term_what(x, y, &a, &c));
39- buf[x] = c;
40- }
41-
42- buf[x] = '\0';
43- while ((x > 0) && (buf[x - 1] == ' '))
44- buf[--x] = '\0';
45-
46- fprintf(fff, _("%s\n", "%s\n"), buf);
47- }
48-
49- display_player(creature_ptr, 1, map_name);
50- for (TERM_LEN y = 10; y < 19; y++)
51- {
52- TERM_LEN x;
53- for (x = 0; x < 79; x++)
54- {
55- (void)(Term_what(x, y, &a, &c));
56- buf[x] = c;
57- }
58-
59- buf[x] = '\0';
60- while ((x > 0) && (buf[x - 1] == ' '))
61- buf[--x] = '\0';
62-
63- fprintf(fff, "%s\n", buf);
64- }
65-
66- fprintf(fff, "\n");
67- display_player(creature_ptr, 2, map_name);
68- for (TERM_LEN y = 2; y < 22; y++)
69- {
70- TERM_LEN x;
71- for (x = 0; x < 79; x++)
72- {
73- (void)(Term_what(x, y, &a, &c));
74- if (a < 128)
75- buf[x] = c;
76- else
77- buf[x] = ' ';
78- }
79-
80- buf[x] = '\0';
81- while ((x > 0) && (buf[x - 1] == ' '))
82- buf[--x] = '\0';
83-
84- fprintf(fff, "%s\n", buf);
85- }
86-
87- fprintf(fff, "\n");
88- display_player(creature_ptr, 3, map_name);
89- for (TERM_LEN y = 1; y < 22; y++)
90- {
91- TERM_LEN x;
92- for (x = 0; x < 79; x++)
93- {
94- (void)(Term_what(x, y, &a, &c));
95- if (a < 128)
96- buf[x] = c;
97- else
98- buf[x] = ' ';
99- }
100-
101- buf[x] = '\0';
102- while ((x > 0) && (buf[x - 1] == ' '))
103- buf[--x] = '\0';
104-
105- fprintf(fff, "%s\n", buf);
106- }
107-
108- fprintf(fff, "\n");
109-}
110-
111-
112-/*!
11320 * @brief プレイヤーのペット情報をファイルにダンプする
11421 * @param creature_ptr プレーヤーへの参照ポインタ
11522 * @param fff ファイルポインタ
@@ -165,217 +72,6 @@ static void dump_aux_pet(player_type *master_ptr, FILE *fff)
16572
16673
16774 /*!
168- * todo ここはenum/switchで扱いたい
169- * @brief プレイヤーの職業能力情報をファイルにダンプする
170- * @param creature_ptr プレーヤーへの参照ポインタ
171- * @param fff ファイルポインタ
172- * @return なし
173- */
174-static void dump_aux_class_special(player_type *creature_ptr, FILE *fff)
175-{
176- bool is_special_class = creature_ptr->pclass == CLASS_MAGIC_EATER;
177- is_special_class |= creature_ptr->pclass == CLASS_SMITH;
178- is_special_class |= creature_ptr->pclass == CLASS_BLUE_MAGE;
179- if (!is_special_class) return;
180-
181- if (creature_ptr->pclass == CLASS_MAGIC_EATER)
182- {
183- char s[EATER_EXT][MAX_NLEN];
184- OBJECT_TYPE_VALUE tval = 0;
185- fprintf(fff, _("\n\n [取り込んだ魔法道具]\n", "\n\n [Magic devices eaten]\n"));
186-
187- for (int ext = 0; ext < 3; ext++)
188- {
189- int eat_num = 0;
190-
191- /* Dump an extent name */
192- switch (ext)
193- {
194- case 0:
195- tval = TV_STAFF;
196- fprintf(fff, _("\n[杖]\n", "\n[Staffs]\n"));
197- break;
198- case 1:
199- tval = TV_WAND;
200- fprintf(fff, _("\n[魔法棒]\n", "\n[Wands]\n"));
201- break;
202- case 2:
203- tval = TV_ROD;
204- fprintf(fff, _("\n[ロッド]\n", "\n[Rods]\n"));
205- break;
206- }
207-
208- /* Get magic device names that were eaten */
209- for (OBJECT_SUBTYPE_VALUE i = 0; i < EATER_EXT; i++)
210- {
211- int idx = EATER_EXT * ext + i;
212- int magic_num = creature_ptr->magic_num2[idx];
213- if (!magic_num) continue;
214-
215- KIND_OBJECT_IDX k_idx = lookup_kind(tval, i);
216- if (!k_idx) continue;
217- sprintf(s[eat_num], "%23s (%2d)", (k_name + k_info[k_idx].name), magic_num);
218- eat_num++;
219- }
220-
221- /* Dump magic devices in this extent */
222- if (eat_num <= 0)
223- {
224- fputs(_(" (なし)\n", " (none)\n"), fff);
225- continue;
226- }
227-
228- OBJECT_SUBTYPE_VALUE i;
229- for (i = 0; i < eat_num; i++)
230- {
231- fputs(s[i], fff);
232- if (i % 3 < 2) fputs(" ", fff);
233- else fputs("\n", fff);
234- }
235-
236- if (i % 3 > 0) fputs("\n", fff);
237- }
238-
239- return;
240- }
241-
242- if (creature_ptr->pclass == CLASS_SMITH)
243- {
244- int i, id[250], n = 0, row;
245-
246- fprintf(fff, _("\n\n [手に入れたエッセンス]\n\n", "\n\n [Get Essence]\n\n"));
247- fprintf(fff, _("エッセンス 個数 エッセンス 個数 エッセンス 個数",
248- "Essence Num Essence Num Essence Num "));
249- for (i = 0; essence_name[i]; i++)
250- {
251- if (!essence_name[i][0]) continue;
252- id[n] = i;
253- n++;
254- }
255-
256- row = n / 3 + 1;
257-
258- for (i = 0; i < row; i++)
259- {
260- fprintf(fff, "\n");
261- fprintf(fff, "%-11s %5d ", essence_name[id[i]], (int)creature_ptr->magic_num1[id[i]]);
262- if (i + row < n) fprintf(fff, "%-11s %5d ", essence_name[id[i + row]], (int)creature_ptr->magic_num1[id[i + row]]);
263- if (i + row * 2 < n) fprintf(fff, "%-11s %5d", essence_name[id[i + row * 2]], (int)creature_ptr->magic_num1[id[i + row * 2]]);
264- }
265-
266- fputs("\n", fff);
267- return;
268- }
269-
270- // Blue mage
271- int l1 = 0;
272- int l2 = 0;
273- int spellnum[MAX_MONSPELLS];
274- BIT_FLAGS f4 = 0, f5 = 0, f6 = 0;
275- char p[60][80];
276- int col = 0;
277- bool pcol = FALSE;
278-
279- for (int i = 0; i < 60; i++)
280- {
281- p[i][0] = '\0';
282- }
283-
284- strcat(p[col], _("\n\n [学習済みの青魔法]\n", "\n\n [Learned Blue Magic]\n"));
285-
286- for (int j = 1; j < 6; j++)
287- {
288- col++;
289- set_rf_masks(&f4, &f5, &f6, j);
290- switch (j)
291- {
292- case MONSPELL_TYPE_BOLT:
293- strcat(p[col], _("\n [ボルト型]\n", "\n [Bolt Type]\n"));
294- break;
295-
296- case MONSPELL_TYPE_BALL:
297- strcat(p[col], _("\n [ボール型]\n", "\n [Ball Type]\n"));
298- break;
299-
300- case MONSPELL_TYPE_BREATH:
301- strcat(p[col], _("\n [ブレス型]\n", "\n [ Breath ]\n"));
302- break;
303-
304- case MONSPELL_TYPE_SUMMON:
305- strcat(p[col], _("\n [召喚魔法]\n", "\n [Summonning]\n"));
306- break;
307-
308- case MONSPELL_TYPE_OTHER:
309- strcat(p[col], _("\n [ その他 ]\n", "\n [Other Type]\n"));
310- break;
311- }
312-
313- int num = 0;
314- for (int i = 0; i < 32; i++)
315- {
316- if ((0x00000001 << i) & f4) spellnum[num++] = i;
317- }
318-
319- for (int i = 32; i < 64; i++)
320- {
321- if ((0x00000001 << (i - 32)) & f5) spellnum[num++] = i;
322- }
323-
324- for (int i = 64; i < 96; i++)
325- {
326- if ((0x00000001 << (i - 64)) & f6) spellnum[num++] = i;
327- }
328-
329- col++;
330- pcol = FALSE;
331- strcat(p[col], " ");
332-
333- for (int i = 0; i < num; i++)
334- {
335- if (creature_ptr->magic_num2[spellnum[i]] == 0) continue;
336-
337- pcol = TRUE;
338- /* Dump blue magic */
339- l1 = strlen(p[col]);
340- l2 = strlen(monster_powers_short[spellnum[i]]);
341- if ((l1 + l2) >= 75)
342- {
343- strcat(p[col], "\n");
344- col++;
345- strcat(p[col], " ");
346- }
347-
348- strcat(p[col], monster_powers_short[spellnum[i]]);
349- strcat(p[col], ", ");
350- }
351-
352- if (!pcol)
353- {
354- strcat(p[col], _("なし", "None"));
355- strcat(p[col], "\n");
356- continue;
357- }
358-
359- if (p[col][strlen(p[col]) - 2] == ',')
360- {
361- p[col][strlen(p[col]) - 2] = '\0';
362- }
363- else
364- {
365- p[col][strlen(p[col]) - 10] = '\0';
366- }
367-
368- strcat(p[col], "\n");
369- }
370-
371- for (int i = 0; i <= col; i++)
372- {
373- fputs(p[i], fff);
374- }
375-}
376-
377-
378-/*!
37975 * @brief クエスト情報をファイルにダンプする
38076 * @param creature_ptr プレーヤーへの参照ポインタ
38177 * @param fff ファイルポインタ
@@ -469,7 +165,6 @@ static void dump_aux_options(FILE *fff)
469165 fprintf(fff, _("\n [オプション設定]\n", "\n [Option Settings]\n"));
470166 if (preserve_mode)
471167 fprintf(fff, _("\n 保存モード: ON", "\n Preserve Mode: ON"));
472-
473168 else
474169 fprintf(fff, _("\n 保存モード: OFF", "\n Preserve Mode: OFF"));
475170
@@ -854,16 +549,11 @@ static void dump_aux_home_museum(player_type *creature_ptr, FILE *fff)
854549 */
855550 void make_character_dump(player_type *creature_ptr, FILE *fff, void(*update_playtime)(void), display_player_pf display_player, map_name_pf map_name)
856551 {
857-#ifdef JP
858- fprintf(fff, " [変愚蛮怒 %d.%d.%d キャラクタ情報]\n\n",
859- FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
860-#else
861- fprintf(fff, " [Hengband %d.%d.%d Character Dump]\n\n",
552+ fprintf(fff, _(" [変愚蛮怒 %d.%d.%d キャラクタ情報]\n\n", " [Hengband %d.%d.%d Character Dump]\n\n"),
862553 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
863-#endif
864554 (*update_playtime)();
865555
866- dump_aux_display_player(creature_ptr, fff, display_player, map_name);
556+ dump_aux_player_status(creature_ptr, fff, display_player, map_name);
867557 dump_aux_last_message(creature_ptr, fff);
868558 dump_aux_options(fff);
869559 dump_aux_recall(fff);
--- a/src/character-dump.h
+++ b/src/character-dump.h
@@ -3,4 +3,4 @@
33 #include "angband.h"
44 #include "files.h"
55
6- void make_character_dump(player_type *creature_ptr, FILE *fff, void(*update_playtime)(void), display_player_pf display_player, map_name_pf map_name);
6+void make_character_dump(player_type *creature_ptr, FILE *fff, void(*update_playtime)(void), display_player_pf display_player, map_name_pf map_name);
--- a/src/cmd/cmd-dump.c
+++ b/src/cmd/cmd-dump.c
@@ -1081,7 +1081,7 @@ void do_cmd_player_status(player_type *creature_ptr)
10811081 {
10821082 if (tmp[0] && (tmp[0] != ' '))
10831083 {
1084- file_character(creature_ptr, tmp, display_player, map_name);
1084+ file_character(creature_ptr, tmp, update_playtime, display_player, map_name);
10851085 }
10861086 }
10871087 }
--- a/src/combat/melee1.c
+++ b/src/combat/melee1.c
@@ -4124,17 +4124,13 @@ bool monst_attack_monst(player_type *subject_ptr, MONSTER_IDX m_idx, MONSTER_IDX
41244124 monster_race *r_ptr = &r_info[m_ptr->r_idx];
41254125 monster_race *tr_ptr = &r_info[t_ptr->r_idx];
41264126
4127- ARMOUR_CLASS ap_cnt;
4128- ARMOUR_CLASS ac;
4129- DEPTH rlev;
41304127 int pt;
41314128 GAME_TEXT m_name[MAX_NLEN], t_name[MAX_NLEN];
4132- char temp[MAX_NLEN];
4133- bool blinked;
4134- bool explode = FALSE, touched = FALSE, fear = FALSE, dead = FALSE;
4129+ char temp[MAX_NLEN];
4130+ bool explode = FALSE, touched = FALSE, fear = FALSE, dead = FALSE;
41354131 POSITION y_saver = t_ptr->fy;
41364132 POSITION x_saver = t_ptr->fx;
4137- int effect_type;
4133+ int effect_type;
41384134
41394135 bool see_m = is_seen(m_ptr);
41404136 bool see_t = is_seen(t_ptr);
@@ -4144,25 +4140,21 @@ bool monst_attack_monst(player_type *subject_ptr, MONSTER_IDX m_idx, MONSTER_IDX
41444140 bool known = (m_ptr->cdis <= MAX_SIGHT) || (t_ptr->cdis <= MAX_SIGHT);
41454141 bool do_silly_attack = (one_in_(2) && subject_ptr->image);
41464142
4147- /* Cannot attack self */
41484143 if (m_idx == t_idx) return FALSE;
4149-
4150- /* Not allowed to attack */
41514144 if (r_ptr->flags1 & RF1_NEVER_BLOW) return FALSE;
4152-
41534145 if (d_info[subject_ptr->dungeon_idx].flags1 & DF1_NO_MELEE) return FALSE;
41544146
41554147 /* Total armor */
4156- ac = tr_ptr->ac;
4148+ ARMOUR_CLASS ac = tr_ptr->ac;
41574149
41584150 /* Extract the effective monster level */
4159- rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1);
4151+ DEPTH rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1);
41604152
41614153 monster_desc(subject_ptr, m_name, m_ptr, 0);
41624154 monster_desc(subject_ptr, t_name, t_ptr, 0);
41634155
41644156 /* Assume no blink */
4165- blinked = FALSE;
4157+ bool blinked = FALSE;
41664158
41674159 if (!see_either && known)
41684160 {
@@ -4172,7 +4164,7 @@ bool monst_attack_monst(player_type *subject_ptr, MONSTER_IDX m_idx, MONSTER_IDX
41724164 if (subject_ptr->riding && (m_idx == subject_ptr->riding)) disturb(subject_ptr, TRUE, TRUE);
41734165
41744166 /* Scan through all four blows */
4175- for (ap_cnt = 0; ap_cnt < 4; ap_cnt++)
4167+ for (ARMOUR_CLASS ap_cnt = 0; ap_cnt < 4; ap_cnt++)
41764168 {
41774169 bool obvious = FALSE;
41784170
--- a/src/files.c
+++ b/src/files.c
@@ -16,9 +16,7 @@
1616 #include "uid-checker.h"
1717 #include "files.h"
1818 #include "core.h" // 暫定。後で消す.
19-
2019 #include "character-dump.h"
21-#include "view-mainwindow.h" // 暫定。後で消す.
2220
2321 concptr ANGBAND_DIR; //!< Path name: The main "lib" directory This variable is not actually used anywhere in the code
2422 concptr ANGBAND_DIR_APEX; //!< High score files (binary) These files may be portable between platforms
@@ -298,7 +296,7 @@ concptr process_pref_file_expr(player_type *creature_ptr, char **sp, char *fp)
298296 * Allow the "full" flag to dump additional info,
299297 * and trigger its usage from various places in the code.
300298 */
301-errr file_character(player_type *creature_ptr, concptr name, display_player_pf display_player, map_name_pf map_name)
299+errr file_character(player_type *creature_ptr, concptr name, update_playtime_pf update_playtime, display_player_pf display_player, map_name_pf map_name)
302300 {
303301 char buf[1024];
304302 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
--- a/src/files.h
+++ b/src/files.h
@@ -19,8 +19,9 @@ extern concptr ANGBAND_DIR_XTRA;
1919
2020 typedef concptr(*map_name_pf)(player_type*);
2121 typedef void(*display_player_pf)(player_type*, int, map_name_pf);
22+typedef void(*update_playtime_pf)(void);
2223
23-extern errr file_character(player_type *creature_ptr, concptr name, display_player_pf display_player, map_name_pf map_name);
24+extern errr file_character(player_type *creature_ptr, concptr name, update_playtime_pf update_playtime, display_player_pf display_player, map_name_pf map_name);
2425 extern concptr process_pref_file_expr(player_type *creature_ptr, char **sp, char *fp);
2526 extern errr get_rnd_line(concptr file_name, int entry, char *output);
2627 void read_dead_file(char* buf, size_t buf_size);
--- a/src/io/interpret-pref-file.c
+++ b/src/io/interpret-pref-file.c
@@ -13,14 +13,16 @@
1313 #include "term.h"
1414 #include "view-mainwindow.h" // 暫定。apply_default_feat_lighting()。後で消す.
1515
16+#define MAX_MACRO_CHARS 65536 // 1つのマクロキー押下で実行可能なコマンド最大数 (エスケープシーケンス含む).
17+
1618 /*!
1719 * @brief Rトークンの解釈 / Process "R:<num>:<a>/<c>" -- attr/char for monster races
1820 * @param buf バッファ
19- * @param zz トークン保管文字列
2021 * @return エラーコード
2122 */
22-static errr interpret_r_file(char *buf, char **zz)
23+static errr interpret_r_token(char *buf)
2324 {
25+ char *zz[16];
2426 if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
2527
2628 monster_race *r_ptr;
@@ -38,341 +40,470 @@ static errr interpret_r_file(char *buf, char **zz)
3840
3941
4042 /*!
41- * @brief 設定ファイルの各行から各種テキスト情報を取得する /
42- * Parse a sub-file of the "extra info" (format shown below)
43- * @param creature_ptr プレーヤーへの参照ポインタ
44- * @param buf データテキストの参照ポインタ
43+ * @brief Kトークンの解釈 / Process "K:<num>:<a>/<c>" -- attr/char for object kinds
44+ * @param buf バッファ
4545 * @return エラーコード
46- * @details
47- * <pre>
48- * Each "action" line has an "action symbol" in the first column,
49- * followed by a colon, followed by some command specific info,
50- * usually in the form of "tokens" separated by colons or slashes.
51- * Blank lines, lines starting with white space, and lines starting
52- * with pound signs ("#") are ignored (as comments).
53- * Note the use of "tokenize()" to allow the use of both colons and
54- * slashes as delimeters, while still allowing final tokens which
55- * may contain any characters including "delimiters".
56- * Note the use of "strtol()" to allow all "integers" to be encoded
57- * in decimal, hexidecimal, or octal form.
58- * Note that "monster zero" is used for the "player" attr/char, "object
59- * zero" will be used for the "stack" attr/char, and "feature zero" is
60- * used for the "nothing" attr/char.
61- * </pre>
6246 */
63-errr interpret_pref_file(player_type *creature_ptr, char *buf)
47+static errr interpret_k_token(char *buf)
6448 {
65- if (buf[1] != ':') return 1;
66-
6749 char *zz[16];
68- switch (buf[0])
50+ if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
51+
52+ object_kind *k_ptr;
53+ int i = (int)strtol(zz[0], NULL, 0);
54+ TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
55+ SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
56+ if (i >= max_k_idx) return 1;
57+
58+ k_ptr = &k_info[i];
59+ if (n1 || (!(n2 & 0x80) && n2)) k_ptr->x_attr = n1; /* Allow TERM_DARK text */
60+ if (n2) k_ptr->x_char = n2;
61+
62+ return 0;
63+}
64+
65+
66+/*!
67+ * @brief トークン数によって地形の文字形と色を決定する
68+ * @param i 地形種別
69+ * @param num トークン数
70+ * @return エラーコード
71+ */
72+static errr decide_feature_type(int i, int num, char **zz)
73+{
74+ feature_type *f_ptr;
75+ f_ptr = &f_info[i];
76+
77+ TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
78+ SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
79+ if (n1 || (!(n2 & 0x80) && n2)) f_ptr->x_attr[F_LIT_STANDARD] = n1; /* Allow TERM_DARK text */
80+ if (n2) f_ptr->x_char[F_LIT_STANDARD] = n2;
81+
82+ switch (num)
6983 {
70- case 'H':
84+ case 3:
7185 {
72- /* Process "H:<history>" */
73- add_history_from_pref_line(buf + 2);
86+ /* No lighting support */
87+ n1 = f_ptr->x_attr[F_LIT_STANDARD];
88+ n2 = f_ptr->x_char[F_LIT_STANDARD];
89+ for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
90+ {
91+ f_ptr->x_attr[j] = n1;
92+ f_ptr->x_char[j] = n2;
93+ }
94+
7495 return 0;
7596 }
76- case 'R':
97+ case 4:
7798 {
78- return interpret_r_file(buf, zz);
99+ /* Use default lighting */
100+ apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
101+ return 0;
79102 }
80- case 'K':
103+ case F_LIT_MAX * 2 + 1:
81104 {
82- /* Process "K:<num>:<a>/<c>" -- attr/char for object kinds */
83- if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
84-
85- object_kind *k_ptr;
86- int i = (int)strtol(zz[0], NULL, 0);
87- TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
88- SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
89- if (i >= max_k_idx) return 1;
90- k_ptr = &k_info[i];
91- if (n1 || (!(n2 & 0x80) && n2)) k_ptr->x_attr = n1; /* Allow TERM_DARK text */
92- if (n2) k_ptr->x_char = n2;
105+ /* Use desired lighting */
106+ for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
107+ {
108+ n1 = (TERM_COLOR)strtol(zz[j * 2 + 1], NULL, 0);
109+ n2 = (SYMBOL_CODE)strtol(zz[j * 2 + 2], NULL, 0);
110+ if (n1 || (!(n2 & 0x80) && n2)) f_ptr->x_attr[j] = n1; /* Allow TERM_DARK text */
111+ if (n2) f_ptr->x_char[j] = n2;
112+ }
113+
93114 return 0;
94115 }
95- case 'F':
116+ default:
117+ return 0;
118+ }
119+}
120+
121+
122+/*!
123+ * @brief Fトークンの解釈 / Process "F:<num>:<a>/<c>" -- attr/char for terrain features
124+ * @param buf バッファ
125+ * @return エラーコード
126+ * @details
127+ * "F:<num>:<a>/<c>"
128+ * "F:<num>:<a>/<c>:LIT"
129+ * "F:<num>:<a>/<c>:<la>/<lc>:<da>/<dc>"
130+ */
131+static errr interpret_f_token(char *buf)
132+{
133+ char *zz[16];
134+ int num = tokenize(buf + 2, F_LIT_MAX * 2 + 1, zz, TOKENIZE_CHECKQUOTE);
135+
136+ if ((num != 3) && (num != 4) && (num != F_LIT_MAX * 2 + 1)) return 1;
137+ else if ((num == 4) && !streq(zz[3], "LIT")) return 1;
138+
139+ int i = (int)strtol(zz[0], NULL, 0);
140+ if (i >= max_f_idx) return 1;
141+
142+ return decide_feature_type(i, num, zz);
143+}
144+
145+
146+/*!
147+ * @brief Fトークンの解釈 / Process "S:<num>:<a>/<c>" -- attr/char for special things
148+ * @param buf バッファ
149+ * @return エラーコード
150+ */
151+static errr interpret_s_token(char *buf)
152+{
153+ char *zz[16];
154+ if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
155+
156+ int j = (byte)strtol(zz[0], NULL, 0);
157+ TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
158+ SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
159+ misc_to_attr[j] = n1;
160+ misc_to_char[j] = n2;
161+ return 0;
162+}
163+
164+
165+/*!
166+ * @brief Uトークンの解釈 / Process "U:<tv>:<a>/<c>" -- attr/char for unaware items
167+ * @param buf バッファ
168+ * @return エラーコード
169+ */
170+static errr interpret_u_token(char *buf)
171+{
172+ char *zz[16];
173+ if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
174+
175+ int j = (int)strtol(zz[0], NULL, 0);
176+ TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
177+ SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
178+ for (int i = 1; i < max_k_idx; i++)
96179 {
97- /* Process "F:<num>:<a>/<c>" -- attr/char for terrain features */
98- /* "F:<num>:<a>/<c>" */
99- /* "F:<num>:<a>/<c>:LIT" */
100- /* "F:<num>:<a>/<c>:<la>/<lc>:<da>/<dc>" */
101- feature_type *f_ptr;
102- int num = tokenize(buf + 2, F_LIT_MAX * 2 + 1, zz, TOKENIZE_CHECKQUOTE);
103-
104- if ((num != 3) && (num != 4) && (num != F_LIT_MAX * 2 + 1)) return 1;
105- else if ((num == 4) && !streq(zz[3], "LIT")) return 1;
106-
107- int i = (int)strtol(zz[0], NULL, 0);
108- if (i >= max_f_idx) return 1;
109- f_ptr = &f_info[i];
110-
111- TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
112- SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
113- if (n1 || (!(n2 & 0x80) && n2)) f_ptr->x_attr[F_LIT_STANDARD] = n1; /* Allow TERM_DARK text */
114- if (n2) f_ptr->x_char[F_LIT_STANDARD] = n2;
115-
116- switch (num)
117- {
118- case 3:
180+ object_kind *k_ptr = &k_info[i];
181+ if (k_ptr->tval == j)
119182 {
120- /* No lighting support */
121- n1 = f_ptr->x_attr[F_LIT_STANDARD];
122- n2 = f_ptr->x_char[F_LIT_STANDARD];
123- for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
124- {
125- f_ptr->x_attr[j] = n1;
126- f_ptr->x_char[j] = n2;
127- }
128-
129- return 0;
183+ if (n1) k_ptr->d_attr = n1;
184+ if (n2) k_ptr->d_char = n2;
130185 }
131- case 4:
186+ }
187+
188+ return 0;
189+}
190+
191+
192+/*!
193+ * @brief Eトークンの解釈 / Process "E:<tv>:<a>" -- attribute for inventory objects
194+ * @param buf バッファ
195+ * @return エラーコード
196+ */
197+static errr interpret_e_token(char *buf)
198+{
199+ char *zz[16];
200+ if (tokenize(buf + 2, 2, zz, TOKENIZE_CHECKQUOTE) != 2) return 1;
201+
202+ int j = (byte)strtol(zz[0], NULL, 0) % 128;
203+ TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
204+ if (n1) tval_to_attr[j] = n1;
205+ return 0;
206+}
207+
208+
209+/*!
210+ * @brief Pトークンの解釈 / Process "P:<str>" -- normal macro
211+ * @param buf バッファ
212+ * @return エラーコード
213+ */
214+static errr interpret_p_token(char *buf)
215+{
216+ char tmp[1024];
217+ text_to_ascii(tmp, buf + 2);
218+ macro_add(tmp, macro__buf);
219+ return 0;
220+}
221+
222+
223+/*!
224+ * @brief Cトークンの解釈 / Process "C:<str>" -- create keymap
225+ * @param buf バッファ
226+ * @return エラーコード
227+ */
228+static errr interpret_c_token(char *buf)
229+{
230+ char *zz[16];
231+ if (tokenize(buf + 2, 2, zz, TOKENIZE_CHECKQUOTE) != 2) return 1;
232+
233+ int mode = strtol(zz[0], NULL, 0);
234+ if ((mode < 0) || (mode >= KEYMAP_MODES)) return 1;
235+
236+ char tmp[1024];
237+ text_to_ascii(tmp, zz[1]);
238+ if (!tmp[0] || tmp[1]) return 1;
239+
240+ int i = (byte)(tmp[0]);
241+ string_free(keymap_act[mode][i]);
242+ keymap_act[mode][i] = string_make(macro__buf);
243+ return 0;
244+}
245+
246+
247+/*!
248+ * @brief Vトークンの解釈 / Process "V:<num>:<kv>:<rv>:<gv>:<bv>" -- visual info
249+ * @param buf バッファ
250+ * @return エラーコード
251+ */
252+static errr interpret_v_token(char *buf)
253+{
254+ char *zz[16];
255+ if (tokenize(buf + 2, 5, zz, TOKENIZE_CHECKQUOTE) != 5) return 1;
256+
257+ int i = (byte)strtol(zz[0], NULL, 0);
258+ angband_color_table[i][0] = (byte)strtol(zz[1], NULL, 0);
259+ angband_color_table[i][1] = (byte)strtol(zz[2], NULL, 0);
260+ angband_color_table[i][2] = (byte)strtol(zz[3], NULL, 0);
261+ angband_color_table[i][3] = (byte)strtol(zz[4], NULL, 0);
262+ return 0;
263+}
264+
265+
266+/*!
267+ * @brief X/Yトークンの解釈
268+ * @param creature_ptr プレーヤーへの参照ポインタ
269+ * @param buf バッファ
270+ * @return エラーコード
271+ * @details
272+ * Process "X:<str>" -- turn option off
273+ * Process "Y:<str>" -- turn option on
274+ */
275+static errr interpret_xy_token(player_type *creature_ptr, char *buf)
276+{
277+ for (int i = 0; option_info[i].o_desc; i++)
278+ {
279+ bool is_option = option_info[i].o_var != NULL;
280+ is_option &= option_info[i].o_text != NULL;
281+ is_option &= streq(option_info[i].o_text, buf + 2);
282+ if (!is_option) continue;
283+
284+ int os = option_info[i].o_set;
285+ int ob = option_info[i].o_bit;
286+
287+ if ((creature_ptr->playing || current_world_ptr->character_xtra) &&
288+ (OPT_PAGE_BIRTH == option_info[i].o_page) && !current_world_ptr->wizard)
132289 {
133- /* Use default lighting */
134- apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
290+ msg_format(_("初期オプションは変更できません! '%s'", "Birth options can not changed! '%s'"), buf);
291+ msg_print(NULL);
135292 return 0;
136293 }
137- case F_LIT_MAX * 2 + 1:
138- {
139- /* Use desired lighting */
140- for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
141- {
142- n1 = (TERM_COLOR)strtol(zz[j * 2 + 1], NULL, 0);
143- n2 = (SYMBOL_CODE)strtol(zz[j * 2 + 2], NULL, 0);
144- if (n1 || (!(n2 & 0x80) && n2)) f_ptr->x_attr[j] = n1; /* Allow TERM_DARK text */
145- if (n2) f_ptr->x_char[j] = n2;
146- }
147294
295+ if (buf[0] == 'X')
296+ {
297+ option_flag[os] &= ~(1L << ob);
298+ (*option_info[i].o_var) = FALSE;
148299 return 0;
149300 }
150- default:
151- return 0;
152- }
153- }
154- case 'S':
155- {
156- /* Process "S:<num>:<a>/<c>" -- attr/char for special things */
157- if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
158-
159- int j = (byte)strtol(zz[0], NULL, 0);
160- TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
161- SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
162- misc_to_attr[j] = n1;
163- misc_to_char[j] = n2;
301+
302+ option_flag[os] |= (1L << ob);
303+ (*option_info[i].o_var) = TRUE;
164304 return 0;
165305 }
166- case 'U':
167- {
168- /* Process "U:<tv>:<a>/<c>" -- attr/char for unaware items */
169- if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
170306
171- int j = (int)strtol(zz[0], NULL, 0);
172- TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
173- SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
174- for (int i = 1; i < max_k_idx; i++)
175- {
176- object_kind *k_ptr = &k_info[i];
177- if (k_ptr->tval == j)
178- {
179- if (n1) k_ptr->d_attr = n1;
180- if (n2) k_ptr->d_char = n2;
181- }
182- }
307+ msg_format(_("オプションの名前が正しくありません: %s", "Ignored invalid option: %s"), buf);
308+ msg_print(NULL);
309+ return 0;
310+}
183311
184- return 0;
185- }
186- case 'E':
187- {
188- /* Process "E:<tv>:<a>" -- attribute for inventory objects */
189- if (tokenize(buf + 2, 2, zz, TOKENIZE_CHECKQUOTE) != 2) return 1;
190312
191- int j = (byte)strtol(zz[0], NULL, 0) % 128;
192- TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
193- if (n1) tval_to_attr[j] = n1;
194- return 0;
195- }
196- case 'A':
197- {
198- /* Process "A:<str>" -- save an "action" for later */
199- text_to_ascii(macro__buf, buf + 2);
200- return 0;
201- }
202- case 'P':
313+/*!
314+ * @brief Zトークンの解釈 / Process "Z:<type>:<str>" -- set spell color
315+ * @param buf バッファ
316+ * @param zz トークン保管文字列
317+ * @return エラーコード
318+ */
319+static errr interpret_z_token(char *buf)
320+{
321+ char *t = my_strchr(buf + 2, ':');
322+ if (!t) return 1;
323+
324+ *(t++) = '\0';
325+ for (int i = 0; i < MAX_NAMED_NUM; i++)
203326 {
204- /* Process "P:<str>" -- normal macro */
205- char tmp[1024];
206- text_to_ascii(tmp, buf + 2);
207- macro_add(tmp, macro__buf);
327+ if (!streq(gf_desc[i].name, buf + 2)) continue;
328+
329+ gf_color[gf_desc[i].num] = (TERM_COLOR)quark_add(t);
208330 return 0;
209331 }
210- case 'C':
211- {
212- /* Process "C:<str>" -- create keymap */
213- if (tokenize(buf + 2, 2, zz, TOKENIZE_CHECKQUOTE) != 2) return 1;
214332
215- int mode = strtol(zz[0], NULL, 0);
216- if ((mode < 0) || (mode >= KEYMAP_MODES)) return 1;
333+ return 1;
334+}
217335
218- char tmp[1024];
219- text_to_ascii(tmp, zz[1]);
220- if (!tmp[0] || tmp[1]) return 1;
221336
222- int i = (byte)(tmp[0]);
223- string_free(keymap_act[mode][i]);
224- keymap_act[mode][i] = string_make(macro__buf);
225- return 0;
226- }
227- case 'V':
228- {
229- /* Process "V:<num>:<kv>:<rv>:<gv>:<bv>" -- visual info */
230- if (tokenize(buf + 2, 5, zz, TOKENIZE_CHECKQUOTE) != 5) return 1;
231-
232- int i = (byte)strtol(zz[0], NULL, 0);
233- angband_color_table[i][0] = (byte)strtol(zz[1], NULL, 0);
234- angband_color_table[i][1] = (byte)strtol(zz[2], NULL, 0);
235- angband_color_table[i][2] = (byte)strtol(zz[3], NULL, 0);
236- angband_color_table[i][3] = (byte)strtol(zz[4], NULL, 0);
237- return 0;
238- }
239- case 'X':
240- case 'Y':
337+/*!
338+ * @brief Tトークンの解釈 / Process "T:<template>:<modifier chr>:<modifier name>:..." for 4 tokens
339+ * @param buf バッファ
340+ * @param zz トークン保管文字列
341+ * @return エラーコード
342+ */
343+static errr decide_template_modifier(int tok, char **zz)
344+{
345+ if (macro_template != NULL)
241346 {
242- /* Process "X:<str>" -- turn option off */
243- /* Process "Y:<str>" -- turn option on */
244- for (int i = 0; option_info[i].o_desc; i++)
347+ int macro_modifier_length = strlen(macro_modifier_chr);
348+ string_free(macro_template);
349+ macro_template = NULL;
350+ string_free(macro_modifier_chr);
351+ for (int i = 0; i < macro_modifier_length; i++)
245352 {
246- bool is_option = option_info[i].o_var != NULL;
247- is_option &= option_info[i].o_text != NULL;
248- is_option &= streq(option_info[i].o_text, buf + 2);
249- if (!is_option) continue;
250-
251- int os = option_info[i].o_set;
252- int ob = option_info[i].o_bit;
253-
254- if ((creature_ptr->playing || current_world_ptr->character_xtra) &&
255- (OPT_PAGE_BIRTH == option_info[i].o_page) && !current_world_ptr->wizard)
256- {
257- msg_format(_("初期オプションは変更できません! '%s'", "Birth options can not changed! '%s'"), buf);
258- msg_print(NULL);
259- return 0;
260- }
261-
262- if (buf[0] == 'X')
263- {
264- option_flag[os] &= ~(1L << ob);
265- (*option_info[i].o_var) = FALSE;
266- return 0;
267- }
268-
269- option_flag[os] |= (1L << ob);
270- (*option_info[i].o_var) = TRUE;
271- return 0;
353+ string_free(macro_modifier_name[i]);
272354 }
273355
274- msg_format(_("オプションの名前が正しくありません: %s", "Ignored invalid option: %s"), buf);
275- msg_print(NULL);
276- return 0;
356+ for (int i = 0; i < max_macrotrigger; i++)
357+ {
358+ string_free(macro_trigger_name[i]);
359+ string_free(macro_trigger_keycode[0][i]);
360+ string_free(macro_trigger_keycode[1][i]);
361+ }
362+
363+ max_macrotrigger = 0;
277364 }
278- case 'Z':
365+
366+ if (*zz[0] == '\0') return 0;
367+
368+ int zz_length = strlen(zz[1]);
369+ zz_length = MIN(MAX_MACRO_MOD, zz_length);
370+ if (2 + zz_length != tok) return 1;
371+
372+ macro_template = string_make(zz[0]);
373+ macro_modifier_chr = string_make(zz[1]);
374+ for (int i = 0; i < zz_length; i++)
279375 {
280- /* Process "Z:<type>:<str>" -- set spell color */
281- char *t = my_strchr(buf + 2, ':');
282- if (!t) return 1;
376+ macro_modifier_name[i] = string_make(zz[2 + i]);
377+ }
283378
284- *(t++) = '\0';
285- for (int i = 0; i < MAX_NAMED_NUM; i++)
286- {
287- if (!streq(gf_desc[i].name, buf + 2)) continue;
379+ return 0;
380+}
288381
289- gf_color[gf_desc[i].num] = (TERM_COLOR)quark_add(t);
290- return 0;
291- }
292382
383+/*!
384+ * @brief Tトークンの解釈 / Process "T:<trigger>:<keycode>:<shift-keycode>" for 2 or 3 tokens
385+ * @param tok トークン数
386+ * @param zz トークン保管文字列
387+ * @return エラーコード
388+ */
389+static errr interpret_macro_keycodes(int tok, char **zz)
390+{
391+ char buf_aux[MAX_MACRO_CHARS];
392+ char *t, *s;
393+ if (max_macrotrigger >= MAX_MACRO_TRIG)
394+ {
395+ msg_print(_("マクロトリガーの設定が多すぎます!", "Too many macro triggers!"));
293396 return 1;
294397 }
295- case 'T':
398+
399+ int m = max_macrotrigger;
400+ max_macrotrigger++;
401+ t = buf_aux;
402+ s = zz[0];
403+ while (*s)
296404 {
297- /* Initialize macro trigger names and a template */
298- /* Process "T:<trigger>:<keycode>:<shift-keycode>" */
299- /* Process "T:<template>:<modifier chr>:<modifier name>:..." */
300- int tok = tokenize(buf + 2, 2 + MAX_MACRO_MOD, zz, 0);
405+ if ('\\' == *s) s++;
406+ *t++ = *s++;
407+ }
301408
302- /* Process "T:<template>:<modifier chr>:<modifier name>:..." */
303- if (tok >= 4)
304- {
305- if (macro_template != NULL)
306- {
307- int macro_modifier_length = strlen(macro_modifier_chr);
308- string_free(macro_template);
309- macro_template = NULL;
310- string_free(macro_modifier_chr);
311- for (int i = 0; i < macro_modifier_length; i++)
312- {
313- string_free(macro_modifier_name[i]);
314- }
315-
316- for (int i = 0; i < max_macrotrigger; i++)
317- {
318- string_free(macro_trigger_name[i]);
319- string_free(macro_trigger_keycode[0][i]);
320- string_free(macro_trigger_keycode[1][i]);
321- }
322-
323- max_macrotrigger = 0;
324- }
325-
326- if (*zz[0] == '\0') return 0;
327-
328- int zz_length = strlen(zz[1]);
329- zz_length = MIN(MAX_MACRO_MOD, zz_length);
330- if (2 + zz_length != tok) return 1;
331-
332- macro_template = string_make(zz[0]);
333- macro_modifier_chr = string_make(zz[1]);
334- for (int i = 0; i < zz_length; i++)
335- {
336- macro_modifier_name[i] = string_make(zz[2 + i]);
337- }
409+ *t = '\0';
410+ macro_trigger_name[m] = string_make(buf_aux);
411+ macro_trigger_keycode[0][m] = string_make(zz[1]);
412+ if (tok == 3)
413+ {
414+ macro_trigger_keycode[1][m] = string_make(zz[2]);
415+ return 0;
416+ }
338417
339- return 0;
340- }
418+ macro_trigger_keycode[1][m] = string_make(zz[1]);
419+ return 0;
420+}
341421
342- /* Process "T:<trigger>:<keycode>:<shift-keycode>" */
343- if (tok < 2) return 0;
344422
345- char buf_aux[1024]; // todo TA勢から「少ない」とコメントがあったので増やす
346- char *t, *s;
347- if (max_macrotrigger >= MAX_MACRO_TRIG)
348- {
349- msg_print(_("マクロトリガーの設定が多すぎます!", "Too many macro triggers!"));
350- return 1;
351- }
423+/*!
424+ * todo 2.2.1r時点のコードからトークン数0~1の場合もエラーコード0だが、1であるべきでは?
425+ * @brief Tトークンの個数調査 (解釈はサブルーチンで) / Initialize macro trigger names and a template
426+ * @param buf バッファ
427+ * @return エラーコード
428+ */
429+static errr interpret_t_token(char *buf)
430+{
431+ char *zz[16];
432+ int tok = tokenize(buf + 2, 2 + MAX_MACRO_MOD, zz, 0);
433+ if (tok >= 4) return decide_template_modifier(tok, zz);
434+ if (tok < 2) return 0;
352435
353- int m = max_macrotrigger;
354- max_macrotrigger++;
355- t = buf_aux;
356- s = zz[0];
357- while (*s)
358- {
359- if ('\\' == *s) s++;
360- *t++ = *s++;
361- }
436+ return interpret_macro_keycodes(tok, zz);
437+}
362438
363- *t = '\0';
364- macro_trigger_name[m] = string_make(buf_aux);
365- macro_trigger_keycode[0][m] = string_make(zz[1]);
366- if (tok == 3)
367- {
368- macro_trigger_keycode[1][m] = string_make(zz[2]);
369- return 0;
370- }
371439
372- macro_trigger_keycode[1][m] = string_make(zz[1]);
440+/*!
441+ * @brief 設定ファイルの各行から各種テキスト情報を取得する /
442+ * Parse a sub-file of the "extra info" (format shown below)
443+ * @param creature_ptr プレーヤーへの参照ポインタ
444+ * @param buf データテキストの参照ポインタ
445+ * @return エラーコード
446+ * @details
447+ * <pre>
448+ * Each "action" line has an "action symbol" in the first column,
449+ * followed by a colon, followed by some command specific info,
450+ * usually in the form of "tokens" separated by colons or slashes.
451+ * Blank lines, lines starting with white space, and lines starting
452+ * with pound signs ("#") are ignored (as comments).
453+ * Note the use of "tokenize()" to allow the use of both colons and
454+ * slashes as delimeters, while still allowing final tokens which
455+ * may contain any characters including "delimiters".
456+ * Note the use of "strtol()" to allow all "integers" to be encoded
457+ * in decimal, hexidecimal, or octal form.
458+ * Note that "monster zero" is used for the "player" attr/char, "object
459+ * zero" will be used for the "stack" attr/char, and "feature zero" is
460+ * used for the "nothing" attr/char.
461+ * </pre>
462+ */
463+errr interpret_pref_file(player_type *creature_ptr, char *buf)
464+{
465+ if (buf[1] != ':') return 1;
466+
467+ switch (buf[0])
468+ {
469+ case 'H':
470+ {
471+ /* Process "H:<history>" */
472+ add_history_from_pref_line(buf + 2);
473+ return 0;
474+ }
475+ case 'R':
476+ return interpret_r_token(buf);
477+ case 'K':
478+ return interpret_k_token(buf);
479+ case 'F':
480+ return interpret_f_token(buf);
481+ case 'S':
482+ return interpret_s_token(buf);
483+ case 'U':
484+ return interpret_u_token(buf);
485+ case 'E':
486+ return interpret_e_token(buf);
487+ case 'A':
488+ {
489+ /* Process "A:<str>" -- save an "action" for later */
490+ text_to_ascii(macro__buf, buf + 2);
373491 return 0;
374492 }
493+ case 'P':
494+ return interpret_p_token(buf);
495+ case 'C':
496+ return interpret_c_token(buf);
497+ case 'V':
498+ return interpret_v_token(buf);
499+ case 'X':
500+ case 'Y':
501+ return interpret_xy_token(creature_ptr, buf);
502+ case 'Z':
503+ return interpret_z_token(buf);
504+ case 'T':
505+ return interpret_t_token(buf);
506+ default:
507+ return 1;
375508 }
376-
377- return 1;
378509 }
--- /dev/null
+++ b/src/io/player-status-dump.c
@@ -0,0 +1,70 @@
1+#include "angband.h"
2+#include "files.h"
3+#include "io/player-status-dump.h"
4+
5+
6+/*!
7+ * @brief 画面番号を指定してダンプする
8+ * @param creature_ptr プレーヤーへの参照ポインタ
9+ * @param fff ファイルポインタ
10+ * @param display_player 画面表示へのコールバック
11+ * @param map_name マップ名へのコールバック
12+ * @param screen_num 画面番号
13+ * @param start_y
14+ * @param end_y
15+ * @param change_color バッファへ詰める文字の変更有無
16+ * @return なし
17+ */
18+static void dump_player_status_with_screen_num(
19+ player_type *creature_ptr, FILE *fff, display_player_pf display_player, map_name_pf map_name,
20+ int screen_num, TERM_LEN start_y, TERM_LEN end_y, bool change_color)
21+{
22+ TERM_COLOR a;
23+ char c;
24+ char buf[1024];
25+ display_player(creature_ptr, screen_num, map_name);
26+ for (TERM_LEN y = start_y; y < end_y; y++)
27+ {
28+ TERM_LEN x;
29+ for (x = 0; x < 79; x++)
30+ {
31+ (void)(Term_what(x, y, &a, &c));
32+ if (!change_color)
33+ {
34+ buf[x] = c;
35+ continue;
36+ }
37+
38+ if (a < 128)
39+ buf[x] = c;
40+ else
41+ buf[x] = ' ';
42+ }
43+
44+ buf[x] = '\0';
45+ while ((x > 0) && (buf[x - 1] == ' '))
46+ buf[--x] = '\0';
47+
48+ fprintf(fff, "%s\n", buf);
49+ }
50+}
51+
52+
53+/*!
54+ * @brief プレイヤーのステータス表示をファイルにダンプする
55+ * @param creature_ptr プレーヤーへの参照ポインタ
56+ * @param fff ファイルポインタ
57+ * @param display_player 画面表示へのコールバック
58+ * @param map_name マップ名へのコールバック
59+ * @return なし
60+ */
61+void dump_aux_player_status(player_type *creature_ptr, FILE *fff, display_player_pf display_player, map_name_pf map_name)
62+{
63+ dump_player_status_with_screen_num(creature_ptr, fff, display_player, map_name, 0, 1, 22, FALSE);
64+ dump_player_status_with_screen_num(creature_ptr, fff, display_player, map_name, 1, 10, 19, FALSE);
65+ fprintf(fff, "\n");
66+ dump_player_status_with_screen_num(creature_ptr, fff, display_player, map_name, 2, 2, 22, TRUE);
67+ fprintf(fff, "\n");
68+ dump_player_status_with_screen_num(creature_ptr, fff, display_player, map_name, 3, 1, 22, TRUE);
69+ fprintf(fff, "\n");
70+}
--- /dev/null
+++ b/src/io/player-status-dump.h
@@ -0,0 +1,3 @@
1+#pragma once
2+
3+void dump_aux_player_status(player_type *creature_ptr, FILE *fff, display_player_pf display_player, map_name_pf map_name);
--- /dev/null
+++ b/src/io/special-class-dump.c
@@ -0,0 +1,268 @@
1+/*!
2+ * @brief
3+ * @date 2020/03/07
4+ * @author Hourier
5+ */
6+
7+#include "angband.h"
8+#include "special-class-dump.h"
9+#include "cmd/cmd-magiceat.h"
10+#include "objectkind.h"
11+#include "monster-spell.h"
12+
13+typedef struct {
14+ BIT_FLAGS f4;
15+ BIT_FLAGS f5;
16+ BIT_FLAGS f6;
17+} learnt_spell_table;
18+
19+/*!
20+ * @brief 魔力喰いを持つクラスの情報をダンプする
21+ * @param creature_ptr プレーヤーへの参照ポインタ
22+ * @param fff ファイルポインタ
23+ * @return なし
24+ */
25+static void dump_magic_eater(player_type *creature_ptr, FILE *fff)
26+{
27+ char s[EATER_EXT][MAX_NLEN];
28+ fprintf(fff, _("\n\n [取り込んだ魔法道具]\n", "\n\n [Magic devices eaten]\n"));
29+
30+ for (int ext = 0; ext < 3; ext++)
31+ {
32+ OBJECT_TYPE_VALUE tval = 0;
33+ switch (ext)
34+ {
35+ case 0:
36+ tval = TV_STAFF;
37+ fprintf(fff, _("\n[杖]\n", "\n[Staffs]\n"));
38+ break;
39+ case 1:
40+ tval = TV_WAND;
41+ fprintf(fff, _("\n[魔法棒]\n", "\n[Wands]\n"));
42+ break;
43+ case 2:
44+ tval = TV_ROD;
45+ fprintf(fff, _("\n[ロッド]\n", "\n[Rods]\n"));
46+ break;
47+ }
48+
49+ int eat_num = 0;
50+ for (OBJECT_SUBTYPE_VALUE i = 0; i < EATER_EXT; i++)
51+ {
52+ int idx = EATER_EXT * ext + i;
53+ int magic_num = creature_ptr->magic_num2[idx];
54+ if (!magic_num) continue;
55+
56+ KIND_OBJECT_IDX k_idx = lookup_kind(tval, i);
57+ if (!k_idx) continue;
58+ sprintf(s[eat_num], "%23s (%2d)", (k_name + k_info[k_idx].name), magic_num);
59+ eat_num++;
60+ }
61+
62+ if (eat_num <= 0)
63+ {
64+ fputs(_(" (なし)\n", " (none)\n"), fff);
65+ continue;
66+ }
67+
68+ OBJECT_SUBTYPE_VALUE i;
69+ for (i = 0; i < eat_num; i++)
70+ {
71+ fputs(s[i], fff);
72+ if (i % 3 < 2) fputs(" ", fff);
73+ else fputs("\n", fff);
74+ }
75+
76+ if (i % 3 > 0) fputs("\n", fff);
77+ }
78+}
79+
80+
81+/*!
82+ * @brief 鍛冶師のエッセンス情報をダンプする
83+ * @param creature_ptr プレーヤーへの参照ポインタ
84+ * @param fff ファイルポインタ
85+ * @return なし
86+ */
87+static void dump_smith(player_type *creature_ptr, FILE *fff)
88+{
89+ int i, id[250], n = 0, row;
90+ fprintf(fff, _("\n\n [手に入れたエッセンス]\n\n", "\n\n [Get Essence]\n\n"));
91+ fprintf(fff, _("エッセンス 個数 エッセンス 個数 エッセンス 個数",
92+ "Essence Num Essence Num Essence Num "));
93+ for (i = 0; essence_name[i]; i++)
94+ {
95+ if (!essence_name[i][0]) continue;
96+ id[n] = i;
97+ n++;
98+ }
99+
100+ row = n / 3 + 1;
101+ for (i = 0; i < row; i++)
102+ {
103+ fprintf(fff, "\n");
104+ fprintf(fff, "%-11s %5d ", essence_name[id[i]], (int)creature_ptr->magic_num1[id[i]]);
105+ if (i + row < n) fprintf(fff, "%-11s %5d ", essence_name[id[i + row]], (int)creature_ptr->magic_num1[id[i + row]]);
106+ if (i + row * 2 < n) fprintf(fff, "%-11s %5d", essence_name[id[i + row * 2]], (int)creature_ptr->magic_num1[id[i + row * 2]]);
107+ }
108+
109+ fputs("\n", fff);
110+}
111+
112+
113+/*!
114+ * @brief ダンプする情報に学習済魔法の種類を追加する
115+ * @param p ダンプ用のバッファ
116+ * @param col 行数
117+ * @param spell_type 魔法の種類
118+ * @param learnt_spell_ptr 学習済魔法のテーブル
119+ * @return なし
120+ */
121+static void add_monster_spell_type(char p[][80], int col, int spell_type, learnt_spell_table *learnt_spell_ptr)
122+{
123+ learnt_spell_ptr->f4 = 0;
124+ learnt_spell_ptr->f5 = 0;
125+ learnt_spell_ptr->f6 = 0;
126+ set_rf_masks(&learnt_spell_ptr->f4, &learnt_spell_ptr->f5, &learnt_spell_ptr->f6, spell_type);
127+ switch (spell_type)
128+ {
129+ case MONSPELL_TYPE_BOLT:
130+ strcat(p[col], _("\n [ボルト型]\n", "\n [Bolt Type]\n"));
131+ break;
132+
133+ case MONSPELL_TYPE_BALL:
134+ strcat(p[col], _("\n [ボール型]\n", "\n [Ball Type]\n"));
135+ break;
136+
137+ case MONSPELL_TYPE_BREATH:
138+ strcat(p[col], _("\n [ブレス型]\n", "\n [ Breath ]\n"));
139+ break;
140+
141+ case MONSPELL_TYPE_SUMMON:
142+ strcat(p[col], _("\n [召喚魔法]\n", "\n [Summonning]\n"));
143+ break;
144+
145+ case MONSPELL_TYPE_OTHER:
146+ strcat(p[col], _("\n [ その他 ]\n", "\n [Other Type]\n"));
147+ break;
148+ }
149+}
150+
151+
152+/*!
153+ * @brief 青魔道士の学習済魔法をダンプする
154+ * @param creature_ptr プレーヤーへの参照ポインタ
155+ * @param fff ファイルポインタ
156+ * @return なし
157+ */
158+static void dump_blue_mage(player_type *creature_ptr, FILE *fff)
159+{
160+ char p[60][80];
161+ for (int i = 0; i < 60; i++)
162+ {
163+ p[i][0] = '\0';
164+ }
165+
166+ int col = 0;
167+ strcat(p[col], _("\n\n [学習済みの青魔法]\n", "\n\n [Learned Blue Magic]\n"));
168+
169+ int spellnum[MAX_MONSPELLS];
170+ for (int spell_type = 1; spell_type < 6; spell_type++)
171+ {
172+ col++;
173+ learnt_spell_table learnt_magic;
174+ add_monster_spell_type(p, col, spell_type, &learnt_magic);
175+
176+ int num = 0;
177+ for (int i = 0; i < 32; i++)
178+ {
179+ if ((0x00000001 << i) & learnt_magic.f4) spellnum[num++] = i;
180+ }
181+
182+ for (int i = 32; i < 64; i++)
183+ {
184+ if ((0x00000001 << (i - 32)) & learnt_magic.f5) spellnum[num++] = i;
185+ }
186+
187+ for (int i = 64; i < 96; i++)
188+ {
189+ if ((0x00000001 << (i - 64)) & learnt_magic.f6) spellnum[num++] = i;
190+ }
191+
192+ col++;
193+ bool pcol = FALSE;
194+ strcat(p[col], " ");
195+
196+ for (int i = 0; i < num; i++)
197+ {
198+ if (creature_ptr->magic_num2[spellnum[i]] == 0) continue;
199+
200+ pcol = TRUE;
201+ int l1 = strlen(p[col]);
202+ int l2 = strlen(monster_powers_short[spellnum[i]]);
203+ if ((l1 + l2) >= 75)
204+ {
205+ strcat(p[col], "\n");
206+ col++;
207+ strcat(p[col], " ");
208+ }
209+
210+ strcat(p[col], monster_powers_short[spellnum[i]]);
211+ strcat(p[col], ", ");
212+ }
213+
214+ if (!pcol)
215+ {
216+ strcat(p[col], _("なし", "None"));
217+ strcat(p[col], "\n");
218+ continue;
219+ }
220+
221+ if (p[col][strlen(p[col]) - 2] == ',')
222+ {
223+ p[col][strlen(p[col]) - 2] = '\0';
224+ }
225+ else
226+ {
227+ p[col][strlen(p[col]) - 10] = '\0';
228+ }
229+
230+ strcat(p[col], "\n");
231+ }
232+
233+ for (int i = 0; i <= col; i++)
234+ {
235+ fputs(p[i], fff);
236+ }
237+}
238+
239+
240+/*!
241+ * @brief プレイヤーの職業能力情報をファイルにダンプする
242+ * @param creature_ptr プレーヤーへの参照ポインタ
243+ * @param fff ファイルポインタ
244+ * @return なし
245+ */
246+void dump_aux_class_special(player_type *creature_ptr, FILE *fff)
247+{
248+ switch (creature_ptr->pclass)
249+ {
250+ case CLASS_MAGIC_EATER:
251+ {
252+ dump_magic_eater(creature_ptr, fff);
253+ return;
254+ }
255+ case CLASS_SMITH:
256+ {
257+ dump_smith(creature_ptr, fff);
258+ return;
259+ }
260+ case CLASS_BLUE_MAGE:
261+ {
262+ dump_blue_mage(creature_ptr, fff);
263+ return;
264+ }
265+ default:
266+ return;
267+ }
268+}
--- /dev/null
+++ b/src/io/special-class-dump.h
@@ -0,0 +1,3 @@
1+#pragma once
2+
3+void dump_aux_class_special(player_type *creature_ptr, FILE *fff);
--- a/src/monster-process.c
+++ b/src/monster-process.c
@@ -15,2568 +15,416 @@
1515
1616 #include "angband.h"
1717 #include "util.h"
18+#include "monster/monster-direction.h"
19+#include "monster/monster-move.h"
20+#include "monster/monster-runaway.h"
21+#include "monster/monster-util.h"
22+#include "monster/monster-update.h"
23+#include "monster/quantum-effect.h"
1824
1925 #include "cmd-dump.h"
2026 #include "cmd-pet.h"
2127 #include "creature.h"
2228 #include "melee.h"
23-#include "spells.h"
24-#include "spells-floor.h"
2529 #include "spells-summon.h"
26-#include "quest.h"
2730 #include "avatar.h"
2831 #include "realm-hex.h"
29-#include "object-flavor.h"
30-#include "object-hook.h"
3132 #include "feature.h"
3233 #include "grid.h"
3334 #include "player-move.h"
3435 #include "monster-status.h"
3536 #include "monster-spell.h"
3637 #include "monster-process.h"
37-#include "monster-dist-offsets.h"
38-#include "monsterrace-hook.h"
39-#include "dungeon.h"
40-#include "floor.h"
41-#include "files.h"
42-#include "view-mainwindow.h"
43-
44-typedef struct {
45- bool see_m;
46- bool aware;
47- bool is_riding_mon;
48- bool do_turn;
49- bool do_move;
50- bool do_view;
51- bool do_take;
52- bool must_alter_to_move;
53-
54- bool did_open_door;
55- bool did_bash_door;
56- bool did_take_item;
57- bool did_kill_item;
58- bool did_move_body;
59- bool did_pass_wall;
60- bool did_kill_wall;
61-} turn_flags;
62-
63-typedef struct {
64- BIT_FLAGS old_r_flags1;
65- BIT_FLAGS old_r_flags2;
66- BIT_FLAGS old_r_flags3;
67- BIT_FLAGS old_r_flags4;
68- BIT_FLAGS old_r_flags5;
69- BIT_FLAGS old_r_flags6;
70- BIT_FLAGS old_r_flagsr;
71-
72- byte old_r_blows0;
73- byte old_r_blows1;
74- byte old_r_blows2;
75- byte old_r_blows3;
76-
77- byte old_r_cast_spell;
78-} old_race_flags;
79-
80-typedef struct {
81- POSITION gy;
82- POSITION gx;
83- POSITION gdis;
84-} coordinate_candidate;
85-
86-turn_flags *init_turn_flags(player_type *target_ptr, MONSTER_IDX m_idx, turn_flags *turn_flags_ptr);
87-old_race_flags *init_old_race_flags(old_race_flags *old_race_flags_ptr);
88-
89-bool get_enemy_dir(player_type *target_ptr, MONSTER_IDX m_idx, int *mm);
90-void decide_enemy_approch_direction(player_type *target_ptr, MONSTER_IDX m_idx, int start, int plus, POSITION *y, POSITION *x);
91-bool decide_pet_approch_direction(player_type *target_ptr, monster_type *m_ptr, monster_type *t_ptr);
92-void store_enemy_approch_direction(int *mm, POSITION y, POSITION x);
93-
94-bool find_safety(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp);
95-coordinate_candidate sweep_safe_coordinate(player_type *target_ptr, MONSTER_IDX m_idx, const POSITION *y_offsets, const POSITION *x_offsets, int d);
96-
97-bool find_hiding(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp);
98-void sweep_hiding_candidate(player_type *target_ptr, monster_type *m_ptr, const POSITION *y_offsets, const POSITION *x_offsets, coordinate_candidate *candidate);
9938
10039 void decide_drop_from_monster(player_type *target_ptr, MONSTER_IDX m_idx, bool is_riding_mon);
10140 bool process_stealth(player_type *target_ptr, MONSTER_IDX m_idx);
10241 bool vanish_summoned_children(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m);
10342 void awake_monster(player_type *target_ptr, MONSTER_IDX m_idx);
10443 void process_angar(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m);
105-bool process_quantum_effect(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m);
106-void vanish_nonunique(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m);
107-void produce_quantum_effect(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m);
108-bool explode_monster(player_type *target_ptr, MONSTER_IDX m_idx);
44+bool explode_grenade(player_type *target_ptr, MONSTER_IDX m_idx);
10945 bool decide_monster_multiplication(player_type *target_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox);
110-bool decide_monster_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx, bool aware);
111-bool random_walk(player_type *target_ptr, DIRECTION *mm, monster_type *m_ptr);
112-bool decide_pet_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx);
113-bool runaway_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx);
114-void escape_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, GAME_TEXT *m_name);
11546 void process_special(player_type *target_ptr, MONSTER_IDX m_idx);
116-void process_speak_sound(player_type *target_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, bool aware);
11747 bool cast_spell(player_type *target_ptr, MONSTER_IDX m_idx, bool aware);
11848
119-bool process_wall(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx, bool can_cross);
120-bool process_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx);
121-bool bash_normal_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx);
122-void bash_glass_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, feature_type *f_ptr, bool may_bash);
123-bool process_protection_rune(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx);
124-bool process_explosive_rune(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx);
125-
126-void exe_monster_attack_to_player(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION ny, POSITION nx);
127-bool process_monster_attack_to_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, grid_type *g_ptr, bool can_cross);
128-bool exe_monster_attack_to_monster(player_type *target_ptr, MONSTER_IDX m_idx, grid_type *g_ptr);
129-
130-bool process_monster_movement(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, DIRECTION *mm, POSITION oy, POSITION ox, int *count);
131-bool process_post_dig_wall(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx);
132-bool update_riding_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, POSITION ny, POSITION nx);
133-
134-void update_object_by_monster_movement(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION ny, POSITION nx);
135-
136-void update_player_type(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_race *r_ptr);
137-void update_monster_race_flags(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr);
138-void update_object_flags(BIT_FLAGS *flgs, BIT_FLAGS *flg2, BIT_FLAGS *flg3, BIT_FLAGS *flgr);
139-void monster_pickup_object(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, object_type *o_ptr, bool is_special_object, POSITION ny, POSITION nx, GAME_TEXT *m_name, GAME_TEXT *o_name, OBJECT_IDX this_o_idx);
14049 bool process_monster_fear(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx);
14150
142-void save_old_race_flags(player_type *target_ptr, old_race_flags *old_race_flags_ptr);
14351 void sweep_monster_process(player_type *target_ptr);
14452 bool decide_process_continue(player_type *target_ptr, monster_type *m_ptr);
145-SPEED decide_monster_speed(player_type *target_ptr, monster_type *m_ptr, int monster_number);
146-void update_player_window(player_type *target_ptr, old_race_flags *old_race_flags_ptr);
147-
148-/*!
149- * @brief モンスターが敵に接近するための方向を計算するメインルーチン
150- * Calculate the direction to the next enemy
151- * @param target_ptr プレーヤーへの参照ポインタ
152- * @param m_idx モンスターの参照ID
153- * @param mm 移動するべき方角IDを返す参照ポインタ
154- * @return 方向が確定した場合TRUE、接近する敵がそもそもいない場合FALSEを返す
155- */
156-bool get_enemy_dir(player_type *target_ptr, MONSTER_IDX m_idx, int *mm)
157-{
158- floor_type *floor_ptr = target_ptr->current_floor_ptr;
159- monster_type *m_ptr = &floor_ptr->m_list[m_idx];
160-
161- POSITION x = 0, y = 0;
162- if (target_ptr->riding_t_m_idx && player_bold(target_ptr, m_ptr->fy, m_ptr->fx))
163- {
164- y = floor_ptr->m_list[target_ptr->riding_t_m_idx].fy;
165- x = floor_ptr->m_list[target_ptr->riding_t_m_idx].fx;
166- }
167- else if (is_pet(m_ptr) && target_ptr->pet_t_m_idx)
168- {
169- y = floor_ptr->m_list[target_ptr->pet_t_m_idx].fy;
170- x = floor_ptr->m_list[target_ptr->pet_t_m_idx].fx;
171- }
172- else
173- {
174- int start;
175- int plus = 1;
176- if (target_ptr->phase_out)
177- {
178- start = randint1(floor_ptr->m_max - 1) + floor_ptr->m_max;
179- if (randint0(2)) plus = -1;
180- }
181- else
182- {
183- start = floor_ptr->m_max + 1;
184- }
185-
186- decide_enemy_approch_direction(target_ptr, m_idx, start, plus, &y, &x);
187-
188- if ((x == 0) && (y == 0)) return FALSE;
189- }
190-
191- x -= m_ptr->fx;
192- y -= m_ptr->fy;
193-
194- store_enemy_approch_direction(mm, y, x);
195- return TRUE;
196-}
197-
19853
19954 /*!
200- * @brief モンスターが敵に接近するための方向を決定する
55+ * @brief モンスター単体の1ターン行動処理メインルーチン /
56+ * Process a monster
20157 * @param target_ptr プレーヤーへの参照ポインタ
202- * @param m_idx モンスターID
203- * @param start モンスターIDの開始
204- * @param plus モンスターIDの増減 (1/2 の確率で+1、1/2の確率で-1)
205- * @param y モンスターの移動方向Y
206- * @param x モンスターの移動方向X
58+ * @param m_idx 行動モンスターの参照ID
20759 * @return なし
208- */
209-void decide_enemy_approch_direction(player_type *target_ptr, MONSTER_IDX m_idx, int start, int plus, POSITION *y, POSITION *x)
210-{
211- floor_type *floor_ptr = target_ptr->current_floor_ptr;
212- monster_type *m_ptr = &floor_ptr->m_list[m_idx];
213- monster_race *r_ptr = &r_info[m_ptr->r_idx];
214- for (int i = start; ((i < start + floor_ptr->m_max) && (i > start - floor_ptr->m_max)); i += plus)
215- {
216- MONSTER_IDX dummy = (i % floor_ptr->m_max);
217- if (dummy == 0) continue;
218-
219- MONSTER_IDX t_idx = dummy;
220- monster_type *t_ptr;
221- t_ptr = &floor_ptr->m_list[t_idx];
222- if (t_ptr == m_ptr) continue;
223- if (!monster_is_valid(t_ptr)) continue;
224- if (decide_pet_approch_direction(target_ptr, m_ptr, t_ptr)) continue;
225- if (!are_enemies(target_ptr, m_ptr, t_ptr)) continue;
226-
227- if (((r_ptr->flags2 & RF2_PASS_WALL) && ((m_idx != target_ptr->riding) || target_ptr->pass_wall)) ||
228- ((r_ptr->flags2 & RF2_KILL_WALL) && (m_idx != target_ptr->riding)))
229- {
230- if (!in_disintegration_range(floor_ptr, m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx)) continue;
231- }
232- else
233- {
234- if (!projectable(target_ptr, m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx)) continue;
235- }
236-
237- *y = t_ptr->fy;
238- *x = t_ptr->fx;
239- return;
240- }
241-}
242-
243-
244-/*!
245- * @brief ペットが敵に接近するための方向を決定する
246- * @param target_ptr プレーヤーへの参照ポインタ
247- * @param m_ptr 移動を試みているモンスターへの参照ポインタ
248- * @param t_ptr 移動先モンスターへの参照ポインタ
249- * @param plus モンスターIDの増減 (1/2 の確率で+1、1/2の確率で-1)
250- * @return ペットがモンスターに近づくならばTRUE
251- */
252-bool decide_pet_approch_direction(player_type *target_ptr, monster_type *m_ptr, monster_type *t_ptr)
253-{
254- monster_race *r_ptr = &r_info[m_ptr->r_idx];
255- if (!is_pet(m_ptr)) return FALSE;
256-
257- if (target_ptr->pet_follow_distance < 0)
258- {
259- if (t_ptr->cdis <= (0 - target_ptr->pet_follow_distance))
260- {
261- return TRUE;
262- }
263- }
264- else if ((m_ptr->cdis < t_ptr->cdis) && (t_ptr->cdis > target_ptr->pet_follow_distance))
265- {
266- return TRUE;
267- }
268-
269- return (r_ptr->aaf < t_ptr->cdis);
270-}
271-
272-
273-/*!
274- * @brief モンスターの移動方向を保存する
275- * @param mm 移動方向
276- * @param y 移動先Y座標
277- * @param x 移動先X座標
278- */
279-void store_enemy_approch_direction(int *mm, POSITION y, POSITION x)
280-{
281- /* North, South, East, West, North-West, North-East, South-West, South-East */
282- if ((y < 0) && (x == 0))
283- {
284- mm[0] = 8;
285- mm[1] = 7;
286- mm[2] = 9;
287- }
288- else if ((y > 0) && (x == 0))
289- {
290- mm[0] = 2;
291- mm[1] = 1;
292- mm[2] = 3;
293- }
294- else if ((x > 0) && (y == 0))
295- {
296- mm[0] = 6;
297- mm[1] = 9;
298- mm[2] = 3;
299- }
300- else if ((x < 0) && (y == 0))
301- {
302- mm[0] = 4;
303- mm[1] = 7;
304- mm[2] = 1;
305- }
306- else if ((y < 0) && (x < 0))
307- {
308- mm[0] = 7;
309- mm[1] = 4;
310- mm[2] = 8;
311- }
312- else if ((y < 0) && (x > 0))
313- {
314- mm[0] = 9;
315- mm[1] = 6;
316- mm[2] = 8;
317- }
318- else if ((y > 0) && (x < 0))
319- {
320- mm[0] = 1;
321- mm[1] = 4;
322- mm[2] = 2;
323- }
324- else if ((y > 0) && (x > 0))
325- {
326- mm[0] = 3;
327- mm[1] = 6;
328- mm[2] = 2;
329- }
330-}
331-
332-
333-/*!
334- * @brief モンスターがプレイヤーから逃走するかどうかを返す /
335- * Returns whether a given monster will try to run from the player.
336- * @param m_idx 逃走するモンスターの参照ID
337- * @return モンスターがプレイヤーから逃走するならばTRUEを返す。
33860 * @details
339- * Monsters will attempt to avoid very powerful players. See below.\n
61+ * The monster is known to be within 100 grids of the player\n
34062 *\n
341- * Because this function is called so often, little details are important\n
342- * for efficiency. Like not using "mod" or "div" when possible. And\n
343- * attempting to check the conditions in an optimal order. Note that\n
344- * "(x << 2) == (x * 4)" if "x" has enough bits to hold the result.\n
63+ * In several cases, we directly update the monster lore\n
34564 *\n
346- * Note that this function is responsible for about one to five percent\n
347- * of the processor use in normal conditions...\n
348- */
349-static bool mon_will_run(player_type *target_ptr, MONSTER_IDX m_idx)
350-{
351- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
352- monster_race *r_ptr = &r_info[m_ptr->r_idx];
353-
354- if (is_pet(m_ptr))
355- {
356- return ((target_ptr->pet_follow_distance < 0) &&
357- (m_ptr->cdis <= (0 - target_ptr->pet_follow_distance)));
358- }
359-
360- if (m_ptr->cdis > MAX_SIGHT + 5) return FALSE;
361- if (MON_MONFEAR(m_ptr)) return TRUE;
362- if (m_ptr->cdis <= 5) return FALSE;
363-
364- PLAYER_LEVEL p_lev = target_ptr->lev;
365- DEPTH m_lev = r_ptr->level + (m_idx & 0x08) + 25;
366- if (m_lev > p_lev + 4) return FALSE;
367- if (m_lev + 4 <= p_lev) return TRUE;
368-
369- HIT_POINT p_chp = target_ptr->chp;
370- HIT_POINT p_mhp = target_ptr->mhp;
371- HIT_POINT m_chp = m_ptr->hp;
372- HIT_POINT m_mhp = m_ptr->maxhp;
373- u32b p_val = (p_lev * p_mhp) + (p_chp << 2);
374- u32b m_val = (m_lev * m_mhp) + (m_chp << 2);
375- if (p_val * m_mhp > m_val * p_mhp) return TRUE;
376-
377- return FALSE;
378-}
379-
380-
381-/*!
382- * @brief モンスターがプレイヤーに向けて遠距離攻撃を行うことが可能なマスを走査する /
383- * Search spell castable grid
384- * @param target_ptr プレーヤーへの参照ポインタ
385- * @param m_idx モンスターの参照ID
386- * @param yp 適したマスのY座標を返す参照ポインタ
387- * @param xp 適したマスのX座標を返す参照ポインタ
388- * @return 有効なマスがあった場合TRUEを返す
389- */
390-static bool get_moves_aux2(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
391-{
392- floor_type *floor_ptr = target_ptr->current_floor_ptr;
393- monster_type *m_ptr = &floor_ptr->m_list[m_idx];
394- monster_race *r_ptr = &r_info[m_ptr->r_idx];
395-
396- POSITION y1 = m_ptr->fy;
397- POSITION x1 = m_ptr->fx;
398-
399- if (projectable(target_ptr, y1, x1, target_ptr->y, target_ptr->x)) return FALSE;
400-
401- int now_cost = floor_ptr->grid_array[y1][x1].cost;
402- if (now_cost == 0) now_cost = 999;
403-
404- bool can_open_door = FALSE;
405- if (r_ptr->flags2 & (RF2_BASH_DOOR | RF2_OPEN_DOOR))
406- {
407- can_open_door = TRUE;
408- }
409-
410- int best = 999;
411- for (int i = 7; i >= 0; i--)
412- {
413- POSITION y = y1 + ddy_ddd[i];
414- POSITION x = x1 + ddx_ddd[i];
415- if (!in_bounds2(floor_ptr, y, x)) continue;
416- if (player_bold(target_ptr, y, x)) return FALSE;
417-
418- grid_type *g_ptr;
419- g_ptr = &floor_ptr->grid_array[y][x];
420- int cost = g_ptr->cost;
421- if (!(((r_ptr->flags2 & RF2_PASS_WALL) && ((m_idx != target_ptr->riding) || target_ptr->pass_wall)) || ((r_ptr->flags2 & RF2_KILL_WALL) && (m_idx != target_ptr->riding))))
422- {
423- if (cost == 0) continue;
424- if (!can_open_door && is_closed_door(target_ptr, g_ptr->feat)) continue;
425- }
426-
427- if (cost == 0) cost = 998;
428-
429- if (now_cost < cost) continue;
430- if (!projectable(target_ptr, y, x, target_ptr->y, target_ptr->x)) continue;
431- if (best < cost) continue;
432-
433- best = cost;
434- *yp = y1 + ddy_ddd[i];
435- *xp = x1 + ddx_ddd[i];
436- }
437-
438- if (best == 999) return FALSE;
439-
440- return TRUE;
441-}
442-
443-
444-/*!
445- * todo まだ分割せず放置 (このままいくと3000行を超えかねない)
446- * @brief モンスターがプレイヤーに向けて接近することが可能なマスを走査する /
447- * Choose the "best" direction for "flowing"
448- * @param m_idx モンスターの参照ID
449- * @param yp 移動先のマスのY座標を返す参照ポインタ
450- * @param xp 移動先のマスのX座標を返す参照ポインタ
451- * @param no_flow モンスターにFLOWフラグが経っていない状態でTRUE
452- * @return 有効なマスがあった場合TRUEを返す
453- * @details
454- * Note that ghosts and rock-eaters are never allowed to "flow",\n
455- * since they should move directly towards the player.\n
65+ * Note that a monster is only allowed to "reproduce" if there\n
66+ * are a limited number of "reproducing" monsters on the current\n
67+ * level. This should prevent the level from being "swamped" by\n
68+ * reproducing monsters. It also allows a large mass of mice to\n
69+ * prevent a louse from multiplying, but this is a small price to\n
70+ * pay for a simple multiplication method.\n
45671 *\n
457- * Prefer "non-diagonal" directions, but twiddle them a little\n
458- * to angle slightly towards the player's actual location.\n
72+ * XXX Monster fear is slightly odd, in particular, monsters will\n
73+ * fixate on opening a door even if they cannot open it. Actually,\n
74+ * the same thing happens to normal monsters when they hit a door\n
45975 *\n
460- * Allow very perceptive monsters to track old "spoor" left by\n
461- * previous locations occupied by the player. This will tend\n
462- * to have monsters end up either near the player or on a grid\n
463- * recently occupied by the player (and left via "teleport").\n
76+ * In addition, monsters which *cannot* open or bash\n
77+ * down a door will still stand there trying to open it...\n
46478 *\n
465- * Note that if "smell" is turned on, all monsters get vicious.\n
79+ * XXX Technically, need to check for monster in the way\n
80+ * combined with that monster being in a wall (or door?)\n
46681 *\n
467- * Also note that teleporting away from a location will cause\n
468- * the monsters who were chasing you to converge on that location\n
469- * as long as you are still near enough to "annoy" them without\n
470- * being close enough to chase directly. I have no idea what will\n
471- * happen if you combine "smell" with low "aaf" values.\n
82+ * A "direction" of "5" means "pick a random direction".\n
47283 */
473-static bool get_moves_aux(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp, bool no_flow)
84+void process_monster(player_type *target_ptr, MONSTER_IDX m_idx)
47485 {
475- grid_type *g_ptr;
476- floor_type *floor_ptr = target_ptr->current_floor_ptr;
477- monster_type *m_ptr = &floor_ptr->m_list[m_idx];
86+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
47887 monster_race *r_ptr = &r_info[m_ptr->r_idx];
88+ turn_flags tmp_flags;
89+ turn_flags *turn_flags_ptr = init_turn_flags(target_ptr->riding, m_idx, &tmp_flags);
90+ turn_flags_ptr->see_m = is_seen(m_ptr);
47991
480- if (r_ptr->flags4 & (RF4_ATTACK_MASK) ||
481- r_ptr->a_ability_flags1 & (RF5_ATTACK_MASK) ||
482- r_ptr->a_ability_flags2 & (RF6_ATTACK_MASK))
92+ decide_drop_from_monster(target_ptr, m_idx, turn_flags_ptr->is_riding_mon);
93+ if ((m_ptr->mflag2 & MFLAG2_CHAMELEON) && one_in_(13) && !MON_CSLEEP(m_ptr))
48394 {
484- if (get_moves_aux2(target_ptr, m_idx, yp, xp)) return TRUE;
95+ choose_new_monster(target_ptr, m_idx, FALSE, 0);
96+ r_ptr = &r_info[m_ptr->r_idx];
48597 }
48698
487- if (no_flow) return FALSE;
488- if ((r_ptr->flags2 & RF2_PASS_WALL) && ((m_idx != target_ptr->riding) || target_ptr->pass_wall)) return FALSE;
489- if ((r_ptr->flags2 & RF2_KILL_WALL) && (m_idx != target_ptr->riding)) return FALSE;
490-
491- POSITION y1 = m_ptr->fy;
492- POSITION x1 = m_ptr->fx;
493- if (player_has_los_bold(target_ptr, y1, x1) && projectable(target_ptr, target_ptr->y, target_ptr->x, y1, x1)) return FALSE;
494-
495- g_ptr = &floor_ptr->grid_array[y1][x1];
496-
497- int best;
498- bool use_scent = FALSE;
499- if (g_ptr->cost)
500- {
501- best = 999;
502- }
503- else if (g_ptr->when)
504- {
505- if (floor_ptr->grid_array[target_ptr->y][target_ptr->x].when - g_ptr->when > 127) return FALSE;
99+ turn_flags_ptr->aware = process_stealth(target_ptr, m_idx);
100+ if (vanish_summoned_children(target_ptr, m_idx, turn_flags_ptr->see_m)) return;
101+ if (process_quantum_effect(target_ptr, m_idx, turn_flags_ptr->see_m)) return;
102+ if (explode_grenade(target_ptr, m_idx)) return;
103+ if (runaway_monster(target_ptr, turn_flags_ptr, m_idx)) return;
506104
507- use_scent = TRUE;
508- best = 0;
509- }
510- else
105+ awake_monster(target_ptr, m_idx);
106+ if (MON_STUNNED(m_ptr))
511107 {
512- return FALSE;
108+ if (one_in_(2)) return;
513109 }
514110
515- for (int i = 7; i >= 0; i--)
111+ if (turn_flags_ptr->is_riding_mon)
516112 {
517- POSITION y = y1 + ddy_ddd[i];
518- POSITION x = x1 + ddx_ddd[i];
519-
520- if (!in_bounds2(floor_ptr, y, x)) continue;
521-
522- g_ptr = &floor_ptr->grid_array[y][x];
523- if (use_scent)
524- {
525- int when = g_ptr->when;
526- if (best > when) continue;
527-
528- best = when;
529- }
530- else
531- {
532- int cost;
533- if (r_ptr->flags2 & (RF2_BASH_DOOR | RF2_OPEN_DOOR))
534- {
535- cost = g_ptr->dist;
536- }
537- else
538- {
539- cost = g_ptr->cost;
540- }
541-
542- if ((cost == 0) || (best < cost)) continue;
543-
544- best = cost;
545- }
546-
547- *yp = target_ptr->y + 16 * ddy_ddd[i];
548- *xp = target_ptr->x + 16 * ddx_ddd[i];
113+ target_ptr->update |= (PU_BONUS);
549114 }
550115
551- if (best == 999 || best == 0) return FALSE;
552-
553- return TRUE;
554-}
555-
556-
557-/*!
558- * @brief モンスターがプレイヤーから逃走することが可能なマスを走査する /
559- * Provide a location to flee to, but give the player a wide berth.
560- * @param m_idx モンスターの参照ID
561- * @param yp 移動先のマスのY座標を返す参照ポインタ
562- * @param xp 移動先のマスのX座標を返す参照ポインタ
563- * @return 有効なマスがあった場合TRUEを返す
564- * @details
565- * A monster may wish to flee to a location that is behind the player,\n
566- * but instead of heading directly for it, the monster should "swerve"\n
567- * around the player so that he has a smaller chance of getting hit.\n
568- */
569-static bool get_fear_moves_aux(floor_type *floor_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
570-{
571- POSITION gy = 0, gx = 0;
572-
573- monster_type *m_ptr = &floor_ptr->m_list[m_idx];
574- POSITION fy = m_ptr->fy;
575- POSITION fx = m_ptr->fx;
576-
577- POSITION y1 = fy - (*yp);
578- POSITION x1 = fx - (*xp);
579-
580- int score = -1;
581- for (int i = 7; i >= 0; i--)
582- {
583- POSITION y = fy + ddy_ddd[i];
584- POSITION x = fx + ddx_ddd[i];
585- if (!in_bounds2(floor_ptr, y, x)) continue;
586-
587- POSITION dis = distance(y, x, y1, x1);
588- POSITION s = 5000 / (dis + 3) - 500 / (floor_ptr->grid_array[y][x].dist + 1);
589- if (s < 0) s = 0;
590-
591- if (s < score) continue;
116+ process_angar(target_ptr, m_idx, turn_flags_ptr->see_m);
592117
593- score = s;
594- gy = y;
595- gx = x;
596- }
118+ POSITION oy = m_ptr->fy;
119+ POSITION ox = m_ptr->fx;
120+ if (decide_monster_multiplication(target_ptr, m_idx, oy, ox)) return;
597121
598- if (score == -1) return FALSE;
122+ process_special(target_ptr, m_idx);
123+ process_speak_sound(target_ptr, m_idx, oy, ox, turn_flags_ptr->aware);
124+ if (cast_spell(target_ptr, m_idx, turn_flags_ptr->aware)) return;
599125
600- (*yp) = fy - gy;
601- (*xp) = fx - gx;
126+ DIRECTION mm[8];
127+ mm[0] = mm[1] = mm[2] = mm[3] = 0;
128+ mm[4] = mm[5] = mm[6] = mm[7] = 0;
602129
603- return TRUE;
604-}
130+ if (!decide_monster_movement_direction(target_ptr, mm, m_idx, turn_flags_ptr->aware)) return;
605131
132+ int count = 0;
133+ if (!process_monster_movement(target_ptr, turn_flags_ptr, m_idx, mm, oy, ox, &count)) return;
606134
607-coordinate_candidate init_coordinate_candidate(void)
608-{
609- coordinate_candidate candidate;
610- candidate.gy = 0;
611- candidate.gx = 0;
612- candidate.gdis = 0;
613- return candidate;
614-}
135+ /*
136+ * Forward movements failed, but now received LOS attack!
137+ * Try to flow by smell.
138+ */
139+ if (target_ptr->no_flowed && count > 2 && m_ptr->target_y)
140+ m_ptr->mflag2 &= ~MFLAG2_NOFLOW;
615141
616-/*!
617- * @brief モンスターが逃げ込める安全な地点を返す /
618- * Choose a "safe" location near a monster for it to run toward.
619- * @param target_ptr プレーヤーへの参照ポインタ
620- * @param m_idx モンスターの参照ID
621- * @param yp 移動先のマスのY座標を返す参照ポインタ
622- * @param xp 移動先のマスのX座標を返す参照ポインタ
623- * @return 有効なマスがあった場合TRUEを返す
624- * @details
625- * A location is "safe" if it can be reached quickly and the player\n
626- * is not able to fire into it (it isn't a "clean shot"). So, this will\n
627- * cause monsters to "duck" behind walls. Hopefully, monsters will also\n
628- * try to run towards corridor openings if they are in a room.\n
629- *\n
630- * This function may take lots of CPU time if lots of monsters are\n
631- * fleeing.\n
632- *\n
633- * Return TRUE if a safe location is available.\n
634- */
635-bool find_safety(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
636-{
637- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
638- for (POSITION d = 1; d < 10; d++)
142+ if (!turn_flags_ptr->do_turn && !turn_flags_ptr->do_move && !MON_MONFEAR(m_ptr) && !turn_flags_ptr->is_riding_mon && turn_flags_ptr->aware)
639143 {
640- const POSITION *y_offsets;
641- y_offsets = dist_offsets_y[d];
642-
643- const POSITION *x_offsets;
644- x_offsets = dist_offsets_x[d];
645-
646- coordinate_candidate candidate = sweep_safe_coordinate(target_ptr, m_idx, y_offsets, x_offsets, d);
647-
648- if (candidate.gdis <= 0) continue;
649-
650- *yp = m_ptr->fy - candidate.gy;
651- *xp = m_ptr->fx - candidate.gx;
652-
653- return TRUE;
654- }
655-
656- return FALSE;
657-}
658-
659-
660-/*!
661- * @brief モンスターが逃げ込める地点を走査する
662- * @param target_ptr プレーヤーへの参照ポインタ
663- * @param m_idx モンスターID
664- * @param y_offsets
665- * @param x_offsets
666- * @param d モンスターがいる地点からの距離
667- * @return 逃げ込める地点の候補地
668- */
669-coordinate_candidate sweep_safe_coordinate(player_type *target_ptr, MONSTER_IDX m_idx, const POSITION *y_offsets, const POSITION *x_offsets, int d)
670-{
671- coordinate_candidate candidate = init_coordinate_candidate();
672- floor_type *floor_ptr = target_ptr->current_floor_ptr;
673- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
674- for (POSITION i = 0, dx = x_offsets[0], dy = y_offsets[0];
675- dx != 0 || dy != 0;
676- i++, dx = x_offsets[i], dy = y_offsets[i])
677- {
678- POSITION y = m_ptr->fy + dy;
679- POSITION x = m_ptr->fx + dx;
680- if (!in_bounds(floor_ptr, y, x)) continue;
681-
682- grid_type *g_ptr;
683- g_ptr = &floor_ptr->grid_array[y][x];
684-
685- BIT_FLAGS16 riding_mode = (m_idx == target_ptr->riding) ? CEM_RIDING : 0;
686- if (!monster_can_cross_terrain(target_ptr, g_ptr->feat, &r_info[m_ptr->r_idx], riding_mode))
687- continue;
688-
689- if (!(m_ptr->mflag2 & MFLAG2_NOFLOW))
690- {
691- if (g_ptr->dist == 0) continue;
692- if (g_ptr->dist > floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].dist + 2 * d) continue;
693- }
694-
695- if (projectable(target_ptr, target_ptr->y, target_ptr->x, y, x)) continue;
696-
697- POSITION dis = distance(y, x, target_ptr->y, target_ptr->x);
698- if (dis <= candidate.gdis) continue;
699-
700- candidate.gy = y;
701- candidate.gx = x;
702- candidate.gdis = dis;
703- }
704-
705- return candidate;
706-}
707-
708-
709-/*!
710- * @brief モンスターが隠れ潜める地点を返す /
711- * Choose a good hiding place near a monster for it to run toward.
712- * @param target_ptr プレーヤーへの参照ポインタ
713- * @param m_idx モンスターの参照ID
714- * @param yp 移動先のマスのY座標を返す参照ポインタ
715- * @param xp 移動先のマスのX座標を返す参照ポインタ
716- * @return 有効なマスがあった場合TRUEを返す
717- * @details
718- * Pack monsters will use this to "ambush" the player and lure him out\n
719- * of corridors into open space so they can swarm him.\n
720- *\n
721- * Return TRUE if a good location is available.\n
722- */
723-bool find_hiding(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
724-{
725- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
726- coordinate_candidate candidate = init_coordinate_candidate();
727- candidate.gdis = 999;
728-
729- for (POSITION d = 1; d < 10; d++)
730- {
731- const POSITION *y_offsets;
732- y_offsets = dist_offsets_y[d];
733-
734- const POSITION *x_offsets;
735- x_offsets = dist_offsets_x[d];
736-
737- sweep_hiding_candidate(target_ptr, m_ptr, y_offsets, x_offsets, &candidate);
738- if (candidate.gdis >= 999) continue;
739-
740- *yp = m_ptr->fy - candidate.gy;
741- *xp = m_ptr->fx - candidate.gx;
742- return TRUE;
743- }
744-
745- return FALSE;
746-}
747-
748-
749-/*!
750- * @brief モンスターが隠れられる地点を走査する
751- * @param target_ptr プレーヤーへの参照ポインタ
752- * @param m_idx モンスターID
753- * @param y_offsets
754- * @param x_offsets
755- * @param candidate 隠れられる地点の候補地
756- * @return なし
757- */
758-void sweep_hiding_candidate(player_type *target_ptr, monster_type *m_ptr, const POSITION *y_offsets, const POSITION *x_offsets, coordinate_candidate *candidate)
759-{
760- monster_race *r_ptr = &r_info[m_ptr->r_idx];
761- for (POSITION i = 0, dx = x_offsets[0], dy = y_offsets[0];
762- dx != 0 || dy != 0;
763- i++, dx = x_offsets[i], dy = y_offsets[i])
764- {
765- POSITION y = m_ptr->fy + dy;
766- POSITION x = m_ptr->fx + dx;
767- if (!in_bounds(target_ptr->current_floor_ptr, y, x)) continue;
768- if (!monster_can_enter(target_ptr, y, x, r_ptr, 0)) continue;
769- if (projectable(target_ptr, target_ptr->y, target_ptr->x, y, x) && clean_shot(target_ptr, m_ptr->fy, m_ptr->fx, y, x, FALSE))
770- continue;
771-
772- POSITION dis = distance(y, x, target_ptr->y, target_ptr->x);
773- if (dis < candidate->gdis && dis >= 2)
774- {
775- candidate->gy = y;
776- candidate->gx = x;
777- candidate->gdis = dis;
778- }
779- }
780-}
781-
782-
783-/*!
784- * todo 分割したいが条件が多すぎて適切な関数名と詳細処理を追いきれない……
785- * @brief モンスターの移動方向を返す /
786- * Choose "logical" directions for monster movement
787- * @param target_ptr プレーヤーへの参照ポインタ
788- * @param m_idx モンスターの参照ID
789- * @param mm 移動方向を返す方向IDの参照ポインタ
790- * @return 有効方向があった場合TRUEを返す
791- */
792-static bool get_moves(player_type *target_ptr, MONSTER_IDX m_idx, DIRECTION *mm)
793-{
794- floor_type *floor_ptr = target_ptr->current_floor_ptr;
795- monster_type *m_ptr = &floor_ptr->m_list[m_idx];
796- monster_race *r_ptr = &r_info[m_ptr->r_idx];
797- POSITION y = 0, ay, x = 0, ax;
798- POSITION y2 = target_ptr->y;
799- POSITION x2 = target_ptr->x;
800- bool done = FALSE;
801- bool will_run = mon_will_run(target_ptr, m_idx);
802- grid_type *g_ptr;
803- bool no_flow = ((m_ptr->mflag2 & MFLAG2_NOFLOW) != 0) && (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].cost > 2);
804- bool can_pass_wall = ((r_ptr->flags2 & RF2_PASS_WALL) != 0) && ((m_idx != target_ptr->riding) || target_ptr->pass_wall);
805-
806- if (!will_run && m_ptr->target_y)
807- {
808- int t_m_idx = floor_ptr->grid_array[m_ptr->target_y][m_ptr->target_x].m_idx;
809- if ((t_m_idx > 0) &&
810- are_enemies(target_ptr, m_ptr, &floor_ptr->m_list[t_m_idx]) &&
811- los(target_ptr, m_ptr->fy, m_ptr->fx, m_ptr->target_y, m_ptr->target_x) &&
812- projectable(target_ptr, m_ptr->fy, m_ptr->fx, m_ptr->target_y, m_ptr->target_x))
813- {
814- y = m_ptr->fy - m_ptr->target_y;
815- x = m_ptr->fx - m_ptr->target_x;
816- done = TRUE;
817- }
818- }
819-
820- if (!done && !will_run && is_hostile(m_ptr) &&
821- (r_ptr->flags1 & RF1_FRIENDS) &&
822- ((los(target_ptr, m_ptr->fy, m_ptr->fx, target_ptr->y, target_ptr->x) && projectable(target_ptr, m_ptr->fy, m_ptr->fx, target_ptr->y, target_ptr->x)) ||
823- (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].dist < MAX_SIGHT / 2)))
824- {
825- if ((r_ptr->flags3 & RF3_ANIMAL) && !can_pass_wall &&
826- !(r_ptr->flags2 & RF2_KILL_WALL))
827- {
828- int room = 0;
829- for (int i = 0; i < 8; i++)
830- {
831- int xx = target_ptr->x + ddx_ddd[i];
832- int yy = target_ptr->y + ddy_ddd[i];
833-
834- if (!in_bounds2(floor_ptr, yy, xx)) continue;
835-
836- g_ptr = &floor_ptr->grid_array[yy][xx];
837- if (monster_can_cross_terrain(target_ptr, g_ptr->feat, r_ptr, 0))
838- {
839- room++;
840- }
841- }
842-
843- if (floor_ptr->grid_array[target_ptr->y][target_ptr->x].info & CAVE_ROOM) room -= 2;
844- if (!r_ptr->flags4 && !r_ptr->a_ability_flags1 && !r_ptr->a_ability_flags2) room -= 2;
845-
846- if (room < (8 * (target_ptr->chp + target_ptr->csp)) /
847- (target_ptr->mhp + target_ptr->msp))
848- {
849- if (find_hiding(target_ptr, m_idx, &y, &x)) done = TRUE;
850- }
851- }
852-
853- if (!done && (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].dist < 3))
854- {
855- for (int i = 0; i < 8; i++)
856- {
857- y2 = target_ptr->y + ddy_ddd[(m_idx + i) & 7];
858- x2 = target_ptr->x + ddx_ddd[(m_idx + i) & 7];
859- if ((m_ptr->fy == y2) && (m_ptr->fx == x2))
860- {
861- y2 = target_ptr->y;
862- x2 = target_ptr->x;
863- break;
864- }
865-
866- if (!in_bounds2(floor_ptr, y2, x2)) continue;
867- if (!monster_can_enter(target_ptr, y2, x2, r_ptr, 0)) continue;
868-
869- break;
870- }
871-
872- y = m_ptr->fy - y2;
873- x = m_ptr->fx - x2;
874- done = TRUE;
875- }
876- }
877-
878- if (!done)
879- {
880- (void)get_moves_aux(target_ptr, m_idx, &y2, &x2, no_flow);
881- y = m_ptr->fy - y2;
882- x = m_ptr->fx - x2;
883- }
884-
885- if (is_pet(m_ptr) && will_run)
886- {
887- y = (-y), x = (-x);
888- }
889- else
890- {
891- if (!done && will_run)
892- {
893- int tmp_x = (-x);
894- int tmp_y = (-y);
895- if (find_safety(target_ptr, m_idx, &y, &x) && !no_flow)
896- {
897- if (get_fear_moves_aux(target_ptr->current_floor_ptr, m_idx, &y, &x))
898- done = TRUE;
899- }
900-
901- if (!done)
902- {
903- y = tmp_y;
904- x = tmp_x;
905- }
906- }
907- }
908-
909- if (!x && !y) return FALSE;
910-
911- ax = ABS(x);
912- ay = ABS(y);
913-
914- int move_val = 0;
915- if (y < 0) move_val += 8;
916- if (x > 0) move_val += 4;
917-
918- if (ay > (ax << 1)) move_val += 2;
919- else if (ax > (ay << 1)) move_val++;
920-
921- switch (move_val)
922- {
923- case 0:
924- mm[0] = 9;
925- if (ay > ax)
926- {
927- mm[1] = 8;
928- mm[2] = 6;
929- mm[3] = 7;
930- mm[4] = 3;
931- }
932- else
933- {
934- mm[1] = 6;
935- mm[2] = 8;
936- mm[3] = 3;
937- mm[4] = 7;
938- }
939- break;
940- case 1:
941- case 9:
942- mm[0] = 6;
943- if (y < 0)
944- {
945- mm[1] = 3;
946- mm[2] = 9;
947- mm[3] = 2;
948- mm[4] = 8;
949- }
950- else
951- {
952- mm[1] = 9;
953- mm[2] = 3;
954- mm[3] = 8;
955- mm[4] = 2;
956- }
957- break;
958- case 2:
959- case 6:
960- mm[0] = 8;
961- if (x < 0)
962- {
963- mm[1] = 9;
964- mm[2] = 7;
965- mm[3] = 6;
966- mm[4] = 4;
967- }
968- else
969- {
970- mm[1] = 7;
971- mm[2] = 9;
972- mm[3] = 4;
973- mm[4] = 6;
974- }
975- break;
976- case 4:
977- mm[0] = 7;
978- if (ay > ax)
979- {
980- mm[1] = 8;
981- mm[2] = 4;
982- mm[3] = 9;
983- mm[4] = 1;
984- }
985- else
986- {
987- mm[1] = 4;
988- mm[2] = 8;
989- mm[3] = 1;
990- mm[4] = 9;
991- }
992- break;
993- case 5:
994- case 13:
995- mm[0] = 4;
996- if (y < 0)
997- {
998- mm[1] = 1;
999- mm[2] = 7;
1000- mm[3] = 2;
1001- mm[4] = 8;
1002- }
1003- else
1004- {
1005- mm[1] = 7;
1006- mm[2] = 1;
1007- mm[3] = 8;
1008- mm[4] = 2;
1009- }
1010- break;
1011- case 8:
1012- mm[0] = 3;
1013- if (ay > ax)
1014- {
1015- mm[1] = 2;
1016- mm[2] = 6;
1017- mm[3] = 1;
1018- mm[4] = 9;
1019- }
1020- else
1021- {
1022- mm[1] = 6;
1023- mm[2] = 2;
1024- mm[3] = 9;
1025- mm[4] = 1;
1026- }
1027- break;
1028- case 10:
1029- case 14:
1030- mm[0] = 2;
1031- if (x < 0)
1032- {
1033- mm[1] = 3;
1034- mm[2] = 1;
1035- mm[3] = 6;
1036- mm[4] = 4;
1037- }
1038- else
1039- {
1040- mm[1] = 1;
1041- mm[2] = 3;
1042- mm[3] = 4;
1043- mm[4] = 6;
1044- }
1045- break;
1046- case 12:
1047- mm[0] = 1;
1048- if (ay > ax)
1049- {
1050- mm[1] = 2;
1051- mm[2] = 4;
1052- mm[3] = 3;
1053- mm[4] = 7;
1054- }
1055- else
1056- {
1057- mm[1] = 4;
1058- mm[2] = 2;
1059- mm[3] = 7;
1060- mm[4] = 3;
1061- }
1062- break;
1063- }
1064-
1065- return TRUE;
1066-}
1067-
1068-
1069-static bool check_hp_for_feat_destruction(feature_type *f_ptr, monster_type *m_ptr)
1070-{
1071- return !have_flag(f_ptr->flags, FF_GLASS) ||
1072- (r_info[m_ptr->r_idx].flags2 & RF2_STUPID) ||
1073- (m_ptr->hp >= MAX(m_ptr->maxhp / 3, 200));
1074-}
1075-
1076-
1077-/*!
1078- * @brief モンスター単体の1ターン行動処理メインルーチン /
1079- * Process a monster
1080- * @param target_ptr プレーヤーへの参照ポインタ
1081- * @param m_idx 行動モンスターの参照ID
1082- * @return なし
1083- * @details
1084- * The monster is known to be within 100 grids of the player\n
1085- *\n
1086- * In several cases, we directly update the monster lore\n
1087- *\n
1088- * Note that a monster is only allowed to "reproduce" if there\n
1089- * are a limited number of "reproducing" monsters on the current\n
1090- * level. This should prevent the level from being "swamped" by\n
1091- * reproducing monsters. It also allows a large mass of mice to\n
1092- * prevent a louse from multiplying, but this is a small price to\n
1093- * pay for a simple multiplication method.\n
1094- *\n
1095- * XXX Monster fear is slightly odd, in particular, monsters will\n
1096- * fixate on opening a door even if they cannot open it. Actually,\n
1097- * the same thing happens to normal monsters when they hit a door\n
1098- *\n
1099- * In addition, monsters which *cannot* open or bash\n
1100- * down a door will still stand there trying to open it...\n
1101- *\n
1102- * XXX Technically, need to check for monster in the way\n
1103- * combined with that monster being in a wall (or door?)\n
1104- *\n
1105- * A "direction" of "5" means "pick a random direction".\n
1106- */
1107-void process_monster(player_type *target_ptr, MONSTER_IDX m_idx)
1108-{
1109- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1110- monster_race *r_ptr = &r_info[m_ptr->r_idx];
1111- turn_flags tmp_flags;
1112- turn_flags *turn_flags_ptr = init_turn_flags(target_ptr, m_idx, &tmp_flags);
1113- turn_flags_ptr->see_m = is_seen(m_ptr);
1114-
1115- decide_drop_from_monster(target_ptr, m_idx, turn_flags_ptr->is_riding_mon);
1116- if ((m_ptr->mflag2 & MFLAG2_CHAMELEON) && one_in_(13) && !MON_CSLEEP(m_ptr))
1117- {
1118- choose_new_monster(target_ptr, m_idx, FALSE, 0);
1119- r_ptr = &r_info[m_ptr->r_idx];
1120- }
1121-
1122- turn_flags_ptr->aware = process_stealth(target_ptr, m_idx);
1123- if (vanish_summoned_children(target_ptr, m_idx, turn_flags_ptr->see_m)) return;
1124- if (process_quantum_effect(target_ptr, m_idx, turn_flags_ptr->see_m)) return;
1125- if (explode_monster(target_ptr, m_idx)) return;
1126- if (runaway_monster(target_ptr, turn_flags_ptr, m_idx)) return;
1127-
1128- awake_monster(target_ptr, m_idx);
1129- if (MON_STUNNED(m_ptr))
1130- {
1131- if (one_in_(2)) return;
1132- }
1133-
1134- if (turn_flags_ptr->is_riding_mon)
1135- {
1136- target_ptr->update |= (PU_BONUS);
1137- }
1138-
1139- process_angar(target_ptr, m_idx, turn_flags_ptr->see_m);
1140-
1141- POSITION oy = m_ptr->fy;
1142- POSITION ox = m_ptr->fx;
1143- if (decide_monster_multiplication(target_ptr, m_idx, oy, ox)) return;
1144-
1145- process_special(target_ptr, m_idx);
1146- process_speak_sound(target_ptr, m_idx, oy, ox, turn_flags_ptr->aware);
1147- if (cast_spell(target_ptr, m_idx, turn_flags_ptr->aware)) return;
1148-
1149- DIRECTION mm[8];
1150- mm[0] = mm[1] = mm[2] = mm[3] = 0;
1151- mm[4] = mm[5] = mm[6] = mm[7] = 0;
1152-
1153- if (!decide_monster_movement_direction(target_ptr, mm, m_idx, turn_flags_ptr->aware)) return;
1154-
1155- int count = 0;
1156- if (!process_monster_movement(target_ptr, turn_flags_ptr, m_idx, mm, oy, ox, &count)) return;
1157-
1158- /*
1159- * Forward movements failed, but now received LOS attack!
1160- * Try to flow by smell.
1161- */
1162- if (target_ptr->no_flowed && count > 2 && m_ptr->target_y)
1163- m_ptr->mflag2 &= ~MFLAG2_NOFLOW;
1164-
1165- if (!turn_flags_ptr->do_turn && !turn_flags_ptr->do_move && !MON_MONFEAR(m_ptr) && !turn_flags_ptr->is_riding_mon && turn_flags_ptr->aware)
1166- {
1167- if (r_ptr->freq_spell && randint1(100) <= r_ptr->freq_spell)
1168- {
1169- if (make_attack_spell(m_idx, target_ptr)) return;
1170- }
144+ if (r_ptr->freq_spell && randint1(100) <= r_ptr->freq_spell)
145+ {
146+ if (make_attack_spell(m_idx, target_ptr)) return;
147+ }
1171148 }
1172149
1173150 update_player_type(target_ptr, turn_flags_ptr, r_ptr);
1174- update_monster_race_flags(target_ptr, turn_flags_ptr, m_ptr);
1175-
1176- if (!process_monster_fear(target_ptr, turn_flags_ptr, m_idx)) return;
1177-
1178- if (m_ptr->ml) chg_virtue(target_ptr, V_COMPASSION, -1);
1179-}
1180-
1181-
1182-/*!
1183- * @brief ターン経過フラグ構造体の初期化
1184- * @param target_ptr プレーヤーへの参照ポインタ
1185- * @param m_idx モンスターID
1186- * @return 初期化済のターン経過フラグ
1187- */
1188-turn_flags *init_turn_flags(player_type *target_ptr, MONSTER_IDX m_idx, turn_flags *turn_flags_ptr)
1189-{
1190- turn_flags_ptr->is_riding_mon = (m_idx == target_ptr->riding);
1191- turn_flags_ptr->do_turn = FALSE;
1192- turn_flags_ptr->do_move = FALSE;
1193- turn_flags_ptr->do_view = FALSE;
1194- turn_flags_ptr->must_alter_to_move = FALSE;
1195- turn_flags_ptr->did_open_door = FALSE;
1196- turn_flags_ptr->did_bash_door = FALSE;
1197- turn_flags_ptr->did_take_item = FALSE;
1198- turn_flags_ptr->did_kill_item = FALSE;
1199- turn_flags_ptr->did_move_body = FALSE;
1200- turn_flags_ptr->did_pass_wall = FALSE;
1201- turn_flags_ptr->did_kill_wall = FALSE;
1202- return turn_flags_ptr;
1203-}
1204-
1205-
1206-/*!
1207- * @brief 超隠密処理
1208- * @param target_ptr プレーヤーへの参照ポインタ
1209- * @param m_idx モンスターID
1210- * @return モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
1211- */
1212-bool process_stealth(player_type *target_ptr, MONSTER_IDX m_idx)
1213-{
1214- if ((target_ptr->special_defense & NINJA_S_STEALTH) == 0) return TRUE;
1215-
1216- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1217- monster_race *r_ptr = &r_info[m_ptr->r_idx];
1218- int tmp = target_ptr->lev * 6 + (target_ptr->skill_stl + 10) * 4;
1219- if (target_ptr->monlite) tmp /= 3;
1220- if (target_ptr->cursed & TRC_AGGRAVATE) tmp /= 2;
1221- if (r_ptr->level > (target_ptr->lev * target_ptr->lev / 20 + 10)) tmp /= 3;
1222- return (randint0(tmp) <= (r_ptr->level + 20));
1223-}
1224-
1225-
1226-/*!
1227- * @brief 死亡したモンスターが乗馬中のモンスターだった場合に落馬処理を行う
1228- * @param target_ptr プレーヤーへの参照ポインタ
1229- * @param m_idx モンスターID
1230- * @param is_riding_mon 騎乗中であればTRUE
1231- * @return なし
1232- */
1233-void decide_drop_from_monster(player_type *target_ptr, MONSTER_IDX m_idx, bool is_riding_mon)
1234-{
1235- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1236- monster_race *r_ptr = &r_info[m_ptr->r_idx];
1237- if (!is_riding_mon || ((r_ptr->flags7 & RF7_RIDING) != 0)) return;
1238-
1239- if (rakuba(target_ptr, 0, TRUE))
1240- {
1241-#ifdef JP
1242- msg_print("地面に落とされた。");
1243-#else
1244- GAME_TEXT m_name[MAX_NLEN];
1245- monster_desc(target_ptr, m_name, &target_ptr->current_floor_ptr->m_list[target_ptr->riding], 0);
1246- msg_format("You have fallen from %s.", m_name);
1247-#endif
1248- }
1249-}
1250-
1251-
1252-/*!
1253- * @brief 召喚の親元が消滅した時、子供も消滅させる
1254- * @param target_ptr プレーヤーへの参照ポインタ
1255- * @param m_idx モンスターID
1256- * @param see_m モンスターが視界内にいたらTRUE
1257- * @return 召喚モンスターが消滅したらTRUE
1258- */
1259-bool vanish_summoned_children(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m)
1260-{
1261- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1262- if ((m_ptr->parent_m_idx == 0) || (target_ptr->current_floor_ptr->m_list[m_ptr->parent_m_idx].r_idx > 0))
1263- return FALSE;
1264-
1265- if (see_m)
1266- {
1267- GAME_TEXT m_name[MAX_NLEN];
1268- monster_desc(target_ptr, m_name, m_ptr, 0);
1269- msg_format(_("%sは消え去った!", "%^s disappears!"), m_name);
1270- }
1271-
1272- if (record_named_pet && is_pet(m_ptr) && m_ptr->nickname)
1273- {
1274- GAME_TEXT m_name[MAX_NLEN];
1275- monster_desc(target_ptr, m_name, m_ptr, MD_INDEF_VISIBLE);
1276- exe_write_diary(target_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_LOSE_PARENT, m_name);
1277- }
1278-
1279- delete_monster_idx(target_ptr, m_idx);
1280- return TRUE;
1281-}
1282-
1283-
1284-/*!
1285- * @brief 寝ているモンスターの起床を判定する
1286- * @param target_ptr プレーヤーへの参照ポインタ
1287- * @param m_idx モンスターID
1288- * @return なし
1289- */
1290-void awake_monster(player_type *target_ptr, MONSTER_IDX m_idx)
1291-{
1292- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1293- monster_race *r_ptr = &r_info[m_ptr->r_idx];
1294- if (!MON_CSLEEP(m_ptr)) return;
1295- if (!(target_ptr->cursed & TRC_AGGRAVATE)) return;
1296-
1297- (void)set_monster_csleep(target_ptr, m_idx, 0);
1298- if (m_ptr->ml)
1299- {
1300- GAME_TEXT m_name[MAX_NLEN];
1301- monster_desc(target_ptr, m_name, m_ptr, 0);
1302- msg_format(_("%^sが目を覚ました。", "%^s wakes up."), m_name);
1303- }
1304-
1305- if (is_original_ap_and_seen(target_ptr, m_ptr) && (r_ptr->r_wake < MAX_UCHAR))
1306- {
1307- r_ptr->r_wake++;
1308- }
1309-}
1310-
1311-
1312-/*!
1313- * @brief モンスターの怒り状態を判定する (起こっていたら敵に回す)
1314- * @param target_ptr プレーヤーへの参照ポインタ
1315- * @param m_idx モンスターID
1316- * @param see_m モンスターが視界内にいたらTRUE
1317- * @return なし
1318- */
1319-void process_angar(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m)
1320-{
1321- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1322- monster_race *r_ptr = &r_info[m_ptr->r_idx];
1323- bool gets_angry = FALSE;
1324- if (is_friendly(m_ptr) && (target_ptr->cursed & TRC_AGGRAVATE))
1325- gets_angry = TRUE;
1326-
1327- if (is_pet(m_ptr) && ((((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NAZGUL)) &&
1328- monster_has_hostile_align(target_ptr, NULL, 10, -10, r_ptr)) || (r_ptr->flagsr & RFR_RES_ALL)))
1329- {
1330- gets_angry = TRUE;
1331- }
1332-
1333- if (target_ptr->phase_out || !gets_angry) return;
1334-
1335- if (is_pet(m_ptr) || see_m)
1336- {
1337- GAME_TEXT m_name[MAX_NLEN];
1338- monster_desc(target_ptr, m_name, m_ptr, is_pet(m_ptr) ? MD_ASSUME_VISIBLE : 0);
1339- msg_format(_("%^sは突然敵にまわった!", "%^s suddenly becomes hostile!"), m_name);
1340- }
1341-
1342- set_hostile(target_ptr, m_ptr);
1343-}
1344-
1345-
1346-/*!
1347- * @brief 量子生物の量子的効果を実行する
1348- * @param target_ptr プレーヤーへの参照ポインタ
1349- * @param m_idx モンスターID
1350- * @param see_m モンスターが視界内にいたらTRUE
1351- * @return モンスターが量子的効果により消滅したらTRUE
1352- */
1353-bool process_quantum_effect(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m)
1354-{
1355- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1356- monster_race *r_ptr = &r_info[m_ptr->r_idx];
1357- if ((r_ptr->flags2 & RF2_QUANTUM) == 0) return FALSE;
1358- if (!randint0(2)) return FALSE;
1359- if (randint0((m_idx % 100) + 10)) return FALSE;
1360-
1361- bool can_disappear = (r_ptr->flags1 & RF1_UNIQUE) == 0;
1362- can_disappear &= (r_ptr->flags1 & RF1_QUESTOR) == 0;
1363- if (can_disappear)
1364- {
1365- vanish_nonunique(target_ptr, m_idx, see_m);
1366- return TRUE;
1367- }
1368-
1369- produce_quantum_effect(target_ptr, m_idx, see_m);
1370- return FALSE;
1371-}
1372-
1373-
1374-/*!
1375- * @brief ユニークでない量子生物を消滅させる
1376- * @param target_ptr プレーヤーへの参照ポインタ
1377- * @param m_idx モンスターID
1378- * @param see_m モンスターが視界内にいたらTRUE
1379- * @return なし
1380- */
1381-void vanish_nonunique(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m)
1382-{
1383- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1384- if (see_m)
1385- {
1386- GAME_TEXT m_name[MAX_NLEN];
1387- monster_desc(target_ptr, m_name, m_ptr, 0);
1388- msg_format(_("%sは消え去った!", "%^s disappears!"), m_name);
1389- }
1390-
1391- monster_death(target_ptr, m_idx, FALSE);
1392- delete_monster_idx(target_ptr, m_idx);
1393- if (is_pet(m_ptr) && !(m_ptr->ml))
1394- {
1395- msg_print(_("少しの間悲しい気分になった。", "You feel sad for a moment."));
1396- }
1397-}
1398-
1399-
1400-/*!
1401- * @brief 量子生物ユニークの量子的効果 (ショート・テレポートまたは距離10のテレポート・アウェイ)を実行する
1402- * @param target_ptr プレーヤーへの参照ポインタ
1403- * @param m_idx モンスターID
1404- * @param see_m モンスターが視界内にいたらTRUE
1405- * @return なし
1406- * @details
1407- * プレーヤーが量子生物を観測しているか、量子生物がプレーヤーを観測している場合、互いの相対的な位置を確定させる
1408- * 波動関数の収縮はテレポートではないので反テレポート無効
1409- * todo パターンは収縮どころか拡散しているが、この際気にしてはいけない
1410- */
1411-void produce_quantum_effect(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m)
1412-{
1413- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1414- bool coherent = los(target_ptr, m_ptr->fy, m_ptr->fx, target_ptr->y, target_ptr->x);
1415- if (!see_m && !coherent) return;
1416-
1417- if (see_m)
1418- {
1419- GAME_TEXT m_name[MAX_NLEN];
1420- monster_desc(target_ptr, m_name, m_ptr, 0);
1421- msg_format(_("%sは量子的効果を起こした!", "%^s produced a decoherence!"), m_name);
1422- }
1423- else
1424- {
1425- msg_print(_("量子的効果が起こった!", "A decoherence was produced!"));
1426- }
1427-
1428- bool target = one_in_(2);
1429- const int blink = 32 * 5 + 4;
1430- if (target)
1431- {
1432- (void)monspell_to_monster(target_ptr, blink, m_ptr->fy, m_ptr->fx, m_idx, m_idx);
1433- }
1434- else
1435- {
1436- teleport_player_away(m_idx, target_ptr, 10, TRUE);
1437- }
1438-}
1439-
1440-
1441-/*!
1442- * @brief モンスターの爆発処理
1443- * @param target_ptr プレーヤーへの参照ポインタ
1444- * @param m_idx モンスターID
1445- * @return 爆死したらTRUE
1446- */
1447-bool explode_monster(player_type *target_ptr, MONSTER_IDX m_idx)
1448-{
1449- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1450- if (m_ptr->r_idx != MON_SHURYUUDAN) return FALSE;
1451-
1452- bool fear, dead;
1453- mon_take_hit_mon(target_ptr, m_idx, 1, &dead, &fear, _("は爆発して粉々になった。", " explodes into tiny shreds."), m_idx);
1454- return dead;
1455-}
1456-
1457-
1458-/*!
1459- * @brief モンスター依存の特別な行動を取らせる
1460- * @param target_ptr プレーヤーへの参照ポインタ
1461- * @param m_idx モンスターID
1462- * @return なし
1463- */
1464-void process_special(player_type *target_ptr, MONSTER_IDX m_idx)
1465-{
1466- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1467- monster_race *r_ptr = &r_info[m_ptr->r_idx];
1468- if ((r_ptr->a_ability_flags2 & RF6_SPECIAL) == 0) return;
1469- if (m_ptr->r_idx != MON_OHMU) return;
1470- if (target_ptr->current_floor_ptr->inside_arena || target_ptr->phase_out) return;
1471- if ((r_ptr->freq_spell == 0) || !(randint1(100) <= r_ptr->freq_spell)) return;
1472-
1473- int count = 0;
1474- DEPTH rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1);
1475- BIT_FLAGS p_mode = is_pet(m_ptr) ? PM_FORCE_PET : 0L;
1476-
1477- for (int k = 0; k < A_MAX; k++)
1478- {
1479- if (summon_specific(target_ptr, m_idx, m_ptr->fy, m_ptr->fx, rlev, SUMMON_MOLD, (PM_ALLOW_GROUP | p_mode)))
1480- {
1481- if (target_ptr->current_floor_ptr->m_list[hack_m_idx_ii].ml) count++;
1482- }
1483- }
1484-
1485- if (count && is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags6 |= (RF6_SPECIAL);
1486-}
1487-
1488-
1489-/*!
1490- * @brief モンスターを喋らせたり足音を立てたりする
1491- * @param target_ptr プレーヤーへの参照ポインタ
1492- * @param m_idx モンスターID
1493- * @param oy モンスターが元々いたY座標
1494- * @param ox モンスターが元々いたX座標
1495- * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
1496- * @return なし
1497- */
1498-void process_speak_sound(player_type *target_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, bool aware)
1499-{
1500- if (target_ptr->phase_out) return;
1501-
1502- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1503- monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
1504- if (m_ptr->ap_r_idx == MON_CYBER &&
1505- one_in_(CYBERNOISE) &&
1506- !m_ptr->ml && (m_ptr->cdis <= MAX_SIGHT))
1507- {
1508- if (disturb_minor) disturb(target_ptr, FALSE, FALSE);
1509- msg_print(_("重厚な足音が聞こえた。", "You hear heavy steps."));
1510- }
1511-
1512- if (((ap_r_ptr->flags2 & RF2_CAN_SPEAK) == 0) || !aware ||
1513- !one_in_(SPEAK_CHANCE) ||
1514- !player_has_los_bold(target_ptr, oy, ox) ||
1515- !projectable(target_ptr, oy, ox, target_ptr->y, target_ptr->x))
1516- return;
1517-
1518- GAME_TEXT m_name[MAX_NLEN];
1519- char monmessage[1024];
1520- concptr filename;
1521-
1522- if (m_ptr->ml)
1523- monster_desc(target_ptr, m_name, m_ptr, 0);
1524- else
1525- strcpy(m_name, _("それ", "It"));
1526-
1527- if (MON_MONFEAR(m_ptr))
1528- filename = _("monfear_j.txt", "monfear.txt");
1529- else if (is_pet(m_ptr))
1530- filename = _("monpet_j.txt", "monpet.txt");
1531- else if (is_friendly(m_ptr))
1532- filename = _("monfrien_j.txt", "monfrien.txt");
1533- else
1534- filename = _("monspeak_j.txt", "monspeak.txt");
1535-
1536- if (get_rnd_line(filename, m_ptr->ap_r_idx, monmessage) == 0)
1537- {
1538- msg_format(_("%^s%s", "%^s %s"), m_name, monmessage);
1539- }
1540-}
1541-
1542-
1543-/*!
1544- * @brief モンスターを分裂させるかどうかを決定する (分裂もさせる)
1545- * @param target_ptr プレーヤーへの参照ポインタ
1546- * @param m_idx モンスターID
1547- * @param oy 分裂元モンスターのY座標
1548- * @param ox 分裂元モンスターのX座標
1549- * @return 実際に分裂したらTRUEを返す
1550- */
1551-bool decide_monster_multiplication(player_type *target_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox)
1552-{
1553- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1554- monster_race *r_ptr = &r_info[m_ptr->r_idx];
1555- if (((r_ptr->flags2 & RF2_MULTIPLY) == 0) || (target_ptr->current_floor_ptr->num_repro >= MAX_REPRO))
1556- return FALSE;
1557-
1558- int k = 0;
1559- for (POSITION y = oy - 1; y <= oy + 1; y++)
1560- {
1561- for (POSITION x = ox - 1; x <= ox + 1; x++)
1562- {
1563- if (!in_bounds2(target_ptr->current_floor_ptr, y, x)) continue;
1564- if (target_ptr->current_floor_ptr->grid_array[y][x].m_idx) k++;
1565- }
1566- }
1567-
1568- if (multiply_barrier(target_ptr, m_idx)) k = 8;
1569-
1570- if ((k < 4) && (!k || !randint0(k * MON_MULT_ADJ)))
1571- {
1572- if (multiply_monster(target_ptr, m_idx, FALSE, (is_pet(m_ptr) ? PM_FORCE_PET : 0)))
1573- {
1574- if (target_ptr->current_floor_ptr->m_list[hack_m_idx_ii].ml && is_original_ap_and_seen(target_ptr, m_ptr))
1575- {
1576- r_ptr->r_flags2 |= (RF2_MULTIPLY);
1577- }
1578-
1579- return TRUE;
1580- }
1581- }
1582-
1583- return FALSE;
1584-}
1585-
1586-
1587-/*!
1588- * @brief モンスターの移動パターンを決定する
1589- * @param target_ptr プレーヤーへの参照ポインタ
1590- * @param mm 移動方向
1591- * @param m_idx モンスターID
1592- * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
1593- * @return 移動先が存在すればTRUE
1594- */
1595-bool decide_monster_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx, bool aware)
1596-{
1597- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1598- monster_race *r_ptr = &r_info[m_ptr->r_idx];
1599-
1600- if (MON_CONFUSED(m_ptr) || !aware)
1601- {
1602- mm[0] = mm[1] = mm[2] = mm[3] = 5;
1603- return TRUE;
1604- }
1605-
1606- if (random_walk(target_ptr, mm, m_ptr)) return TRUE;
1607-
1608- if ((r_ptr->flags1 & RF1_NEVER_MOVE) && (m_ptr->cdis > 1))
1609- {
1610- mm[0] = mm[1] = mm[2] = mm[3] = 5;
1611- return TRUE;
1612- }
1613-
1614- if (decide_pet_movement_direction(target_ptr, mm, m_idx)) return TRUE;
1615-
1616- if (!is_hostile(m_ptr))
1617- {
1618- mm[0] = mm[1] = mm[2] = mm[3] = 5;
1619- get_enemy_dir(target_ptr, m_idx, mm);
1620- return TRUE;
1621- }
1622-
1623- if (!get_moves(target_ptr, m_idx, mm)) return FALSE;
1624-
1625- return TRUE;
1626-}
1627-
1628-
1629-/*!
1630- * todo ↓のように書いたが、"5"とはもしかして「その場に留まる」という意味か?
1631- * @brief 不規則歩行フラグを持つモンスターの移動方向をその確率に基づいて決定する
1632- * @param target_ptr プレーヤーへの参照ポインタ
1633- * @param mm 移動方向
1634- * @param m_ptr モンスターへの参照ポインタ
1635- * @return 不規則な方向へ歩くことになったらTRUE
1636- */
1637-bool random_walk(player_type *target_ptr, DIRECTION *mm, monster_type *m_ptr)
1638-{
1639- monster_race *r_ptr = &r_info[m_ptr->r_idx];
1640- if (((r_ptr->flags1 & (RF1_RAND_50 | RF1_RAND_25)) == (RF1_RAND_50 | RF1_RAND_25)) && (randint0(100) < 75))
1641- {
1642- if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags1 |= (RF1_RAND_50 | RF1_RAND_25);
1643-
1644- mm[0] = mm[1] = mm[2] = mm[3] = 5;
1645- return TRUE;
1646- }
1647-
1648- if ((r_ptr->flags1 & RF1_RAND_50) && (randint0(100) < 50))
1649- {
1650- if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags1 |= RF1_RAND_50;
1651-
1652- mm[0] = mm[1] = mm[2] = mm[3] = 5;
1653- return TRUE;
1654- }
1655-
1656- if ((r_ptr->flags1 & RF1_RAND_25) && (randint0(100) < 25))
1657- {
1658- if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags1 |= RF1_RAND_25;
1659-
1660- mm[0] = mm[1] = mm[2] = mm[3] = 5;
1661- return TRUE;
1662- }
1663-
1664- return FALSE;
1665-}
1666-
1667-
1668-/*!
1669- * @brief ペットや友好的なモンスターがフロアから逃げる処理を行う
1670- * @param target_ptr プレーヤーへの参照ポインタ
1671- * @param mm 移動方向
1672- * @param m_idx モンスターID
1673- * @return モンスターがペットであればTRUE
1674- */
1675-bool decide_pet_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx)
1676-{
1677- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1678- if (!is_pet(m_ptr)) return FALSE;
1679-
1680- bool avoid = ((target_ptr->pet_follow_distance < 0) && (m_ptr->cdis <= (0 - target_ptr->pet_follow_distance)));
1681- bool lonely = (!avoid && (m_ptr->cdis > target_ptr->pet_follow_distance));
1682- bool distant = (m_ptr->cdis > PET_SEEK_DIST);
1683- mm[0] = mm[1] = mm[2] = mm[3] = 5;
1684- if (get_enemy_dir(target_ptr, m_idx, mm)) return TRUE;
1685- if (!avoid && !lonely && !distant) return TRUE;
1686-
1687- POSITION dis = target_ptr->pet_follow_distance;
1688- if (target_ptr->pet_follow_distance > PET_SEEK_DIST)
1689- {
1690- target_ptr->pet_follow_distance = PET_SEEK_DIST;
1691- }
1692-
1693- (void)get_moves(target_ptr, m_idx, mm);
1694- target_ptr->pet_follow_distance = (s16b)dis;
1695- return TRUE;
1696-}
1697-
1698-
1699-/*!
1700- * @brief ペットや友好的なモンスターがフロアから逃げる処理を行う
1701- * @param target_ptr プレーヤーへの参照ポインタ
1702- * @param m_idx モンスターID
1703- * @param is_riding_mon 騎乗状態ならばTRUE
1704- * @param see_m モンスターが視界内にいたらTRUE
1705- * @return モンスターがフロアから消えたらTRUE
1706- */
1707-bool runaway_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx)
1708-{
1709- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1710- monster_race *r_ptr = &r_info[m_ptr->r_idx];
1711- bool can_runaway = is_pet(m_ptr) || is_friendly(m_ptr);
1712- can_runaway &= ((r_ptr->flags1 & RF1_UNIQUE) != 0) || ((r_ptr->flags7 & RF7_NAZGUL) != 0);
1713- can_runaway &= !target_ptr->phase_out;
1714- if (!can_runaway) return FALSE;
1715-
1716- static int riding_pinch = 0;
1717-
1718- if (m_ptr->hp >= m_ptr->maxhp / 3)
1719- {
1720- /* Reset the counter */
1721- if (turn_flags_ptr->is_riding_mon) riding_pinch = 0;
1722-
1723- return FALSE;
1724- }
1725-
1726- GAME_TEXT m_name[MAX_NLEN];
1727- monster_desc(target_ptr, m_name, m_ptr, 0);
1728- if (turn_flags_ptr->is_riding_mon && riding_pinch < 2)
1729- {
1730- msg_format(_("%sは傷の痛さの余りあなたの束縛から逃れようとしている。",
1731- "%^s seems to be in so much pain and tries to escape from your restriction."), m_name);
1732- riding_pinch++;
1733- disturb(target_ptr, TRUE, TRUE);
1734- return FALSE;
1735- }
1736-
1737- escape_monster(target_ptr, turn_flags_ptr, m_ptr, m_name);
1738- check_quest_completion(target_ptr, m_ptr);
1739- delete_monster_idx(target_ptr, m_idx);
1740- return TRUE;
1741-}
1742-
1743-
1744-/*!
1745- * @brief HPが1/3未満になった有効的なユニークモンスターの逃走処理を行う
1746- * @param target_ptr プレーヤーへの参照ポインタ
1747- * @param is_riding_mon 騎乗状態ならばTRUE
1748- * @param m_ptr モンスターへの参照ポインタ
1749- * @param m_name モンスター名称
1750- * @param see_m モンスターが視界内にいたらTRUE
1751- * @return なし
1752- */
1753-void escape_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, GAME_TEXT *m_name)
1754-{
1755- monster_race *r_ptr = &r_info[m_ptr->r_idx];
1756- if (turn_flags_ptr->is_riding_mon)
1757- {
1758- msg_format(_("%sはあなたの束縛から脱出した。", "%^s succeeded to escape from your restriction!"), m_name);
1759- if (rakuba(target_ptr, -1, FALSE))
1760- {
1761- msg_print(_("地面に落とされた。", "You have fallen from the pet you were riding."));
1762- }
1763- }
1764-
1765- if (turn_flags_ptr->see_m)
1766- {
1767- if ((r_ptr->flags2 & RF2_CAN_SPEAK) && (m_ptr->r_idx != MON_GRIP) && (m_ptr->r_idx != MON_WOLF) && (m_ptr->r_idx != MON_FANG) &&
1768- player_has_los_bold(target_ptr, m_ptr->fy, m_ptr->fx) && projectable(target_ptr, m_ptr->fy, m_ptr->fx, target_ptr->y, target_ptr->x))
1769- {
1770- msg_format(_("%^s「ピンチだ!退却させてもらう!」", "%^s says 'It is the pinch! I will retreat'."), m_name);
1771- }
1772-
1773- msg_format(_("%^sがテレポート・レベルの巻物を読んだ。", "%^s reads a scroll of teleport level."), m_name);
1774- msg_format(_("%^sが消え去った。", "%^s disappears."), m_name);
1775- }
1776-
1777- if (turn_flags_ptr->is_riding_mon && rakuba(target_ptr, -1, FALSE))
1778- {
1779- msg_print(_("地面に落とされた。", "You have fallen from the pet you were riding."));
1780- }
1781-}
1782-
1783-
1784-/*!
1785- * @brief モンスターに魔法を試行させる
1786- * @param target_ptr プレーヤーへの参照ポインタ
1787- * @param m_idx モンスターID
1788- * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
1789- * @return 魔法を唱えられなければ強制的にFALSE、その後モンスターが実際に魔法を唱えればTRUE
1790- */
1791-bool cast_spell(player_type *target_ptr, MONSTER_IDX m_idx, bool aware)
1792-{
1793- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1794- monster_race *r_ptr = &r_info[m_ptr->r_idx];
1795- if ((r_ptr->freq_spell == 0) || (randint1(100) > r_ptr->freq_spell))
1796- return FALSE;
1797-
1798- bool counterattack = FALSE;
1799- if (m_ptr->target_y)
1800- {
1801- MONSTER_IDX t_m_idx = target_ptr->current_floor_ptr->grid_array[m_ptr->target_y][m_ptr->target_x].m_idx;
1802- if (t_m_idx && are_enemies(target_ptr, m_ptr, &target_ptr->current_floor_ptr->m_list[t_m_idx]) &&
1803- projectable(target_ptr, m_ptr->fy, m_ptr->fx, m_ptr->target_y, m_ptr->target_x))
1804- {
1805- counterattack = TRUE;
1806- }
1807- }
1808-
1809- if (counterattack)
1810- {
1811- if (monst_spell_monst(target_ptr, m_idx)) return TRUE;
1812- if (aware && make_attack_spell(m_idx, target_ptr)) return TRUE;
1813- }
1814- else
1815- {
1816- if (aware && make_attack_spell(m_idx, target_ptr)) return TRUE;
1817- if (monst_spell_monst(target_ptr, m_idx)) return TRUE;
1818- }
1819-
1820- return FALSE;
1821-}
1822-
1823-
1824-/*!
1825- * todo 少し長いが、これといってブロックとしてまとまった部分もないので暫定でこのままとする
1826- * @brief モンスターの移動に関するメインルーチン
1827- * @param target_ptr プレーヤーへの参照ポインタ
1828- * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
1829- * @param m_idx モンスターID
1830- * @param mm モンスターの移動方向
1831- * @param oy 移動前の、モンスターのY座標
1832- * @param ox 移動前の、モンスターのX座標
1833- * @param count 移動回数 (のはず todo)
1834- * @return 移動が阻害される何か (ドア等)があったらFALSE
1835- */
1836-bool process_monster_movement(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, DIRECTION *mm, POSITION oy, POSITION ox, int *count)
1837-{
1838- for (int i = 0; mm[i]; i++)
1839- {
1840- int d = mm[i];
1841- if (d == 5) d = ddd[randint0(8)];
1842-
1843- POSITION ny = oy + ddy[d];
1844- POSITION nx = ox + ddx[d];
1845- if (!in_bounds2(target_ptr->current_floor_ptr, ny, nx)) continue;
1846-
1847- grid_type *g_ptr;
1848- g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
1849- monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1850- monster_race *r_ptr = &r_info[m_ptr->r_idx];
1851- bool can_cross = monster_can_cross_terrain(target_ptr, g_ptr->feat, r_ptr, turn_flags_ptr->is_riding_mon ? CEM_RIDING : 0);
1852-
1853- if (!process_wall(target_ptr, turn_flags_ptr, m_ptr, ny, nx, can_cross))
1854- {
1855- if (!process_door(target_ptr, turn_flags_ptr, m_ptr, ny, nx))
1856- return FALSE;
1857- }
1858-
1859- if (!process_protection_rune(target_ptr, turn_flags_ptr, m_ptr, ny, nx))
1860- {
1861- if (!process_explosive_rune(target_ptr, turn_flags_ptr, m_ptr, ny, nx))
1862- return FALSE;
1863- }
1864-
1865- exe_monster_attack_to_player(target_ptr, turn_flags_ptr, m_idx, ny, nx);
1866- if (process_monster_attack_to_monster(target_ptr, turn_flags_ptr, m_idx, g_ptr, can_cross)) return FALSE;
1867-
1868- if (turn_flags_ptr->is_riding_mon)
1869- {
1870- if (!target_ptr->riding_ryoute && !MON_MONFEAR(&target_ptr->current_floor_ptr->m_list[target_ptr->riding])) turn_flags_ptr->do_move = FALSE;
1871- }
1872-
1873- if (!process_post_dig_wall(target_ptr, turn_flags_ptr, m_ptr, ny, nx)) return FALSE;
1874-
1875- if (turn_flags_ptr->must_alter_to_move && (r_ptr->flags7 & RF7_AQUATIC))
1876- {
1877- if (!monster_can_cross_terrain(target_ptr, g_ptr->feat, r_ptr, turn_flags_ptr->is_riding_mon ? CEM_RIDING : 0))
1878- turn_flags_ptr->do_move = FALSE;
1879- }
1880-
1881- if (turn_flags_ptr->do_move && !can_cross && !turn_flags_ptr->did_kill_wall && !turn_flags_ptr->did_bash_door)
1882- turn_flags_ptr->do_move = FALSE;
1883-
1884- if (turn_flags_ptr->do_move && (r_ptr->flags1 & RF1_NEVER_MOVE))
1885- {
1886- if (is_original_ap_and_seen(target_ptr, m_ptr))
1887- r_ptr->r_flags1 |= (RF1_NEVER_MOVE);
1888-
1889- turn_flags_ptr->do_move = FALSE;
1890- }
1891-
1892- if (!turn_flags_ptr->do_move)
1893- {
1894- if (turn_flags_ptr->do_turn) break;
1895-
1896- continue;
1897- }
1898-
1899- turn_flags_ptr->do_turn = TRUE;
1900- feature_type *f_ptr;
1901- f_ptr = &f_info[g_ptr->feat];
1902- if (have_flag(f_ptr->flags, FF_TREE))
1903- {
1904- if (!(r_ptr->flags7 & RF7_CAN_FLY) && !(r_ptr->flags8 & RF8_WILD_WOOD))
1905- {
1906- m_ptr->energy_need += ENERGY_NEED();
1907- }
1908- }
1909-
1910- if (!update_riding_monster(target_ptr, turn_flags_ptr, m_idx, oy, ox, ny, nx)) break;
1911-
1912- monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
1913- if (m_ptr->ml &&
1914- (disturb_move ||
1915- (disturb_near && (m_ptr->mflag & MFLAG_VIEW) && projectable(target_ptr, target_ptr->y, target_ptr->x, m_ptr->fy, m_ptr->fx)) ||
1916- (disturb_high && ap_r_ptr->r_tkills && ap_r_ptr->level >= target_ptr->lev)))
1917- {
1918- if (is_hostile(m_ptr))
1919- disturb(target_ptr, FALSE, TRUE);
1920- }
1921-
1922- bool is_takable_or_killable = g_ptr->o_idx > 0;
1923- is_takable_or_killable &= (r_ptr->flags2 & (RF2_TAKE_ITEM | RF2_KILL_ITEM)) != 0;
1924-
1925- bool is_pickup_items = (target_ptr->pet_extra_flags & PF_PICKUP_ITEMS) != 0;
1926- is_pickup_items &= (r_ptr->flags2 & RF2_TAKE_ITEM) != 0;
1927-
1928- is_takable_or_killable &= !is_pet(m_ptr) || is_pickup_items;
1929- if (!is_takable_or_killable)
1930- {
1931- if (turn_flags_ptr->do_turn) break;
1932-
1933- continue;
1934- }
1935-
1936- update_object_by_monster_movement(target_ptr, turn_flags_ptr, m_idx, ny, nx);
1937- if (turn_flags_ptr->do_turn) break;
1938-
1939- (*count)++;
1940- }
1941-
1942- return TRUE;
1943-}
1944-
1945-
1946-/*!
1947- * @brief モンスターによる壁の透過・破壊を行う
1948- * @param target_ptr プレーヤーへの参照ポインタ
1949- * @param m_ptr モンスターへの参照ポインタ
1950- * @param ny モンスターのY座標
1951- * @param nx モンスターのX座標
1952- * @param can_cross モンスターが地形を踏破できるならばTRUE
1953- * @return 透過も破壊もしなかった場合はFALSE、それ以外はTRUE
1954- */
1955-bool process_wall(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx, bool can_cross)
1956-{
1957- monster_race *r_ptr = &r_info[m_ptr->r_idx];
1958- grid_type *g_ptr;
1959- g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
1960- feature_type *f_ptr;
1961- f_ptr = &f_info[g_ptr->feat];
1962- if (player_bold(target_ptr, ny, nx))
1963- {
1964- turn_flags_ptr->do_move = TRUE;
1965- return TRUE;
1966- }
1967-
1968- if (g_ptr->m_idx > 0)
1969- {
1970- turn_flags_ptr->do_move = TRUE;
1971- return TRUE;
1972- }
1973-
1974- if (((r_ptr->flags2 & RF2_KILL_WALL) != 0) &&
1975- (can_cross ? !have_flag(f_ptr->flags, FF_LOS) : !turn_flags_ptr->is_riding_mon) &&
1976- have_flag(f_ptr->flags, FF_HURT_DISI) && !have_flag(f_ptr->flags, FF_PERMANENT) &&
1977- check_hp_for_feat_destruction(f_ptr, m_ptr))
1978- {
1979- turn_flags_ptr->do_move = TRUE;
1980- if (!can_cross) turn_flags_ptr->must_alter_to_move = TRUE;
1981-
1982- turn_flags_ptr->did_kill_wall = TRUE;
1983- return TRUE;
1984- }
1985-
1986- if (!can_cross) return FALSE;
1987-
1988- turn_flags_ptr->do_move = TRUE;
1989- if (((r_ptr->flags2 & RF2_PASS_WALL) != 0) && (!turn_flags_ptr->is_riding_mon || target_ptr->pass_wall) &&
1990- have_flag(f_ptr->flags, FF_CAN_PASS))
1991- {
1992- turn_flags_ptr->did_pass_wall = TRUE;
1993- }
1994-
1995- return TRUE;
1996-}
1997-
1998-
1999-/*!
2000- * @brief モンスターによるドアの開放・破壊を行う
2001- * @param target_ptr プレーヤーへの参照ポインタ
2002- * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
2003- * @param m_ptr モンスターへの参照ポインタ
2004- * @param ny モンスターのY座標
2005- * @param nx モンスターのX座標
2006- * @return モンスターが死亡した場合のみFALSE
2007- */
2008-bool process_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
2009-{
2010- monster_race *r_ptr = &r_info[m_ptr->r_idx];
2011- grid_type *g_ptr;
2012- g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
2013- if (!is_closed_door(target_ptr, g_ptr->feat)) return TRUE;
2014-
2015- feature_type *f_ptr;
2016- f_ptr = &f_info[g_ptr->feat];
2017- bool may_bash = bash_normal_door(target_ptr, turn_flags_ptr, m_ptr, ny, nx);
2018- bash_glass_door(target_ptr, turn_flags_ptr, m_ptr, f_ptr, may_bash);
2019-
2020- if (!turn_flags_ptr->did_open_door && !turn_flags_ptr->did_bash_door) return TRUE;
2021-
2022- if (turn_flags_ptr->did_bash_door &&
2023- ((randint0(100) < 50) || (feat_state(target_ptr, g_ptr->feat, FF_OPEN) == g_ptr->feat) || have_flag(f_ptr->flags, FF_GLASS)))
2024- {
2025- cave_alter_feat(target_ptr, ny, nx, FF_BASH);
2026- if (!monster_is_valid(m_ptr))
2027- {
2028- target_ptr->update |= (PU_FLOW);
2029- target_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
2030- if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags2 |= (RF2_BASH_DOOR);
2031-
2032- return FALSE;
2033- }
2034- }
2035- else
2036- {
2037- cave_alter_feat(target_ptr, ny, nx, FF_OPEN);
2038- }
2039-
2040- f_ptr = &f_info[g_ptr->feat];
2041- turn_flags_ptr->do_view = TRUE;
2042- return TRUE;
2043-}
2044-
2045-
2046-/*!
2047- * @brief モンスターが普通のドアを開ける処理
2048- * @param target_ptr プレーヤーへの参照ポインタ
2049- * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
2050- * @param m_ptr モンスターへの参照ポインタ
2051- * @param ny モンスターのY座標
2052- * @param nx モンスターのX座標
2053- * @return ここではドアを開けず、ガラスのドアを開ける可能性があるならTRUE
2054- */
2055-bool bash_normal_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
2056-{
2057- monster_race *r_ptr = &r_info[m_ptr->r_idx];
2058- grid_type *g_ptr;
2059- g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
2060- feature_type *f_ptr;
2061- f_ptr = &f_info[g_ptr->feat];
2062- turn_flags_ptr->do_move = FALSE;
2063- if (((r_ptr->flags2 & RF2_OPEN_DOOR) == 0) || !have_flag(f_ptr->flags, FF_OPEN) ||
2064- (is_pet(m_ptr) && ((target_ptr->pet_extra_flags & PF_OPEN_DOORS) == 0)))
2065- return TRUE;
2066-
2067- if (f_ptr->power == 0)
2068- {
2069- turn_flags_ptr->did_open_door = TRUE;
2070- turn_flags_ptr->do_turn = TRUE;
2071- return FALSE;
2072- }
2073-
2074- if (randint0(m_ptr->hp / 10) > f_ptr->power)
2075- {
2076- cave_alter_feat(target_ptr, ny, nx, FF_DISARM);
2077- turn_flags_ptr->do_turn = TRUE;
2078- return FALSE;
2079- }
2080-
2081- return TRUE;
2082-}
2083-
2084-
2085-/*!
2086- * @brief モンスターがガラスのドアを開ける処理
2087- * @param target_ptr プレーヤーへの参照ポインタ
2088- * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
2089- * @param m_ptr モンスターへの参照ポインタ
2090- * @param g_ptr グリッドへの参照ポインタ
2091- * @param f_ptr 地形への参照ポインタ
2092- * @return なし
2093- */
2094-void bash_glass_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, feature_type *f_ptr, bool may_bash)
2095-{
2096- monster_race *r_ptr = &r_info[m_ptr->r_idx];
2097- if (!may_bash || ((r_ptr->flags2 & RF2_BASH_DOOR) == 0) || !have_flag(f_ptr->flags, FF_BASH) ||
2098- (is_pet(m_ptr) && ((target_ptr->pet_extra_flags & PF_OPEN_DOORS) == 0)))
2099- return;
2100-
2101- if (!check_hp_for_feat_destruction(f_ptr, m_ptr) || (randint0(m_ptr->hp / 10) <= f_ptr->power))
2102- return;
2103-
2104- if (have_flag(f_ptr->flags, FF_GLASS))
2105- msg_print(_("ガラスが砕ける音がした!", "You hear glass breaking!"));
2106- else
2107- msg_print(_("ドアを叩き開ける音がした!", "You hear a door burst open!"));
2108-
2109- if (disturb_minor) disturb(target_ptr, FALSE, FALSE);
2110-
2111- turn_flags_ptr->did_bash_door = TRUE;
2112- turn_flags_ptr->do_move = TRUE;
2113- turn_flags_ptr->must_alter_to_move = TRUE;
2114-}
2115-
2116-
2117-/*!
2118- * @brief 守りのルーンによるモンスターの移動制限を処理する
2119- * @param target_ptr プレーヤーへの参照ポインタ
2120- * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
2121- * @param m_ptr モンスターへの参照ポインタ
2122- * @param ny モンスターのY座標
2123- * @param nx モンスターのX座標
2124- * @return ルーンのある/なし
2125- */
2126-bool process_protection_rune(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
2127-{
2128- grid_type *g_ptr;
2129- g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
2130- monster_race *r_ptr = &r_info[m_ptr->r_idx];
2131- if (!turn_flags_ptr->do_move || !is_glyph_grid(g_ptr) ||
2132- (((r_ptr->flags1 & RF1_NEVER_BLOW) != 0) && player_bold(target_ptr, ny, nx)))
2133- return FALSE;
2134-
2135- turn_flags_ptr->do_move = FALSE;
2136- if (is_pet(m_ptr) || (randint1(BREAK_GLYPH) >= r_ptr->level))
2137- return TRUE;
2138-
2139- if (g_ptr->info & CAVE_MARK)
2140- {
2141- msg_print(_("守りのルーンが壊れた!", "The rune of protection is broken!"));
2142- }
2143-
2144- g_ptr->info &= ~(CAVE_MARK);
2145- g_ptr->info &= ~(CAVE_OBJECT);
2146- g_ptr->mimic = 0;
2147- turn_flags_ptr->do_move = TRUE;
2148- note_spot(target_ptr, ny, nx);
2149- return TRUE;
2150-}
2151-
2152-
2153-/*!
2154- * @brief 爆発のルーンにを処理する
2155- * @param target_ptr プレーヤーへの参照ポインタ
2156- * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
2157- * @param m_ptr モンスターへの参照ポインタ
2158- * @param ny モンスターのY座標
2159- * @param nx モンスターのX座標
2160- * @return モンスターが死亡した場合のみFALSE
2161- */
2162-bool process_explosive_rune(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
2163-{
2164- grid_type *g_ptr;
2165- g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
2166- monster_race *r_ptr = &r_info[m_ptr->r_idx];
2167- if (!turn_flags_ptr->do_move || !is_explosive_rune_grid(g_ptr) ||
2168- (((r_ptr->flags1 & RF1_NEVER_BLOW) != 0) && player_bold(target_ptr, ny, nx)))
2169- return TRUE;
2170-
2171- turn_flags_ptr->do_move = FALSE;
2172- if (is_pet(m_ptr)) return TRUE;
2173-
2174- if (randint1(BREAK_MINOR_GLYPH) > r_ptr->level)
2175- {
2176- if (g_ptr->info & CAVE_MARK)
2177- {
2178- msg_print(_("ルーンが爆発した!", "The rune explodes!"));
2179- BIT_FLAGS project_flags = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP | PROJECT_NO_HANGEKI;
2180- project(target_ptr, 0, 2, ny, nx, 2 * (target_ptr->lev + damroll(7, 7)), GF_MANA, project_flags, -1);
2181- }
2182- }
2183- else
2184- {
2185- msg_print(_("爆発のルーンは解除された。", "An explosive rune was disarmed."));
2186- }
151+ update_monster_race_flags(target_ptr, turn_flags_ptr, m_ptr);
2187152
2188- g_ptr->info &= ~(CAVE_MARK);
2189- g_ptr->info &= ~(CAVE_OBJECT);
2190- g_ptr->mimic = 0;
153+ if (!process_monster_fear(target_ptr, turn_flags_ptr, m_idx)) return;
2191154
2192- note_spot(target_ptr, ny, nx);
2193- lite_spot(target_ptr, ny, nx);
155+ if (m_ptr->ml) chg_virtue(target_ptr, V_COMPASSION, -1);
156+}
2194157
2195- if (!monster_is_valid(m_ptr)) return FALSE;
2196158
2197- turn_flags_ptr->do_move = TRUE;
2198- return TRUE;
159+/*!
160+ * @brief 超隠密処理
161+ * @param target_ptr プレーヤーへの参照ポインタ
162+ * @param m_idx モンスターID
163+ * @return モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
164+ */
165+bool process_stealth(player_type *target_ptr, MONSTER_IDX m_idx)
166+{
167+ if ((target_ptr->special_defense & NINJA_S_STEALTH) == 0) return TRUE;
168+
169+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
170+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
171+ int tmp = target_ptr->lev * 6 + (target_ptr->skill_stl + 10) * 4;
172+ if (target_ptr->monlite) tmp /= 3;
173+ if (target_ptr->cursed & TRC_AGGRAVATE) tmp /= 2;
174+ if (r_ptr->level > (target_ptr->lev * target_ptr->lev / 20 + 10)) tmp /= 3;
175+ return (randint0(tmp) <= (r_ptr->level + 20));
2199176 }
2200177
2201178
2202179 /*!
2203- * @brief モンスターが移動した結果、そこにプレーヤーがいたら直接攻撃を行う
180+ * @brief 死亡したモンスターが乗馬中のモンスターだった場合に落馬処理を行う
2204181 * @param target_ptr プレーヤーへの参照ポインタ
2205- * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
2206182 * @param m_idx モンスターID
2207- * @param ny 移動後の、モンスターのY座標
2208- * @param nx 移動後の、モンスターのX座標
183+ * @param is_riding_mon 騎乗中であればTRUE
2209184 * @return なし
2210- * @details
2211- * 反攻撃の洞窟など、直接攻撃ができない場所では処理をスキップする
2212185 */
2213-void exe_monster_attack_to_player(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION ny, POSITION nx)
186+void decide_drop_from_monster(player_type *target_ptr, MONSTER_IDX m_idx, bool is_riding_mon)
2214187 {
2215188 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
2216189 monster_race *r_ptr = &r_info[m_ptr->r_idx];
2217- if (!turn_flags_ptr->do_move || !player_bold(target_ptr, ny, nx))
2218- return;
2219-
2220- if (r_ptr->flags1 & RF1_NEVER_BLOW)
2221- {
2222- if (is_original_ap_and_seen(target_ptr, m_ptr))
2223- r_ptr->r_flags1 |= (RF1_NEVER_BLOW);
2224-
2225- turn_flags_ptr->do_move = FALSE;
2226- }
2227-
2228- if (turn_flags_ptr->do_move && ((d_info[target_ptr->dungeon_idx].flags1 & DF1_NO_MELEE) != 0) && !MON_CONFUSED(m_ptr))
2229- {
2230- if (!(r_ptr->flags2 & RF2_STUPID))
2231- turn_flags_ptr->do_move = FALSE;
2232- else if (is_original_ap_and_seen(target_ptr, m_ptr))
2233- r_ptr->r_flags2 |= (RF2_STUPID);
2234- }
2235-
2236- if (!turn_flags_ptr->do_move) return;
190+ if (!is_riding_mon || ((r_ptr->flags7 & RF7_RIDING) != 0)) return;
2237191
2238- if (!target_ptr->riding || one_in_(2))
192+ if (rakuba(target_ptr, 0, TRUE))
2239193 {
2240- (void)make_attack_normal(target_ptr, m_idx);
2241- turn_flags_ptr->do_move = FALSE;
2242- turn_flags_ptr->do_turn = TRUE;
194+#ifdef JP
195+ msg_print("地面に落とされた。");
196+#else
197+ GAME_TEXT m_name[MAX_NLEN];
198+ monster_desc(target_ptr, m_name, &target_ptr->current_floor_ptr->m_list[target_ptr->riding], 0);
199+ msg_format("You have fallen from %s.", m_name);
200+#endif
2243201 }
2244202 }
2245203
2246204
2247205 /*!
2248- * @brief モンスターからモンスターへの攻撃処理
206+ * @brief 召喚の親元が消滅した時、子供も消滅させる
2249207 * @param target_ptr プレーヤーへの参照ポインタ
2250- * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
2251208 * @param m_idx モンスターID
2252- * @param g_ptr グリッドへの参照ポインタ
2253- * @param can_cross モンスターが地形を踏破できるならばTRUE
2254- * @return ターン消費が発生したらTRUE
209+ * @param see_m モンスターが視界内にいたらTRUE
210+ * @return 召喚モンスターが消滅したらTRUE
2255211 */
2256-bool process_monster_attack_to_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, grid_type *g_ptr, bool can_cross)
212+bool vanish_summoned_children(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m)
2257213 {
2258214 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
2259- monster_race *r_ptr = &r_info[m_ptr->r_idx];
2260- monster_type *y_ptr;
2261- y_ptr = &target_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
2262- if (!turn_flags_ptr->do_move || (g_ptr->m_idx == 0)) return FALSE;
2263-
2264- monster_race *z_ptr = &r_info[y_ptr->r_idx];
2265- turn_flags_ptr->do_move = FALSE;
2266- if ((((r_ptr->flags2 & RF2_KILL_BODY) != 0) && ((r_ptr->flags1 & RF1_NEVER_BLOW) == 0) &&
2267- (r_ptr->mexp * r_ptr->level > z_ptr->mexp * z_ptr->level) &&
2268- can_cross && (g_ptr->m_idx != target_ptr->riding)) ||
2269- are_enemies(target_ptr, m_ptr, y_ptr) || MON_CONFUSED(m_ptr))
215+ if ((m_ptr->parent_m_idx == 0) || (target_ptr->current_floor_ptr->m_list[m_ptr->parent_m_idx].r_idx > 0))
216+ return FALSE;
217+
218+ if (see_m)
2270219 {
2271- return exe_monster_attack_to_monster(target_ptr, m_idx, g_ptr);
220+ GAME_TEXT m_name[MAX_NLEN];
221+ monster_desc(target_ptr, m_name, m_ptr, 0);
222+ msg_format(_("%sは消え去った!", "%^s disappears!"), m_name);
2272223 }
2273224
2274- if (((r_ptr->flags2 & RF2_MOVE_BODY) != 0) && ((r_ptr->flags1 & RF1_NEVER_MOVE) == 0) &&
2275- (r_ptr->mexp > z_ptr->mexp) &&
2276- can_cross && (g_ptr->m_idx != target_ptr->riding) &&
2277- monster_can_cross_terrain(target_ptr, target_ptr->current_floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].feat, z_ptr, 0))
225+ if (record_named_pet && is_pet(m_ptr) && m_ptr->nickname)
2278226 {
2279- turn_flags_ptr->do_move = TRUE;
2280- turn_flags_ptr->did_move_body = TRUE;
2281- (void)set_monster_csleep(target_ptr, g_ptr->m_idx, 0);
227+ GAME_TEXT m_name[MAX_NLEN];
228+ monster_desc(target_ptr, m_name, m_ptr, MD_INDEF_VISIBLE);
229+ exe_write_diary(target_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_LOSE_PARENT, m_name);
2282230 }
2283231
2284- return FALSE;
232+ delete_monster_idx(target_ptr, m_idx);
233+ return TRUE;
2285234 }
2286235
2287236
2288237 /*!
2289- * @brief モンスターからモンスターへの直接攻撃を実行する
238+ * @brief 寝ているモンスターの起床を判定する
2290239 * @param target_ptr プレーヤーへの参照ポインタ
2291240 * @param m_idx モンスターID
2292- * @param g_ptr グリッドへの参照ポインタ
241+ * @return なし
2293242 */
2294-bool exe_monster_attack_to_monster(player_type *target_ptr, MONSTER_IDX m_idx, grid_type *g_ptr)
243+void awake_monster(player_type *target_ptr, MONSTER_IDX m_idx)
2295244 {
2296245 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
2297246 monster_race *r_ptr = &r_info[m_ptr->r_idx];
2298- monster_type *y_ptr;
2299- y_ptr = &target_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
2300- if ((r_ptr->flags1 & RF1_NEVER_BLOW) != 0) return FALSE;
2301-
2302- if (((r_ptr->flags2 & RF2_KILL_BODY) == 0) && is_original_ap_and_seen(target_ptr, m_ptr))
2303- r_ptr->r_flags2 |= (RF2_KILL_BODY);
2304-
2305- if ((y_ptr->r_idx == 0) || (y_ptr->hp < 0)) return FALSE;
2306- if (monst_attack_monst(target_ptr, m_idx, g_ptr->m_idx)) return TRUE;
2307- if ((d_info[target_ptr->dungeon_idx].flags1 & DF1_NO_MELEE) == 0) return FALSE;
2308- if (MON_CONFUSED(m_ptr)) return TRUE;
2309- if ((r_ptr->flags2 & RF2_STUPID) == 0) return FALSE;
247+ if (!MON_CSLEEP(m_ptr)) return;
248+ if (!(target_ptr->cursed & TRC_AGGRAVATE)) return;
2310249
2311- if (is_original_ap_and_seen(target_ptr, m_ptr))
2312- r_ptr->r_flags2 |= (RF2_STUPID);
250+ (void)set_monster_csleep(target_ptr, m_idx, 0);
251+ if (m_ptr->ml)
252+ {
253+ GAME_TEXT m_name[MAX_NLEN];
254+ monster_desc(target_ptr, m_name, m_ptr, 0);
255+ msg_format(_("%^sが目を覚ました。", "%^s wakes up."), m_name);
256+ }
2313257
2314- return TRUE;
258+ if (is_original_ap_and_seen(target_ptr, m_ptr) && (r_ptr->r_wake < MAX_UCHAR))
259+ {
260+ r_ptr->r_wake++;
261+ }
2315262 }
2316263
2317264
2318265 /*!
2319- * @brief モンスターが壁を掘った後続処理を実行する
266+ * @brief モンスターの怒り状態を判定する (起こっていたら敵に回す)
2320267 * @param target_ptr プレーヤーへの参照ポインタ
2321- * @turn_flags_ptr ターン経過処理フラグへの参照ポインタ
2322- * @param m_ptr モンスターへの参照ポインタ
2323- * @param ny モンスターのY座標
2324- * @param nx モンスターのX座標
2325- * @return モンスターが死亡した場合のみFALSE
268+ * @param m_idx モンスターID
269+ * @param see_m モンスターが視界内にいたらTRUE
270+ * @return なし
2326271 */
2327-bool process_post_dig_wall(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
272+void process_angar(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m)
2328273 {
274+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
2329275 monster_race *r_ptr = &r_info[m_ptr->r_idx];
2330- grid_type *g_ptr;
2331- g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
2332- feature_type *f_ptr;
2333- f_ptr = &f_info[g_ptr->feat];
2334- if (!turn_flags_ptr->did_kill_wall || !turn_flags_ptr->do_move) return TRUE;
276+ bool gets_angry = FALSE;
277+ if (is_friendly(m_ptr) && (target_ptr->cursed & TRC_AGGRAVATE))
278+ gets_angry = TRUE;
2335279
2336- if (one_in_(GRINDNOISE))
280+ if (is_pet(m_ptr) && ((((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NAZGUL)) &&
281+ monster_has_hostile_align(target_ptr, NULL, 10, -10, r_ptr)) || (r_ptr->flagsr & RFR_RES_ALL)))
2337282 {
2338- if (have_flag(f_ptr->flags, FF_GLASS))
2339- msg_print(_("何かの砕ける音が聞こえる。", "There is a crashing sound."));
2340- else
2341- msg_print(_("ギシギシいう音が聞こえる。", "There is a grinding sound."));
283+ gets_angry = TRUE;
2342284 }
2343285
2344- cave_alter_feat(target_ptr, ny, nx, FF_HURT_DISI);
286+ if (target_ptr->phase_out || !gets_angry) return;
2345287
2346- if (!monster_is_valid(m_ptr))
288+ if (is_pet(m_ptr) || see_m)
2347289 {
2348- target_ptr->update |= (PU_FLOW);
2349- target_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
2350- if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags2 |= (RF2_KILL_WALL);
2351-
2352- return FALSE;
290+ GAME_TEXT m_name[MAX_NLEN];
291+ monster_desc(target_ptr, m_name, m_ptr, is_pet(m_ptr) ? MD_ASSUME_VISIBLE : 0);
292+ msg_format(_("%^sは突然敵にまわった!", "%^s suddenly becomes hostile!"), m_name);
2353293 }
2354294
2355- f_ptr = &f_info[g_ptr->feat];
2356- turn_flags_ptr->do_view = TRUE;
2357- turn_flags_ptr->do_turn = TRUE;
2358- return TRUE;
295+ set_hostile(target_ptr, m_ptr);
2359296 }
2360297
2361298
2362299 /*!
2363- * @brief 騎乗中のモンスター情報を更新する
300+ * @brief 手榴弾の爆発処理
2364301 * @param target_ptr プレーヤーへの参照ポインタ
2365- * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
2366302 * @param m_idx モンスターID
2367- * @param oy 移動前の、モンスターのY座標
2368- * @param ox 移動前の、モンスターのX座標
2369- * @param ny 移動後の、モンスターのY座標
2370- * @param ox 移動後の、モンスターのX座標
2371- * @return アイテム等に影響を及ぼしたらTRUE
303+ * @return 爆死したらTRUE
2372304 */
2373-bool update_riding_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, POSITION ny, POSITION nx)
305+bool explode_grenade(player_type *target_ptr, MONSTER_IDX m_idx)
2374306 {
2375307 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
2376- grid_type *g_ptr;
2377- g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
2378- monster_type *y_ptr;
2379- y_ptr = &target_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
2380- if (turn_flags_ptr->is_riding_mon)
2381- return move_player_effect(target_ptr, ny, nx, MPE_DONT_PICKUP);
2382-
2383- target_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = g_ptr->m_idx;
2384- if (g_ptr->m_idx)
2385- {
2386- y_ptr->fy = oy;
2387- y_ptr->fx = ox;
2388- update_monster(target_ptr, g_ptr->m_idx, TRUE);
2389- }
308+ if (m_ptr->r_idx != MON_GRENADE) return FALSE;
2390309
2391- g_ptr->m_idx = m_idx;
2392- m_ptr->fy = ny;
2393- m_ptr->fx = nx;
2394- update_monster(target_ptr, m_idx, TRUE);
2395-
2396- lite_spot(target_ptr, oy, ox);
2397- lite_spot(target_ptr, ny, nx);
2398- return TRUE;
310+ bool fear, dead;
311+ mon_take_hit_mon(target_ptr, m_idx, 1, &dead, &fear, _("は爆発して粉々になった。", " explodes into tiny shreds."), m_idx);
312+ return dead;
2399313 }
2400314
2401315
2402316 /*!
2403- * @brief モンスターの移動に伴うオブジェクト処理 (アイテム破壊等)
317+ * @brief モンスター依存の特別な行動を取らせる
2404318 * @param target_ptr プレーヤーへの参照ポインタ
2405- * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
2406319 * @param m_idx モンスターID
2407- * @param ny 移動後の、モンスターのY座標
2408- * @param nx 移動後の、モンスターのX座標
320+ * @return なし
2409321 */
2410-void update_object_by_monster_movement(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION ny, POSITION nx)
322+void process_special(player_type *target_ptr, MONSTER_IDX m_idx)
2411323 {
2412324 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
2413325 monster_race *r_ptr = &r_info[m_ptr->r_idx];
2414- grid_type *g_ptr;
2415- g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
326+ if ((r_ptr->a_ability_flags2 & RF6_SPECIAL) == 0) return;
327+ if (m_ptr->r_idx != MON_OHMU) return;
328+ if (target_ptr->current_floor_ptr->inside_arena || target_ptr->phase_out) return;
329+ if ((r_ptr->freq_spell == 0) || !(randint1(100) <= r_ptr->freq_spell)) return;
2416330
2417- OBJECT_IDX this_o_idx, next_o_idx;
2418- turn_flags_ptr->do_take = (r_ptr->flags2 & RF2_TAKE_ITEM) != 0;
2419- for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
2420- {
2421- BIT_FLAGS flgs[TR_FLAG_SIZE], flg2 = 0L, flg3 = 0L, flgr = 0L;
2422- GAME_TEXT m_name[MAX_NLEN], o_name[MAX_NLEN];
2423- object_type *o_ptr = &target_ptr->current_floor_ptr->o_list[this_o_idx];
2424- next_o_idx = o_ptr->next_o_idx;
331+ int count = 0;
332+ DEPTH rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1);
333+ BIT_FLAGS p_mode = is_pet(m_ptr) ? PM_FORCE_PET : 0L;
2425334
2426- if (turn_flags_ptr->do_take)
335+ for (int k = 0; k < A_MAX; k++)
336+ {
337+ if (summon_specific(target_ptr, m_idx, m_ptr->fy, m_ptr->fx, rlev, SUMMON_MOLD, (PM_ALLOW_GROUP | p_mode)))
2427338 {
2428- /* Skip gold, corpse and statue */
2429- if (o_ptr->tval == TV_GOLD || (o_ptr->tval == TV_CORPSE) || (o_ptr->tval == TV_STATUE))
2430- continue;
339+ if (target_ptr->current_floor_ptr->m_list[hack_m_idx_ii].ml) count++;
2431340 }
2432-
2433- object_flags(o_ptr, flgs);
2434- object_desc(target_ptr, o_name, o_ptr, 0);
2435- monster_desc(target_ptr, m_name, m_ptr, MD_INDEF_HIDDEN);
2436- update_object_flags(flgs, &flg2, &flg3, &flgr);
2437-
2438- bool is_special_object = object_is_artifact(o_ptr) ||
2439- ((r_ptr->flags3 & flg3) != 0) ||
2440- ((r_ptr->flags2 & flg2) != 0) ||
2441- (((~(r_ptr->flagsr) & flgr) != 0) && !(r_ptr->flagsr & RFR_RES_ALL));
2442- monster_pickup_object(target_ptr, turn_flags_ptr, m_idx, o_ptr, is_special_object, ny, nx, m_name, o_name, this_o_idx);
2443341 }
2444-}
2445342
2446-
2447-/*!
2448- * @brief オブジェクトのフラグを更新する
2449- */
2450-void update_object_flags(BIT_FLAGS *flgs, BIT_FLAGS *flg2, BIT_FLAGS *flg3, BIT_FLAGS *flgr)
2451-{
2452- if (have_flag(flgs, TR_SLAY_DRAGON)) *flg3 |= (RF3_DRAGON);
2453- if (have_flag(flgs, TR_KILL_DRAGON)) *flg3 |= (RF3_DRAGON);
2454- if (have_flag(flgs, TR_SLAY_TROLL)) *flg3 |= (RF3_TROLL);
2455- if (have_flag(flgs, TR_KILL_TROLL)) *flg3 |= (RF3_TROLL);
2456- if (have_flag(flgs, TR_SLAY_GIANT)) *flg3 |= (RF3_GIANT);
2457- if (have_flag(flgs, TR_KILL_GIANT)) *flg3 |= (RF3_GIANT);
2458- if (have_flag(flgs, TR_SLAY_ORC)) *flg3 |= (RF3_ORC);
2459- if (have_flag(flgs, TR_KILL_ORC)) *flg3 |= (RF3_ORC);
2460- if (have_flag(flgs, TR_SLAY_DEMON)) *flg3 |= (RF3_DEMON);
2461- if (have_flag(flgs, TR_KILL_DEMON)) *flg3 |= (RF3_DEMON);
2462- if (have_flag(flgs, TR_SLAY_UNDEAD)) *flg3 |= (RF3_UNDEAD);
2463- if (have_flag(flgs, TR_KILL_UNDEAD)) *flg3 |= (RF3_UNDEAD);
2464- if (have_flag(flgs, TR_SLAY_ANIMAL)) *flg3 |= (RF3_ANIMAL);
2465- if (have_flag(flgs, TR_KILL_ANIMAL)) *flg3 |= (RF3_ANIMAL);
2466- if (have_flag(flgs, TR_SLAY_EVIL)) *flg3 |= (RF3_EVIL);
2467- if (have_flag(flgs, TR_KILL_EVIL)) *flg3 |= (RF3_EVIL);
2468- if (have_flag(flgs, TR_SLAY_HUMAN)) *flg2 |= (RF2_HUMAN);
2469- if (have_flag(flgs, TR_KILL_HUMAN)) *flg2 |= (RF2_HUMAN);
2470- if (have_flag(flgs, TR_BRAND_ACID)) *flgr |= (RFR_IM_ACID);
2471- if (have_flag(flgs, TR_BRAND_ELEC)) *flgr |= (RFR_IM_ELEC);
2472- if (have_flag(flgs, TR_BRAND_FIRE)) *flgr |= (RFR_IM_FIRE);
2473- if (have_flag(flgs, TR_BRAND_COLD)) *flgr |= (RFR_IM_COLD);
2474- if (have_flag(flgs, TR_BRAND_POIS)) *flgr |= (RFR_IM_POIS);
343+ if (count && is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags6 |= (RF6_SPECIAL);
2475344 }
2476345
2477346
2478347 /*!
2479- * @brief モンスターがアイテムを拾うか壊す処理
348+ * @brief モンスターを分裂させるかどうかを決定する (分裂もさせる)
2480349 * @param target_ptr プレーヤーへの参照ポインタ
2481- * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
2482350 * @param m_idx モンスターID
2483- * @param o_ptr オブジェクトへの参照ポインタ
2484- * @param is_special_object モンスターが拾えないアイテム (アーティファクト等)であればTRUE
2485- * @param ny 移動後の、モンスターのY座標
2486- * @param nx 移動後の、モンスターのX座標
2487- * @param m_name モンスター名
2488- * @param o_name アイテム名
2489- * @param this_o_idx モンスターが乗ったオブジェクトID
2490- * @return なし
351+ * @param oy 分裂元モンスターのY座標
352+ * @param ox 分裂元モンスターのX座標
353+ * @return 実際に分裂したらTRUEを返す
2491354 */
2492-void monster_pickup_object(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, object_type *o_ptr, bool is_special_object, POSITION ny, POSITION nx, GAME_TEXT *m_name, GAME_TEXT *o_name, OBJECT_IDX this_o_idx)
355+bool decide_monster_multiplication(player_type *target_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox)
2493356 {
2494357 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
2495358 monster_race *r_ptr = &r_info[m_ptr->r_idx];
2496- if (is_special_object)
2497- {
2498- if (turn_flags_ptr->do_take && (r_ptr->flags2 & RF2_STUPID))
2499- {
2500- turn_flags_ptr->did_take_item = TRUE;
2501- if (m_ptr->ml && player_can_see_bold(target_ptr, ny, nx))
2502- {
2503- msg_format(_("%^sは%sを拾おうとしたが、だめだった。", "%^s tries to pick up %s, but fails."), m_name, o_name);
2504- }
2505- }
2506-
2507- return;
2508- }
359+ if (((r_ptr->flags2 & RF2_MULTIPLY) == 0) || (target_ptr->current_floor_ptr->num_repro >= MAX_REPRO))
360+ return FALSE;
2509361
2510- if (turn_flags_ptr->do_take)
362+ int k = 0;
363+ for (POSITION y = oy - 1; y <= oy + 1; y++)
2511364 {
2512- turn_flags_ptr->did_take_item = TRUE;
2513- if (player_can_see_bold(target_ptr, ny, nx))
365+ for (POSITION x = ox - 1; x <= ox + 1; x++)
2514366 {
2515- msg_format(_("%^sが%sを拾った。", "%^s picks up %s."), m_name, o_name);
367+ if (!in_bounds2(target_ptr->current_floor_ptr, y, x)) continue;
368+ if (target_ptr->current_floor_ptr->grid_array[y][x].m_idx) k++;
2516369 }
2517-
2518- excise_object_idx(target_ptr->current_floor_ptr, this_o_idx);
2519- o_ptr->marked &= OM_TOUCHED;
2520- o_ptr->iy = o_ptr->ix = 0;
2521- o_ptr->held_m_idx = m_idx;
2522- o_ptr->next_o_idx = m_ptr->hold_o_idx;
2523- m_ptr->hold_o_idx = this_o_idx;
2524- return;
2525370 }
2526371
2527- if (is_pet(m_ptr)) return;
372+ if (multiply_barrier(target_ptr, m_idx)) k = 8;
2528373
2529- turn_flags_ptr->did_kill_item = TRUE;
2530- if (player_has_los_bold(target_ptr, ny, nx))
374+ if ((k < 4) && (!k || !randint0(k * MON_MULT_ADJ)))
2531375 {
2532- msg_format(_("%^sが%sを破壊した。", "%^s destroys %s."), m_name, o_name);
376+ if (multiply_monster(target_ptr, m_idx, FALSE, (is_pet(m_ptr) ? PM_FORCE_PET : 0)))
377+ {
378+ if (target_ptr->current_floor_ptr->m_list[hack_m_idx_ii].ml && is_original_ap_and_seen(target_ptr, m_ptr))
379+ {
380+ r_ptr->r_flags2 |= (RF2_MULTIPLY);
381+ }
382+
383+ return TRUE;
384+ }
2533385 }
2534386
2535- delete_object_idx(target_ptr, this_o_idx);
387+ return FALSE;
2536388 }
2537389
2538390
2539391 /*!
2540- * @brief updateフィールドを更新する
392+ * @brief モンスターに魔法を試行させる
2541393 * @param target_ptr プレーヤーへの参照ポインタ
2542- * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
2543- * @return なし
394+ * @param m_idx モンスターID
395+ * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
396+ * @return 魔法を唱えられなければ強制的にFALSE、その後モンスターが実際に魔法を唱えればTRUE
2544397 */
2545-void update_player_type(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_race *r_ptr)
398+bool cast_spell(player_type *target_ptr, MONSTER_IDX m_idx, bool aware)
2546399 {
2547- if (turn_flags_ptr->do_view)
400+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
401+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
402+ if ((r_ptr->freq_spell == 0) || (randint1(100) > r_ptr->freq_spell))
403+ return FALSE;
404+
405+ bool counterattack = FALSE;
406+ if (m_ptr->target_y)
2548407 {
2549- target_ptr->update |= (PU_FLOW);
2550- target_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
408+ MONSTER_IDX t_m_idx = target_ptr->current_floor_ptr->grid_array[m_ptr->target_y][m_ptr->target_x].m_idx;
409+ if (t_m_idx && are_enemies(target_ptr, m_ptr, &target_ptr->current_floor_ptr->m_list[t_m_idx]) &&
410+ projectable(target_ptr, m_ptr->fy, m_ptr->fx, m_ptr->target_y, m_ptr->target_x))
411+ {
412+ counterattack = TRUE;
413+ }
2551414 }
2552415
2553- if (turn_flags_ptr->do_move && ((r_ptr->flags7 & (RF7_SELF_LD_MASK | RF7_HAS_DARK_1 | RF7_HAS_DARK_2))
2554- || ((r_ptr->flags7 & (RF7_HAS_LITE_1 | RF7_HAS_LITE_2)) && !target_ptr->phase_out)))
416+ if (counterattack)
417+ {
418+ if (monst_spell_monst(target_ptr, m_idx)) return TRUE;
419+ if (aware && make_attack_spell(m_idx, target_ptr)) return TRUE;
420+ }
421+ else
2555422 {
2556- target_ptr->update |= (PU_MON_LITE);
423+ if (aware && make_attack_spell(m_idx, target_ptr)) return TRUE;
424+ if (monst_spell_monst(target_ptr, m_idx)) return TRUE;
2557425 }
2558-}
2559426
2560-
2561-/*!
2562- * @brief モンスターのフラグを更新する
2563- * @param target_ptr プレーヤーへの参照ポインタ
2564- * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
2565- * @param m_ptr モンスターへの参照ポインタ
2566- * @return なし
2567- */
2568-void update_monster_race_flags(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr)
2569-{
2570- monster_race *r_ptr = &r_info[m_ptr->r_idx];
2571- if (!is_original_ap_and_seen(target_ptr, m_ptr)) return;
2572-
2573- if (turn_flags_ptr->did_open_door) r_ptr->r_flags2 |= (RF2_OPEN_DOOR);
2574- if (turn_flags_ptr->did_bash_door) r_ptr->r_flags2 |= (RF2_BASH_DOOR);
2575- if (turn_flags_ptr->did_take_item) r_ptr->r_flags2 |= (RF2_TAKE_ITEM);
2576- if (turn_flags_ptr->did_kill_item) r_ptr->r_flags2 |= (RF2_KILL_ITEM);
2577- if (turn_flags_ptr->did_move_body) r_ptr->r_flags2 |= (RF2_MOVE_BODY);
2578- if (turn_flags_ptr->did_pass_wall) r_ptr->r_flags2 |= (RF2_PASS_WALL);
2579- if (turn_flags_ptr->did_kill_wall) r_ptr->r_flags2 |= (RF2_KILL_WALL);
427+ return FALSE;
2580428 }
2581429
2582430
@@ -2647,7 +495,7 @@ void process_monsters(player_type *target_ptr)
2647495 floor_ptr->monster_noise = FALSE;
2648496
2649497 MONRACE_IDX old_monster_race_idx = target_ptr->monster_race_idx;
2650- save_old_race_flags(target_ptr, old_race_flags_ptr);
498+ save_old_race_flags(target_ptr->monster_race_idx, old_race_flags_ptr);
2651499 sweep_monster_process(target_ptr);
2652500
2653501 hack_m_idx = 0;
@@ -2659,59 +507,6 @@ void process_monsters(player_type *target_ptr)
2659507
2660508
2661509 /*!
2662- * @brief old_race_flags_ptr の初期化
2663- */
2664-old_race_flags *init_old_race_flags(old_race_flags *old_race_flags_ptr)
2665-{
2666- old_race_flags_ptr->old_r_flags1 = 0L;
2667- old_race_flags_ptr->old_r_flags2 = 0L;
2668- old_race_flags_ptr->old_r_flags3 = 0L;
2669- old_race_flags_ptr->old_r_flags4 = 0L;
2670- old_race_flags_ptr->old_r_flags5 = 0L;
2671- old_race_flags_ptr->old_r_flags6 = 0L;
2672- old_race_flags_ptr->old_r_flagsr = 0L;
2673-
2674- old_race_flags_ptr->old_r_blows0 = 0;
2675- old_race_flags_ptr->old_r_blows1 = 0;
2676- old_race_flags_ptr->old_r_blows2 = 0;
2677- old_race_flags_ptr->old_r_blows3 = 0;
2678-
2679- old_race_flags_ptr->old_r_cast_spell = 0;
2680- return old_race_flags_ptr;
2681-}
2682-
2683-
2684-/*!
2685- * @brief 古いモンスター情報の保存
2686- * @param target_ptr プレーヤーへの参照ポインタ
2687- * @param old_race_flags_ptr モンスターフラグへの参照ポインタ
2688- * @return なし
2689- */
2690-void save_old_race_flags(player_type *target_ptr, old_race_flags *old_race_flags_ptr)
2691-{
2692- if (target_ptr->monster_race_idx == 0) return;
2693-
2694- monster_race *r_ptr;
2695- r_ptr = &r_info[target_ptr->monster_race_idx];
2696-
2697- old_race_flags_ptr->old_r_flags1 = r_ptr->r_flags1;
2698- old_race_flags_ptr->old_r_flags2 = r_ptr->r_flags2;
2699- old_race_flags_ptr->old_r_flags3 = r_ptr->r_flags3;
2700- old_race_flags_ptr->old_r_flags4 = r_ptr->r_flags4;
2701- old_race_flags_ptr->old_r_flags5 = r_ptr->r_flags5;
2702- old_race_flags_ptr->old_r_flags6 = r_ptr->r_flags6;
2703- old_race_flags_ptr->old_r_flagsr = r_ptr->r_flagsr;
2704-
2705- old_race_flags_ptr->old_r_blows0 = r_ptr->r_blows[0];
2706- old_race_flags_ptr->old_r_blows1 = r_ptr->r_blows[1];
2707- old_race_flags_ptr->old_r_blows2 = r_ptr->r_blows[2];
2708- old_race_flags_ptr->old_r_blows3 = r_ptr->r_blows[3];
2709-
2710- old_race_flags_ptr->old_r_cast_spell = r_ptr->r_cast_spell;
2711-}
2712-
2713-
2714-/*!
2715510 * @brief フロア内のモンスターについてターン終了時の処理を繰り返す
2716511 * @param target_ptr プレーヤーへの参照ポインタ
2717512 */
@@ -2736,7 +531,7 @@ void sweep_monster_process(player_type *target_ptr)
2736531 if (m_ptr->cdis >= AAF_LIMIT) continue;
2737532 if (!decide_process_continue(target_ptr, m_ptr)) continue;
2738533
2739- SPEED speed = decide_monster_speed(target_ptr, m_ptr, i);
534+ SPEED speed = (target_ptr->riding == i) ? target_ptr->pspeed : decide_monster_speed(m_ptr);
2740535 m_ptr->energy_need -= SPEED_TO_ENERGY(speed);
2741536 if (m_ptr->energy_need > 0) continue;
2742537
@@ -2781,57 +576,3 @@ bool decide_process_continue(player_type *target_ptr, monster_type *m_ptr)
2781576
2782577 return FALSE;
2783578 }
2784-
2785-
2786-/*!
2787- * @brief モンスターの加速値を決定する
2788- * @param target_ptr プレーヤーへの参照ポインタ
2789- * @param m_ptr モンスターへの参照ポインタ
2790- * @param monster_number 走査中のモンスター番号
2791- * return モンスターの加速値
2792- */
2793-SPEED decide_monster_speed(player_type *target_ptr, monster_type *m_ptr, int monster_number)
2794-{
2795- SPEED speed;
2796- if (target_ptr->riding == monster_number)
2797- {
2798- speed = target_ptr->pspeed;
2799- return speed;
2800- }
2801-
2802- speed = m_ptr->mspeed;
2803- if (ironman_nightmare) speed += 5;
2804-
2805- if (MON_FAST(m_ptr)) speed += 10;
2806- if (MON_SLOW(m_ptr)) speed -= 10;
2807-
2808- return speed;
2809-}
2810-
2811-
2812-/*!
2813- * @brief モンスターフラグの更新に基づき、モンスター表示を更新する
2814- * @param target_ptr プレーヤーへの参照ポインタ
2815- * @param old_race_flags_ptr モンスターフラグへの参照ポインタ
2816- * @return なし
2817- */
2818-void update_player_window(player_type *target_ptr, old_race_flags *old_race_flags_ptr)
2819-{
2820- monster_race *r_ptr;
2821- r_ptr = &r_info[target_ptr->monster_race_idx];
2822- if ((old_race_flags_ptr->old_r_flags1 != r_ptr->r_flags1) ||
2823- (old_race_flags_ptr->old_r_flags2 != r_ptr->r_flags2) ||
2824- (old_race_flags_ptr->old_r_flags3 != r_ptr->r_flags3) ||
2825- (old_race_flags_ptr->old_r_flags4 != r_ptr->r_flags4) ||
2826- (old_race_flags_ptr->old_r_flags5 != r_ptr->r_flags5) ||
2827- (old_race_flags_ptr->old_r_flags6 != r_ptr->r_flags6) ||
2828- (old_race_flags_ptr->old_r_flagsr != r_ptr->r_flagsr) ||
2829- (old_race_flags_ptr->old_r_blows0 != r_ptr->r_blows[0]) ||
2830- (old_race_flags_ptr->old_r_blows1 != r_ptr->r_blows[1]) ||
2831- (old_race_flags_ptr->old_r_blows2 != r_ptr->r_blows[2]) ||
2832- (old_race_flags_ptr->old_r_blows3 != r_ptr->r_blows[3]) ||
2833- (old_race_flags_ptr->old_r_cast_spell != r_ptr->r_cast_spell))
2834- {
2835- target_ptr->window |= (PW_MONSTER);
2836- }
2837-}
--- a/src/monster-process.h
+++ b/src/monster-process.h
@@ -1,5 +1,4 @@
11 #pragma once
22
3-/* monster-process.c */
43 extern void process_monsters(player_type *target_ptr);
54 extern void process_monster(player_type *target_ptr, MONSTER_IDX m_idx);
--- a/src/monster-spell.h
+++ b/src/monster-spell.h
@@ -328,7 +328,7 @@ extern void set_rf_masks(BIT_FLAGS *f4, BIT_FLAGS *f5, BIT_FLAGS *f6, BIT_FLAGS
328328 /* mspells4.c */
329329 extern bool spell_learnable(player_type *target_ptr, MONSTER_IDX m_idx);
330330 extern HIT_POINT monspell_to_player(player_type *target_ptr, int SPELL_NUM, POSITION y, POSITION x, MONSTER_IDX m_idx);
331-extern HIT_POINT monspell_to_monster(player_type *target_ptr, int SPELL_NUM, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx);
331+extern HIT_POINT monspell_to_monster(player_type *target_ptr, int SPELL_NUM, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, bool is_special_spell);
332332 extern HIT_POINT monspell_damage(player_type *target_ptr, int SPELL_NUM, MONSTER_IDX m_idx, int TYPE);
333333 extern HIT_POINT monspell_race_damage(player_type *target_ptr, int SPELL_NUM, MONRACE_IDX r_idx, int TYPE);
334334 extern HIT_POINT monspell_bluemage_damage(player_type *target_ptr, int SPELL_NUM, PLAYER_LEVEL plev, int TYPE);
--- a/src/monster.h
+++ b/src/monster.h
@@ -35,9 +35,7 @@ extern MONSTER_IDX hack_m_idx_ii;
3535 */
3636
3737 typedef struct floor_type floor_type;
38-typedef struct monster_type monster_type;
39-
40-struct monster_type
38+typedef struct
4139 {
4240 MONRACE_IDX r_idx; /* Monster race index 0 = dead. */
4341 MONRACE_IDX ap_r_idx; /* Monster race appearance index */
@@ -128,13 +126,11 @@ struct monster_type
128126 #define SM_IMM_MANA 0x80000000 /*!< モンスターの学習フラグ: プレイヤーにMPがない */
129127
130128 MONSTER_IDX parent_m_idx;
131-};
129+} monster_type;
132130
133131 #define MON_BEGGAR 12
134132 #define MON_LEPER 13
135-#define MON_BLACK_MARKET 14
136133 #define MON_LION_HEART 19
137-#define MON_GHB 39
138134 #define MON_NOV_PRIEST 45
139135 #define MON_GRIP 53
140136 #define MON_WOLF 54
@@ -143,13 +139,10 @@ struct monster_type
143139 #define MON_PIRANHA 70
144140 #define MON_COPPER_COINS 85
145141 #define MON_NOV_PALADIN 97
146-#define MON_GREEN_G 100
147142 #define MON_NOV_PRIEST_G 109
148143 #define MON_SILVER_COINS 117
149144 #define MON_D_ELF 122
150145 #define MON_MANES 128
151-#define MON_LOST_SOUL 133
152-#define MON_ROBIN_HOOD 138
153146 #define MON_NOV_PALADIN_G 147
154147 #define MON_PHANTOM_W 152
155148 #define MON_WOUNDED_BEAR 159
@@ -157,98 +150,41 @@ struct monster_type
157150 #define MON_D_ELF_WARRIOR 182
158151 #define MON_BLUE_HORROR 189
159152 #define MON_GOLD_COINS 195
160-#define MON_VORPAL_BUNNY 205
161153 #define MON_MASTER_YEEK 224
162154 #define MON_PRIEST 225
163155 #define MON_D_ELF_PRIEST 226
164-#define MON_TIGER 230
165156 #define MON_MITHRIL_COINS 239
166-#define MON_DRUID 241
167157 #define MON_PINK_HORROR 242
168-#define MON_HILL_GIANT 255
169-#define MON_WERERAT 270
170-#define MON_UMBER_HULK 283
171-#define MON_ORC_CAPTAIN 285
172-#define MON_BERSERKER 293
173158 #define MON_IMP 296
174-#define MON_SHAGRAT 314
175-#define MON_GORBAG 315
176-#define MON_STONE_GIANT 321
177159 #define MON_LIZARD_KING 332
178160 #define MON_WYVERN 334
179161 #define MON_SABRE_TIGER 339
180162 #define MON_D_ELF_LORD 348
181-#define MON_FIRE_VOR 354
182-#define MON_WATER_VOR 355
183163 #define MON_ARCH_VILE 357
184-#define MON_COLD_VOR 358
185-#define MON_ENERGY_VOR 359
186-#define MON_IRON_GOLEM 367
187164 #define MON_JADE_MONK 370
188165 #define MON_D_ELF_WARLOCK 375
189-#define MON_HAGEN 383
190166 #define MON_MENELDOR 384
191167 #define MON_PHANTOM_B 385
192-#define MON_C_CRAWLER 395
193-#define MON_XICLOTLAN 396
194168 #define MON_D_ELF_DRUID 400
195-#define MON_TROLL_PRIEST 403
196169 #define MON_GWAIHIR 410
197-#define MON_ANGEL 417
198170 #define MON_ADAMANT_COINS 423
199171 #define MON_COLBRAN 435
200-#define MON_SPIRIT_NAGA 436
201-#define MON_GACHAPIN 441
202-#define MON_BASILISK 453
203-#define MON_ARCHANGEL 456
204172 #define MON_MITHRIL_GOLEM 464
205173 #define MON_THORONDOR 468
206-#define MON_SHADOW_DRAKE 471
207-#define MON_GHOST 477
208-#define MON_OGRE_SHAMAN 479
209174 #define MON_GHOUL_KING 483
210175 #define MON_NINJA 485
211176 #define MON_BICLOPS 490
212177 #define MON_IVORY_MONK 492
213-#define MON_LOG_MASTER 498
214-#define MON_ETHER_DRAKE 504
215178 #define MON_GOEMON 505
216-#define MON_CHERUB 511
217179 #define MON_WATER_ELEM 512
218-#define MON_JURT 517
219-#define MON_LICH 518
220180 #define MON_BLOODLETTER 523
221-#define MON_HALFLING_S 539
222-#define MON_GRAV_HOUND 540
223-#define MON_REVENANT 555
224181 #define MON_RAAL 557
225-#define MON_COLOSSUS 558
226182 #define MON_NIGHTBLADE 564
227-#define MON_ELDER_THING 569
228-#define MON_CRYPT_THING 577
229-#define MON_NEXUS_VOR 587
230-#define MON_PLASMA_VOR 588
231-#define MON_TIME_VOR 589
232-#define MON_M_MH_DRAGON 593
233-#define MON_MANDOR 598
234-#define MON_SHIM_VOR 600
235-#define MON_SERAPH 605
236183 #define MON_BARON_HELL 609
237-#define MON_KAVLAX 616
238-#define MON_ETTIN 621
239-#define MON_VAMPIRE_LORD 623
240-#define MON_JUBJUB 640
241184 #define MON_G_C_DRAKE 646
242-#define MON_CLUB_DEMON 648
243185 #define MON_F_ANGEL 652
244186 #define MON_D_ELF_SORC 657
245-#define MON_MASTER_LICH 658
246-#define MON_RINALDO 660
247-#define MON_ARCHON 661
248-#define MON_UND_BEHOLDER 664
249187 #define MON_IRON_LICH 666
250-#define MON_JACK_SHADOWS 670
251-#define MON_LLOIGOR 682
252188 #define MON_DREADMASTER 690
253189 #define MON_DROLEM 691
254190 #define MON_DAWN 693
@@ -260,89 +196,37 @@ struct monster_type
260196 #define MON_S_TYRANNO 705
261197 #define MON_FAFNER 712
262198 #define MON_G_BALROG 720
263-#define MON_TIME_HOUND 725
264-#define MON_PLASMA_HOUND 726
265199 #define MON_BULLGATES 732
266-#define MON_SANTACLAUS 733
267200 #define MON_LORD_CHAOS 737
268-#define MON_TINDALOS 739
269-#define MON_DEMILICH 742
270-#define MON_NIGHTCRAWLER 744
271-#define MON_CHAOS_VOR 751
272-#define MON_AETHER_VOR 752
273-#define MON_FUNDIN 762
274-#define MON_DWORKIN 763
275201 #define MON_NIGHTWALKER 768
276-#define MON_RAPHAEL 769
277-#define MON_SARUMAN 771
278-#define MON_GANDALF 772
279-#define MON_BRAND 773
280202 #define MON_SHADOWLORD 774
281-#define MON_ARCHLICH 776
282203 #define MON_JABBERWOCK 778
283-#define MON_CHAOS_HOUND 779
284204 #define MON_ULT_BEHOLDER 781
285205 #define MON_SHAMBLER 786
286-#define MON_BLEYS 789
287-#define MON_FIONA 791
288-#define MON_SKY_DRAKE 793
289-#define MON_JULIAN 794
290206 #define MON_BLACK_REAVER 798
291-#define MON_CAINE 799
292-#define MON_GERARD 807
293-#define MON_UNGOLIANT 808
294-#define MON_ATLACH_NACHA 809
295-#define MON_Y_GOLONAC 810
296-#define MON_AETHER_HOUND 811
297-#define MON_WARP_DEMON 812
298-#define MON_ERIC 813
299207 #define MON_UNMAKER 815
300208 #define MON_CYBER 816
301-#define MON_KLING 819
302-#define MON_CORWIN 820
303209 #define MON_ANGMAR 825
304-#define MON_CANTORAS 830
305-#define MON_GODZILLA 832
306-#define MON_SPAWN_CTH 836
307-#define MON_SURTUR 837
308-#define MON_TARRASQUE 838
309-#define MON_LUNGORTHIN 839
310-#define MON_CYBER_KING 843
311210 #define MON_WYRM_POWER 847
312-#define MON_NODENS 849
313211 #define MON_JORMUNGAND 854
314-#define MON_DESTROYER 855
315-#define MON_GOTHMOG 856
316-#define MON_G_CTHULHU 857
317212 #define MON_SAURON 858
318213 #define MON_UNICORN_ORD 859
319214 #define MON_OBERON 860
320215 #define MON_MORGOTH 861
321216 #define MON_SERPENT 862
322217 #define MON_ONE_RING 864
323-#define MON_CAAWS 866
324-#define MON_CULVERIN 867
325218 #define MON_EBONY_MONK 870
326219 #define MON_HAGURE 871
327-#define MON_OROCHI 872
328-#define MON_ECHIZEN 873
329-#define MON_SPECT_WYRM 874
330220 #define MON_DIO 878
331221 #define MON_OHMU 879
332222 #define MON_WONG 880
333223 #define MON_ZOMBI_SERPENT 883
334224 #define MON_D_ELF_SHADE 886
335-#define MON_MANA_HOUND 887
336-#define MON_VENOM_WYRM 890
337225 #define MON_TROLL_KING 894
338-#define MON_BAZOOKER 896
339-#define MON_SHARD_VOR 897
340226 #define MON_ELF_LORD 900
341-#define MON_MASTER_MYS 916
342227 #define MON_G_MASTER_MYS 917
343228 #define MON_IE 921
344229 #define MON_TSUCHINOKO 926
345-#define MON_GCWADL 929
346230 #define MON_LOCKE_CLONE 930
347231 #define MON_CALDARM 931
348232 #define MON_BANORLUPART 932
@@ -350,10 +234,7 @@ struct monster_type
350234 #define MON_LUPART 934
351235 #define MON_KENSHIROU 936
352236 #define MON_W_KNIGHT 938
353-#define MON_PLANETAR 942
354-#define MON_SOLAR 943
355237 #define MON_BIKETAL 945
356-#define MON_RICH 948
357238 #define MON_IKETA 949
358239 #define MON_B_DEATH_SWORD 953
359240 #define MON_YASE_HORSE 955
@@ -361,22 +242,14 @@ struct monster_type
361242 #define MON_BOTEI 963
362243 #define MON_KAGE 964
363244 #define MON_JAIAN 967
364-#define MON_BELD 973
365-#define MON_THAT_BAT 975
366-#define MON_SHUTEN 979
367245 #define MON_FENGHUANG 988
368-#define MON_KIRIN 989
369-#define MON_BAHAMUT 1000
370246 #define MON_SUKE 1001
371247 #define MON_KAKU 1002
372-#define MON_GHOST_Q 1003
373-#define MON_PIP 1004
374248 #define MON_A_GOLD 1010
375249 #define MON_A_SILVER 1011
376250 #define MON_ROLENTO 1013
377251 #define MON_RAOU 1018
378-#define MON_SHURYUUDAN 1023
379-#define MON_WAHHA 1031
252+#define MON_GRENADE 1023
380253 #define MON_DEBBY 1032
381254 #define MON_KNI_TEMPLAR 1037
382255 #define MON_PALADIN 1038
@@ -394,8 +267,6 @@ struct monster_type
394267 #define MON_JIZOTAKO 1065
395268 #define MON_TANUKI 1067
396269 #define MON_ALIEN_JURAL 1082
397-#define MON_HATOPOPPO 1083
398-#define MON_KOGAN 1096
399270
400271 /*
401272 * Bit flags for the place_monster_???() (etc)
--- /dev/null
+++ b/src/monster/monster-attack.c
@@ -0,0 +1,125 @@
1+/*!
2+ * @brief モンスターの攻撃に関する処理
3+ * @date 2020/03/08
4+ * @author Hourier
5+ */
6+
7+#include "monster/monster-attack.h"
8+#include "monster-status.h"
9+#include "dungeon.h"
10+#include "combat/melee.h" // 暫定。後で引っ越し.
11+
12+ /*!
13+ * @brief モンスターが移動した結果、そこにプレーヤーがいたら直接攻撃を行う
14+ * @param target_ptr プレーヤーへの参照ポインタ
15+ * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
16+ * @param m_idx モンスターID
17+ * @param ny 移動後の、モンスターのY座標
18+ * @param nx 移動後の、モンスターのX座標
19+ * @return なし
20+ * @details
21+ * 反攻撃の洞窟など、直接攻撃ができない場所では処理をスキップする
22+ */
23+void exe_monster_attack_to_player(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION ny, POSITION nx)
24+{
25+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
26+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
27+ if (!turn_flags_ptr->do_move || !player_bold(target_ptr, ny, nx))
28+ return;
29+
30+ if (r_ptr->flags1 & RF1_NEVER_BLOW)
31+ {
32+ if (is_original_ap_and_seen(target_ptr, m_ptr))
33+ r_ptr->r_flags1 |= (RF1_NEVER_BLOW);
34+
35+ turn_flags_ptr->do_move = FALSE;
36+ }
37+
38+ if (turn_flags_ptr->do_move && ((d_info[target_ptr->dungeon_idx].flags1 & DF1_NO_MELEE) != 0) && !MON_CONFUSED(m_ptr))
39+ {
40+ if (!(r_ptr->flags2 & RF2_STUPID))
41+ turn_flags_ptr->do_move = FALSE;
42+ else if (is_original_ap_and_seen(target_ptr, m_ptr))
43+ r_ptr->r_flags2 |= (RF2_STUPID);
44+ }
45+
46+ if (!turn_flags_ptr->do_move) return;
47+
48+ if (!target_ptr->riding || one_in_(2))
49+ {
50+ (void)make_attack_normal(target_ptr, m_idx);
51+ turn_flags_ptr->do_move = FALSE;
52+ turn_flags_ptr->do_turn = TRUE;
53+ }
54+}
55+
56+
57+/*!
58+ * @brief モンスターからモンスターへの直接攻撃を実行する
59+ * @param target_ptr プレーヤーへの参照ポインタ
60+ * @param m_idx モンスターID
61+ * @param g_ptr グリッドへの参照ポインタ
62+ */
63+static bool exe_monster_attack_to_monster(player_type *target_ptr, MONSTER_IDX m_idx, grid_type *g_ptr)
64+{
65+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
66+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
67+ monster_type *y_ptr;
68+ y_ptr = &target_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
69+ if ((r_ptr->flags1 & RF1_NEVER_BLOW) != 0) return FALSE;
70+
71+ if (((r_ptr->flags2 & RF2_KILL_BODY) == 0) && is_original_ap_and_seen(target_ptr, m_ptr))
72+ r_ptr->r_flags2 |= (RF2_KILL_BODY);
73+
74+ if ((y_ptr->r_idx == 0) || (y_ptr->hp < 0)) return FALSE;
75+ if (monst_attack_monst(target_ptr, m_idx, g_ptr->m_idx)) return TRUE;
76+ if ((d_info[target_ptr->dungeon_idx].flags1 & DF1_NO_MELEE) == 0) return FALSE;
77+ if (MON_CONFUSED(m_ptr)) return TRUE;
78+ if ((r_ptr->flags2 & RF2_STUPID) == 0) return FALSE;
79+
80+ if (is_original_ap_and_seen(target_ptr, m_ptr))
81+ r_ptr->r_flags2 |= (RF2_STUPID);
82+
83+ return TRUE;
84+}
85+
86+
87+/*!
88+ * @brief モンスターからモンスターへの攻撃処理
89+ * @param target_ptr プレーヤーへの参照ポインタ
90+ * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
91+ * @param m_idx モンスターID
92+ * @param g_ptr グリッドへの参照ポインタ
93+ * @param can_cross モンスターが地形を踏破できるならばTRUE
94+ * @return ターン消費が発生したらTRUE
95+ */
96+bool process_monster_attack_to_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, grid_type *g_ptr, bool can_cross)
97+{
98+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
99+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
100+ monster_type *y_ptr;
101+ y_ptr = &target_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
102+ if (!turn_flags_ptr->do_move || (g_ptr->m_idx == 0)) return FALSE;
103+
104+ monster_race *z_ptr = &r_info[y_ptr->r_idx];
105+ turn_flags_ptr->do_move = FALSE;
106+ if ((((r_ptr->flags2 & RF2_KILL_BODY) != 0) && ((r_ptr->flags1 & RF1_NEVER_BLOW) == 0) &&
107+ (r_ptr->mexp * r_ptr->level > z_ptr->mexp * z_ptr->level) &&
108+ can_cross && (g_ptr->m_idx != target_ptr->riding)) ||
109+ are_enemies(target_ptr, m_ptr, y_ptr) || MON_CONFUSED(m_ptr))
110+ {
111+ return exe_monster_attack_to_monster(target_ptr, m_idx, g_ptr);
112+ }
113+
114+ if (((r_ptr->flags2 & RF2_MOVE_BODY) != 0) && ((r_ptr->flags1 & RF1_NEVER_MOVE) == 0) &&
115+ (r_ptr->mexp > z_ptr->mexp) &&
116+ can_cross && (g_ptr->m_idx != target_ptr->riding) &&
117+ monster_can_cross_terrain(target_ptr, target_ptr->current_floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].feat, z_ptr, 0))
118+ {
119+ turn_flags_ptr->do_move = TRUE;
120+ turn_flags_ptr->did_move_body = TRUE;
121+ (void)set_monster_csleep(target_ptr, g_ptr->m_idx, 0);
122+ }
123+
124+ return FALSE;
125+}
--- /dev/null
+++ b/src/monster/monster-attack.h
@@ -0,0 +1,7 @@
1+#pragma once
2+
3+#include "angband.h"
4+#include "monster/monster-util.h"
5+
6+void exe_monster_attack_to_player(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION ny, POSITION nx);
7+bool process_monster_attack_to_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, grid_type *g_ptr, bool can_cross);
--- /dev/null
+++ b/src/monster/monster-direction.c
@@ -0,0 +1,247 @@
1+/*!
2+ * @brief モンスターの移動方向を決定する処理
3+ * @date 2020/03/08
4+ * @author Hourier
5+ */
6+
7+#include "monster/monster-direction.h"
8+#include "monster/monster-sweep-grid.h"
9+#include "monster/monster-util.h"
10+#include "monster-status.h"
11+#include "cmd/cmd-pet.h"
12+
13+/*!
14+ * @brief ペットが敵に接近するための方向を決定する
15+ * @param target_ptr プレーヤーへの参照ポインタ
16+ * @param m_ptr 移動を試みているモンスターへの参照ポインタ
17+ * @param t_ptr 移動先モンスターへの参照ポインタ
18+ * @param plus モンスターIDの増減 (1/2 の確率で+1、1/2の確率で-1)
19+ * @return ペットがモンスターに近づくならばTRUE
20+ */
21+static bool decide_pet_approch_direction(player_type *target_ptr, monster_type *m_ptr, monster_type *t_ptr)
22+{
23+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
24+ if (!is_pet(m_ptr)) return FALSE;
25+
26+ if (target_ptr->pet_follow_distance < 0)
27+ {
28+ if (t_ptr->cdis <= (0 - target_ptr->pet_follow_distance))
29+ {
30+ return TRUE;
31+ }
32+ }
33+ else if ((m_ptr->cdis < t_ptr->cdis) && (t_ptr->cdis > target_ptr->pet_follow_distance))
34+ {
35+ return TRUE;
36+ }
37+
38+ return (r_ptr->aaf < t_ptr->cdis);
39+}
40+
41+
42+/*!
43+ * @brief モンスターが敵に接近するための方向を決定する
44+ * @param target_ptr プレーヤーへの参照ポインタ
45+ * @param m_idx モンスターID
46+ * @param start モンスターIDの開始
47+ * @param plus モンスターIDの増減 (1/2 の確率で+1、1/2の確率で-1)
48+ * @param y モンスターの移動方向Y
49+ * @param x モンスターの移動方向X
50+ * @return なし
51+ */
52+static void decide_enemy_approch_direction(player_type *target_ptr, MONSTER_IDX m_idx, int start, int plus, POSITION *y, POSITION *x)
53+{
54+ floor_type *floor_ptr = target_ptr->current_floor_ptr;
55+ monster_type *m_ptr = &floor_ptr->m_list[m_idx];
56+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
57+ for (int i = start; ((i < start + floor_ptr->m_max) && (i > start - floor_ptr->m_max)); i += plus)
58+ {
59+ MONSTER_IDX dummy = (i % floor_ptr->m_max);
60+ if (dummy == 0) continue;
61+
62+ MONSTER_IDX t_idx = dummy;
63+ monster_type *t_ptr;
64+ t_ptr = &floor_ptr->m_list[t_idx];
65+ if (t_ptr == m_ptr) continue;
66+ if (!monster_is_valid(t_ptr)) continue;
67+ if (decide_pet_approch_direction(target_ptr, m_ptr, t_ptr)) continue;
68+ if (!are_enemies(target_ptr, m_ptr, t_ptr)) continue;
69+
70+ if (((r_ptr->flags2 & RF2_PASS_WALL) && ((m_idx != target_ptr->riding) || target_ptr->pass_wall)) ||
71+ ((r_ptr->flags2 & RF2_KILL_WALL) && (m_idx != target_ptr->riding)))
72+ {
73+ if (!in_disintegration_range(floor_ptr, m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx)) continue;
74+ }
75+ else
76+ {
77+ if (!projectable(target_ptr, m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx)) continue;
78+ }
79+
80+ *y = t_ptr->fy;
81+ *x = t_ptr->fx;
82+ return;
83+ }
84+}
85+
86+
87+/*!
88+ * @brief モンスターが敵に接近するための方向を計算するメインルーチン
89+ * Calculate the direction to the next enemy
90+ * @param target_ptr プレーヤーへの参照ポインタ
91+ * @param m_idx モンスターの参照ID
92+ * @param mm 移動するべき方角IDを返す参照ポインタ
93+ * @return 方向が確定した場合TRUE、接近する敵がそもそもいない場合FALSEを返す
94+ */
95+bool get_enemy_dir(player_type *target_ptr, MONSTER_IDX m_idx, int *mm)
96+{
97+ floor_type *floor_ptr = target_ptr->current_floor_ptr;
98+ monster_type *m_ptr = &floor_ptr->m_list[m_idx];
99+
100+ POSITION x = 0, y = 0;
101+ if (target_ptr->riding_t_m_idx && player_bold(target_ptr, m_ptr->fy, m_ptr->fx))
102+ {
103+ y = floor_ptr->m_list[target_ptr->riding_t_m_idx].fy;
104+ x = floor_ptr->m_list[target_ptr->riding_t_m_idx].fx;
105+ }
106+ else if (is_pet(m_ptr) && target_ptr->pet_t_m_idx)
107+ {
108+ y = floor_ptr->m_list[target_ptr->pet_t_m_idx].fy;
109+ x = floor_ptr->m_list[target_ptr->pet_t_m_idx].fx;
110+ }
111+ else
112+ {
113+ int start;
114+ int plus = 1;
115+ if (target_ptr->phase_out)
116+ {
117+ start = randint1(floor_ptr->m_max - 1) + floor_ptr->m_max;
118+ if (randint0(2)) plus = -1;
119+ }
120+ else
121+ {
122+ start = floor_ptr->m_max + 1;
123+ }
124+
125+ decide_enemy_approch_direction(target_ptr, m_idx, start, plus, &y, &x);
126+
127+ if ((x == 0) && (y == 0)) return FALSE;
128+ }
129+
130+ x -= m_ptr->fx;
131+ y -= m_ptr->fy;
132+
133+ store_enemy_approch_direction(mm, y, x);
134+ return TRUE;
135+}
136+
137+
138+/*!
139+ * todo ↓のように書いたが、"5"とはもしかして「その場に留まる」という意味か?
140+ * @brief 不規則歩行フラグを持つモンスターの移動方向をその確率に基づいて決定する
141+ * @param target_ptr プレーヤーへの参照ポインタ
142+ * @param mm 移動方向
143+ * @param m_ptr モンスターへの参照ポインタ
144+ * @return 不規則な方向へ歩くことになったらTRUE
145+ */
146+static bool random_walk(player_type *target_ptr, DIRECTION *mm, monster_type *m_ptr)
147+{
148+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
149+ if (((r_ptr->flags1 & (RF1_RAND_50 | RF1_RAND_25)) == (RF1_RAND_50 | RF1_RAND_25)) && (randint0(100) < 75))
150+ {
151+ if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags1 |= (RF1_RAND_50 | RF1_RAND_25);
152+
153+ mm[0] = mm[1] = mm[2] = mm[3] = 5;
154+ return TRUE;
155+ }
156+
157+ if ((r_ptr->flags1 & RF1_RAND_50) && (randint0(100) < 50))
158+ {
159+ if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags1 |= RF1_RAND_50;
160+
161+ mm[0] = mm[1] = mm[2] = mm[3] = 5;
162+ return TRUE;
163+ }
164+
165+ if ((r_ptr->flags1 & RF1_RAND_25) && (randint0(100) < 25))
166+ {
167+ if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags1 |= RF1_RAND_25;
168+
169+ mm[0] = mm[1] = mm[2] = mm[3] = 5;
170+ return TRUE;
171+ }
172+
173+ return FALSE;
174+}
175+
176+
177+/*!
178+ * @brief ペットや友好的なモンスターがフロアから逃げる処理を行う
179+ * @param target_ptr プレーヤーへの参照ポインタ
180+ * @param mm 移動方向
181+ * @param m_idx モンスターID
182+ * @return モンスターがペットであればTRUE
183+ */
184+static bool decide_pet_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx)
185+{
186+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
187+ if (!is_pet(m_ptr)) return FALSE;
188+
189+ bool avoid = ((target_ptr->pet_follow_distance < 0) && (m_ptr->cdis <= (0 - target_ptr->pet_follow_distance)));
190+ bool lonely = (!avoid && (m_ptr->cdis > target_ptr->pet_follow_distance));
191+ bool distant = (m_ptr->cdis > PET_SEEK_DIST);
192+ mm[0] = mm[1] = mm[2] = mm[3] = 5;
193+ if (get_enemy_dir(target_ptr, m_idx, mm)) return TRUE;
194+ if (!avoid && !lonely && !distant) return TRUE;
195+
196+ POSITION dis = target_ptr->pet_follow_distance;
197+ if (target_ptr->pet_follow_distance > PET_SEEK_DIST)
198+ {
199+ target_ptr->pet_follow_distance = PET_SEEK_DIST;
200+ }
201+
202+ (void)get_movable_grid(target_ptr, m_idx, mm);
203+ target_ptr->pet_follow_distance = (s16b)dis;
204+ return TRUE;
205+}
206+
207+
208+/*!
209+ * @brief モンスターの移動パターンを決定する
210+ * @param target_ptr プレーヤーへの参照ポインタ
211+ * @param mm 移動方向
212+ * @param m_idx モンスターID
213+ * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
214+ * @return 移動先が存在すればTRUE
215+ */
216+bool decide_monster_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx, bool aware)
217+{
218+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
219+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
220+
221+ if (MON_CONFUSED(m_ptr) || !aware)
222+ {
223+ mm[0] = mm[1] = mm[2] = mm[3] = 5;
224+ return TRUE;
225+ }
226+
227+ if (random_walk(target_ptr, mm, m_ptr)) return TRUE;
228+
229+ if ((r_ptr->flags1 & RF1_NEVER_MOVE) && (m_ptr->cdis > 1))
230+ {
231+ mm[0] = mm[1] = mm[2] = mm[3] = 5;
232+ return TRUE;
233+ }
234+
235+ if (decide_pet_movement_direction(target_ptr, mm, m_idx)) return TRUE;
236+
237+ if (!is_hostile(m_ptr))
238+ {
239+ mm[0] = mm[1] = mm[2] = mm[3] = 5;
240+ get_enemy_dir(target_ptr, m_idx, mm);
241+ return TRUE;
242+ }
243+
244+ if (!get_movable_grid(target_ptr, m_idx, mm)) return FALSE;
245+
246+ return TRUE;
247+}
--- /dev/null
+++ b/src/monster/monster-direction.h
@@ -0,0 +1,6 @@
1+#pragma once
2+
3+#include "angband.h"
4+
5+bool get_enemy_dir(player_type *target_ptr, MONSTER_IDX m_idx, int *mm);
6+bool decide_monster_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx, bool aware);
--- /dev/null
+++ b/src/monster/monster-move.c
@@ -0,0 +1,498 @@
1+/*!
2+ * @brief モンスターの移動に関する処理
3+ * @date 2020/03/08
4+ * @author Hourier
5+ */
6+
7+#include "monster/monster-move.h"
8+#include "monster/monster-attack.h"
9+#include "monster/monster-object.h"
10+#include "monster/monster-update.h"
11+#include "cmd/cmd-pet.h"
12+#include "creature.h"
13+#include "files.h"
14+#include "monster-status.h"
15+#include "player-move.h"
16+
17+static bool check_hp_for_feat_destruction(feature_type *f_ptr, monster_type *m_ptr)
18+{
19+ return !have_flag(f_ptr->flags, FF_GLASS) ||
20+ (r_info[m_ptr->r_idx].flags2 & RF2_STUPID) ||
21+ (m_ptr->hp >= MAX(m_ptr->maxhp / 3, 200));
22+}
23+
24+
25+/*!
26+ * @brief モンスターによる壁の透過・破壊を行う
27+ * @param target_ptr プレーヤーへの参照ポインタ
28+ * @param m_ptr モンスターへの参照ポインタ
29+ * @param ny モンスターのY座標
30+ * @param nx モンスターのX座標
31+ * @param can_cross モンスターが地形を踏破できるならばTRUE
32+ * @return 透過も破壊もしなかった場合はFALSE、それ以外はTRUE
33+ */
34+static bool process_wall(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx, bool can_cross)
35+{
36+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
37+ grid_type *g_ptr;
38+ g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
39+ feature_type *f_ptr;
40+ f_ptr = &f_info[g_ptr->feat];
41+ if (player_bold(target_ptr, ny, nx))
42+ {
43+ turn_flags_ptr->do_move = TRUE;
44+ return TRUE;
45+ }
46+
47+ if (g_ptr->m_idx > 0)
48+ {
49+ turn_flags_ptr->do_move = TRUE;
50+ return TRUE;
51+ }
52+
53+ if (((r_ptr->flags2 & RF2_KILL_WALL) != 0) &&
54+ (can_cross ? !have_flag(f_ptr->flags, FF_LOS) : !turn_flags_ptr->is_riding_mon) &&
55+ have_flag(f_ptr->flags, FF_HURT_DISI) && !have_flag(f_ptr->flags, FF_PERMANENT) &&
56+ check_hp_for_feat_destruction(f_ptr, m_ptr))
57+ {
58+ turn_flags_ptr->do_move = TRUE;
59+ if (!can_cross) turn_flags_ptr->must_alter_to_move = TRUE;
60+
61+ turn_flags_ptr->did_kill_wall = TRUE;
62+ return TRUE;
63+ }
64+
65+ if (!can_cross) return FALSE;
66+
67+ turn_flags_ptr->do_move = TRUE;
68+ if (((r_ptr->flags2 & RF2_PASS_WALL) != 0) && (!turn_flags_ptr->is_riding_mon || target_ptr->pass_wall) &&
69+ have_flag(f_ptr->flags, FF_CAN_PASS))
70+ {
71+ turn_flags_ptr->did_pass_wall = TRUE;
72+ }
73+
74+ return TRUE;
75+}
76+
77+
78+/*!
79+ * @brief モンスターが普通のドアを開ける処理
80+ * @param target_ptr プレーヤーへの参照ポインタ
81+ * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
82+ * @param m_ptr モンスターへの参照ポインタ
83+ * @param ny モンスターのY座標
84+ * @param nx モンスターのX座標
85+ * @return ここではドアを開けず、ガラスのドアを開ける可能性があるならTRUE
86+ */
87+static bool bash_normal_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
88+{
89+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
90+ grid_type *g_ptr;
91+ g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
92+ feature_type *f_ptr;
93+ f_ptr = &f_info[g_ptr->feat];
94+ turn_flags_ptr->do_move = FALSE;
95+ if (((r_ptr->flags2 & RF2_OPEN_DOOR) == 0) || !have_flag(f_ptr->flags, FF_OPEN) ||
96+ (is_pet(m_ptr) && ((target_ptr->pet_extra_flags & PF_OPEN_DOORS) == 0)))
97+ return TRUE;
98+
99+ if (f_ptr->power == 0)
100+ {
101+ turn_flags_ptr->did_open_door = TRUE;
102+ turn_flags_ptr->do_turn = TRUE;
103+ return FALSE;
104+ }
105+
106+ if (randint0(m_ptr->hp / 10) > f_ptr->power)
107+ {
108+ cave_alter_feat(target_ptr, ny, nx, FF_DISARM);
109+ turn_flags_ptr->do_turn = TRUE;
110+ return FALSE;
111+ }
112+
113+ return TRUE;
114+}
115+
116+
117+/*!
118+ * @brief モンスターがガラスのドアを開ける処理
119+ * @param target_ptr プレーヤーへの参照ポインタ
120+ * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
121+ * @param m_ptr モンスターへの参照ポインタ
122+ * @param g_ptr グリッドへの参照ポインタ
123+ * @param f_ptr 地形への参照ポインタ
124+ * @return なし
125+ */
126+static void bash_glass_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, feature_type *f_ptr, bool may_bash)
127+{
128+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
129+ if (!may_bash || ((r_ptr->flags2 & RF2_BASH_DOOR) == 0) || !have_flag(f_ptr->flags, FF_BASH) ||
130+ (is_pet(m_ptr) && ((target_ptr->pet_extra_flags & PF_OPEN_DOORS) == 0)))
131+ return;
132+
133+ if (!check_hp_for_feat_destruction(f_ptr, m_ptr) || (randint0(m_ptr->hp / 10) <= f_ptr->power))
134+ return;
135+
136+ if (have_flag(f_ptr->flags, FF_GLASS))
137+ msg_print(_("ガラスが砕ける音がした!", "You hear glass breaking!"));
138+ else
139+ msg_print(_("ドアを叩き開ける音がした!", "You hear a door burst open!"));
140+
141+ if (disturb_minor) disturb(target_ptr, FALSE, FALSE);
142+
143+ turn_flags_ptr->did_bash_door = TRUE;
144+ turn_flags_ptr->do_move = TRUE;
145+ turn_flags_ptr->must_alter_to_move = TRUE;
146+}
147+
148+
149+/*!
150+ * @brief モンスターによるドアの開放・破壊を行う
151+ * @param target_ptr プレーヤーへの参照ポインタ
152+ * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
153+ * @param m_ptr モンスターへの参照ポインタ
154+ * @param ny モンスターのY座標
155+ * @param nx モンスターのX座標
156+ * @return モンスターが死亡した場合のみFALSE
157+ */
158+static bool process_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
159+{
160+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
161+ grid_type *g_ptr;
162+ g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
163+ if (!is_closed_door(target_ptr, g_ptr->feat)) return TRUE;
164+
165+ feature_type *f_ptr;
166+ f_ptr = &f_info[g_ptr->feat];
167+ bool may_bash = bash_normal_door(target_ptr, turn_flags_ptr, m_ptr, ny, nx);
168+ bash_glass_door(target_ptr, turn_flags_ptr, m_ptr, f_ptr, may_bash);
169+
170+ if (!turn_flags_ptr->did_open_door && !turn_flags_ptr->did_bash_door) return TRUE;
171+
172+ if (turn_flags_ptr->did_bash_door &&
173+ ((randint0(100) < 50) || (feat_state(target_ptr, g_ptr->feat, FF_OPEN) == g_ptr->feat) || have_flag(f_ptr->flags, FF_GLASS)))
174+ {
175+ cave_alter_feat(target_ptr, ny, nx, FF_BASH);
176+ if (!monster_is_valid(m_ptr))
177+ {
178+ target_ptr->update |= (PU_FLOW);
179+ target_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
180+ if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags2 |= (RF2_BASH_DOOR);
181+
182+ return FALSE;
183+ }
184+ }
185+ else
186+ {
187+ cave_alter_feat(target_ptr, ny, nx, FF_OPEN);
188+ }
189+
190+ f_ptr = &f_info[g_ptr->feat];
191+ turn_flags_ptr->do_view = TRUE;
192+ return TRUE;
193+}
194+
195+
196+/*!
197+ * @brief 守りのルーンによるモンスターの移動制限を処理する
198+ * @param target_ptr プレーヤーへの参照ポインタ
199+ * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
200+ * @param m_ptr モンスターへの参照ポインタ
201+ * @param ny モンスターのY座標
202+ * @param nx モンスターのX座標
203+ * @return ルーンのある/なし
204+ */
205+static bool process_protection_rune(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
206+{
207+ grid_type *g_ptr;
208+ g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
209+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
210+ if (!turn_flags_ptr->do_move || !is_glyph_grid(g_ptr) ||
211+ (((r_ptr->flags1 & RF1_NEVER_BLOW) != 0) && player_bold(target_ptr, ny, nx)))
212+ return FALSE;
213+
214+ turn_flags_ptr->do_move = FALSE;
215+ if (is_pet(m_ptr) || (randint1(BREAK_GLYPH) >= r_ptr->level))
216+ return TRUE;
217+
218+ if (g_ptr->info & CAVE_MARK)
219+ {
220+ msg_print(_("守りのルーンが壊れた!", "The rune of protection is broken!"));
221+ }
222+
223+ g_ptr->info &= ~(CAVE_MARK);
224+ g_ptr->info &= ~(CAVE_OBJECT);
225+ g_ptr->mimic = 0;
226+ turn_flags_ptr->do_move = TRUE;
227+ note_spot(target_ptr, ny, nx);
228+ return TRUE;
229+}
230+
231+
232+/*!
233+ * @brief 爆発のルーンを処理する
234+ * @param target_ptr プレーヤーへの参照ポインタ
235+ * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
236+ * @param m_ptr モンスターへの参照ポインタ
237+ * @param ny モンスターのY座標
238+ * @param nx モンスターのX座標
239+ * @return モンスターが死亡した場合のみFALSE
240+ */
241+static bool process_explosive_rune(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
242+{
243+ grid_type *g_ptr;
244+ g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
245+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
246+ if (!turn_flags_ptr->do_move || !is_explosive_rune_grid(g_ptr) ||
247+ (((r_ptr->flags1 & RF1_NEVER_BLOW) != 0) && player_bold(target_ptr, ny, nx)))
248+ return TRUE;
249+
250+ turn_flags_ptr->do_move = FALSE;
251+ if (is_pet(m_ptr)) return TRUE;
252+
253+ if (randint1(BREAK_MINOR_GLYPH) > r_ptr->level)
254+ {
255+ if (g_ptr->info & CAVE_MARK)
256+ {
257+ msg_print(_("ルーンが爆発した!", "The rune explodes!"));
258+ BIT_FLAGS project_flags = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP | PROJECT_NO_HANGEKI;
259+ project(target_ptr, 0, 2, ny, nx, 2 * (target_ptr->lev + damroll(7, 7)), GF_MANA, project_flags, -1);
260+ }
261+ }
262+ else
263+ {
264+ msg_print(_("爆発のルーンは解除された。", "An explosive rune was disarmed."));
265+ }
266+
267+ g_ptr->info &= ~(CAVE_MARK);
268+ g_ptr->info &= ~(CAVE_OBJECT);
269+ g_ptr->mimic = 0;
270+
271+ note_spot(target_ptr, ny, nx);
272+ lite_spot(target_ptr, ny, nx);
273+
274+ if (!monster_is_valid(m_ptr)) return FALSE;
275+
276+ turn_flags_ptr->do_move = TRUE;
277+ return TRUE;
278+}
279+
280+
281+/*!
282+ * @brief モンスターが壁を掘った後続処理を実行する
283+ * @param target_ptr プレーヤーへの参照ポインタ
284+ * @turn_flags_ptr ターン経過処理フラグへの参照ポインタ
285+ * @param m_ptr モンスターへの参照ポインタ
286+ * @param ny モンスターのY座標
287+ * @param nx モンスターのX座標
288+ * @return モンスターが死亡した場合のみFALSE
289+ */
290+static bool process_post_dig_wall(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
291+{
292+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
293+ grid_type *g_ptr;
294+ g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
295+ feature_type *f_ptr;
296+ f_ptr = &f_info[g_ptr->feat];
297+ if (!turn_flags_ptr->did_kill_wall || !turn_flags_ptr->do_move) return TRUE;
298+
299+ if (one_in_(GRINDNOISE))
300+ {
301+ if (have_flag(f_ptr->flags, FF_GLASS))
302+ msg_print(_("何かの砕ける音が聞こえる。", "There is a crashing sound."));
303+ else
304+ msg_print(_("ギシギシいう音が聞こえる。", "There is a grinding sound."));
305+ }
306+
307+ cave_alter_feat(target_ptr, ny, nx, FF_HURT_DISI);
308+
309+ if (!monster_is_valid(m_ptr))
310+ {
311+ target_ptr->update |= (PU_FLOW);
312+ target_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
313+ if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags2 |= (RF2_KILL_WALL);
314+
315+ return FALSE;
316+ }
317+
318+ f_ptr = &f_info[g_ptr->feat];
319+ turn_flags_ptr->do_view = TRUE;
320+ turn_flags_ptr->do_turn = TRUE;
321+ return TRUE;
322+}
323+
324+
325+/*!
326+ * todo 少し長いが、これといってブロックとしてまとまった部分もないので暫定でこのままとする
327+ * @brief モンスターの移動に関するメインルーチン
328+ * @param target_ptr プレーヤーへの参照ポインタ
329+ * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
330+ * @param m_idx モンスターID
331+ * @param mm モンスターの移動方向
332+ * @param oy 移動前の、モンスターのY座標
333+ * @param ox 移動前の、モンスターのX座標
334+ * @param count 移動回数 (のはず todo)
335+ * @return 移動が阻害される何か (ドア等)があったらFALSE
336+ */
337+bool process_monster_movement(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, DIRECTION *mm, POSITION oy, POSITION ox, int *count)
338+{
339+ for (int i = 0; mm[i]; i++)
340+ {
341+ int d = mm[i];
342+ if (d == 5) d = ddd[randint0(8)];
343+
344+ POSITION ny = oy + ddy[d];
345+ POSITION nx = ox + ddx[d];
346+ if (!in_bounds2(target_ptr->current_floor_ptr, ny, nx)) continue;
347+
348+ grid_type *g_ptr;
349+ g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
350+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
351+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
352+ bool can_cross = monster_can_cross_terrain(target_ptr, g_ptr->feat, r_ptr, turn_flags_ptr->is_riding_mon ? CEM_RIDING : 0);
353+
354+ if (!process_wall(target_ptr, turn_flags_ptr, m_ptr, ny, nx, can_cross))
355+ {
356+ if (!process_door(target_ptr, turn_flags_ptr, m_ptr, ny, nx))
357+ return FALSE;
358+ }
359+
360+ if (!process_protection_rune(target_ptr, turn_flags_ptr, m_ptr, ny, nx))
361+ {
362+ if (!process_explosive_rune(target_ptr, turn_flags_ptr, m_ptr, ny, nx))
363+ return FALSE;
364+ }
365+
366+ exe_monster_attack_to_player(target_ptr, turn_flags_ptr, m_idx, ny, nx);
367+ if (process_monster_attack_to_monster(target_ptr, turn_flags_ptr, m_idx, g_ptr, can_cross)) return FALSE;
368+
369+ if (turn_flags_ptr->is_riding_mon)
370+ {
371+ if (!target_ptr->riding_ryoute && !MON_MONFEAR(&target_ptr->current_floor_ptr->m_list[target_ptr->riding])) turn_flags_ptr->do_move = FALSE;
372+ }
373+
374+ if (!process_post_dig_wall(target_ptr, turn_flags_ptr, m_ptr, ny, nx)) return FALSE;
375+
376+ if (turn_flags_ptr->must_alter_to_move && (r_ptr->flags7 & RF7_AQUATIC))
377+ {
378+ if (!monster_can_cross_terrain(target_ptr, g_ptr->feat, r_ptr, turn_flags_ptr->is_riding_mon ? CEM_RIDING : 0))
379+ turn_flags_ptr->do_move = FALSE;
380+ }
381+
382+ if (turn_flags_ptr->do_move && !can_cross && !turn_flags_ptr->did_kill_wall && !turn_flags_ptr->did_bash_door)
383+ turn_flags_ptr->do_move = FALSE;
384+
385+ if (turn_flags_ptr->do_move && (r_ptr->flags1 & RF1_NEVER_MOVE))
386+ {
387+ if (is_original_ap_and_seen(target_ptr, m_ptr))
388+ r_ptr->r_flags1 |= (RF1_NEVER_MOVE);
389+
390+ turn_flags_ptr->do_move = FALSE;
391+ }
392+
393+ if (!turn_flags_ptr->do_move)
394+ {
395+ if (turn_flags_ptr->do_turn) break;
396+
397+ continue;
398+ }
399+
400+ turn_flags_ptr->do_turn = TRUE;
401+ feature_type *f_ptr;
402+ f_ptr = &f_info[g_ptr->feat];
403+ if (have_flag(f_ptr->flags, FF_TREE))
404+ {
405+ if (!(r_ptr->flags7 & RF7_CAN_FLY) && !(r_ptr->flags8 & RF8_WILD_WOOD))
406+ {
407+ m_ptr->energy_need += ENERGY_NEED();
408+ }
409+ }
410+
411+ if (!update_riding_monster(target_ptr, turn_flags_ptr, m_idx, oy, ox, ny, nx)) break;
412+
413+ monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
414+ if (m_ptr->ml &&
415+ (disturb_move ||
416+ (disturb_near && (m_ptr->mflag & MFLAG_VIEW) && projectable(target_ptr, target_ptr->y, target_ptr->x, m_ptr->fy, m_ptr->fx)) ||
417+ (disturb_high && ap_r_ptr->r_tkills && ap_r_ptr->level >= target_ptr->lev)))
418+ {
419+ if (is_hostile(m_ptr))
420+ disturb(target_ptr, FALSE, TRUE);
421+ }
422+
423+ bool is_takable_or_killable = g_ptr->o_idx > 0;
424+ is_takable_or_killable &= (r_ptr->flags2 & (RF2_TAKE_ITEM | RF2_KILL_ITEM)) != 0;
425+
426+ bool is_pickup_items = (target_ptr->pet_extra_flags & PF_PICKUP_ITEMS) != 0;
427+ is_pickup_items &= (r_ptr->flags2 & RF2_TAKE_ITEM) != 0;
428+
429+ is_takable_or_killable &= !is_pet(m_ptr) || is_pickup_items;
430+ if (!is_takable_or_killable)
431+ {
432+ if (turn_flags_ptr->do_turn) break;
433+
434+ continue;
435+ }
436+
437+ update_object_by_monster_movement(target_ptr, turn_flags_ptr, m_idx, ny, nx);
438+ if (turn_flags_ptr->do_turn) break;
439+
440+ (*count)++;
441+ }
442+
443+ return TRUE;
444+}
445+
446+
447+/*!
448+ * @brief モンスターを喋らせたり足音を立てたりする
449+ * @param target_ptr プレーヤーへの参照ポインタ
450+ * @param m_idx モンスターID
451+ * @param oy モンスターが元々いたY座標
452+ * @param ox モンスターが元々いたX座標
453+ * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
454+ * @return なし
455+ */
456+void process_speak_sound(player_type *target_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, bool aware)
457+{
458+ if (target_ptr->phase_out) return;
459+
460+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
461+ monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
462+ if (m_ptr->ap_r_idx == MON_CYBER &&
463+ one_in_(CYBERNOISE) &&
464+ !m_ptr->ml && (m_ptr->cdis <= MAX_SIGHT))
465+ {
466+ if (disturb_minor) disturb(target_ptr, FALSE, FALSE);
467+ msg_print(_("重厚な足音が聞こえた。", "You hear heavy steps."));
468+ }
469+
470+ if (((ap_r_ptr->flags2 & RF2_CAN_SPEAK) == 0) || !aware ||
471+ !one_in_(SPEAK_CHANCE) ||
472+ !player_has_los_bold(target_ptr, oy, ox) ||
473+ !projectable(target_ptr, oy, ox, target_ptr->y, target_ptr->x))
474+ return;
475+
476+ GAME_TEXT m_name[MAX_NLEN];
477+ char monmessage[1024];
478+ concptr filename;
479+
480+ if (m_ptr->ml)
481+ monster_desc(target_ptr, m_name, m_ptr, 0);
482+ else
483+ strcpy(m_name, _("それ", "It"));
484+
485+ if (MON_MONFEAR(m_ptr))
486+ filename = _("monfear_j.txt", "monfear.txt");
487+ else if (is_pet(m_ptr))
488+ filename = _("monpet_j.txt", "monpet.txt");
489+ else if (is_friendly(m_ptr))
490+ filename = _("monfrien_j.txt", "monfrien.txt");
491+ else
492+ filename = _("monspeak_j.txt", "monspeak.txt");
493+
494+ if (get_rnd_line(filename, m_ptr->ap_r_idx, monmessage) == 0)
495+ {
496+ msg_format(_("%^s%s", "%^s %s"), m_name, monmessage);
497+ }
498+}
--- /dev/null
+++ b/src/monster/monster-move.h
@@ -0,0 +1,7 @@
1+#pragma once
2+
3+#include "angband.h"
4+#include "monster/monster-util.h"
5+
6+bool process_monster_movement(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, DIRECTION *mm, POSITION oy, POSITION ox, int *count);
7+void process_speak_sound(player_type *target_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, bool aware);
--- /dev/null
+++ b/src/monster/monster-object.c
@@ -0,0 +1,147 @@
1+/*!
2+ * @brief モンスターが移動した結果、床のアイテムに重なった時の処理
3+ * @date 2020/03/07
4+ * @author Hourier
5+ */
6+
7+#include "monster/monster-object.h"
8+#include "object-flavor.h"
9+#include "object-hook.h"
10+
11+ /*!
12+ * @brief オブジェクトのフラグを更新する
13+ */
14+static void update_object_flags(BIT_FLAGS *flgs, BIT_FLAGS *flg2, BIT_FLAGS *flg3, BIT_FLAGS *flgr)
15+{
16+ if (have_flag(flgs, TR_SLAY_DRAGON)) *flg3 |= (RF3_DRAGON);
17+ if (have_flag(flgs, TR_KILL_DRAGON)) *flg3 |= (RF3_DRAGON);
18+ if (have_flag(flgs, TR_SLAY_TROLL)) *flg3 |= (RF3_TROLL);
19+ if (have_flag(flgs, TR_KILL_TROLL)) *flg3 |= (RF3_TROLL);
20+ if (have_flag(flgs, TR_SLAY_GIANT)) *flg3 |= (RF3_GIANT);
21+ if (have_flag(flgs, TR_KILL_GIANT)) *flg3 |= (RF3_GIANT);
22+ if (have_flag(flgs, TR_SLAY_ORC)) *flg3 |= (RF3_ORC);
23+ if (have_flag(flgs, TR_KILL_ORC)) *flg3 |= (RF3_ORC);
24+ if (have_flag(flgs, TR_SLAY_DEMON)) *flg3 |= (RF3_DEMON);
25+ if (have_flag(flgs, TR_KILL_DEMON)) *flg3 |= (RF3_DEMON);
26+ if (have_flag(flgs, TR_SLAY_UNDEAD)) *flg3 |= (RF3_UNDEAD);
27+ if (have_flag(flgs, TR_KILL_UNDEAD)) *flg3 |= (RF3_UNDEAD);
28+ if (have_flag(flgs, TR_SLAY_ANIMAL)) *flg3 |= (RF3_ANIMAL);
29+ if (have_flag(flgs, TR_KILL_ANIMAL)) *flg3 |= (RF3_ANIMAL);
30+ if (have_flag(flgs, TR_SLAY_EVIL)) *flg3 |= (RF3_EVIL);
31+ if (have_flag(flgs, TR_KILL_EVIL)) *flg3 |= (RF3_EVIL);
32+ if (have_flag(flgs, TR_SLAY_HUMAN)) *flg2 |= (RF2_HUMAN);
33+ if (have_flag(flgs, TR_KILL_HUMAN)) *flg2 |= (RF2_HUMAN);
34+ if (have_flag(flgs, TR_BRAND_ACID)) *flgr |= (RFR_IM_ACID);
35+ if (have_flag(flgs, TR_BRAND_ELEC)) *flgr |= (RFR_IM_ELEC);
36+ if (have_flag(flgs, TR_BRAND_FIRE)) *flgr |= (RFR_IM_FIRE);
37+ if (have_flag(flgs, TR_BRAND_COLD)) *flgr |= (RFR_IM_COLD);
38+ if (have_flag(flgs, TR_BRAND_POIS)) *flgr |= (RFR_IM_POIS);
39+}
40+
41+
42+/*!
43+ * @brief モンスターがアイテムを拾うか壊す処理
44+ * @param target_ptr プレーヤーへの参照ポインタ
45+ * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
46+ * @param m_idx モンスターID
47+ * @param o_ptr オブジェクトへの参照ポインタ
48+ * @param is_special_object モンスターが拾えないアイテム (アーティファクト等)であればTRUE
49+ * @param ny 移動後の、モンスターのY座標
50+ * @param nx 移動後の、モンスターのX座標
51+ * @param m_name モンスター名
52+ * @param o_name アイテム名
53+ * @param this_o_idx モンスターが乗ったオブジェクトID
54+ * @return なし
55+ */
56+static void monster_pickup_object(
57+ player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, object_type *o_ptr, bool is_special_object,
58+ POSITION ny, POSITION nx, GAME_TEXT *m_name, GAME_TEXT *o_name, OBJECT_IDX this_o_idx)
59+{
60+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
61+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
62+ if (is_special_object)
63+ {
64+ if (turn_flags_ptr->do_take && (r_ptr->flags2 & RF2_STUPID))
65+ {
66+ turn_flags_ptr->did_take_item = TRUE;
67+ if (m_ptr->ml && player_can_see_bold(target_ptr, ny, nx))
68+ {
69+ msg_format(_("%^sは%sを拾おうとしたが、だめだった。", "%^s tries to pick up %s, but fails."), m_name, o_name);
70+ }
71+ }
72+
73+ return;
74+ }
75+
76+ if (turn_flags_ptr->do_take)
77+ {
78+ turn_flags_ptr->did_take_item = TRUE;
79+ if (player_can_see_bold(target_ptr, ny, nx))
80+ {
81+ msg_format(_("%^sが%sを拾った。", "%^s picks up %s."), m_name, o_name);
82+ }
83+
84+ excise_object_idx(target_ptr->current_floor_ptr, this_o_idx);
85+ o_ptr->marked &= OM_TOUCHED;
86+ o_ptr->iy = o_ptr->ix = 0;
87+ o_ptr->held_m_idx = m_idx;
88+ o_ptr->next_o_idx = m_ptr->hold_o_idx;
89+ m_ptr->hold_o_idx = this_o_idx;
90+ return;
91+ }
92+
93+ if (is_pet(m_ptr)) return;
94+
95+ turn_flags_ptr->did_kill_item = TRUE;
96+ if (player_has_los_bold(target_ptr, ny, nx))
97+ {
98+ msg_format(_("%^sが%sを破壊した。", "%^s destroys %s."), m_name, o_name);
99+ }
100+
101+ delete_object_idx(target_ptr, this_o_idx);
102+}
103+
104+
105+/*!
106+ * @brief モンスターの移動に伴うオブジェクト処理 (アイテム破壊等)
107+ * @param target_ptr プレーヤーへの参照ポインタ
108+ * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
109+ * @param m_idx モンスターID
110+ * @param ny 移動後の、モンスターのY座標
111+ * @param nx 移動後の、モンスターのX座標
112+ */
113+void update_object_by_monster_movement(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION ny, POSITION nx)
114+{
115+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
116+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
117+ grid_type *g_ptr;
118+ g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
119+
120+ turn_flags_ptr->do_take = (r_ptr->flags2 & RF2_TAKE_ITEM) != 0;
121+ OBJECT_IDX next_o_idx;
122+ for (OBJECT_IDX this_o_idx = g_ptr->o_idx; this_o_idx > 0; this_o_idx = next_o_idx)
123+ {
124+ BIT_FLAGS flgs[TR_FLAG_SIZE], flg2 = 0L, flg3 = 0L, flgr = 0L;
125+ GAME_TEXT m_name[MAX_NLEN], o_name[MAX_NLEN];
126+ object_type *o_ptr = &target_ptr->current_floor_ptr->o_list[this_o_idx];
127+ next_o_idx = o_ptr->next_o_idx;
128+
129+ if (turn_flags_ptr->do_take)
130+ {
131+ /* Skip gold, corpse and statue */
132+ if (o_ptr->tval == TV_GOLD || (o_ptr->tval == TV_CORPSE) || (o_ptr->tval == TV_STATUE))
133+ continue;
134+ }
135+
136+ object_flags(o_ptr, flgs);
137+ object_desc(target_ptr, o_name, o_ptr, 0);
138+ monster_desc(target_ptr, m_name, m_ptr, MD_INDEF_HIDDEN);
139+ update_object_flags(flgs, &flg2, &flg3, &flgr);
140+
141+ bool is_special_object = object_is_artifact(o_ptr) ||
142+ ((r_ptr->flags3 & flg3) != 0) ||
143+ ((r_ptr->flags2 & flg2) != 0) ||
144+ (((~(r_ptr->flagsr) & flgr) != 0) && !(r_ptr->flagsr & RFR_RES_ALL));
145+ monster_pickup_object(target_ptr, turn_flags_ptr, m_idx, o_ptr, is_special_object, ny, nx, m_name, o_name, this_o_idx);
146+ }
147+}
--- /dev/null
+++ b/src/monster/monster-object.h
@@ -0,0 +1,12 @@
1+/*!
2+ * @brief monster-processのための構造体群
3+ * @date 2020/03/07
4+ * @author Hourier
5+ */
6+
7+#pragma once
8+
9+#include "angband.h"
10+#include "monster/monster-util.h"
11+
12+void update_object_by_monster_movement(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION ny, POSITION nx);
--- /dev/null
+++ b/src/monster/monster-runaway.c
@@ -0,0 +1,94 @@
1+/*!
2+ * @brief モンスターの逃走に関する処理
3+ * @date 2020/03/08
4+ * @author Hourier
5+ */
6+
7+#include "monster/monster-runaway.h"
8+#include "player-move.h"
9+#include "cmd/cmd-pet.h"
10+#include "quest.h"
11+
12+ /*!
13+ * @brief HPが1/3未満になった有効的なユニークモンスターの逃走処理を行う
14+ * @param target_ptr プレーヤーへの参照ポインタ
15+ * @param is_riding_mon 騎乗状態ならばTRUE
16+ * @param m_ptr モンスターへの参照ポインタ
17+ * @param m_name モンスター名称
18+ * @param see_m モンスターが視界内にいたらTRUE
19+ * @return なし
20+ */
21+static void escape_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, GAME_TEXT *m_name)
22+{
23+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
24+ if (turn_flags_ptr->is_riding_mon)
25+ {
26+ msg_format(_("%sはあなたの束縛から脱出した。", "%^s succeeded to escape from your restriction!"), m_name);
27+ if (rakuba(target_ptr, -1, FALSE))
28+ {
29+ msg_print(_("地面に落とされた。", "You have fallen from the pet you were riding."));
30+ }
31+ }
32+
33+ if (turn_flags_ptr->see_m)
34+ {
35+ if ((r_ptr->flags2 & RF2_CAN_SPEAK) && (m_ptr->r_idx != MON_GRIP) && (m_ptr->r_idx != MON_WOLF) && (m_ptr->r_idx != MON_FANG) &&
36+ player_has_los_bold(target_ptr, m_ptr->fy, m_ptr->fx) && projectable(target_ptr, m_ptr->fy, m_ptr->fx, target_ptr->y, target_ptr->x))
37+ {
38+ msg_format(_("%^s「ピンチだ!退却させてもらう!」", "%^s says 'It is the pinch! I will retreat'."), m_name);
39+ }
40+
41+ msg_format(_("%^sがテレポート・レベルの巻物を読んだ。", "%^s reads a scroll of teleport level."), m_name);
42+ msg_format(_("%^sが消え去った。", "%^s disappears."), m_name);
43+ }
44+
45+ if (turn_flags_ptr->is_riding_mon && rakuba(target_ptr, -1, FALSE))
46+ {
47+ msg_print(_("地面に落とされた。", "You have fallen from the pet you were riding."));
48+ }
49+}
50+
51+
52+/*!
53+ * @brief ペットや友好的なモンスターがフロアから逃げる処理を行う
54+ * @param target_ptr プレーヤーへの参照ポインタ
55+ * @param m_idx モンスターID
56+ * @param is_riding_mon 騎乗状態ならばTRUE
57+ * @param see_m モンスターが視界内にいたらTRUE
58+ * @return モンスターがフロアから消えたらTRUE
59+ */
60+bool runaway_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx)
61+{
62+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
63+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
64+ bool can_runaway = is_pet(m_ptr) || is_friendly(m_ptr);
65+ can_runaway &= ((r_ptr->flags1 & RF1_UNIQUE) != 0) || ((r_ptr->flags7 & RF7_NAZGUL) != 0);
66+ can_runaway &= !target_ptr->phase_out;
67+ if (!can_runaway) return FALSE;
68+
69+ static int riding_pinch = 0;
70+
71+ if (m_ptr->hp >= m_ptr->maxhp / 3)
72+ {
73+ /* Reset the counter */
74+ if (turn_flags_ptr->is_riding_mon) riding_pinch = 0;
75+
76+ return FALSE;
77+ }
78+
79+ GAME_TEXT m_name[MAX_NLEN];
80+ monster_desc(target_ptr, m_name, m_ptr, 0);
81+ if (turn_flags_ptr->is_riding_mon && riding_pinch < 2)
82+ {
83+ msg_format(_("%sは傷の痛さの余りあなたの束縛から逃れようとしている。",
84+ "%^s seems to be in so much pain and tries to escape from your restriction."), m_name);
85+ riding_pinch++;
86+ disturb(target_ptr, TRUE, TRUE);
87+ return FALSE;
88+ }
89+
90+ escape_monster(target_ptr, turn_flags_ptr, m_ptr, m_name);
91+ check_quest_completion(target_ptr, m_ptr);
92+ delete_monster_idx(target_ptr, m_idx);
93+ return TRUE;
94+}
--- /dev/null
+++ b/src/monster/monster-runaway.h
@@ -0,0 +1,6 @@
1+#pragma once
2+
3+#include "angband.h"
4+#include "monster/monster-util.h"
5+
6+bool runaway_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx);
--- /dev/null
+++ b/src/monster/monster-safety-hiding.c
@@ -0,0 +1,175 @@
1+/*!
2+ * @brief モンスターの逃走・隠匿に関する処理
3+ * @date 2020/03/08
4+ * @author Hourier
5+ */
6+
7+#include "monster/monster-safety-hiding.h"
8+#include "monster-dist-offsets.h"
9+#include "monster-spell.h"
10+
11+ /*!
12+ * @brief モンスターが逃げ込める地点を走査する
13+ * @param target_ptr プレーヤーへの参照ポインタ
14+ * @param m_idx モンスターID
15+ * @param y_offsets
16+ * @param x_offsets
17+ * @param d モンスターがいる地点からの距離
18+ * @return 逃げ込める地点の候補地
19+ */
20+static coordinate_candidate sweep_safe_coordinate(player_type *target_ptr, MONSTER_IDX m_idx, const POSITION *y_offsets, const POSITION *x_offsets, int d)
21+{
22+ coordinate_candidate candidate = init_coordinate_candidate();
23+ floor_type *floor_ptr = target_ptr->current_floor_ptr;
24+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
25+ for (POSITION i = 0, dx = x_offsets[0], dy = y_offsets[0];
26+ dx != 0 || dy != 0;
27+ i++, dx = x_offsets[i], dy = y_offsets[i])
28+ {
29+ POSITION y = m_ptr->fy + dy;
30+ POSITION x = m_ptr->fx + dx;
31+ if (!in_bounds(floor_ptr, y, x)) continue;
32+
33+ grid_type *g_ptr;
34+ g_ptr = &floor_ptr->grid_array[y][x];
35+
36+ BIT_FLAGS16 riding_mode = (m_idx == target_ptr->riding) ? CEM_RIDING : 0;
37+ if (!monster_can_cross_terrain(target_ptr, g_ptr->feat, &r_info[m_ptr->r_idx], riding_mode))
38+ continue;
39+
40+ if (!(m_ptr->mflag2 & MFLAG2_NOFLOW))
41+ {
42+ if (g_ptr->dist == 0) continue;
43+ if (g_ptr->dist > floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].dist + 2 * d) continue;
44+ }
45+
46+ if (projectable(target_ptr, target_ptr->y, target_ptr->x, y, x)) continue;
47+
48+ POSITION dis = distance(y, x, target_ptr->y, target_ptr->x);
49+ if (dis <= candidate.gdis) continue;
50+
51+ candidate.gy = y;
52+ candidate.gx = x;
53+ candidate.gdis = dis;
54+ }
55+
56+ return candidate;
57+}
58+
59+
60+/*!
61+ * @brief モンスターが逃げ込める安全な地点を返す /
62+ * Choose a "safe" location near a monster for it to run toward.
63+ * @param target_ptr プレーヤーへの参照ポインタ
64+ * @param m_idx モンスターの参照ID
65+ * @param yp 移動先のマスのY座標を返す参照ポインタ
66+ * @param xp 移動先のマスのX座標を返す参照ポインタ
67+ * @return 有効なマスがあった場合TRUEを返す
68+ * @details
69+ * A location is "safe" if it can be reached quickly and the player\n
70+ * is not able to fire into it (it isn't a "clean shot"). So, this will\n
71+ * cause monsters to "duck" behind walls. Hopefully, monsters will also\n
72+ * try to run towards corridor openings if they are in a room.\n
73+ *\n
74+ * This function may take lots of CPU time if lots of monsters are\n
75+ * fleeing.\n
76+ *\n
77+ * Return TRUE if a safe location is available.\n
78+ */
79+bool find_safety(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
80+{
81+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
82+ for (POSITION d = 1; d < 10; d++)
83+ {
84+ const POSITION *y_offsets;
85+ y_offsets = dist_offsets_y[d];
86+
87+ const POSITION *x_offsets;
88+ x_offsets = dist_offsets_x[d];
89+
90+ coordinate_candidate candidate = sweep_safe_coordinate(target_ptr, m_idx, y_offsets, x_offsets, d);
91+
92+ if (candidate.gdis <= 0) continue;
93+
94+ *yp = m_ptr->fy - candidate.gy;
95+ *xp = m_ptr->fx - candidate.gx;
96+
97+ return TRUE;
98+ }
99+
100+ return FALSE;
101+}
102+
103+
104+/*!
105+ * @brief モンスターが隠れられる地点を走査する
106+ * @param target_ptr プレーヤーへの参照ポインタ
107+ * @param m_idx モンスターID
108+ * @param y_offsets
109+ * @param x_offsets
110+ * @param candidate 隠れられる地点の候補地
111+ * @return なし
112+ */
113+static void sweep_hiding_candidate(player_type *target_ptr, monster_type *m_ptr, const POSITION *y_offsets, const POSITION *x_offsets, coordinate_candidate *candidate)
114+{
115+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
116+ for (POSITION i = 0, dx = x_offsets[0], dy = y_offsets[0];
117+ dx != 0 || dy != 0;
118+ i++, dx = x_offsets[i], dy = y_offsets[i])
119+ {
120+ POSITION y = m_ptr->fy + dy;
121+ POSITION x = m_ptr->fx + dx;
122+ if (!in_bounds(target_ptr->current_floor_ptr, y, x)) continue;
123+ if (!monster_can_enter(target_ptr, y, x, r_ptr, 0)) continue;
124+ if (projectable(target_ptr, target_ptr->y, target_ptr->x, y, x) && clean_shot(target_ptr, m_ptr->fy, m_ptr->fx, y, x, FALSE))
125+ continue;
126+
127+ POSITION dis = distance(y, x, target_ptr->y, target_ptr->x);
128+ if (dis < candidate->gdis && dis >= 2)
129+ {
130+ candidate->gy = y;
131+ candidate->gx = x;
132+ candidate->gdis = dis;
133+ }
134+ }
135+}
136+
137+
138+/*!
139+ * @brief モンスターが隠れ潜める地点を返す /
140+ * Choose a good hiding place near a monster for it to run toward.
141+ * @param target_ptr プレーヤーへの参照ポインタ
142+ * @param m_idx モンスターの参照ID
143+ * @param yp 移動先のマスのY座標を返す参照ポインタ
144+ * @param xp 移動先のマスのX座標を返す参照ポインタ
145+ * @return 有効なマスがあった場合TRUEを返す
146+ * @details
147+ * Pack monsters will use this to "ambush" the player and lure him out\n
148+ * of corridors into open space so they can swarm him.\n
149+ *\n
150+ * Return TRUE if a good location is available.\n
151+ */
152+bool find_hiding(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
153+{
154+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
155+ coordinate_candidate candidate = init_coordinate_candidate();
156+ candidate.gdis = 999;
157+
158+ for (POSITION d = 1; d < 10; d++)
159+ {
160+ const POSITION *y_offsets;
161+ y_offsets = dist_offsets_y[d];
162+
163+ const POSITION *x_offsets;
164+ x_offsets = dist_offsets_x[d];
165+
166+ sweep_hiding_candidate(target_ptr, m_ptr, y_offsets, x_offsets, &candidate);
167+ if (candidate.gdis >= 999) continue;
168+
169+ *yp = m_ptr->fy - candidate.gy;
170+ *xp = m_ptr->fx - candidate.gx;
171+ return TRUE;
172+ }
173+
174+ return FALSE;
175+}
--- /dev/null
+++ b/src/monster/monster-safety-hiding.h
@@ -0,0 +1,7 @@
1+#pragma once
2+
3+#include "angband.h"
4+#include "monster/monster-util.h"
5+
6+bool find_safety(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp);
7+bool find_hiding(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp);
--- /dev/null
+++ b/src/monster/monster-sweep-grid.c
@@ -0,0 +1,410 @@
1+/*!
2+ * @brief モンスターの移動方向を走査する処理
3+ * @date 2020/03/08
4+ * @author Hourier
5+ */
6+
7+#include "monster/monster-sweep-grid.h"
8+#include "monster/monster-safety-hiding.h"
9+#include "monster-spell.h"
10+
11+ /*!
12+ * @brief モンスターがプレイヤーから逃走するかどうかを返す /
13+ * Returns whether a given monster will try to run from the player.
14+ * @param m_idx 逃走するモンスターの参照ID
15+ * @return モンスターがプレイヤーから逃走するならばTRUEを返す。
16+ * @details
17+ * Monsters will attempt to avoid very powerful players. See below.\n
18+ *\n
19+ * Because this function is called so often, little details are important\n
20+ * for efficiency. Like not using "mod" or "div" when possible. And\n
21+ * attempting to check the conditions in an optimal order. Note that\n
22+ * "(x << 2) == (x * 4)" if "x" has enough bits to hold the result.\n
23+ *\n
24+ * Note that this function is responsible for about one to five percent\n
25+ * of the processor use in normal conditions...\n
26+ */
27+static bool mon_will_run(player_type *target_ptr, MONSTER_IDX m_idx)
28+{
29+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
30+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
31+
32+ if (is_pet(m_ptr))
33+ {
34+ return ((target_ptr->pet_follow_distance < 0) &&
35+ (m_ptr->cdis <= (0 - target_ptr->pet_follow_distance)));
36+ }
37+
38+ if (m_ptr->cdis > MAX_SIGHT + 5) return FALSE;
39+ if (MON_MONFEAR(m_ptr)) return TRUE;
40+ if (m_ptr->cdis <= 5) return FALSE;
41+
42+ PLAYER_LEVEL p_lev = target_ptr->lev;
43+ DEPTH m_lev = r_ptr->level + (m_idx & 0x08) + 25;
44+ if (m_lev > p_lev + 4) return FALSE;
45+ if (m_lev + 4 <= p_lev) return TRUE;
46+
47+ HIT_POINT p_chp = target_ptr->chp;
48+ HIT_POINT p_mhp = target_ptr->mhp;
49+ HIT_POINT m_chp = m_ptr->hp;
50+ HIT_POINT m_mhp = m_ptr->maxhp;
51+ u32b p_val = (p_lev * p_mhp) + (p_chp << 2);
52+ u32b m_val = (m_lev * m_mhp) + (m_chp << 2);
53+ if (p_val * m_mhp > m_val * p_mhp) return TRUE;
54+
55+ return FALSE;
56+}
57+
58+
59+/*!
60+ * @brief モンスターがプレイヤーに向けて遠距離攻撃を行うことが可能なマスを走査する /
61+ * Search spell castable grid
62+ * @param target_ptr プレーヤーへの参照ポインタ
63+ * @param m_idx モンスターの参照ID
64+ * @param yp 適したマスのY座標を返す参照ポインタ
65+ * @param xp 適したマスのX座標を返す参照ポインタ
66+ * @return 有効なマスがあった場合TRUEを返す
67+ */
68+static bool sweep_ranged_attack_grid(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
69+{
70+ floor_type *floor_ptr = target_ptr->current_floor_ptr;
71+ monster_type *m_ptr = &floor_ptr->m_list[m_idx];
72+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
73+
74+ POSITION y1 = m_ptr->fy;
75+ POSITION x1 = m_ptr->fx;
76+
77+ if (projectable(target_ptr, y1, x1, target_ptr->y, target_ptr->x)) return FALSE;
78+
79+ int now_cost = floor_ptr->grid_array[y1][x1].cost;
80+ if (now_cost == 0) now_cost = 999;
81+
82+ bool can_open_door = FALSE;
83+ if (r_ptr->flags2 & (RF2_BASH_DOOR | RF2_OPEN_DOOR))
84+ {
85+ can_open_door = TRUE;
86+ }
87+
88+ int best = 999;
89+ for (int i = 7; i >= 0; i--)
90+ {
91+ POSITION y = y1 + ddy_ddd[i];
92+ POSITION x = x1 + ddx_ddd[i];
93+ if (!in_bounds2(floor_ptr, y, x)) continue;
94+ if (player_bold(target_ptr, y, x)) return FALSE;
95+
96+ grid_type *g_ptr;
97+ g_ptr = &floor_ptr->grid_array[y][x];
98+ int cost = g_ptr->cost;
99+ if (!(((r_ptr->flags2 & RF2_PASS_WALL) && ((m_idx != target_ptr->riding) || target_ptr->pass_wall)) || ((r_ptr->flags2 & RF2_KILL_WALL) && (m_idx != target_ptr->riding))))
100+ {
101+ if (cost == 0) continue;
102+ if (!can_open_door && is_closed_door(target_ptr, g_ptr->feat)) continue;
103+ }
104+
105+ if (cost == 0) cost = 998;
106+
107+ if (now_cost < cost) continue;
108+ if (!projectable(target_ptr, y, x, target_ptr->y, target_ptr->x)) continue;
109+ if (best < cost) continue;
110+
111+ best = cost;
112+ *yp = y1 + ddy_ddd[i];
113+ *xp = x1 + ddx_ddd[i];
114+ }
115+
116+ if (best == 999) return FALSE;
117+
118+ return TRUE;
119+}
120+
121+
122+/*!
123+ * @brief モンスターがプレイヤーに向けて接近することが可能なマスを走査する /
124+ * Choose the "best" direction for "flowing"
125+ * @param m_idx モンスターの参照ID
126+ * @param yp 移動先のマスのY座標を返す参照ポインタ
127+ * @param xp 移動先のマスのX座標を返す参照ポインタ
128+ * @param no_flow モンスターにFLOWフラグが経っていない状態でTRUE
129+ * @return なし
130+ * @details
131+ * Note that ghosts and rock-eaters are never allowed to "flow",\n
132+ * since they should move directly towards the player.\n
133+ *\n
134+ * Prefer "non-diagonal" directions, but twiddle them a little\n
135+ * to angle slightly towards the player's actual location.\n
136+ *\n
137+ * Allow very perceptive monsters to track old "spoor" left by\n
138+ * previous locations occupied by the player. This will tend\n
139+ * to have monsters end up either near the player or on a grid\n
140+ * recently occupied by the player (and left via "teleport").\n
141+ *\n
142+ * Note that if "smell" is turned on, all monsters get vicious.\n
143+ *\n
144+ * Also note that teleporting away from a location will cause\n
145+ * the monsters who were chasing you to converge on that location\n
146+ * as long as you are still near enough to "annoy" them without\n
147+ * being close enough to chase directly. I have no idea what will\n
148+ * happen if you combine "smell" with low "aaf" values.\n
149+ */
150+static void sweep_movable_grid(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp, bool no_flow)
151+{
152+ grid_type *g_ptr;
153+ floor_type *floor_ptr = target_ptr->current_floor_ptr;
154+ monster_type *m_ptr = &floor_ptr->m_list[m_idx];
155+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
156+
157+ if (r_ptr->flags4 & (RF4_ATTACK_MASK) ||
158+ r_ptr->a_ability_flags1 & (RF5_ATTACK_MASK) ||
159+ r_ptr->a_ability_flags2 & (RF6_ATTACK_MASK))
160+ {
161+ if (sweep_ranged_attack_grid(target_ptr, m_idx, yp, xp)) return;
162+ }
163+
164+ if (no_flow) return;
165+ if ((r_ptr->flags2 & RF2_PASS_WALL) && ((m_idx != target_ptr->riding) || target_ptr->pass_wall)) return;
166+ if ((r_ptr->flags2 & RF2_KILL_WALL) && (m_idx != target_ptr->riding)) return;
167+
168+ POSITION y1 = m_ptr->fy;
169+ POSITION x1 = m_ptr->fx;
170+ if (player_has_los_bold(target_ptr, y1, x1) && projectable(target_ptr, target_ptr->y, target_ptr->x, y1, x1)) return;
171+
172+ g_ptr = &floor_ptr->grid_array[y1][x1];
173+
174+ int best;
175+ bool use_scent = FALSE;
176+ if (g_ptr->cost)
177+ {
178+ best = 999;
179+ }
180+ else if (g_ptr->when)
181+ {
182+ if (floor_ptr->grid_array[target_ptr->y][target_ptr->x].when - g_ptr->when > 127) return;
183+
184+ use_scent = TRUE;
185+ best = 0;
186+ }
187+ else
188+ {
189+ return;
190+ }
191+
192+ for (int i = 7; i >= 0; i--)
193+ {
194+ POSITION y = y1 + ddy_ddd[i];
195+ POSITION x = x1 + ddx_ddd[i];
196+
197+ if (!in_bounds2(floor_ptr, y, x)) continue;
198+
199+ g_ptr = &floor_ptr->grid_array[y][x];
200+ if (use_scent)
201+ {
202+ int when = g_ptr->when;
203+ if (best > when) continue;
204+
205+ best = when;
206+ }
207+ else
208+ {
209+ int cost;
210+ if (r_ptr->flags2 & (RF2_BASH_DOOR | RF2_OPEN_DOOR))
211+ {
212+ cost = g_ptr->dist;
213+ }
214+ else
215+ {
216+ cost = g_ptr->cost;
217+ }
218+
219+ if ((cost == 0) || (best < cost)) continue;
220+
221+ best = cost;
222+ }
223+
224+ *yp = target_ptr->y + 16 * ddy_ddd[i];
225+ *xp = target_ptr->x + 16 * ddx_ddd[i];
226+ }
227+}
228+
229+
230+/*!
231+ * @brief モンスターがプレイヤーから逃走することが可能なマスを走査する /
232+ * Provide a location to flee to, but give the player a wide berth.
233+ * @param m_idx モンスターの参照ID
234+ * @param yp 移動先のマスのY座標を返す参照ポインタ
235+ * @param xp 移動先のマスのX座標を返す参照ポインタ
236+ * @return 有効なマスがあった場合TRUEを返す
237+ * @details
238+ * A monster may wish to flee to a location that is behind the player,\n
239+ * but instead of heading directly for it, the monster should "swerve"\n
240+ * around the player so that he has a smaller chance of getting hit.\n
241+ */
242+static bool sweep_runnable_away_grid(floor_type *floor_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
243+{
244+ POSITION gy = 0, gx = 0;
245+
246+ monster_type *m_ptr = &floor_ptr->m_list[m_idx];
247+ POSITION fy = m_ptr->fy;
248+ POSITION fx = m_ptr->fx;
249+
250+ POSITION y1 = fy - (*yp);
251+ POSITION x1 = fx - (*xp);
252+
253+ int score = -1;
254+ for (int i = 7; i >= 0; i--)
255+ {
256+ POSITION y = fy + ddy_ddd[i];
257+ POSITION x = fx + ddx_ddd[i];
258+ if (!in_bounds2(floor_ptr, y, x)) continue;
259+
260+ POSITION dis = distance(y, x, y1, x1);
261+ POSITION s = 5000 / (dis + 3) - 500 / (floor_ptr->grid_array[y][x].dist + 1);
262+ if (s < 0) s = 0;
263+
264+ if (s < score) continue;
265+
266+ score = s;
267+ gy = y;
268+ gx = x;
269+ }
270+
271+ if (score == -1) return FALSE;
272+
273+ (*yp) = fy - gy;
274+ (*xp) = fx - gx;
275+
276+ return TRUE;
277+}
278+
279+
280+/*!
281+ * todo 分割したいが条件が多すぎて適切な関数名と詳細処理を追いきれない……
282+ * @brief モンスターの移動方向を返す /
283+ * Choose "logical" directions for monster movement
284+ * @param target_ptr プレーヤーへの参照ポインタ
285+ * @param m_idx モンスターの参照ID
286+ * @param mm 移動方向を返す方向IDの参照ポインタ
287+ * @return 有効方向があった場合TRUEを返す
288+ */
289+bool get_movable_grid(player_type *target_ptr, MONSTER_IDX m_idx, DIRECTION *mm)
290+{
291+ floor_type *floor_ptr = target_ptr->current_floor_ptr;
292+ monster_type *m_ptr = &floor_ptr->m_list[m_idx];
293+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
294+ POSITION y = 0, x = 0;
295+ POSITION y2 = target_ptr->y;
296+ POSITION x2 = target_ptr->x;
297+ bool done = FALSE;
298+ bool will_run = mon_will_run(target_ptr, m_idx);
299+ grid_type *g_ptr;
300+ bool no_flow = ((m_ptr->mflag2 & MFLAG2_NOFLOW) != 0) && (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].cost > 2);
301+ bool can_pass_wall = ((r_ptr->flags2 & RF2_PASS_WALL) != 0) && ((m_idx != target_ptr->riding) || target_ptr->pass_wall);
302+
303+ if (!will_run && m_ptr->target_y)
304+ {
305+ int t_m_idx = floor_ptr->grid_array[m_ptr->target_y][m_ptr->target_x].m_idx;
306+ if ((t_m_idx > 0) &&
307+ are_enemies(target_ptr, m_ptr, &floor_ptr->m_list[t_m_idx]) &&
308+ los(target_ptr, m_ptr->fy, m_ptr->fx, m_ptr->target_y, m_ptr->target_x) &&
309+ projectable(target_ptr, m_ptr->fy, m_ptr->fx, m_ptr->target_y, m_ptr->target_x))
310+ {
311+ y = m_ptr->fy - m_ptr->target_y;
312+ x = m_ptr->fx - m_ptr->target_x;
313+ done = TRUE;
314+ }
315+ }
316+
317+ if (!done && !will_run && is_hostile(m_ptr) &&
318+ (r_ptr->flags1 & RF1_FRIENDS) &&
319+ ((los(target_ptr, m_ptr->fy, m_ptr->fx, target_ptr->y, target_ptr->x) && projectable(target_ptr, m_ptr->fy, m_ptr->fx, target_ptr->y, target_ptr->x)) ||
320+ (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].dist < MAX_SIGHT / 2)))
321+ {
322+ if ((r_ptr->flags3 & RF3_ANIMAL) && !can_pass_wall &&
323+ !(r_ptr->flags2 & RF2_KILL_WALL))
324+ {
325+ int room = 0;
326+ for (int i = 0; i < 8; i++)
327+ {
328+ int xx = target_ptr->x + ddx_ddd[i];
329+ int yy = target_ptr->y + ddy_ddd[i];
330+
331+ if (!in_bounds2(floor_ptr, yy, xx)) continue;
332+
333+ g_ptr = &floor_ptr->grid_array[yy][xx];
334+ if (monster_can_cross_terrain(target_ptr, g_ptr->feat, r_ptr, 0))
335+ {
336+ room++;
337+ }
338+ }
339+
340+ if (floor_ptr->grid_array[target_ptr->y][target_ptr->x].info & CAVE_ROOM) room -= 2;
341+ if (!r_ptr->flags4 && !r_ptr->a_ability_flags1 && !r_ptr->a_ability_flags2) room -= 2;
342+
343+ if (room < (8 * (target_ptr->chp + target_ptr->csp)) /
344+ (target_ptr->mhp + target_ptr->msp))
345+ {
346+ if (find_hiding(target_ptr, m_idx, &y, &x)) done = TRUE;
347+ }
348+ }
349+
350+ if (!done && (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].dist < 3))
351+ {
352+ for (int i = 0; i < 8; i++)
353+ {
354+ y2 = target_ptr->y + ddy_ddd[(m_idx + i) & 7];
355+ x2 = target_ptr->x + ddx_ddd[(m_idx + i) & 7];
356+ if ((m_ptr->fy == y2) && (m_ptr->fx == x2))
357+ {
358+ y2 = target_ptr->y;
359+ x2 = target_ptr->x;
360+ break;
361+ }
362+
363+ if (!in_bounds2(floor_ptr, y2, x2)) continue;
364+ if (!monster_can_enter(target_ptr, y2, x2, r_ptr, 0)) continue;
365+
366+ break;
367+ }
368+
369+ y = m_ptr->fy - y2;
370+ x = m_ptr->fx - x2;
371+ done = TRUE;
372+ }
373+ }
374+
375+ if (!done)
376+ {
377+ sweep_movable_grid(target_ptr, m_idx, &y2, &x2, no_flow);
378+ y = m_ptr->fy - y2;
379+ x = m_ptr->fx - x2;
380+ }
381+
382+ if (is_pet(m_ptr) && will_run)
383+ {
384+ y = (-y), x = (-x);
385+ }
386+ else
387+ {
388+ if (!done && will_run)
389+ {
390+ int tmp_x = (-x);
391+ int tmp_y = (-y);
392+ if (find_safety(target_ptr, m_idx, &y, &x) && !no_flow)
393+ {
394+ if (sweep_runnable_away_grid(target_ptr->current_floor_ptr, m_idx, &y, &x))
395+ done = TRUE;
396+ }
397+
398+ if (!done)
399+ {
400+ y = tmp_y;
401+ x = tmp_x;
402+ }
403+ }
404+ }
405+
406+ if (!x && !y) return FALSE;
407+
408+ store_moves_val(mm, y, x);
409+ return TRUE;
410+}
--- /dev/null
+++ b/src/monster/monster-sweep-grid.h
@@ -0,0 +1,6 @@
1+#pragma once
2+
3+#include "angband.h"
4+#include "monster/monster-util.h"
5+
6+bool get_movable_grid(player_type *target_ptr, MONSTER_IDX m_idx, DIRECTION *mm);
\ No newline at end of file
--- /dev/null
+++ b/src/monster/monster-update.c
@@ -0,0 +1,120 @@
1+/*!
2+ * @brief モンスター情報のアップデート処理
3+ * @date 2020/03/08
4+ * @author Hourier
5+ */
6+
7+#include "monster/monster-update.h"
8+#include "player-move.h"
9+
10+/*!
11+ * @brief 騎乗中のモンスター情報を更新する
12+ * @param target_ptr プレーヤーへの参照ポインタ
13+ * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
14+ * @param m_idx モンスターID
15+ * @param oy 移動前の、モンスターのY座標
16+ * @param ox 移動前の、モンスターのX座標
17+ * @param ny 移動後の、モンスターのY座標
18+ * @param ox 移動後の、モンスターのX座標
19+ * @return アイテム等に影響を及ぼしたらTRUE
20+ */
21+bool update_riding_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, POSITION ny, POSITION nx)
22+{
23+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
24+ grid_type *g_ptr;
25+ g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
26+ monster_type *y_ptr;
27+ y_ptr = &target_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
28+ if (turn_flags_ptr->is_riding_mon)
29+ return move_player_effect(target_ptr, ny, nx, MPE_DONT_PICKUP);
30+
31+ target_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = g_ptr->m_idx;
32+ if (g_ptr->m_idx)
33+ {
34+ y_ptr->fy = oy;
35+ y_ptr->fx = ox;
36+ update_monster(target_ptr, g_ptr->m_idx, TRUE);
37+ }
38+
39+ g_ptr->m_idx = m_idx;
40+ m_ptr->fy = ny;
41+ m_ptr->fx = nx;
42+ update_monster(target_ptr, m_idx, TRUE);
43+
44+ lite_spot(target_ptr, oy, ox);
45+ lite_spot(target_ptr, ny, nx);
46+ return TRUE;
47+}
48+
49+
50+/*!
51+ * @brief updateフィールドを更新する
52+ * @param target_ptr プレーヤーへの参照ポインタ
53+ * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
54+ * @return なし
55+ */
56+void update_player_type(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_race *r_ptr)
57+{
58+ if (turn_flags_ptr->do_view)
59+ {
60+ target_ptr->update |= (PU_FLOW);
61+ target_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
62+ }
63+
64+ if (turn_flags_ptr->do_move && ((r_ptr->flags7 & (RF7_SELF_LD_MASK | RF7_HAS_DARK_1 | RF7_HAS_DARK_2))
65+ || ((r_ptr->flags7 & (RF7_HAS_LITE_1 | RF7_HAS_LITE_2)) && !target_ptr->phase_out)))
66+ {
67+ target_ptr->update |= (PU_MON_LITE);
68+ }
69+}
70+
71+
72+/*!
73+ * @brief モンスターのフラグを更新する
74+ * @param target_ptr プレーヤーへの参照ポインタ
75+ * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
76+ * @param m_ptr モンスターへの参照ポインタ
77+ * @return なし
78+ */
79+void update_monster_race_flags(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr)
80+{
81+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
82+ if (!is_original_ap_and_seen(target_ptr, m_ptr)) return;
83+
84+ if (turn_flags_ptr->did_open_door) r_ptr->r_flags2 |= (RF2_OPEN_DOOR);
85+ if (turn_flags_ptr->did_bash_door) r_ptr->r_flags2 |= (RF2_BASH_DOOR);
86+ if (turn_flags_ptr->did_take_item) r_ptr->r_flags2 |= (RF2_TAKE_ITEM);
87+ if (turn_flags_ptr->did_kill_item) r_ptr->r_flags2 |= (RF2_KILL_ITEM);
88+ if (turn_flags_ptr->did_move_body) r_ptr->r_flags2 |= (RF2_MOVE_BODY);
89+ if (turn_flags_ptr->did_pass_wall) r_ptr->r_flags2 |= (RF2_PASS_WALL);
90+ if (turn_flags_ptr->did_kill_wall) r_ptr->r_flags2 |= (RF2_KILL_WALL);
91+}
92+
93+
94+/*!
95+ * @brief モンスターフラグの更新に基づき、モンスター表示を更新する
96+ * @param monster_race_idx モンスターID
97+ * @param window ウィンドウフラグ
98+ * @param old_race_flags_ptr モンスターフラグへの参照ポインタ
99+ * @return なし
100+ */
101+void update_player_window(player_type *target_ptr, old_race_flags *old_race_flags_ptr)
102+{
103+ monster_race *r_ptr;
104+ r_ptr = &r_info[target_ptr->monster_race_idx];
105+ if ((old_race_flags_ptr->old_r_flags1 != r_ptr->r_flags1) ||
106+ (old_race_flags_ptr->old_r_flags2 != r_ptr->r_flags2) ||
107+ (old_race_flags_ptr->old_r_flags3 != r_ptr->r_flags3) ||
108+ (old_race_flags_ptr->old_r_flags4 != r_ptr->r_flags4) ||
109+ (old_race_flags_ptr->old_r_flags5 != r_ptr->r_flags5) ||
110+ (old_race_flags_ptr->old_r_flags6 != r_ptr->r_flags6) ||
111+ (old_race_flags_ptr->old_r_flagsr != r_ptr->r_flagsr) ||
112+ (old_race_flags_ptr->old_r_blows0 != r_ptr->r_blows[0]) ||
113+ (old_race_flags_ptr->old_r_blows1 != r_ptr->r_blows[1]) ||
114+ (old_race_flags_ptr->old_r_blows2 != r_ptr->r_blows[2]) ||
115+ (old_race_flags_ptr->old_r_blows3 != r_ptr->r_blows[3]) ||
116+ (old_race_flags_ptr->old_r_cast_spell != r_ptr->r_cast_spell))
117+ {
118+ target_ptr->window |= (PW_MONSTER);
119+ }
120+}
--- /dev/null
+++ b/src/monster/monster-update.h
@@ -0,0 +1,9 @@
1+#pragma once
2+
3+#include "angband.h"
4+#include "monster/monster-util.h"
5+
6+bool update_riding_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, POSITION ny, POSITION nx);
7+void update_player_type(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_race *r_ptr);
8+void update_monster_race_flags(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr);
9+void update_player_window(player_type *target_ptr, old_race_flags *old_race_flags_ptr);
--- /dev/null
+++ b/src/monster/monster-util.c
@@ -0,0 +1,368 @@
1+/*!
2+ * @brief monster-processのための構造体群初期化処理と共通性の極めて高い処理
3+ * @date 2020/03/07
4+ * @author Hourier
5+ * @details
6+ * 概ね、player_type 構造体が引数でない場合はここへ移動させることを検討しても良い
7+ * 引数に入っていたらここには移動させないこと
8+ */
9+
10+#include "angband.h"
11+#include "monster-util.h"
12+
13+ /*!
14+ * @brief ターン経過フラグ構造体の初期化
15+ * @param riding_idx 乗馬中のモンスターID
16+ * @param m_idx モンスターID
17+ * @return 初期化済のターン経過フラグ
18+ */
19+turn_flags *init_turn_flags(MONSTER_IDX riding_idx, MONSTER_IDX m_idx, turn_flags *turn_flags_ptr)
20+{
21+ turn_flags_ptr->is_riding_mon = (m_idx == riding_idx);
22+ turn_flags_ptr->do_turn = FALSE;
23+ turn_flags_ptr->do_move = FALSE;
24+ turn_flags_ptr->do_view = FALSE;
25+ turn_flags_ptr->must_alter_to_move = FALSE;
26+ turn_flags_ptr->did_open_door = FALSE;
27+ turn_flags_ptr->did_bash_door = FALSE;
28+ turn_flags_ptr->did_take_item = FALSE;
29+ turn_flags_ptr->did_kill_item = FALSE;
30+ turn_flags_ptr->did_move_body = FALSE;
31+ turn_flags_ptr->did_pass_wall = FALSE;
32+ turn_flags_ptr->did_kill_wall = FALSE;
33+ return turn_flags_ptr;
34+}
35+
36+
37+/*!
38+ * @brief old_race_flags_ptr の初期化
39+ */
40+old_race_flags *init_old_race_flags(old_race_flags *old_race_flags_ptr)
41+{
42+ old_race_flags_ptr->old_r_flags1 = 0L;
43+ old_race_flags_ptr->old_r_flags2 = 0L;
44+ old_race_flags_ptr->old_r_flags3 = 0L;
45+ old_race_flags_ptr->old_r_flags4 = 0L;
46+ old_race_flags_ptr->old_r_flags5 = 0L;
47+ old_race_flags_ptr->old_r_flags6 = 0L;
48+ old_race_flags_ptr->old_r_flagsr = 0L;
49+
50+ old_race_flags_ptr->old_r_blows0 = 0;
51+ old_race_flags_ptr->old_r_blows1 = 0;
52+ old_race_flags_ptr->old_r_blows2 = 0;
53+ old_race_flags_ptr->old_r_blows3 = 0;
54+
55+ old_race_flags_ptr->old_r_cast_spell = 0;
56+ return old_race_flags_ptr;
57+}
58+
59+
60+/*!
61+ * @brief coordinate_candidate の初期化
62+ * @param なし
63+ * @return 初期化済の構造体
64+ */
65+coordinate_candidate init_coordinate_candidate(void)
66+{
67+ coordinate_candidate candidate;
68+ candidate.gy = 0;
69+ candidate.gx = 0;
70+ candidate.gdis = 0;
71+ return candidate;
72+}
73+
74+
75+/*!
76+ * @brief モンスターの移動方向を保存する
77+ * @param mm 移動方向
78+ * @param y 移動先Y座標
79+ * @param x 移動先X座標
80+ */
81+void store_enemy_approch_direction(int *mm, POSITION y, POSITION x)
82+{
83+ /* North, South, East, West, North-West, North-East, South-West, South-East */
84+ if ((y < 0) && (x == 0))
85+ {
86+ mm[0] = 8;
87+ mm[1] = 7;
88+ mm[2] = 9;
89+ }
90+ else if ((y > 0) && (x == 0))
91+ {
92+ mm[0] = 2;
93+ mm[1] = 1;
94+ mm[2] = 3;
95+ }
96+ else if ((x > 0) && (y == 0))
97+ {
98+ mm[0] = 6;
99+ mm[1] = 9;
100+ mm[2] = 3;
101+ }
102+ else if ((x < 0) && (y == 0))
103+ {
104+ mm[0] = 4;
105+ mm[1] = 7;
106+ mm[2] = 1;
107+ }
108+ else if ((y < 0) && (x < 0))
109+ {
110+ mm[0] = 7;
111+ mm[1] = 4;
112+ mm[2] = 8;
113+ }
114+ else if ((y < 0) && (x > 0))
115+ {
116+ mm[0] = 9;
117+ mm[1] = 6;
118+ mm[2] = 8;
119+ }
120+ else if ((y > 0) && (x < 0))
121+ {
122+ mm[0] = 1;
123+ mm[1] = 4;
124+ mm[2] = 2;
125+ }
126+ else if ((y > 0) && (x > 0))
127+ {
128+ mm[0] = 3;
129+ mm[1] = 6;
130+ mm[2] = 2;
131+ }
132+}
133+
134+
135+/*!
136+ * @brief get_movable_grid() における移動の方向を保存する
137+ * @param mm 移動方向
138+ * @param y 移動先Y座標
139+ * @param x 移動先X座標
140+ * @return なし
141+ */
142+void store_moves_val(int *mm, int y, int x)
143+{
144+ POSITION ax = ABS(x);
145+ POSITION ay = ABS(y);
146+
147+ int move_val = 0;
148+ if (y < 0) move_val += 8;
149+ if (x > 0) move_val += 4;
150+
151+ if (ay > (ax << 1)) move_val += 2;
152+ else if (ax > (ay << 1)) move_val++;
153+
154+ switch (move_val)
155+ {
156+ case 0:
157+ {
158+ mm[0] = 9;
159+ if (ay > ax)
160+ {
161+ mm[1] = 8;
162+ mm[2] = 6;
163+ mm[3] = 7;
164+ mm[4] = 3;
165+ }
166+ else
167+ {
168+ mm[1] = 6;
169+ mm[2] = 8;
170+ mm[3] = 3;
171+ mm[4] = 7;
172+ }
173+
174+ break;
175+ }
176+ case 1:
177+ case 9:
178+ {
179+ mm[0] = 6;
180+ if (y < 0)
181+ {
182+ mm[1] = 3;
183+ mm[2] = 9;
184+ mm[3] = 2;
185+ mm[4] = 8;
186+ }
187+ else
188+ {
189+ mm[1] = 9;
190+ mm[2] = 3;
191+ mm[3] = 8;
192+ mm[4] = 2;
193+ }
194+
195+ break;
196+ }
197+ case 2:
198+ case 6:
199+ {
200+ mm[0] = 8;
201+ if (x < 0)
202+ {
203+ mm[1] = 9;
204+ mm[2] = 7;
205+ mm[3] = 6;
206+ mm[4] = 4;
207+ }
208+ else
209+ {
210+ mm[1] = 7;
211+ mm[2] = 9;
212+ mm[3] = 4;
213+ mm[4] = 6;
214+ }
215+
216+ break;
217+ }
218+ case 4:
219+ {
220+ mm[0] = 7;
221+ if (ay > ax)
222+ {
223+ mm[1] = 8;
224+ mm[2] = 4;
225+ mm[3] = 9;
226+ mm[4] = 1;
227+ }
228+ else
229+ {
230+ mm[1] = 4;
231+ mm[2] = 8;
232+ mm[3] = 1;
233+ mm[4] = 9;
234+ }
235+
236+ break;
237+ }
238+ case 5:
239+ case 13:
240+ {
241+ mm[0] = 4;
242+ if (y < 0)
243+ {
244+ mm[1] = 1;
245+ mm[2] = 7;
246+ mm[3] = 2;
247+ mm[4] = 8;
248+ }
249+ else
250+ {
251+ mm[1] = 7;
252+ mm[2] = 1;
253+ mm[3] = 8;
254+ mm[4] = 2;
255+ }
256+
257+ break;
258+ }
259+ case 8:
260+ {
261+ mm[0] = 3;
262+ if (ay > ax)
263+ {
264+ mm[1] = 2;
265+ mm[2] = 6;
266+ mm[3] = 1;
267+ mm[4] = 9;
268+ }
269+ else
270+ {
271+ mm[1] = 6;
272+ mm[2] = 2;
273+ mm[3] = 9;
274+ mm[4] = 1;
275+ }
276+
277+ break;
278+ }
279+ case 10:
280+ case 14:
281+ {
282+ mm[0] = 2;
283+ if (x < 0)
284+ {
285+ mm[1] = 3;
286+ mm[2] = 1;
287+ mm[3] = 6;
288+ mm[4] = 4;
289+ }
290+ else
291+ {
292+ mm[1] = 1;
293+ mm[2] = 3;
294+ mm[3] = 4;
295+ mm[4] = 6;
296+ }
297+
298+ break;
299+ }
300+ case 12:
301+ {
302+ mm[0] = 1;
303+ if (ay > ax)
304+ {
305+ mm[1] = 2;
306+ mm[2] = 4;
307+ mm[3] = 3;
308+ mm[4] = 7;
309+ }
310+ else
311+ {
312+ mm[1] = 4;
313+ mm[2] = 2;
314+ mm[3] = 7;
315+ mm[4] = 3;
316+ }
317+
318+ break;
319+ }
320+ }
321+}
322+
323+
324+/*!
325+ * @brief 古いモンスター情報の保存
326+ * @param monster_race_idx モンスターID
327+ * @param old_race_flags_ptr モンスターフラグへの参照ポインタ
328+ * @return なし
329+ */
330+void save_old_race_flags(MONRACE_IDX monster_race_idx, old_race_flags *old_race_flags_ptr)
331+{
332+ if (monster_race_idx == 0) return;
333+
334+ monster_race *r_ptr;
335+ r_ptr = &r_info[monster_race_idx];
336+
337+ old_race_flags_ptr->old_r_flags1 = r_ptr->r_flags1;
338+ old_race_flags_ptr->old_r_flags2 = r_ptr->r_flags2;
339+ old_race_flags_ptr->old_r_flags3 = r_ptr->r_flags3;
340+ old_race_flags_ptr->old_r_flags4 = r_ptr->r_flags4;
341+ old_race_flags_ptr->old_r_flags5 = r_ptr->r_flags5;
342+ old_race_flags_ptr->old_r_flags6 = r_ptr->r_flags6;
343+ old_race_flags_ptr->old_r_flagsr = r_ptr->r_flagsr;
344+
345+ old_race_flags_ptr->old_r_blows0 = r_ptr->r_blows[0];
346+ old_race_flags_ptr->old_r_blows1 = r_ptr->r_blows[1];
347+ old_race_flags_ptr->old_r_blows2 = r_ptr->r_blows[2];
348+ old_race_flags_ptr->old_r_blows3 = r_ptr->r_blows[3];
349+
350+ old_race_flags_ptr->old_r_cast_spell = r_ptr->r_cast_spell;
351+}
352+
353+
354+/*!
355+ * @brief モンスターの加速値を決定する
356+ * @param m_ptr モンスターへの参照ポインタ
357+ * return モンスターの加速値
358+ */
359+SPEED decide_monster_speed(monster_type *m_ptr)
360+{
361+ SPEED speed = m_ptr->mspeed;
362+ if (ironman_nightmare) speed += 5;
363+
364+ if (MON_FAST(m_ptr)) speed += 10;
365+ if (MON_SLOW(m_ptr)) speed -= 10;
366+
367+ return speed;
368+}
--- /dev/null
+++ b/src/monster/monster-util.h
@@ -0,0 +1,58 @@
1+/*!
2+ * @brief monster-processのための構造体群
3+ * @date 2020/03/07
4+ * @author Hourier
5+ */
6+
7+#pragma once
8+
9+typedef struct {
10+ bool see_m;
11+ bool aware;
12+ bool is_riding_mon;
13+ bool do_turn;
14+ bool do_move;
15+ bool do_view;
16+ bool do_take;
17+ bool must_alter_to_move;
18+
19+ bool did_open_door;
20+ bool did_bash_door;
21+ bool did_take_item;
22+ bool did_kill_item;
23+ bool did_move_body;
24+ bool did_pass_wall;
25+ bool did_kill_wall;
26+} turn_flags;
27+
28+typedef struct {
29+ BIT_FLAGS old_r_flags1;
30+ BIT_FLAGS old_r_flags2;
31+ BIT_FLAGS old_r_flags3;
32+ BIT_FLAGS old_r_flags4;
33+ BIT_FLAGS old_r_flags5;
34+ BIT_FLAGS old_r_flags6;
35+ BIT_FLAGS old_r_flagsr;
36+
37+ byte old_r_blows0;
38+ byte old_r_blows1;
39+ byte old_r_blows2;
40+ byte old_r_blows3;
41+
42+ byte old_r_cast_spell;
43+} old_race_flags;
44+
45+typedef struct {
46+ POSITION gy;
47+ POSITION gx;
48+ POSITION gdis;
49+} coordinate_candidate;
50+
51+turn_flags *init_turn_flags(MONSTER_IDX riding_idx, MONSTER_IDX m_idx, turn_flags *turn_flags_ptr);
52+old_race_flags *init_old_race_flags(old_race_flags *old_race_flags_ptr);
53+coordinate_candidate init_coordinate_candidate(void);
54+
55+void store_enemy_approch_direction(int *mm, POSITION y, POSITION x);
56+void store_moves_val(int *mm, int y, int x);
57+void save_old_race_flags(MONRACE_IDX monster_race_idx, old_race_flags *old_race_flags_ptr);
58+SPEED decide_monster_speed(monster_type *m_ptr);
--- /dev/null
+++ b/src/monster/quantum-effect.c
@@ -0,0 +1,99 @@
1+#include "angband.h"
2+#include "quantum-effect.h"
3+#include "monster-spell.h"
4+
5+/*!
6+ * @brief ユニークでない量子生物を消滅させる
7+ * @param target_ptr プレーヤーへの参照ポインタ
8+ * @param m_idx モンスターID
9+ * @param see_m モンスターが視界内にいたらTRUE
10+ * @return なし
11+ */
12+static void vanish_nonunique(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m)
13+{
14+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
15+ if (see_m)
16+ {
17+ GAME_TEXT m_name[MAX_NLEN];
18+ monster_desc(target_ptr, m_name, m_ptr, 0);
19+ msg_format(_("%sは消え去った!", "%^s disappears!"), m_name);
20+ }
21+
22+ monster_death(target_ptr, m_idx, FALSE);
23+ delete_monster_idx(target_ptr, m_idx);
24+ if (is_pet(m_ptr) && !(m_ptr->ml))
25+ {
26+ msg_print(_("少しの間悲しい気分になった。", "You feel sad for a moment."));
27+ }
28+}
29+
30+
31+/*!
32+ * todo ユニークとプレーヤーとの間でしか効果が発生しない。ユニークとその他のモンスター間では何もしなくてよい?
33+ * @brief 量子生物ユニークの量子的効果 (ショート・テレポートまたは距離10のテレポート・アウェイ)を実行する
34+ * @param target_ptr プレーヤーへの参照ポインタ
35+ * @param m_idx モンスターID
36+ * @param see_m モンスターが視界内にいたらTRUE
37+ * @return なし
38+ * @details
39+ * プレーヤーが量子生物を観測しているか、量子生物がプレーヤーを観測している場合、互いの相対的な位置を確定させる
40+ * 波動関数の収縮はテレポートではないので反テレポート無効
41+ * @notes
42+ * パターンは収縮どころか拡散しているが、この際気にしてはいけない
43+ */
44+static void produce_quantum_effect(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m)
45+{
46+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
47+ bool coherent = los(target_ptr, m_ptr->fy, m_ptr->fx, target_ptr->y, target_ptr->x);
48+ if (!see_m && !coherent) return;
49+
50+ if (see_m)
51+ {
52+ GAME_TEXT m_name[MAX_NLEN];
53+ monster_desc(target_ptr, m_name, m_ptr, 0);
54+ msg_format(_("%sは量子的効果を起こした!", "%^s produced a decoherence!"), m_name);
55+ }
56+ else
57+ {
58+ msg_print(_("量子的効果が起こった!", "A decoherence was produced!"));
59+ }
60+
61+ bool target = one_in_(2);
62+ const int blink = 32 * 5 + 4;
63+ if (target)
64+ {
65+ (void)monspell_to_monster(target_ptr, blink, m_ptr->fy, m_ptr->fx, m_idx, m_idx, TRUE);
66+ }
67+ else
68+ {
69+ teleport_player_away(m_idx, target_ptr, 10, TRUE);
70+ }
71+}
72+
73+
74+/*!
75+ * @brief 量子生物の量子的効果を実行する
76+ * @param target_ptr プレーヤーへの参照ポインタ
77+ * @param m_idx モンスターID
78+ * @param see_m モンスターが視界内にいたらTRUE
79+ * @return モンスターが量子的効果により消滅したらTRUE
80+ */
81+bool process_quantum_effect(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m)
82+{
83+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
84+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
85+ if ((r_ptr->flags2 & RF2_QUANTUM) == 0) return FALSE;
86+ if (!randint0(2)) return FALSE;
87+ if (randint0((m_idx % 100) + 10)) return FALSE;
88+
89+ bool can_disappear = (r_ptr->flags1 & RF1_UNIQUE) == 0;
90+ can_disappear &= (r_ptr->flags1 & RF1_QUESTOR) == 0;
91+ if (can_disappear)
92+ {
93+ vanish_nonunique(target_ptr, m_idx, see_m);
94+ return TRUE;
95+ }
96+
97+ produce_quantum_effect(target_ptr, m_idx, see_m);
98+ return FALSE;
99+}
--- /dev/null
+++ b/src/monster/quantum-effect.h
@@ -0,0 +1,3 @@
1+#pragma once
2+
3+bool process_quantum_effect(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m);
--- a/src/mspells2.c
+++ b/src/mspells2.c
@@ -697,7 +697,7 @@ bool monst_spell_monst(player_type *target_ptr, MONSTER_IDX m_idx)
697697
698698 can_remember = is_original_ap_and_seen(target_ptr, m_ptr);
699699
700- dam = monspell_to_monster(target_ptr, thrown_spell, y, x, m_idx, target_idx);
700+ dam = monspell_to_monster(target_ptr, thrown_spell, y, x, m_idx, target_idx, FALSE);
701701 if (dam < 0) return FALSE;
702702
703703 bool is_special_magic = m_ptr->ml;
--- a/src/mspells3.c
+++ b/src/mspells3.c
@@ -1803,6 +1803,7 @@ void learn_spell(player_type *learner_ptr, int monspell)
18031803
18041804
18051805 /*!
1806+ * todo f4, f5, f6を構造体にまとめ直す
18061807 * @brief モンスター特殊能力のフラグ配列から特定条件の魔法だけを抜き出す処理
18071808 * Extract monster spells mask for the given mode
18081809 * @param f4 モンスター特殊能力の4番目のフラグ配列
--- a/src/mspells4.c
+++ b/src/mspells4.c
@@ -1992,9 +1992,10 @@ void spell_RF6_INVULNER(player_type *target_ptr, MONSTER_IDX m_idx, MONSTER_IDX
19921992 * @brief RF6_BLINKの処理。ショート・テレポート。 /
19931993 * @param target_ptr プレーヤーへの参照ポインタ
19941994 * @param m_idx 呪文を唱えるモンスターID
1995+* @param is_quantum_effect 量子的効果によるショート・テレポートの場合時TRUE
19951996 * @param TARGET_TYPE プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
19961997 */
1997-void spell_RF6_BLINK(player_type *target_ptr, MONSTER_IDX m_idx, int TARGET_TYPE)
1998+void spell_RF6_BLINK(player_type *target_ptr, MONSTER_IDX m_idx, int TARGET_TYPE, bool is_quantum_effect)
19981999 {
19992000 GAME_TEXT m_name[MAX_NLEN];
20002001 monster_name(target_ptr, m_idx, m_name);
@@ -2003,7 +2004,7 @@ void spell_RF6_BLINK(player_type *target_ptr, MONSTER_IDX m_idx, int TARGET_TYPE
20032004 disturb(target_ptr, TRUE, TRUE);
20042005
20052006 floor_type *floor_ptr = target_ptr->current_floor_ptr;
2006- if (teleport_barrier(target_ptr, m_idx))
2007+ if (!is_quantum_effect && teleport_barrier(target_ptr, m_idx))
20072008 {
20082009 if (see_monster(floor_ptr, m_idx))
20092010 msg_format(_("魔法のバリアが%^sのテレポートを邪魔した。",
@@ -2163,7 +2164,7 @@ HIT_POINT spell_RF6_SPECIAL_ROLENTO(player_type *target_ptr, POSITION y, POSITIO
21632164
21642165 for (k = 0; k < num; k++)
21652166 {
2166- count += summon_named_creature(target_ptr, m_idx, y, x, MON_SHURYUUDAN, mode);
2167+ count += summon_named_creature(target_ptr, m_idx, y, x, MON_GRENADE, mode);
21672168 }
21682169 if (target_ptr->blind && count)
21692170 {
@@ -3691,7 +3692,7 @@ HIT_POINT monspell_to_player(player_type *target_ptr, int SPELL_NUM, POSITION y,
36913692 case RF6_SPELL_START + 1: return spell_RF6_HAND_DOOM(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_HAND_DOOM */
36923693 case RF6_SPELL_START + 2: spell_RF6_HEAL(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); break; /* RF6_HEAL */
36933694 case RF6_SPELL_START + 3: spell_RF6_INVULNER(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); break; /* RF6_INVULNER */
3694- case RF6_SPELL_START + 4: spell_RF6_BLINK(target_ptr, m_idx, MONSTER_TO_PLAYER); break; /* RF6_BLINK */
3695+ case RF6_SPELL_START + 4: spell_RF6_BLINK(target_ptr, m_idx, MONSTER_TO_PLAYER, FALSE); break; /* RF6_BLINK */
36953696 case RF6_SPELL_START + 5: spell_RF6_TPORT(target_ptr, m_idx, MONSTER_TO_PLAYER); break; /* RF6_TPORT */
36963697 case RF6_SPELL_START + 6: return spell_RF6_WORLD(target_ptr, m_idx); break; /* RF6_WORLD */
36973698 case RF6_SPELL_START + 7: return spell_RF6_SPECIAL(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_SPECIAL */
@@ -3734,9 +3735,10 @@ HIT_POINT monspell_to_player(player_type *target_ptr, int SPELL_NUM, POSITION y,
37343735 * @param x 対象の地点のx座標
37353736 * @param m_idx 呪文を唱えるモンスターID
37363737 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
3738+* @param is_special_spell 特殊な行動である時TRUE
37373739 * @return 攻撃呪文のダメージ、または召喚したモンスターの数を返す。その他の場合0。以降の処理を中断するなら-1を返す。
37383740 */
3739-HIT_POINT monspell_to_monster(player_type *target_ptr, int SPELL_NUM, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx)
3741+HIT_POINT monspell_to_monster(player_type *target_ptr, int SPELL_NUM, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, bool is_special_spell)
37403742 {
37413743 switch (SPELL_NUM)
37423744 {
@@ -3808,7 +3810,7 @@ HIT_POINT monspell_to_monster(player_type *target_ptr, int SPELL_NUM, POSITION y
38083810 case RF6_SPELL_START + 1: return spell_RF6_HAND_DOOM(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_HAND_DOOM */
38093811 case RF6_SPELL_START + 2: spell_RF6_HEAL(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); break; /* RF6_HEAL */
38103812 case RF6_SPELL_START + 3: spell_RF6_INVULNER(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); break; /* RF6_INVULNER */
3811- case RF6_SPELL_START + 4: spell_RF6_BLINK(target_ptr, m_idx, MONSTER_TO_MONSTER); break; /* RF6_BLINK */
3813+ case RF6_SPELL_START + 4: spell_RF6_BLINK(target_ptr, m_idx, MONSTER_TO_MONSTER, is_special_spell); break; /* RF6_BLINK */
38123814 case RF6_SPELL_START + 5: spell_RF6_TPORT(target_ptr, m_idx, MONSTER_TO_MONSTER); break; /* RF6_TPORT */
38133815 case RF6_SPELL_START + 6: return -1; break; /* RF6_WORLD */
38143816 case RF6_SPELL_START + 7: return spell_RF6_SPECIAL(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_SPECIAL */
--- a/src/player/process-death.c
+++ b/src/player/process-death.c
@@ -369,7 +369,7 @@ static void show_dead_home_items(player_type *creature_ptr)
369369 * @param file_character ステータスダンプへのコールバック
370370 * @return なし
371371 */
372-static void export_player_info(player_type *creature_ptr, display_player_pf display_player, map_name_pf map_name)
372+static void export_player_info(player_type *creature_ptr, update_playtime_pf update_playtime, display_player_pf display_player, map_name_pf map_name)
373373 {
374374 prt(_("キャラクターの記録をファイルに書き出すことができます。", "You may now dump a character record to one or more files."), 21, 0);
375375 prt(_("リターンキーでキャラクターを見ます。ESCで中断します。", "Then, hit RETURN to see the character, or ESC to abort."), 22, 0);
@@ -382,7 +382,7 @@ static void export_player_info(player_type *creature_ptr, display_player_pf disp
382382 if (!out_val[0]) break;
383383
384384 screen_save();
385- (void)file_character(creature_ptr, out_val, display_player, map_name);
385+ (void)file_character(creature_ptr, out_val, update_playtime, display_player, map_name);
386386 screen_load();
387387 }
388388 }
@@ -397,7 +397,7 @@ static void export_player_info(player_type *creature_ptr, display_player_pf disp
397397 * @param display_player ステータス表示へのコールバック
398398 * @return なし
399399 */
400-void show_info(player_type *creature_ptr, void(*handle_stuff)(player_type*), void(*update_playtime)(void), display_player_pf display_player, map_name_pf map_name)
400+void show_info(player_type *creature_ptr, void(*handle_stuff)(player_type*), update_playtime_pf update_playtime, display_player_pf display_player, map_name_pf map_name)
401401 {
402402 inventory_aware(creature_ptr);
403403 home_aware(creature_ptr);
@@ -407,7 +407,7 @@ void show_info(player_type *creature_ptr, void(*handle_stuff)(player_type*), voi
407407 flush();
408408 msg_erase();
409409
410- export_player_info(creature_ptr, display_player, map_name);
410+ export_player_info(creature_ptr, update_playtime, display_player, map_name);
411411 (*update_playtime)();
412412 (*display_player)(creature_ptr, 0, map_name);
413413 prt(_("何かキーを押すとさらに情報が続きます (ESCで中断): ", "Hit any key to see more information (ESC to abort): "), 23, 0);
--- a/src/player/process-death.h
+++ b/src/player/process-death.h
@@ -4,4 +4,4 @@
44 #include "files.h"
55
66 void print_tomb(player_type *dead_ptr);
7-void show_info(player_type *creature_ptr, void(*handle_stuff)(player_type*), void(*update_playtime)(void), display_player_pf display_player, map_name_pf map_name);
7+void show_info(player_type *creature_ptr, void(*handle_stuff)(player_type*), update_playtime_pf update_playtime, display_player_pf display_player, map_name_pf map_name);