変愚蛮怒のメインリポジトリです
Révision | 4fab351a44340ad8bdd82cd1c622fb78b83c74cc (tree) |
---|---|
l'heure | 2020-03-08 14:44:10 |
Auteur | deskull <deskull@user...> |
Commiter | deskull |
Merge remote-tracking branch 'remotes/origin/For2.2.2-Fix-Hourier' into For2.2.2-Refactoring
@@ -195,13 +195,25 @@ | ||
195 | 195 | <ClCompile Include="..\..\src\init.c" /> |
196 | 196 | <ClCompile Include="..\..\src\io\gf-descriptions.c" /> |
197 | 197 | <ClCompile Include="..\..\src\io\interpret-pref-file.c" /> |
198 | + <ClCompile Include="..\..\src\io\player-status-dump.c" /> | |
198 | 199 | <ClCompile Include="..\..\src\io\read-pref-file.c" /> |
200 | + <ClCompile Include="..\..\src\io\special-class-dump.c" /> | |
199 | 201 | <ClCompile Include="..\..\src\io\tokenizer.c" /> |
200 | 202 | <ClCompile Include="..\..\src\monster-dist-offsets.c" /> |
201 | 203 | <ClCompile Include="..\..\src\monster-process.c" /> |
202 | 204 | <ClCompile Include="..\..\src\monster-status.c" /> |
203 | 205 | <ClCompile Include="..\..\src\monsterrace-hook.c" /> |
204 | 206 | <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" /> | |
205 | 217 | <ClCompile Include="..\..\src\object-boost.c" /> |
206 | 218 | <ClCompile Include="..\..\src\object-curse.c" /> |
207 | 219 | <ClCompile Include="..\..\src\object-ego.c" /> |
@@ -343,9 +355,21 @@ | ||
343 | 355 | <ClInclude Include="..\..\src\horror-descriptions.h" /> |
344 | 356 | <ClInclude Include="..\..\src\io\gf-descriptions.h" /> |
345 | 357 | <ClInclude Include="..\..\src\io\interpret-pref-file.h" /> |
358 | + <ClInclude Include="..\..\src\io\player-status-dump.h" /> | |
346 | 359 | <ClInclude Include="..\..\src\io\read-pref-file.h" /> |
360 | + <ClInclude Include="..\..\src\io\special-class-dump.h" /> | |
347 | 361 | <ClInclude Include="..\..\src\io\tokenizer.h" /> |
348 | 362 | <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" /> | |
349 | 373 | <ClInclude Include="..\..\src\object-flavor.h" /> |
350 | 374 | <ClInclude Include="..\..\src\player-inventory.h" /> |
351 | 375 | <ClInclude Include="..\..\src\player\permanent-resistances.h" /> |
@@ -472,6 +472,42 @@ | ||
472 | 472 | <ClCompile Include="..\..\src\io\interpret-pref-file.c"> |
473 | 473 | <Filter>io</Filter> |
474 | 474 | </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> | |
475 | 511 | </ItemGroup> |
476 | 512 | <ItemGroup> |
477 | 513 | <ClInclude Include="..\..\src\gamevalue.h" /> |
@@ -926,6 +962,42 @@ | ||
926 | 962 | <ClInclude Include="..\..\src\io\interpret-pref-file.h"> |
927 | 963 | <Filter>io</Filter> |
928 | 964 | </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> | |
929 | 1001 | </ItemGroup> |
930 | 1002 | <ItemGroup> |
931 | 1003 | <None Include="..\..\src\wall.bmp" /> |
@@ -13,7 +13,7 @@ M:WX:99 | ||
13 | 13 | M:WY:66 |
14 | 14 | |
15 | 15 | # Maximum number of monsters in r_info.txt |
16 | -M:R:1140 | |
16 | +M:R:1141 | |
17 | 17 | |
18 | 18 | # Maximum number of items in k_info.txt |
19 | 19 | M:K:672 |
@@ -2270,7 +2270,7 @@ S:SHOOT | HEAL | TRAPS | ||
2270 | 2270 | A:221:1:5 |
2271 | 2271 | V:75 |
2272 | 2272 | D:$The legendary archer steals from the rich (you qualify). |
2273 | -D:この伝説の射手は金持ち(あなたは合格)から金を盗む | |
2273 | +D:この伝説の射手は金持ち(あなたは合格)から金を盗む。 | |
2274 | 2274 | |
2275 | 2275 | #JZ# |
2276 | 2276 | N:139:ナーグリング |
@@ -22604,7 +22604,7 @@ F:DROP_1D2 | ||
22604 | 22604 | F:OPEN_DOOR | BASH_DOOR | DROP_SKELETON | DROP_CORPSE |
22605 | 22605 | F:EVIL | IM_POIS | EAT_POISONOUS | CAN_SWIM |
22606 | 22606 | 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! | |
22608 | 22608 | D:気をつけろ! |
22609 | 22609 | D:やつの毒は大の大人を無力な子供に変えてしまう! |
22610 | 22610 |
@@ -22622,7 +22622,7 @@ F:EVIL | IM_POIS | EAT_POISONOUS | ||
22622 | 22622 | F:ESCORT | ESCORTS | RES_SOUN | CAN_FLY |
22623 | 22623 | F:NO_CONF |
22624 | 22624 | 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! | |
22626 | 22626 | D:「悪いなのび太、このダンジョンは3人用なんだ」 |
22627 | 22627 | D:しかし、彼に群がる金の亡者は明らかに3人よりも多い! |
22628 | 22628 |
@@ -22637,11 +22637,12 @@ B:HIT:FIRE:8d4 | ||
22637 | 22637 | F:MALE | |
22638 | 22638 | F:FORCE_MAXHP | FRIENDS | DROP_60 | |
22639 | 22639 | 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 | |
22641 | 22642 | S:1_IN_8 |
22642 | 22643 | 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. | |
22645 | 22646 | D:このオークの体にはデーモンの血が流れており、そこから来る暗黒の炎をまとっている。 |
22646 | 22647 | D:この不浄な結合は、暗き風習を持つ生き物の中でしばしば育まれる。 |
22647 | 22648 |
@@ -22662,8 +22663,10 @@ S:1_IN_5 | S_KIN | SHOOT | BO_ELEC | ||
22662 | 22663 | D:$The leader of this family, worried about the death of his homeland |
22663 | 22664 | D:$ after the death of Isshin Ashina, |
22664 | 22665 | 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:いかなる異形の力をも顧みず手に入れようとする。 | |
22667 | 22670 | D:ゆえにそれらを求め鉄獄に至ったこともまた必然であるだろう。 |
22668 | 22671 | |
22669 | 22672 | N:1124:撲殺の天使 |
@@ -22888,7 +22891,8 @@ F:NO_FEAR | NO_CONF | NO_SLEEP | ||
22888 | 22891 | S:1_IN_2 | BA_NETH | BA_WATE | BA_DARK | BA_NUKE | BA_CHAO |
22889 | 22892 | S:S_HI_UNDEAD | S_DEMON | DISPEL |
22890 | 22893 | 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. | |
22892 | 22896 | D:$ It is told that his book, Necronomicon, namely stargate to the abyss, |
22893 | 22897 | D:$ is still slept somewhere in the land. |
22894 | 22898 | D:呪われしアーティファクトを世に解き放ち、 |
@@ -22906,8 +22910,10 @@ B:BITE:HURT:6d2 | ||
22906 | 22910 | F:MALE | WILD_SWAMP | WILD_WASTE |
22907 | 22911 | F:OPEN_DOOR | BASH_DOOR | DROP_CORPSE | DROP_SKELETON |
22908 | 22912 | 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:目についた獲物を片っ端から屠っていく。 | |
22911 | 22917 | |
22912 | 22918 | N:1137:殺人イタチ |
22913 | 22919 | E:Killer weasel |
@@ -22966,3 +22972,22 @@ D:$She recognizes you as a bug that appears to be | ||
22966 | 22972 | D:$ a myriad of connected consciousness in the Wired. |
22967 | 22973 | D:あなたは、相互に結合している無数の意識達に表れたちっぽけなバグだと |
22968 | 22974 | 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:同族にすると言われている。 |
@@ -30,6 +30,8 @@ hengband_SOURCES = \ | ||
30 | 30 | io/gf-descriptions.c io/gf-descriptions.h \ |
31 | 31 | io/tokenizer.c io/tokenizer.h \ |
32 | 32 | 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 \ | |
33 | 35 | io/read-pref-file.c io/read-pref-file.h \ |
34 | 36 | io/exit-panic.c io/exit-panic.h \ |
35 | 37 | signal-handlers.c signal-handlers.h uid-checker.c uid-checker.h \ |
@@ -56,6 +58,16 @@ hengband_SOURCES = \ | ||
56 | 58 | mind.c mind.h \ |
57 | 59 | \ |
58 | 60 | 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 \ | |
59 | 71 | monsterrace-hook.c monsterrace-hook.h \ |
60 | 72 | monster-dist-offsets.c monster-dist-offsets.h \ |
61 | 73 | monster-process.c monster-process.h \ |
@@ -142,7 +154,7 @@ EXTRA_DIST = \ | ||
142 | 154 | CFLAGS += $(XFT_CFLAGS) |
143 | 155 | LIBS += $(XFT_LIBS) |
144 | 156 | 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 | |
146 | 158 | |
147 | 159 | install-exec-hook: |
148 | 160 | if SET_GID |
@@ -5,9 +5,6 @@ | ||
5 | 5 | #include "dungeon.h" |
6 | 6 | #include "store.h" |
7 | 7 | #include "cmd/cmd-pet.h" |
8 | -#include "cmd/cmd-magiceat.h" | |
9 | -#include "objectkind.h" | |
10 | -#include "monster-spell.h" | |
11 | 8 | #include "monster-status.h" |
12 | 9 | #include "sort.h" |
13 | 10 | #include "quest.h" |
@@ -15,101 +12,11 @@ | ||
15 | 12 | #include "mutation.h" |
16 | 13 | #include "object-flavor.h" |
17 | 14 | #include "cmd/cmd-dump.h" |
15 | +#include "io/special-class-dump.h" | |
16 | +#include "io/player-status-dump.h" | |
18 | 17 | #include "avatar.h" |
19 | 18 | |
20 | 19 | /*! |
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 | -/*! | |
113 | 20 | * @brief プレイヤーのペット情報をファイルにダンプする |
114 | 21 | * @param creature_ptr プレーヤーへの参照ポインタ |
115 | 22 | * @param fff ファイルポインタ |
@@ -165,217 +72,6 @@ static void dump_aux_pet(player_type *master_ptr, FILE *fff) | ||
165 | 72 | |
166 | 73 | |
167 | 74 | /*! |
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 | -/*! | |
379 | 75 | * @brief クエスト情報をファイルにダンプする |
380 | 76 | * @param creature_ptr プレーヤーへの参照ポインタ |
381 | 77 | * @param fff ファイルポインタ |
@@ -469,7 +165,6 @@ static void dump_aux_options(FILE *fff) | ||
469 | 165 | fprintf(fff, _("\n [オプション設定]\n", "\n [Option Settings]\n")); |
470 | 166 | if (preserve_mode) |
471 | 167 | fprintf(fff, _("\n 保存モード: ON", "\n Preserve Mode: ON")); |
472 | - | |
473 | 168 | else |
474 | 169 | fprintf(fff, _("\n 保存モード: OFF", "\n Preserve Mode: OFF")); |
475 | 170 |
@@ -854,16 +549,11 @@ static void dump_aux_home_museum(player_type *creature_ptr, FILE *fff) | ||
854 | 549 | */ |
855 | 550 | void make_character_dump(player_type *creature_ptr, FILE *fff, void(*update_playtime)(void), display_player_pf display_player, map_name_pf map_name) |
856 | 551 | { |
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"), | |
862 | 553 | FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH); |
863 | -#endif | |
864 | 554 | (*update_playtime)(); |
865 | 555 | |
866 | - dump_aux_display_player(creature_ptr, fff, display_player, map_name); | |
556 | + dump_aux_player_status(creature_ptr, fff, display_player, map_name); | |
867 | 557 | dump_aux_last_message(creature_ptr, fff); |
868 | 558 | dump_aux_options(fff); |
869 | 559 | dump_aux_recall(fff); |
@@ -3,4 +3,4 @@ | ||
3 | 3 | #include "angband.h" |
4 | 4 | #include "files.h" |
5 | 5 | |
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); |
@@ -1081,7 +1081,7 @@ void do_cmd_player_status(player_type *creature_ptr) | ||
1081 | 1081 | { |
1082 | 1082 | if (tmp[0] && (tmp[0] != ' ')) |
1083 | 1083 | { |
1084 | - file_character(creature_ptr, tmp, display_player, map_name); | |
1084 | + file_character(creature_ptr, tmp, update_playtime, display_player, map_name); | |
1085 | 1085 | } |
1086 | 1086 | } |
1087 | 1087 | } |
@@ -4124,17 +4124,13 @@ bool monst_attack_monst(player_type *subject_ptr, MONSTER_IDX m_idx, MONSTER_IDX | ||
4124 | 4124 | monster_race *r_ptr = &r_info[m_ptr->r_idx]; |
4125 | 4125 | monster_race *tr_ptr = &r_info[t_ptr->r_idx]; |
4126 | 4126 | |
4127 | - ARMOUR_CLASS ap_cnt; | |
4128 | - ARMOUR_CLASS ac; | |
4129 | - DEPTH rlev; | |
4130 | 4127 | int pt; |
4131 | 4128 | 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; | |
4135 | 4131 | POSITION y_saver = t_ptr->fy; |
4136 | 4132 | POSITION x_saver = t_ptr->fx; |
4137 | - int effect_type; | |
4133 | + int effect_type; | |
4138 | 4134 | |
4139 | 4135 | bool see_m = is_seen(m_ptr); |
4140 | 4136 | 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 | ||
4144 | 4140 | bool known = (m_ptr->cdis <= MAX_SIGHT) || (t_ptr->cdis <= MAX_SIGHT); |
4145 | 4141 | bool do_silly_attack = (one_in_(2) && subject_ptr->image); |
4146 | 4142 | |
4147 | - /* Cannot attack self */ | |
4148 | 4143 | if (m_idx == t_idx) return FALSE; |
4149 | - | |
4150 | - /* Not allowed to attack */ | |
4151 | 4144 | if (r_ptr->flags1 & RF1_NEVER_BLOW) return FALSE; |
4152 | - | |
4153 | 4145 | if (d_info[subject_ptr->dungeon_idx].flags1 & DF1_NO_MELEE) return FALSE; |
4154 | 4146 | |
4155 | 4147 | /* Total armor */ |
4156 | - ac = tr_ptr->ac; | |
4148 | + ARMOUR_CLASS ac = tr_ptr->ac; | |
4157 | 4149 | |
4158 | 4150 | /* 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); | |
4160 | 4152 | |
4161 | 4153 | monster_desc(subject_ptr, m_name, m_ptr, 0); |
4162 | 4154 | monster_desc(subject_ptr, t_name, t_ptr, 0); |
4163 | 4155 | |
4164 | 4156 | /* Assume no blink */ |
4165 | - blinked = FALSE; | |
4157 | + bool blinked = FALSE; | |
4166 | 4158 | |
4167 | 4159 | if (!see_either && known) |
4168 | 4160 | { |
@@ -4172,7 +4164,7 @@ bool monst_attack_monst(player_type *subject_ptr, MONSTER_IDX m_idx, MONSTER_IDX | ||
4172 | 4164 | if (subject_ptr->riding && (m_idx == subject_ptr->riding)) disturb(subject_ptr, TRUE, TRUE); |
4173 | 4165 | |
4174 | 4166 | /* 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++) | |
4176 | 4168 | { |
4177 | 4169 | bool obvious = FALSE; |
4178 | 4170 |
@@ -16,9 +16,7 @@ | ||
16 | 16 | #include "uid-checker.h" |
17 | 17 | #include "files.h" |
18 | 18 | #include "core.h" // 暫定。後で消す. |
19 | - | |
20 | 19 | #include "character-dump.h" |
21 | -#include "view-mainwindow.h" // 暫定。後で消す. | |
22 | 20 | |
23 | 21 | concptr ANGBAND_DIR; //!< Path name: The main "lib" directory This variable is not actually used anywhere in the code |
24 | 22 | 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) | ||
298 | 296 | * Allow the "full" flag to dump additional info, |
299 | 297 | * and trigger its usage from various places in the code. |
300 | 298 | */ |
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) | |
302 | 300 | { |
303 | 301 | char buf[1024]; |
304 | 302 | path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name); |
@@ -19,8 +19,9 @@ extern concptr ANGBAND_DIR_XTRA; | ||
19 | 19 | |
20 | 20 | typedef concptr(*map_name_pf)(player_type*); |
21 | 21 | typedef void(*display_player_pf)(player_type*, int, map_name_pf); |
22 | +typedef void(*update_playtime_pf)(void); | |
22 | 23 | |
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); | |
24 | 25 | extern concptr process_pref_file_expr(player_type *creature_ptr, char **sp, char *fp); |
25 | 26 | extern errr get_rnd_line(concptr file_name, int entry, char *output); |
26 | 27 | void read_dead_file(char* buf, size_t buf_size); |
@@ -13,14 +13,16 @@ | ||
13 | 13 | #include "term.h" |
14 | 14 | #include "view-mainwindow.h" // 暫定。apply_default_feat_lighting()。後で消す. |
15 | 15 | |
16 | +#define MAX_MACRO_CHARS 65536 // 1つのマクロキー押下で実行可能なコマンド最大数 (エスケープシーケンス含む). | |
17 | + | |
16 | 18 | /*! |
17 | 19 | * @brief Rトークンの解釈 / Process "R:<num>:<a>/<c>" -- attr/char for monster races |
18 | 20 | * @param buf バッファ |
19 | - * @param zz トークン保管文字列 | |
20 | 21 | * @return エラーコード |
21 | 22 | */ |
22 | -static errr interpret_r_file(char *buf, char **zz) | |
23 | +static errr interpret_r_token(char *buf) | |
23 | 24 | { |
25 | + char *zz[16]; | |
24 | 26 | if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1; |
25 | 27 | |
26 | 28 | monster_race *r_ptr; |
@@ -38,341 +40,470 @@ static errr interpret_r_file(char *buf, char **zz) | ||
38 | 40 | |
39 | 41 | |
40 | 42 | /*! |
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 バッファ | |
45 | 45 | * @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> | |
62 | 46 | */ |
63 | -errr interpret_pref_file(player_type *creature_ptr, char *buf) | |
47 | +static errr interpret_k_token(char *buf) | |
64 | 48 | { |
65 | - if (buf[1] != ':') return 1; | |
66 | - | |
67 | 49 | 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) | |
69 | 83 | { |
70 | - case 'H': | |
84 | + case 3: | |
71 | 85 | { |
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 | + | |
74 | 95 | return 0; |
75 | 96 | } |
76 | - case 'R': | |
97 | + case 4: | |
77 | 98 | { |
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; | |
79 | 102 | } |
80 | - case 'K': | |
103 | + case F_LIT_MAX * 2 + 1: | |
81 | 104 | { |
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 | + | |
93 | 114 | return 0; |
94 | 115 | } |
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++) | |
96 | 179 | { |
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) | |
119 | 182 | { |
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; | |
130 | 185 | } |
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) | |
132 | 289 | { |
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); | |
135 | 292 | return 0; |
136 | 293 | } |
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 | - } | |
147 | 294 | |
295 | + if (buf[0] == 'X') | |
296 | + { | |
297 | + option_flag[os] &= ~(1L << ob); | |
298 | + (*option_info[i].o_var) = FALSE; | |
148 | 299 | return 0; |
149 | 300 | } |
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; | |
164 | 304 | return 0; |
165 | 305 | } |
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; | |
170 | 306 | |
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 | +} | |
183 | 311 | |
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; | |
190 | 312 | |
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++) | |
203 | 326 | { |
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); | |
208 | 330 | return 0; |
209 | 331 | } |
210 | - case 'C': | |
211 | - { | |
212 | - /* Process "C:<str>" -- create keymap */ | |
213 | - if (tokenize(buf + 2, 2, zz, TOKENIZE_CHECKQUOTE) != 2) return 1; | |
214 | 332 | |
215 | - int mode = strtol(zz[0], NULL, 0); | |
216 | - if ((mode < 0) || (mode >= KEYMAP_MODES)) return 1; | |
333 | + return 1; | |
334 | +} | |
217 | 335 | |
218 | - char tmp[1024]; | |
219 | - text_to_ascii(tmp, zz[1]); | |
220 | - if (!tmp[0] || tmp[1]) return 1; | |
221 | 336 | |
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) | |
241 | 346 | { |
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++) | |
245 | 352 | { |
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]); | |
272 | 354 | } |
273 | 355 | |
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; | |
277 | 364 | } |
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++) | |
279 | 375 | { |
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 | + } | |
283 | 378 | |
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 | +} | |
288 | 381 | |
289 | - gf_color[gf_desc[i].num] = (TERM_COLOR)quark_add(t); | |
290 | - return 0; | |
291 | - } | |
292 | 382 | |
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!")); | |
293 | 396 | return 1; |
294 | 397 | } |
295 | - case 'T': | |
398 | + | |
399 | + int m = max_macrotrigger; | |
400 | + max_macrotrigger++; | |
401 | + t = buf_aux; | |
402 | + s = zz[0]; | |
403 | + while (*s) | |
296 | 404 | { |
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 | + } | |
301 | 408 | |
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 | + } | |
338 | 417 | |
339 | - return 0; | |
340 | - } | |
418 | + macro_trigger_keycode[1][m] = string_make(zz[1]); | |
419 | + return 0; | |
420 | +} | |
341 | 421 | |
342 | - /* Process "T:<trigger>:<keycode>:<shift-keycode>" */ | |
343 | - if (tok < 2) return 0; | |
344 | 422 | |
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; | |
352 | 435 | |
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 | +} | |
362 | 438 | |
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 | - } | |
371 | 439 | |
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); | |
373 | 491 | return 0; |
374 | 492 | } |
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; | |
375 | 508 | } |
376 | - | |
377 | - return 1; | |
378 | 509 | } |
@@ -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 | +} |
@@ -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); |
@@ -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 | +} |
@@ -0,0 +1,3 @@ | ||
1 | +#pragma once | |
2 | + | |
3 | +void dump_aux_class_special(player_type *creature_ptr, FILE *fff); |
@@ -15,2568 +15,416 @@ | ||
15 | 15 | |
16 | 16 | #include "angband.h" |
17 | 17 | #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" | |
18 | 24 | |
19 | 25 | #include "cmd-dump.h" |
20 | 26 | #include "cmd-pet.h" |
21 | 27 | #include "creature.h" |
22 | 28 | #include "melee.h" |
23 | -#include "spells.h" | |
24 | -#include "spells-floor.h" | |
25 | 29 | #include "spells-summon.h" |
26 | -#include "quest.h" | |
27 | 30 | #include "avatar.h" |
28 | 31 | #include "realm-hex.h" |
29 | -#include "object-flavor.h" | |
30 | -#include "object-hook.h" | |
31 | 32 | #include "feature.h" |
32 | 33 | #include "grid.h" |
33 | 34 | #include "player-move.h" |
34 | 35 | #include "monster-status.h" |
35 | 36 | #include "monster-spell.h" |
36 | 37 | #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); | |
99 | 38 | |
100 | 39 | void decide_drop_from_monster(player_type *target_ptr, MONSTER_IDX m_idx, bool is_riding_mon); |
101 | 40 | bool process_stealth(player_type *target_ptr, MONSTER_IDX m_idx); |
102 | 41 | bool vanish_summoned_children(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m); |
103 | 42 | void awake_monster(player_type *target_ptr, MONSTER_IDX m_idx); |
104 | 43 | 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); | |
109 | 45 | 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); | |
115 | 46 | 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); | |
117 | 47 | bool cast_spell(player_type *target_ptr, MONSTER_IDX m_idx, bool aware); |
118 | 48 | |
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); | |
140 | 49 | bool process_monster_fear(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx); |
141 | 50 | |
142 | -void save_old_race_flags(player_type *target_ptr, old_race_flags *old_race_flags_ptr); | |
143 | 51 | void sweep_monster_process(player_type *target_ptr); |
144 | 52 | 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 | - | |
198 | 53 | |
199 | 54 | /*! |
200 | - * @brief モンスターが敵に接近するための方向を決定する | |
55 | + * @brief モンスター単体の1ターン行動処理メインルーチン / | |
56 | + * Process a monster | |
201 | 57 | * @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 | |
207 | 59 | * @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を返す。 | |
338 | 60 | * @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 | |
340 | 62 | *\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 | |
345 | 64 | *\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 | |
456 | 71 | *\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 | |
459 | 75 | *\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 | |
464 | 78 | *\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 | |
466 | 81 | *\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 | |
472 | 83 | */ |
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) | |
474 | 85 | { |
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]; | |
478 | 87 | 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); | |
479 | 91 | |
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)) | |
483 | 94 | { |
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]; | |
485 | 97 | } |
486 | 98 | |
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; | |
506 | 104 | |
507 | - use_scent = TRUE; | |
508 | - best = 0; | |
509 | - } | |
510 | - else | |
105 | + awake_monster(target_ptr, m_idx); | |
106 | + if (MON_STUNNED(m_ptr)) | |
511 | 107 | { |
512 | - return FALSE; | |
108 | + if (one_in_(2)) return; | |
513 | 109 | } |
514 | 110 | |
515 | - for (int i = 7; i >= 0; i--) | |
111 | + if (turn_flags_ptr->is_riding_mon) | |
516 | 112 | { |
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); | |
549 | 114 | } |
550 | 115 | |
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); | |
592 | 117 | |
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; | |
597 | 121 | |
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; | |
599 | 125 | |
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; | |
602 | 129 | |
603 | - return TRUE; | |
604 | -} | |
130 | + if (!decide_monster_movement_direction(target_ptr, mm, m_idx, turn_flags_ptr->aware)) return; | |
605 | 131 | |
132 | + int count = 0; | |
133 | + if (!process_monster_movement(target_ptr, turn_flags_ptr, m_idx, mm, oy, ox, &count)) return; | |
606 | 134 | |
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; | |
615 | 141 | |
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) | |
639 | 143 | { |
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 | + } | |
1171 | 148 | } |
1172 | 149 | |
1173 | 150 | 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); | |
2187 | 152 | |
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; | |
2191 | 154 | |
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 | +} | |
2194 | 157 | |
2195 | - if (!monster_is_valid(m_ptr)) return FALSE; | |
2196 | 158 | |
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)); | |
2199 | 176 | } |
2200 | 177 | |
2201 | 178 | |
2202 | 179 | /*! |
2203 | - * @brief モンスターが移動した結果、そこにプレーヤーがいたら直接攻撃を行う | |
180 | + * @brief 死亡したモンスターが乗馬中のモンスターだった場合に落馬処理を行う | |
2204 | 181 | * @param target_ptr プレーヤーへの参照ポインタ |
2205 | - * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ | |
2206 | 182 | * @param m_idx モンスターID |
2207 | - * @param ny 移動後の、モンスターのY座標 | |
2208 | - * @param nx 移動後の、モンスターのX座標 | |
183 | + * @param is_riding_mon 騎乗中であればTRUE | |
2209 | 184 | * @return なし |
2210 | - * @details | |
2211 | - * 反攻撃の洞窟など、直接攻撃ができない場所では処理をスキップする | |
2212 | 185 | */ |
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) | |
2214 | 187 | { |
2215 | 188 | monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx]; |
2216 | 189 | 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; | |
2237 | 191 | |
2238 | - if (!target_ptr->riding || one_in_(2)) | |
192 | + if (rakuba(target_ptr, 0, TRUE)) | |
2239 | 193 | { |
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 | |
2243 | 201 | } |
2244 | 202 | } |
2245 | 203 | |
2246 | 204 | |
2247 | 205 | /*! |
2248 | - * @brief モンスターからモンスターへの攻撃処理 | |
206 | + * @brief 召喚の親元が消滅した時、子供も消滅させる | |
2249 | 207 | * @param target_ptr プレーヤーへの参照ポインタ |
2250 | - * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ | |
2251 | 208 | * @param m_idx モンスターID |
2252 | - * @param g_ptr グリッドへの参照ポインタ | |
2253 | - * @param can_cross モンスターが地形を踏破できるならばTRUE | |
2254 | - * @return ターン消費が発生したらTRUE | |
209 | + * @param see_m モンスターが視界内にいたらTRUE | |
210 | + * @return 召喚モンスターが消滅したらTRUE | |
2255 | 211 | */ |
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) | |
2257 | 213 | { |
2258 | 214 | 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) | |
2270 | 219 | { |
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); | |
2272 | 223 | } |
2273 | 224 | |
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) | |
2278 | 226 | { |
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); | |
2282 | 230 | } |
2283 | 231 | |
2284 | - return FALSE; | |
232 | + delete_monster_idx(target_ptr, m_idx); | |
233 | + return TRUE; | |
2285 | 234 | } |
2286 | 235 | |
2287 | 236 | |
2288 | 237 | /*! |
2289 | - * @brief モンスターからモンスターへの直接攻撃を実行する | |
238 | + * @brief 寝ているモンスターの起床を判定する | |
2290 | 239 | * @param target_ptr プレーヤーへの参照ポインタ |
2291 | 240 | * @param m_idx モンスターID |
2292 | - * @param g_ptr グリッドへの参照ポインタ | |
241 | + * @return なし | |
2293 | 242 | */ |
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) | |
2295 | 244 | { |
2296 | 245 | monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx]; |
2297 | 246 | 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; | |
2310 | 249 | |
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 | + } | |
2313 | 257 | |
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 | + } | |
2315 | 262 | } |
2316 | 263 | |
2317 | 264 | |
2318 | 265 | /*! |
2319 | - * @brief モンスターが壁を掘った後続処理を実行する | |
266 | + * @brief モンスターの怒り状態を判定する (起こっていたら敵に回す) | |
2320 | 267 | * @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 なし | |
2326 | 271 | */ |
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) | |
2328 | 273 | { |
274 | + monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx]; | |
2329 | 275 | 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; | |
2335 | 279 | |
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))) | |
2337 | 282 | { |
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; | |
2342 | 284 | } |
2343 | 285 | |
2344 | - cave_alter_feat(target_ptr, ny, nx, FF_HURT_DISI); | |
286 | + if (target_ptr->phase_out || !gets_angry) return; | |
2345 | 287 | |
2346 | - if (!monster_is_valid(m_ptr)) | |
288 | + if (is_pet(m_ptr) || see_m) | |
2347 | 289 | { |
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); | |
2353 | 293 | } |
2354 | 294 | |
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); | |
2359 | 296 | } |
2360 | 297 | |
2361 | 298 | |
2362 | 299 | /*! |
2363 | - * @brief 騎乗中のモンスター情報を更新する | |
300 | + * @brief 手榴弾の爆発処理 | |
2364 | 301 | * @param target_ptr プレーヤーへの参照ポインタ |
2365 | - * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ | |
2366 | 302 | * @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 | |
2372 | 304 | */ |
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) | |
2374 | 306 | { |
2375 | 307 | 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; | |
2390 | 309 | |
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; | |
2399 | 313 | } |
2400 | 314 | |
2401 | 315 | |
2402 | 316 | /*! |
2403 | - * @brief モンスターの移動に伴うオブジェクト処理 (アイテム破壊等) | |
317 | + * @brief モンスター依存の特別な行動を取らせる | |
2404 | 318 | * @param target_ptr プレーヤーへの参照ポインタ |
2405 | - * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ | |
2406 | 319 | * @param m_idx モンスターID |
2407 | - * @param ny 移動後の、モンスターのY座標 | |
2408 | - * @param nx 移動後の、モンスターのX座標 | |
320 | + * @return なし | |
2409 | 321 | */ |
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) | |
2411 | 323 | { |
2412 | 324 | monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx]; |
2413 | 325 | 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; | |
2416 | 330 | |
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; | |
2425 | 334 | |
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))) | |
2427 | 338 | { |
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++; | |
2431 | 340 | } |
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); | |
2443 | 341 | } |
2444 | -} | |
2445 | 342 | |
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); | |
2475 | 344 | } |
2476 | 345 | |
2477 | 346 | |
2478 | 347 | /*! |
2479 | - * @brief モンスターがアイテムを拾うか壊す処理 | |
348 | + * @brief モンスターを分裂させるかどうかを決定する (分裂もさせる) | |
2480 | 349 | * @param target_ptr プレーヤーへの参照ポインタ |
2481 | - * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ | |
2482 | 350 | * @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を返す | |
2491 | 354 | */ |
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) | |
2493 | 356 | { |
2494 | 357 | monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx]; |
2495 | 358 | 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; | |
2509 | 361 | |
2510 | - if (turn_flags_ptr->do_take) | |
362 | + int k = 0; | |
363 | + for (POSITION y = oy - 1; y <= oy + 1; y++) | |
2511 | 364 | { |
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++) | |
2514 | 366 | { |
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++; | |
2516 | 369 | } |
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; | |
2525 | 370 | } |
2526 | 371 | |
2527 | - if (is_pet(m_ptr)) return; | |
372 | + if (multiply_barrier(target_ptr, m_idx)) k = 8; | |
2528 | 373 | |
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))) | |
2531 | 375 | { |
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 | + } | |
2533 | 385 | } |
2534 | 386 | |
2535 | - delete_object_idx(target_ptr, this_o_idx); | |
387 | + return FALSE; | |
2536 | 388 | } |
2537 | 389 | |
2538 | 390 | |
2539 | 391 | /*! |
2540 | - * @brief updateフィールドを更新する | |
392 | + * @brief モンスターに魔法を試行させる | |
2541 | 393 | * @param target_ptr プレーヤーへの参照ポインタ |
2542 | - * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ | |
2543 | - * @return なし | |
394 | + * @param m_idx モンスターID | |
395 | + * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE | |
396 | + * @return 魔法を唱えられなければ強制的にFALSE、その後モンスターが実際に魔法を唱えればTRUE | |
2544 | 397 | */ |
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) | |
2546 | 399 | { |
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) | |
2548 | 407 | { |
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 | + } | |
2551 | 414 | } |
2552 | 415 | |
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 | |
2555 | 422 | { |
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; | |
2557 | 425 | } |
2558 | -} | |
2559 | 426 | |
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; | |
2580 | 428 | } |
2581 | 429 | |
2582 | 430 |
@@ -2647,7 +495,7 @@ void process_monsters(player_type *target_ptr) | ||
2647 | 495 | floor_ptr->monster_noise = FALSE; |
2648 | 496 | |
2649 | 497 | 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); | |
2651 | 499 | sweep_monster_process(target_ptr); |
2652 | 500 | |
2653 | 501 | hack_m_idx = 0; |
@@ -2659,59 +507,6 @@ void process_monsters(player_type *target_ptr) | ||
2659 | 507 | |
2660 | 508 | |
2661 | 509 | /*! |
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 | -/*! | |
2715 | 510 | * @brief フロア内のモンスターについてターン終了時の処理を繰り返す |
2716 | 511 | * @param target_ptr プレーヤーへの参照ポインタ |
2717 | 512 | */ |
@@ -2736,7 +531,7 @@ void sweep_monster_process(player_type *target_ptr) | ||
2736 | 531 | if (m_ptr->cdis >= AAF_LIMIT) continue; |
2737 | 532 | if (!decide_process_continue(target_ptr, m_ptr)) continue; |
2738 | 533 | |
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); | |
2740 | 535 | m_ptr->energy_need -= SPEED_TO_ENERGY(speed); |
2741 | 536 | if (m_ptr->energy_need > 0) continue; |
2742 | 537 |
@@ -2781,57 +576,3 @@ bool decide_process_continue(player_type *target_ptr, monster_type *m_ptr) | ||
2781 | 576 | |
2782 | 577 | return FALSE; |
2783 | 578 | } |
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 | -} |
@@ -1,5 +1,4 @@ | ||
1 | 1 | #pragma once |
2 | 2 | |
3 | -/* monster-process.c */ | |
4 | 3 | extern void process_monsters(player_type *target_ptr); |
5 | 4 | extern void process_monster(player_type *target_ptr, MONSTER_IDX m_idx); |
@@ -328,7 +328,7 @@ extern void set_rf_masks(BIT_FLAGS *f4, BIT_FLAGS *f5, BIT_FLAGS *f6, BIT_FLAGS | ||
328 | 328 | /* mspells4.c */ |
329 | 329 | extern bool spell_learnable(player_type *target_ptr, MONSTER_IDX m_idx); |
330 | 330 | 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); | |
332 | 332 | extern HIT_POINT monspell_damage(player_type *target_ptr, int SPELL_NUM, MONSTER_IDX m_idx, int TYPE); |
333 | 333 | extern HIT_POINT monspell_race_damage(player_type *target_ptr, int SPELL_NUM, MONRACE_IDX r_idx, int TYPE); |
334 | 334 | extern HIT_POINT monspell_bluemage_damage(player_type *target_ptr, int SPELL_NUM, PLAYER_LEVEL plev, int TYPE); |
@@ -35,9 +35,7 @@ extern MONSTER_IDX hack_m_idx_ii; | ||
35 | 35 | */ |
36 | 36 | |
37 | 37 | typedef struct floor_type floor_type; |
38 | -typedef struct monster_type monster_type; | |
39 | - | |
40 | -struct monster_type | |
38 | +typedef struct | |
41 | 39 | { |
42 | 40 | MONRACE_IDX r_idx; /* Monster race index 0 = dead. */ |
43 | 41 | MONRACE_IDX ap_r_idx; /* Monster race appearance index */ |
@@ -128,13 +126,11 @@ struct monster_type | ||
128 | 126 | #define SM_IMM_MANA 0x80000000 /*!< モンスターの学習フラグ: プレイヤーにMPがない */ |
129 | 127 | |
130 | 128 | MONSTER_IDX parent_m_idx; |
131 | -}; | |
129 | +} monster_type; | |
132 | 130 | |
133 | 131 | #define MON_BEGGAR 12 |
134 | 132 | #define MON_LEPER 13 |
135 | -#define MON_BLACK_MARKET 14 | |
136 | 133 | #define MON_LION_HEART 19 |
137 | -#define MON_GHB 39 | |
138 | 134 | #define MON_NOV_PRIEST 45 |
139 | 135 | #define MON_GRIP 53 |
140 | 136 | #define MON_WOLF 54 |
@@ -143,13 +139,10 @@ struct monster_type | ||
143 | 139 | #define MON_PIRANHA 70 |
144 | 140 | #define MON_COPPER_COINS 85 |
145 | 141 | #define MON_NOV_PALADIN 97 |
146 | -#define MON_GREEN_G 100 | |
147 | 142 | #define MON_NOV_PRIEST_G 109 |
148 | 143 | #define MON_SILVER_COINS 117 |
149 | 144 | #define MON_D_ELF 122 |
150 | 145 | #define MON_MANES 128 |
151 | -#define MON_LOST_SOUL 133 | |
152 | -#define MON_ROBIN_HOOD 138 | |
153 | 146 | #define MON_NOV_PALADIN_G 147 |
154 | 147 | #define MON_PHANTOM_W 152 |
155 | 148 | #define MON_WOUNDED_BEAR 159 |
@@ -157,98 +150,41 @@ struct monster_type | ||
157 | 150 | #define MON_D_ELF_WARRIOR 182 |
158 | 151 | #define MON_BLUE_HORROR 189 |
159 | 152 | #define MON_GOLD_COINS 195 |
160 | -#define MON_VORPAL_BUNNY 205 | |
161 | 153 | #define MON_MASTER_YEEK 224 |
162 | 154 | #define MON_PRIEST 225 |
163 | 155 | #define MON_D_ELF_PRIEST 226 |
164 | -#define MON_TIGER 230 | |
165 | 156 | #define MON_MITHRIL_COINS 239 |
166 | -#define MON_DRUID 241 | |
167 | 157 | #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 | |
173 | 158 | #define MON_IMP 296 |
174 | -#define MON_SHAGRAT 314 | |
175 | -#define MON_GORBAG 315 | |
176 | -#define MON_STONE_GIANT 321 | |
177 | 159 | #define MON_LIZARD_KING 332 |
178 | 160 | #define MON_WYVERN 334 |
179 | 161 | #define MON_SABRE_TIGER 339 |
180 | 162 | #define MON_D_ELF_LORD 348 |
181 | -#define MON_FIRE_VOR 354 | |
182 | -#define MON_WATER_VOR 355 | |
183 | 163 | #define MON_ARCH_VILE 357 |
184 | -#define MON_COLD_VOR 358 | |
185 | -#define MON_ENERGY_VOR 359 | |
186 | -#define MON_IRON_GOLEM 367 | |
187 | 164 | #define MON_JADE_MONK 370 |
188 | 165 | #define MON_D_ELF_WARLOCK 375 |
189 | -#define MON_HAGEN 383 | |
190 | 166 | #define MON_MENELDOR 384 |
191 | 167 | #define MON_PHANTOM_B 385 |
192 | -#define MON_C_CRAWLER 395 | |
193 | -#define MON_XICLOTLAN 396 | |
194 | 168 | #define MON_D_ELF_DRUID 400 |
195 | -#define MON_TROLL_PRIEST 403 | |
196 | 169 | #define MON_GWAIHIR 410 |
197 | -#define MON_ANGEL 417 | |
198 | 170 | #define MON_ADAMANT_COINS 423 |
199 | 171 | #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 | |
204 | 172 | #define MON_MITHRIL_GOLEM 464 |
205 | 173 | #define MON_THORONDOR 468 |
206 | -#define MON_SHADOW_DRAKE 471 | |
207 | -#define MON_GHOST 477 | |
208 | -#define MON_OGRE_SHAMAN 479 | |
209 | 174 | #define MON_GHOUL_KING 483 |
210 | 175 | #define MON_NINJA 485 |
211 | 176 | #define MON_BICLOPS 490 |
212 | 177 | #define MON_IVORY_MONK 492 |
213 | -#define MON_LOG_MASTER 498 | |
214 | -#define MON_ETHER_DRAKE 504 | |
215 | 178 | #define MON_GOEMON 505 |
216 | -#define MON_CHERUB 511 | |
217 | 179 | #define MON_WATER_ELEM 512 |
218 | -#define MON_JURT 517 | |
219 | -#define MON_LICH 518 | |
220 | 180 | #define MON_BLOODLETTER 523 |
221 | -#define MON_HALFLING_S 539 | |
222 | -#define MON_GRAV_HOUND 540 | |
223 | -#define MON_REVENANT 555 | |
224 | 181 | #define MON_RAAL 557 |
225 | -#define MON_COLOSSUS 558 | |
226 | 182 | #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 | |
236 | 183 | #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 | |
241 | 184 | #define MON_G_C_DRAKE 646 |
242 | -#define MON_CLUB_DEMON 648 | |
243 | 185 | #define MON_F_ANGEL 652 |
244 | 186 | #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 | |
249 | 187 | #define MON_IRON_LICH 666 |
250 | -#define MON_JACK_SHADOWS 670 | |
251 | -#define MON_LLOIGOR 682 | |
252 | 188 | #define MON_DREADMASTER 690 |
253 | 189 | #define MON_DROLEM 691 |
254 | 190 | #define MON_DAWN 693 |
@@ -260,89 +196,37 @@ struct monster_type | ||
260 | 196 | #define MON_S_TYRANNO 705 |
261 | 197 | #define MON_FAFNER 712 |
262 | 198 | #define MON_G_BALROG 720 |
263 | -#define MON_TIME_HOUND 725 | |
264 | -#define MON_PLASMA_HOUND 726 | |
265 | 199 | #define MON_BULLGATES 732 |
266 | -#define MON_SANTACLAUS 733 | |
267 | 200 | #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 | |
275 | 201 | #define MON_NIGHTWALKER 768 |
276 | -#define MON_RAPHAEL 769 | |
277 | -#define MON_SARUMAN 771 | |
278 | -#define MON_GANDALF 772 | |
279 | -#define MON_BRAND 773 | |
280 | 202 | #define MON_SHADOWLORD 774 |
281 | -#define MON_ARCHLICH 776 | |
282 | 203 | #define MON_JABBERWOCK 778 |
283 | -#define MON_CHAOS_HOUND 779 | |
284 | 204 | #define MON_ULT_BEHOLDER 781 |
285 | 205 | #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 | |
290 | 206 | #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 | |
299 | 207 | #define MON_UNMAKER 815 |
300 | 208 | #define MON_CYBER 816 |
301 | -#define MON_KLING 819 | |
302 | -#define MON_CORWIN 820 | |
303 | 209 | #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 | |
311 | 210 | #define MON_WYRM_POWER 847 |
312 | -#define MON_NODENS 849 | |
313 | 211 | #define MON_JORMUNGAND 854 |
314 | -#define MON_DESTROYER 855 | |
315 | -#define MON_GOTHMOG 856 | |
316 | -#define MON_G_CTHULHU 857 | |
317 | 212 | #define MON_SAURON 858 |
318 | 213 | #define MON_UNICORN_ORD 859 |
319 | 214 | #define MON_OBERON 860 |
320 | 215 | #define MON_MORGOTH 861 |
321 | 216 | #define MON_SERPENT 862 |
322 | 217 | #define MON_ONE_RING 864 |
323 | -#define MON_CAAWS 866 | |
324 | -#define MON_CULVERIN 867 | |
325 | 218 | #define MON_EBONY_MONK 870 |
326 | 219 | #define MON_HAGURE 871 |
327 | -#define MON_OROCHI 872 | |
328 | -#define MON_ECHIZEN 873 | |
329 | -#define MON_SPECT_WYRM 874 | |
330 | 220 | #define MON_DIO 878 |
331 | 221 | #define MON_OHMU 879 |
332 | 222 | #define MON_WONG 880 |
333 | 223 | #define MON_ZOMBI_SERPENT 883 |
334 | 224 | #define MON_D_ELF_SHADE 886 |
335 | -#define MON_MANA_HOUND 887 | |
336 | -#define MON_VENOM_WYRM 890 | |
337 | 225 | #define MON_TROLL_KING 894 |
338 | -#define MON_BAZOOKER 896 | |
339 | -#define MON_SHARD_VOR 897 | |
340 | 226 | #define MON_ELF_LORD 900 |
341 | -#define MON_MASTER_MYS 916 | |
342 | 227 | #define MON_G_MASTER_MYS 917 |
343 | 228 | #define MON_IE 921 |
344 | 229 | #define MON_TSUCHINOKO 926 |
345 | -#define MON_GCWADL 929 | |
346 | 230 | #define MON_LOCKE_CLONE 930 |
347 | 231 | #define MON_CALDARM 931 |
348 | 232 | #define MON_BANORLUPART 932 |
@@ -350,10 +234,7 @@ struct monster_type | ||
350 | 234 | #define MON_LUPART 934 |
351 | 235 | #define MON_KENSHIROU 936 |
352 | 236 | #define MON_W_KNIGHT 938 |
353 | -#define MON_PLANETAR 942 | |
354 | -#define MON_SOLAR 943 | |
355 | 237 | #define MON_BIKETAL 945 |
356 | -#define MON_RICH 948 | |
357 | 238 | #define MON_IKETA 949 |
358 | 239 | #define MON_B_DEATH_SWORD 953 |
359 | 240 | #define MON_YASE_HORSE 955 |
@@ -361,22 +242,14 @@ struct monster_type | ||
361 | 242 | #define MON_BOTEI 963 |
362 | 243 | #define MON_KAGE 964 |
363 | 244 | #define MON_JAIAN 967 |
364 | -#define MON_BELD 973 | |
365 | -#define MON_THAT_BAT 975 | |
366 | -#define MON_SHUTEN 979 | |
367 | 245 | #define MON_FENGHUANG 988 |
368 | -#define MON_KIRIN 989 | |
369 | -#define MON_BAHAMUT 1000 | |
370 | 246 | #define MON_SUKE 1001 |
371 | 247 | #define MON_KAKU 1002 |
372 | -#define MON_GHOST_Q 1003 | |
373 | -#define MON_PIP 1004 | |
374 | 248 | #define MON_A_GOLD 1010 |
375 | 249 | #define MON_A_SILVER 1011 |
376 | 250 | #define MON_ROLENTO 1013 |
377 | 251 | #define MON_RAOU 1018 |
378 | -#define MON_SHURYUUDAN 1023 | |
379 | -#define MON_WAHHA 1031 | |
252 | +#define MON_GRENADE 1023 | |
380 | 253 | #define MON_DEBBY 1032 |
381 | 254 | #define MON_KNI_TEMPLAR 1037 |
382 | 255 | #define MON_PALADIN 1038 |
@@ -394,8 +267,6 @@ struct monster_type | ||
394 | 267 | #define MON_JIZOTAKO 1065 |
395 | 268 | #define MON_TANUKI 1067 |
396 | 269 | #define MON_ALIEN_JURAL 1082 |
397 | -#define MON_HATOPOPPO 1083 | |
398 | -#define MON_KOGAN 1096 | |
399 | 270 | |
400 | 271 | /* |
401 | 272 | * Bit flags for the place_monster_???() (etc) |
@@ -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 | +} |
@@ -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); |
@@ -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 | +} |
@@ -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); |
@@ -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 | +} |
@@ -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); |
@@ -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 | +} |
@@ -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); |
@@ -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 | +} |
@@ -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); |
@@ -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 | +} |
@@ -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); |
@@ -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 | +} |
@@ -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 |
@@ -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 | +} |
@@ -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); |
@@ -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 | +} |
@@ -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); |
@@ -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 | +} |
@@ -0,0 +1,3 @@ | ||
1 | +#pragma once | |
2 | + | |
3 | +bool process_quantum_effect(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m); |
@@ -697,7 +697,7 @@ bool monst_spell_monst(player_type *target_ptr, MONSTER_IDX m_idx) | ||
697 | 697 | |
698 | 698 | can_remember = is_original_ap_and_seen(target_ptr, m_ptr); |
699 | 699 | |
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); | |
701 | 701 | if (dam < 0) return FALSE; |
702 | 702 | |
703 | 703 | bool is_special_magic = m_ptr->ml; |
@@ -1803,6 +1803,7 @@ void learn_spell(player_type *learner_ptr, int monspell) | ||
1803 | 1803 | |
1804 | 1804 | |
1805 | 1805 | /*! |
1806 | + * todo f4, f5, f6を構造体にまとめ直す | |
1806 | 1807 | * @brief モンスター特殊能力のフラグ配列から特定条件の魔法だけを抜き出す処理 |
1807 | 1808 | * Extract monster spells mask for the given mode |
1808 | 1809 | * @param f4 モンスター特殊能力の4番目のフラグ配列 |
@@ -1992,9 +1992,10 @@ void spell_RF6_INVULNER(player_type *target_ptr, MONSTER_IDX m_idx, MONSTER_IDX | ||
1992 | 1992 | * @brief RF6_BLINKの処理。ショート・テレポート。 / |
1993 | 1993 | * @param target_ptr プレーヤーへの参照ポインタ |
1994 | 1994 | * @param m_idx 呪文を唱えるモンスターID |
1995 | +* @param is_quantum_effect 量子的効果によるショート・テレポートの場合時TRUE | |
1995 | 1996 | * @param TARGET_TYPE プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER |
1996 | 1997 | */ |
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) | |
1998 | 1999 | { |
1999 | 2000 | GAME_TEXT m_name[MAX_NLEN]; |
2000 | 2001 | 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 | ||
2003 | 2004 | disturb(target_ptr, TRUE, TRUE); |
2004 | 2005 | |
2005 | 2006 | 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)) | |
2007 | 2008 | { |
2008 | 2009 | if (see_monster(floor_ptr, m_idx)) |
2009 | 2010 | msg_format(_("魔法のバリアが%^sのテレポートを邪魔した。", |
@@ -2163,7 +2164,7 @@ HIT_POINT spell_RF6_SPECIAL_ROLENTO(player_type *target_ptr, POSITION y, POSITIO | ||
2163 | 2164 | |
2164 | 2165 | for (k = 0; k < num; k++) |
2165 | 2166 | { |
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); | |
2167 | 2168 | } |
2168 | 2169 | if (target_ptr->blind && count) |
2169 | 2170 | { |
@@ -3691,7 +3692,7 @@ HIT_POINT monspell_to_player(player_type *target_ptr, int SPELL_NUM, POSITION y, | ||
3691 | 3692 | case RF6_SPELL_START + 1: return spell_RF6_HAND_DOOM(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_HAND_DOOM */ |
3692 | 3693 | case RF6_SPELL_START + 2: spell_RF6_HEAL(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); break; /* RF6_HEAL */ |
3693 | 3694 | 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 */ | |
3695 | 3696 | case RF6_SPELL_START + 5: spell_RF6_TPORT(target_ptr, m_idx, MONSTER_TO_PLAYER); break; /* RF6_TPORT */ |
3696 | 3697 | case RF6_SPELL_START + 6: return spell_RF6_WORLD(target_ptr, m_idx); break; /* RF6_WORLD */ |
3697 | 3698 | 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, | ||
3734 | 3735 | * @param x 対象の地点のx座標 |
3735 | 3736 | * @param m_idx 呪文を唱えるモンスターID |
3736 | 3737 | * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。 |
3738 | +* @param is_special_spell 特殊な行動である時TRUE | |
3737 | 3739 | * @return 攻撃呪文のダメージ、または召喚したモンスターの数を返す。その他の場合0。以降の処理を中断するなら-1を返す。 |
3738 | 3740 | */ |
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) | |
3740 | 3742 | { |
3741 | 3743 | switch (SPELL_NUM) |
3742 | 3744 | { |
@@ -3808,7 +3810,7 @@ HIT_POINT monspell_to_monster(player_type *target_ptr, int SPELL_NUM, POSITION y | ||
3808 | 3810 | case RF6_SPELL_START + 1: return spell_RF6_HAND_DOOM(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_HAND_DOOM */ |
3809 | 3811 | case RF6_SPELL_START + 2: spell_RF6_HEAL(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); break; /* RF6_HEAL */ |
3810 | 3812 | 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 */ | |
3812 | 3814 | case RF6_SPELL_START + 5: spell_RF6_TPORT(target_ptr, m_idx, MONSTER_TO_MONSTER); break; /* RF6_TPORT */ |
3813 | 3815 | case RF6_SPELL_START + 6: return -1; break; /* RF6_WORLD */ |
3814 | 3816 | case RF6_SPELL_START + 7: return spell_RF6_SPECIAL(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_SPECIAL */ |
@@ -369,7 +369,7 @@ static void show_dead_home_items(player_type *creature_ptr) | ||
369 | 369 | * @param file_character ステータスダンプへのコールバック |
370 | 370 | * @return なし |
371 | 371 | */ |
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) | |
373 | 373 | { |
374 | 374 | prt(_("キャラクターの記録をファイルに書き出すことができます。", "You may now dump a character record to one or more files."), 21, 0); |
375 | 375 | 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 | ||
382 | 382 | if (!out_val[0]) break; |
383 | 383 | |
384 | 384 | 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); | |
386 | 386 | screen_load(); |
387 | 387 | } |
388 | 388 | } |
@@ -397,7 +397,7 @@ static void export_player_info(player_type *creature_ptr, display_player_pf disp | ||
397 | 397 | * @param display_player ステータス表示へのコールバック |
398 | 398 | * @return なし |
399 | 399 | */ |
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) | |
401 | 401 | { |
402 | 402 | inventory_aware(creature_ptr); |
403 | 403 | home_aware(creature_ptr); |
@@ -407,7 +407,7 @@ void show_info(player_type *creature_ptr, void(*handle_stuff)(player_type*), voi | ||
407 | 407 | flush(); |
408 | 408 | msg_erase(); |
409 | 409 | |
410 | - export_player_info(creature_ptr, display_player, map_name); | |
410 | + export_player_info(creature_ptr, update_playtime, display_player, map_name); | |
411 | 411 | (*update_playtime)(); |
412 | 412 | (*display_player)(creature_ptr, 0, map_name); |
413 | 413 | prt(_("何かキーを押すとさらに情報が続きます (ESCで中断): ", "Hit any key to see more information (ESC to abort): "), 23, 0); |
@@ -4,4 +4,4 @@ | ||
4 | 4 | #include "files.h" |
5 | 5 | |
6 | 6 | 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); |