OSDN Git Service

[Refactor] #40014 Reshaped process_monster_lore()
[hengband/hengband.git] / src / lore / monster-lore.c
1 /*!
2  * @brief モンスターの思い出表示に必要なフラグ類の処理
3  * @date 2020/06/09
4  * @author Hourier
5  */
6
7 #include "lore/monster-lore.h"
8 #include "locale/english.h"
9 #include "locale/japanese.h"
10 #include "lore/lore-calculator.h"
11 #include "lore/lore-util.h"
12 #include "lore/magic-types-setter.h"
13 #include "monster-race/race-flags-ability1.h"
14 #include "monster-race/race-flags-ability2.h"
15 #include "monster-race/race-flags-resistance.h"
16 #include "monster-race/race-flags1.h"
17 #include "monster-race/race-flags2.h"
18 #include "monster-race/race-flags3.h"
19 #include "monster-race/race-flags4.h"
20 #include "monster-race/race-flags7.h"
21 #include "monster-race/race-indice-types.h"
22 #include "mspell/monster-spell.h"
23 #include "mspell/mspell-damage-calculator.h"
24 #include "mspell/mspell-type.h"
25 #include "term/term-color-types.h"
26 #include "util/util.h"
27 #include "view/display-lore-drops.h"
28 #include "view/display-lore-magics.h"
29 #include "view/display-lore-status.h"
30 #include "view/display-lore.h"
31
32 static void set_msex_flags(lore_type *lore_ptr)
33 {
34     lore_ptr->msex = MSEX_NONE;
35     if (lore_ptr->r_ptr->flags1 & RF1_FEMALE) {
36         lore_ptr->msex = MSEX_FEMALE;
37         return;
38     }
39
40     if (lore_ptr->r_ptr->flags1 & RF1_MALE)
41         lore_ptr->msex = MSEX_MALE;
42 }
43
44 static void set_flags1(lore_type *lore_ptr)
45 {
46     if (lore_ptr->r_ptr->flags1 & RF1_UNIQUE)
47         lore_ptr->flags1 |= (RF1_UNIQUE);
48
49     if (lore_ptr->r_ptr->flags1 & RF1_QUESTOR)
50         lore_ptr->flags1 |= (RF1_QUESTOR);
51
52     if (lore_ptr->r_ptr->flags1 & RF1_MALE)
53         lore_ptr->flags1 |= (RF1_MALE);
54
55     if (lore_ptr->r_ptr->flags1 & RF1_FEMALE)
56         lore_ptr->flags1 |= (RF1_FEMALE);
57
58     if (lore_ptr->r_ptr->flags1 & RF1_FRIENDS)
59         lore_ptr->flags1 |= (RF1_FRIENDS);
60
61     if (lore_ptr->r_ptr->flags1 & RF1_ESCORT)
62         lore_ptr->flags1 |= (RF1_ESCORT);
63
64     if (lore_ptr->r_ptr->flags1 & RF1_ESCORTS)
65         lore_ptr->flags1 |= (RF1_ESCORTS);
66 }
67
68 static void set_race_flags(lore_type *lore_ptr)
69 {
70     if (!lore_ptr->r_ptr->r_tkills && !lore_ptr->know_everything)
71         return;
72
73     if (lore_ptr->r_ptr->flags3 & RF3_ORC)
74         lore_ptr->flags3 |= (RF3_ORC);
75
76     if (lore_ptr->r_ptr->flags3 & RF3_TROLL)
77         lore_ptr->flags3 |= (RF3_TROLL);
78
79     if (lore_ptr->r_ptr->flags3 & RF3_GIANT)
80         lore_ptr->flags3 |= (RF3_GIANT);
81
82     if (lore_ptr->r_ptr->flags3 & RF3_DRAGON)
83         lore_ptr->flags3 |= (RF3_DRAGON);
84
85     if (lore_ptr->r_ptr->flags3 & RF3_DEMON)
86         lore_ptr->flags3 |= (RF3_DEMON);
87
88     if (lore_ptr->r_ptr->flags3 & RF3_UNDEAD)
89         lore_ptr->flags3 |= (RF3_UNDEAD);
90
91     if (lore_ptr->r_ptr->flags3 & RF3_EVIL)
92         lore_ptr->flags3 |= (RF3_EVIL);
93
94     if (lore_ptr->r_ptr->flags3 & RF3_GOOD)
95         lore_ptr->flags3 |= (RF3_GOOD);
96
97     if (lore_ptr->r_ptr->flags3 & RF3_ANIMAL)
98         lore_ptr->flags3 |= (RF3_ANIMAL);
99
100     if (lore_ptr->r_ptr->flags3 & RF3_AMBERITE)
101         lore_ptr->flags3 |= (RF3_AMBERITE);
102
103     if (lore_ptr->r_ptr->flags2 & RF2_HUMAN)
104         lore_ptr->flags2 |= (RF2_HUMAN);
105
106     if (lore_ptr->r_ptr->flags2 & RF2_QUANTUM)
107         lore_ptr->flags2 |= (RF2_QUANTUM);
108
109     if (lore_ptr->r_ptr->flags1 & RF1_FORCE_DEPTH)
110         lore_ptr->flags1 |= (RF1_FORCE_DEPTH);
111
112     if (lore_ptr->r_ptr->flags1 & RF1_FORCE_MAXHP)
113         lore_ptr->flags1 |= (RF1_FORCE_MAXHP);
114 }
115
116 /*!
117  * @brief モンスターの思い出情報を表示するメインルーチン
118  * Hack -- display monster information using "hooked_roff()"
119  * @param r_idx モンスターの種族ID
120  * @param mode 表示オプション
121  * @return なし
122  * @details
123  * This function should only be called with the cursor placed at the
124  * left edge of the screen, on a cleared line, in which the recall is
125  * to take place.  One extra blank line is left after the recall.
126  */
127 void process_monster_lore(player_type *player_ptr, MONRACE_IDX r_idx, BIT_FLAGS mode)
128 {
129     lore_type tmp_lore;
130     lore_type *lore_ptr = initialize_lore_type(&tmp_lore, r_idx, mode);
131     for (int n = 0; n < A_MAX; n++) {
132         if (lore_ptr->r_ptr->reinforce_id[n] > 0)
133             lore_ptr->reinforce = TRUE;
134     }
135
136     if (cheat_know || (mode & 0x01))
137         lore_ptr->know_everything = TRUE;
138
139     set_drop_flags(lore_ptr);
140     set_msex_flags(lore_ptr);
141     set_flags1(lore_ptr);
142     set_race_flags(lore_ptr);
143     display_kill_numbers(lore_ptr);
144     concptr tmp = r_text + lore_ptr->r_ptr->text;
145     if (tmp[0]) {
146         hooked_roff(tmp);
147         hooked_roff("\n");
148     }
149
150     if (r_idx == MON_KAGE) {
151         hooked_roff("\n");
152         return;
153     }
154
155     if (!display_where_to_appear(lore_ptr))
156         return;
157
158     display_monster_move(lore_ptr);
159     display_monster_never_move(lore_ptr);
160     if (lore_ptr->old) {
161         hooked_roff(_("。", ".  "));
162         lore_ptr->old = FALSE;
163     }
164
165     display_lore_this(player_ptr, lore_ptr);
166     display_monster_aura(lore_ptr);
167     if (lore_ptr->flags2 & RF2_REFLECTING)
168         hooked_roff(format(_("%^sは矢の呪文を跳ね返す。", "%^s reflects bolt spells.  "), wd_he[lore_ptr->msex]));
169
170     display_monster_collective(lore_ptr);
171     lore_ptr->vn = 0;
172     if (lore_ptr->flags4 & RF4_SHRIEK) {
173         lore_ptr->vp[lore_ptr->vn] = _("悲鳴で助けを求める", "shriek for help");
174         lore_ptr->color[lore_ptr->vn++] = TERM_L_WHITE;
175     }
176
177     display_monster_launching(player_ptr, lore_ptr);
178     if (lore_ptr->a_ability_flags2 & (RF6_SPECIAL)) {
179         lore_ptr->vp[lore_ptr->vn] = _("特別な行動をする", "do something");
180         lore_ptr->color[lore_ptr->vn++] = TERM_VIOLET;
181     }
182
183     display_monster_sometimes(lore_ptr);
184     set_breath_types(player_ptr, lore_ptr);
185     display_monster_breath(lore_ptr);
186
187     lore_ptr->vn = 0;
188     set_ball_types(player_ptr, lore_ptr);
189     set_particular_types(player_ptr, lore_ptr);
190     set_bolt_types(player_ptr, lore_ptr);
191     set_status_types(lore_ptr);
192     set_teleport_types(lore_ptr);
193     set_floor_types(player_ptr, lore_ptr);
194     set_summon_types(lore_ptr);
195     display_monster_magic_types(lore_ptr);
196     display_mosnter_magic_possibility(lore_ptr);
197     display_monster_hp_ac(lore_ptr);
198
199     lore_ptr->vn = 0;
200     display_monster_concrete_abilities(lore_ptr);
201     display_monster_abilities(lore_ptr);
202     display_monster_constitutions(lore_ptr);
203
204     lore_ptr->vn = 0;
205     display_monster_concrete_weakness(lore_ptr);
206     display_monster_weakness(lore_ptr);
207
208     lore_ptr->vn = 0;
209     display_monster_concrete_resistances(lore_ptr);
210     display_monster_resistances(lore_ptr);
211     display_monster_evolution(lore_ptr);
212
213     lore_ptr->vn = 0;
214     display_monster_concrete_immunities(lore_ptr);
215     display_monster_immunities(lore_ptr);
216     display_monster_alert(lore_ptr);
217     display_monster_drop(lore_ptr);
218
219     const int max_attack_numbers = 4;
220     int count = 0;
221     for (int m = 0; m < max_attack_numbers; m++) {
222         if (!lore_ptr->r_ptr->blow[m].method || (lore_ptr->r_ptr->blow[m].method == RBM_SHOOT))
223             continue;
224
225         if (lore_ptr->r_ptr->r_blows[m] || lore_ptr->know_everything)
226             count++;
227     }
228
229     int attack_numbers = 0;
230     for (int m = 0; m < max_attack_numbers; m++) {
231         if (!lore_ptr->r_ptr->blow[m].method || (lore_ptr->r_ptr->blow[m].method == RBM_SHOOT)
232             || (((lore_ptr->r_ptr->r_blows[m] == 0) && !lore_ptr->know_everything)))
233             continue;
234
235         rbm_type method = lore_ptr->r_ptr->blow[m].method;
236         int effect = lore_ptr->r_ptr->blow[m].effect;
237         int d1 = lore_ptr->r_ptr->blow[m].d_dice;
238         int d2 = lore_ptr->r_ptr->blow[m].d_side;
239
240         concptr p = NULL;
241         switch (method) {
242         case RBM_HIT:
243             p = _("殴る", "hit");
244             break;
245         case RBM_TOUCH:
246             p = _("触る", "touch");
247             break;
248         case RBM_PUNCH:
249             p = _("パンチする", "punch");
250             break;
251         case RBM_KICK:
252             p = _("蹴る", "kick");
253             break;
254         case RBM_CLAW:
255             p = _("ひっかく", "claw");
256             break;
257         case RBM_BITE:
258             p = _("噛む", "bite");
259             break;
260         case RBM_STING:
261             p = _("刺す", "sting");
262             break;
263         case RBM_SLASH:
264             p = _("斬る", "slash");
265             break;
266         case RBM_BUTT:
267             p = _("角で突く", "butt");
268             break;
269         case RBM_CRUSH:
270             p = _("体当たりする", "crush");
271             break;
272         case RBM_ENGULF:
273             p = _("飲み込む", "engulf");
274             break;
275         case RBM_CHARGE:
276             p = _("請求書をよこす", "charge");
277             break;
278         case RBM_CRAWL:
279             p = _("体の上を這い回る", "crawl on you");
280             break;
281         case RBM_DROOL:
282             p = _("よだれをたらす", "drool on you");
283             break;
284         case RBM_SPIT:
285             p = _("つばを吐く", "spit");
286             break;
287         case RBM_EXPLODE:
288             p = _("爆発する", "explode");
289             break;
290         case RBM_GAZE:
291             p = _("にらむ", "gaze");
292             break;
293         case RBM_WAIL:
294             p = _("泣き叫ぶ", "wail");
295             break;
296         case RBM_SPORE:
297             p = _("胞子を飛ばす", "release spores");
298             break;
299         case RBM_XXX4:
300             break;
301         case RBM_BEG:
302             p = _("金をせがむ", "beg");
303             break;
304         case RBM_INSULT:
305             p = _("侮辱する", "insult");
306             break;
307         case RBM_MOAN:
308             p = _("うめく", "moan");
309             break;
310         case RBM_SHOW:
311             p = _("歌う", "sing");
312             break;
313         }
314
315         concptr q = NULL;
316         switch (effect) {
317         case RBE_SUPERHURT:
318             q = _("強力に攻撃する", "slaughter");
319             break;
320         case RBE_HURT:
321             q = _("攻撃する", "attack");
322             break;
323         case RBE_POISON:
324             q = _("毒をくらわす", "poison");
325             break;
326         case RBE_UN_BONUS:
327             q = _("劣化させる", "disenchant");
328             break;
329         case RBE_UN_POWER:
330             q = _("充填魔力を吸収する", "drain charges");
331             break;
332         case RBE_EAT_GOLD:
333             q = _("金を盗む", "steal gold");
334             break;
335         case RBE_EAT_ITEM:
336             q = _("アイテムを盗む", "steal items");
337             break;
338         case RBE_EAT_FOOD:
339             q = _("あなたの食料を食べる", "eat your food");
340             break;
341         case RBE_EAT_LITE:
342             q = _("明かりを吸収する", "absorb light");
343             break;
344         case RBE_ACID:
345             q = _("酸を飛ばす", "shoot acid");
346             break;
347         case RBE_ELEC:
348             q = _("感電させる", "electrocute");
349             break;
350         case RBE_FIRE:
351             q = _("燃やす", "burn");
352             break;
353         case RBE_COLD:
354             q = _("凍らせる", "freeze");
355             break;
356         case RBE_BLIND:
357             q = _("盲目にする", "blind");
358             break;
359         case RBE_CONFUSE:
360             q = _("混乱させる", "confuse");
361             break;
362         case RBE_TERRIFY:
363             q = _("恐怖させる", "terrify");
364             break;
365         case RBE_PARALYZE:
366             q = _("麻痺させる", "paralyze");
367             break;
368         case RBE_LOSE_STR:
369             q = _("腕力を減少させる", "reduce strength");
370             break;
371         case RBE_LOSE_INT:
372             q = _("知能を減少させる", "reduce intelligence");
373             break;
374         case RBE_LOSE_WIS:
375             q = _("賢さを減少させる", "reduce wisdom");
376             break;
377         case RBE_LOSE_DEX:
378             q = _("器用さを減少させる", "reduce dexterity");
379             break;
380         case RBE_LOSE_CON:
381             q = _("耐久力を減少させる", "reduce constitution");
382             break;
383         case RBE_LOSE_CHR:
384             q = _("魅力を減少させる", "reduce charisma");
385             break;
386         case RBE_LOSE_ALL:
387             q = _("全ステータスを減少させる", "reduce all stats");
388             break;
389         case RBE_SHATTER:
390             q = _("粉砕する", "shatter");
391             break;
392         case RBE_EXP_10:
393             q = _("経験値を減少(10d6+)させる", "lower experience (by 10d6+)");
394             break;
395         case RBE_EXP_20:
396             q = _("経験値を減少(20d6+)させる", "lower experience (by 20d6+)");
397             break;
398         case RBE_EXP_40:
399             q = _("経験値を減少(40d6+)させる", "lower experience (by 40d6+)");
400             break;
401         case RBE_EXP_80:
402             q = _("経験値を減少(80d6+)させる", "lower experience (by 80d6+)");
403             break;
404         case RBE_DISEASE:
405             q = _("病気にする", "disease");
406             break;
407         case RBE_TIME:
408             q = _("時間を逆戻りさせる", "time");
409             break;
410         case RBE_DR_LIFE:
411             q = _("生命力を吸収する", "drain life");
412             break;
413         case RBE_DR_MANA:
414             q = _("魔力を奪う", "drain mana force");
415             break;
416         case RBE_INERTIA:
417             q = _("減速させる", "slow");
418             break;
419         case RBE_STUN:
420             q = _("朦朧とさせる", "stun");
421             break;
422         }
423
424 #ifdef JP
425         if (attack_numbers == 0) {
426             hooked_roff(format("%^sは", wd_he[lore_ptr->msex]));
427         }
428
429         if (d1 && d2 && (lore_ptr->know_everything || know_damage(r_idx, m))) {
430             hooked_roff(format(" %dd%d ", d1, d2));
431             hooked_roff("のダメージで");
432         }
433
434         if (!p)
435             p = "何か奇妙なことをする";
436
437         /* XXしてYYし/XXしてYYする/XXし/XXする */
438         if (q != NULL)
439             jverb(p, lore_ptr->jverb_buf, JVERB_TO);
440         else if (attack_numbers != count - 1)
441             jverb(p, lore_ptr->jverb_buf, JVERB_AND);
442         else
443             strcpy(lore_ptr->jverb_buf, p);
444
445         hooked_roff(lore_ptr->jverb_buf);
446         if (q) {
447             if (attack_numbers != count - 1)
448                 jverb(q, lore_ptr->jverb_buf, JVERB_AND);
449             else
450                 strcpy(lore_ptr->jverb_buf, q);
451             hooked_roff(lore_ptr->jverb_buf);
452         }
453
454         if (attack_numbers != count - 1)
455             hooked_roff("、");
456 #else
457         if (attack_numbers == 0) {
458             hooked_roff(format("%^s can ", wd_he[lore_ptr->msex]));
459         } else if (attack_numbers < count - 1) {
460             hooked_roff(", ");
461         } else {
462             hooked_roff(", and ");
463         }
464
465         if (!p)
466             p = "do something weird";
467         hooked_roff(p);
468         if (q) {
469             hooked_roff(" to ");
470             hooked_roff(q);
471             if (d1 && d2 && (lore_ptr->know_everything || know_damage(r_idx, m))) {
472                 hooked_roff(" with damage");
473                 hooked_roff(format(" %dd%d", d1, d2));
474             }
475         }
476 #endif
477
478         attack_numbers++;
479     }
480
481     if (attack_numbers > 0) {
482         hooked_roff(_("。", ".  "));
483     } else if (lore_ptr->flags1 & RF1_NEVER_BLOW) {
484         hooked_roff(format(_("%^sは物理的な攻撃方法を持たない。", "%^s has no physical attacks.  "), wd_he[lore_ptr->msex]));
485     } else {
486         hooked_roff(format(_("%s攻撃については何も知らない。", "Nothing is known about %s attack.  "), wd_his[lore_ptr->msex]));
487     }
488
489     bool is_kingpin = (lore_ptr->flags1 & RF1_QUESTOR) != 0;
490     is_kingpin &= lore_ptr->r_ptr->r_sights > 0;
491     is_kingpin &= lore_ptr->r_ptr->max_num > 0;
492     is_kingpin &= (r_idx == MON_OBERON) || (r_idx == MON_SERPENT);
493     if (is_kingpin) {
494         hook_c_roff(TERM_VIOLET, _("あなたはこのモンスターを殺したいという強い欲望を感じている...", "You feel an intense desire to kill this monster...  "));
495     } else if (lore_ptr->flags7 & RF7_GUARDIAN) {
496         hook_c_roff(TERM_L_RED, _("このモンスターはダンジョンの主である。", "This monster is the master of a dungeon."));
497     }
498
499     hooked_roff("\n");
500 }