OSDN Git Service

[Refactor] #40233 Separated display-store.c/h from store.c
[hengband/hengband.git] / src / view / display-lore.c
1 /*!
2  * @brief モンスターの思い出を表示する処理
3  * @date 2020/06/09
4  * @author Hourier
5  */
6
7 #include "view/display-lore.h"
8 #include "game-option/text-display-options.h"
9 #include "lore/lore-calculator.h"
10 #include "lore/monster-lore.h"
11 #include "monster-race/monster-race.h"
12 #include "monster-race/race-flags1.h"
13 #include "monster-race/race-flags2.h"
14 #include "monster-race/race-flags3.h"
15 #include "monster-race/race-flags4.h"
16 #include "monster-race/race-flags7.h"
17 #include "monster-race/race-indice-types.h"
18 #include "mspell/mspell-type.h"
19 #include "term/screen-processor.h"
20 #include "term/term-color-types.h"
21 #include "view/display-messages.h"
22 #include "world/world.h"
23 #ifdef JP
24 #include "locale/japanese.h"
25 #else
26 #include "locale/english.h"
27 #endif
28
29 /*!
30  * 英語の複数系記述用マクロ / Pluralizer.  Args(count, singular, plural)
31  */
32 #define plural(c, s, p) (((c) == 1) ? (s) : (p))
33
34 /*!
35  * @brief モンスター情報のヘッダを記述する
36  * Hack -- Display the "name" and "attr/chars" of a monster race
37  * @param r_idx モンスターの種族ID
38  * @return なし
39  */
40 void roff_top(MONRACE_IDX r_idx)
41 {
42     monster_race *r_ptr = &r_info[r_idx];
43     char c1 = r_ptr->d_char;
44     char c2 = r_ptr->x_char;
45
46     TERM_COLOR a1 = r_ptr->d_attr;
47     TERM_COLOR a2 = r_ptr->x_attr;
48
49     term_erase(0, 0, 255);
50     term_gotoxy(0, 0);
51
52 #ifdef JP
53 #else
54     if (!(r_ptr->flags1 & RF1_UNIQUE)) {
55         term_addstr(-1, TERM_WHITE, "The ");
56     }
57 #endif
58
59     term_addstr(-1, TERM_WHITE, (r_name + r_ptr->name));
60
61     term_addstr(-1, TERM_WHITE, " ('");
62     term_add_bigch(a1, c1);
63     term_addstr(-1, TERM_WHITE, "')");
64
65     term_addstr(-1, TERM_WHITE, "/('");
66     term_add_bigch(a2, c2);
67     term_addstr(-1, TERM_WHITE, "'):");
68
69     if (!current_world_ptr->wizard)
70         return;
71
72     char buf[16];
73     sprintf(buf, "%d", r_idx);
74     term_addstr(-1, TERM_WHITE, " (");
75     term_addstr(-1, TERM_L_BLUE, buf);
76     term_addch(TERM_WHITE, ')');
77 }
78
79 /*!
80  * @brief  モンスター情報の表示と共に画面を一時消去するサブルーチン /
81  * Hack -- describe the given monster race at the top of the screen
82  * @param r_idx モンスターの種族ID
83  * @param mode 表示オプション
84  * @return なし
85  */
86 void screen_roff(player_type *player_ptr, MONRACE_IDX r_idx, BIT_FLAGS mode)
87 {
88     msg_erase();
89     term_erase(0, 1, 255);
90     hook_c_roff = c_roff;
91     process_monster_lore(player_ptr, r_idx, mode);
92     roff_top(r_idx);
93 }
94
95 /*!
96  * @brief モンスター情報の現在のウィンドウに表示する /
97  * Hack -- describe the given monster race in the current "term" window
98  * @param r_idx モンスターの種族ID
99  * @return なし
100  */
101 void display_roff(player_type *player_ptr)
102 {
103     for (int y = 0; y < Term->hgt; y++) {
104         term_erase(0, y, 255);
105     }
106
107     term_gotoxy(0, 1);
108     hook_c_roff = c_roff;
109     MONRACE_IDX r_idx = player_ptr->monster_race_idx;
110     process_monster_lore(player_ptr, r_idx, 0);
111     roff_top(r_idx);
112 }
113
114 /*!
115  * @brief モンスター詳細情報を自動スポイラー向けに出力する /
116  * Hack -- output description of the given monster race
117  * @param r_idx モンスターの種族ID
118  * @param roff_func 出力処理を行う関数ポインタ
119  * @return なし
120  */
121 void output_monster_spoiler(player_type *player_ptr, MONRACE_IDX r_idx, void (*roff_func)(TERM_COLOR attr, concptr str))
122 {
123     hook_c_roff = roff_func;
124     process_monster_lore(player_ptr, r_idx, 0x03);
125 }
126
127 static bool display_kill_unique(lore_type *lore_ptr)
128 {
129     if ((lore_ptr->flags1 & RF1_UNIQUE) == 0)
130         return FALSE;
131
132     bool dead = (lore_ptr->r_ptr->max_num == 0);
133     if (lore_ptr->r_ptr->r_deaths) {
134         hooked_roff(format(_("%^sはあなたの先祖を %d 人葬っている", "%^s has slain %d of your ancestors"), wd_he[lore_ptr->msex], lore_ptr->r_ptr->r_deaths));
135
136         if (dead) {
137             hooked_roff(
138                 _(format("が、すでに仇討ちは果たしている!"), format(", but you have avenged %s!  ", plural(lore_ptr->r_ptr->r_deaths, "him", "them"))));
139         } else {
140             hooked_roff(
141                 _(format("のに、まだ仇討ちを果たしていない。"), format(", who %s unavenged.  ", plural(lore_ptr->r_ptr->r_deaths, "remains", "remain"))));
142         }
143
144         hooked_roff("\n");
145     } else if (dead) {
146         hooked_roff(_("あなたはこの仇敵をすでに葬り去っている。", "You have slain this foe.  "));
147         hooked_roff("\n");
148     }
149
150     return TRUE;
151 }
152
153 static bool display_killed(lore_type *lore_ptr)
154 {
155     if (lore_ptr->r_ptr->r_deaths == 0)
156         return FALSE;
157
158     hooked_roff(_(format("このモンスターはあなたの先祖を %d 人葬っている", lore_ptr->r_ptr->r_deaths),
159         format("%d of your ancestors %s been killed by this creature, ", lore_ptr->r_ptr->r_deaths, plural(lore_ptr->r_ptr->r_deaths, "has", "have"))));
160
161     if (lore_ptr->r_ptr->r_pkills) {
162         hooked_roff(format(_("が、あなたはこのモンスターを少なくとも %d 体は倒している。", "and you have exterminated at least %d of the creatures.  "),
163             lore_ptr->r_ptr->r_pkills));
164     } else if (lore_ptr->r_ptr->r_tkills) {
165         hooked_roff(format(
166             _("が、あなたの先祖はこのモンスターを少なくとも %d 体は倒している。", "and your ancestors have exterminated at least %d of the creatures.  "),
167             lore_ptr->r_ptr->r_tkills));
168     } else {
169         hooked_roff(format(_("が、まだ%sを倒したことはない。", "and %s is not ever known to have been defeated.  "), wd_he[lore_ptr->msex]));
170     }
171
172     hooked_roff("\n");
173     return TRUE;
174 }
175
176 void display_kill_numbers(lore_type *lore_ptr)
177 {
178     if ((lore_ptr->mode & 0x02) != 0)
179         return;
180
181     if (display_kill_unique(lore_ptr))
182         return;
183
184     if (display_killed(lore_ptr))
185         return;
186
187     if (lore_ptr->r_ptr->r_pkills) {
188         hooked_roff(format(
189             _("あなたはこのモンスターを少なくとも %d 体は殺している。", "You have killed at least %d of these creatures.  "), lore_ptr->r_ptr->r_pkills));
190     } else if (lore_ptr->r_ptr->r_tkills) {
191         hooked_roff(format(_("あなたの先祖はこのモンスターを少なくとも %d 体は殺している。", "Your ancestors have killed at least %d of these creatures.  "),
192             lore_ptr->r_ptr->r_tkills));
193     } else {
194         hooked_roff(_("このモンスターを倒したことはない。", "No battles to the death are recalled.  "));
195     }
196
197     hooked_roff("\n");
198 }
199
200 /*!
201  * @brief どこに出没するかを表示する
202  * @param lore_ptr モンスターの思い出構造体への参照ポインタ
203  * @return たぬきならFALSE、それ以外はTRUE
204  */
205 bool display_where_to_appear(lore_type *lore_ptr)
206 {
207     lore_ptr->old = FALSE;
208     if (lore_ptr->r_ptr->level == 0) {
209         hooked_roff(format(_("%^sは町に住み", "%^s lives in the town"), wd_he[lore_ptr->msex]));
210         lore_ptr->old = TRUE;
211     } else if (lore_ptr->r_ptr->r_tkills || lore_ptr->know_everything) {
212         if (depth_in_feet) {
213             hooked_roff(format(
214                 _("%^sは通常地下 %d フィートで出現し", "%^s is normally found at depths of %d feet"), wd_he[lore_ptr->msex], lore_ptr->r_ptr->level * 50));
215         } else {
216             hooked_roff(format(_("%^sは通常地下 %d 階で出現し", "%^s is normally found on dungeon level %d"), wd_he[lore_ptr->msex], lore_ptr->r_ptr->level));
217         }
218
219         lore_ptr->old = TRUE;
220     }
221
222     if (lore_ptr->r_idx == MON_CHAMELEON) {
223         hooked_roff(_("、他のモンスターに化ける。", "and can take the shape of other monster."));
224         return FALSE;
225     }
226
227     if (lore_ptr->old) {
228         hooked_roff(_("、", ", and "));
229     } else {
230         hooked_roff(format(_("%^sは", "%^s "), wd_he[lore_ptr->msex]));
231         lore_ptr->old = TRUE;
232     }
233
234     return TRUE;
235 }
236
237 void display_monster_move(lore_type *lore_ptr)
238 {
239 #ifdef JP
240 #else
241     hooked_roff("moves");
242 #endif
243
244     display_random_move(lore_ptr);
245     if (lore_ptr->speed > 110) {
246         if (lore_ptr->speed > 139)
247             hook_c_roff(TERM_RED, _("信じ難いほど", " incredibly"));
248         else if (lore_ptr->speed > 134)
249             hook_c_roff(TERM_ORANGE, _("猛烈に", " extremely"));
250         else if (lore_ptr->speed > 129)
251             hook_c_roff(TERM_ORANGE, _("非常に", " very"));
252         else if (lore_ptr->speed > 124)
253             hook_c_roff(TERM_UMBER, _("かなり", " fairly"));
254         else if (lore_ptr->speed < 120)
255             hook_c_roff(TERM_L_UMBER, _("やや", " somewhat"));
256         hook_c_roff(TERM_L_RED, _("素早く", " quickly"));
257     } else if (lore_ptr->speed < 110) {
258         if (lore_ptr->speed < 90)
259             hook_c_roff(TERM_L_GREEN, _("信じ難いほど", " incredibly"));
260         else if (lore_ptr->speed < 95)
261             hook_c_roff(TERM_BLUE, _("非常に", " very"));
262         else if (lore_ptr->speed < 100)
263             hook_c_roff(TERM_BLUE, _("かなり", " fairly"));
264         else if (lore_ptr->speed > 104)
265             hook_c_roff(TERM_GREEN, _("やや", " somewhat"));
266         hook_c_roff(TERM_L_BLUE, _("ゆっくりと", " slowly"));
267     } else {
268         hooked_roff(_("普通の速さで", " at normal speed"));
269     }
270
271 #ifdef JP
272     hooked_roff("動いている");
273 #endif
274 }
275
276 void display_random_move(lore_type *lore_ptr)
277 {
278     if (((lore_ptr->flags1 & RF1_RAND_50) == 0) && ((lore_ptr->flags1 & RF1_RAND_25) == 0))
279         return;
280
281     if ((lore_ptr->flags1 & RF1_RAND_50) && (lore_ptr->flags1 & RF1_RAND_25)) {
282         hooked_roff(_("かなり", " extremely"));
283     } else if (lore_ptr->flags1 & RF1_RAND_50) {
284         hooked_roff(_("幾分", " somewhat"));
285     } else if (lore_ptr->flags1 & RF1_RAND_25) {
286         hooked_roff(_("少々", " a bit"));
287     }
288
289     hooked_roff(_("不規則に", " erratically"));
290     if (lore_ptr->speed != 110)
291         hooked_roff(_("、かつ", ", and"));
292 }
293
294 void display_monster_never_move(lore_type *lore_ptr)
295 {
296     if ((lore_ptr->flags1 & RF1_NEVER_MOVE) == 0)
297         return;
298
299     if (lore_ptr->old) {
300         hooked_roff(_("、しかし", ", but "));
301     } else {
302         hooked_roff(format(_("%^sは", "%^s "), wd_he[lore_ptr->msex]));
303         lore_ptr->old = TRUE;
304     }
305
306     hooked_roff(_("侵入者を追跡しない", "does not deign to chase intruders"));
307 }
308
309 void display_monster_kind(lore_type *lore_ptr)
310 {
311     if (((lore_ptr->flags3 & (RF3_DRAGON | RF3_DEMON | RF3_GIANT | RF3_TROLL | RF3_ORC | RF3_ANGEL)) == 0) && ((lore_ptr->flags2 & (RF2_QUANTUM | RF2_HUMAN)) == 0)) {
312         hooked_roff(_("モンスター", " creature"));
313         return;
314     }
315
316     if (lore_ptr->flags3 & RF3_DRAGON)
317         hook_c_roff(TERM_ORANGE, _("ドラゴン", " dragon"));
318
319     if (lore_ptr->flags3 & RF3_DEMON)
320         hook_c_roff(TERM_VIOLET, _("デーモン", " demon"));
321
322     if (lore_ptr->flags3 & RF3_GIANT)
323         hook_c_roff(TERM_L_UMBER, _("巨人", " giant"));
324
325     if (lore_ptr->flags3 & RF3_TROLL)
326         hook_c_roff(TERM_BLUE, _("トロル", " troll"));
327
328     if (lore_ptr->flags3 & RF3_ORC)
329         hook_c_roff(TERM_UMBER, _("オーク", " orc"));
330
331     if (lore_ptr->flags2 & RF2_HUMAN)
332         hook_c_roff(TERM_L_WHITE, _("人間", " human"));
333
334     if (lore_ptr->flags2 & RF2_QUANTUM)
335         hook_c_roff(TERM_VIOLET, _("量子生物", " quantum creature"));
336
337     if (lore_ptr->flags3 & RF3_ANGEL)
338         hook_c_roff(TERM_YELLOW, _("天使", " angel"));
339 }
340
341 void display_monster_alignment(lore_type *lore_ptr)
342 {
343     if (lore_ptr->flags2 & RF2_ELDRITCH_HORROR)
344         hook_c_roff(TERM_VIOLET, _("狂気を誘う", " sanity-blasting"));
345
346     if (lore_ptr->flags3 & RF3_ANIMAL)
347         hook_c_roff(TERM_L_GREEN, _("自然界の", " natural"));
348
349     if (lore_ptr->flags3 & RF3_EVIL)
350         hook_c_roff(TERM_L_DARK, _("邪悪なる", " evil"));
351
352     if (lore_ptr->flags3 & RF3_GOOD)
353         hook_c_roff(TERM_YELLOW, _("善良な", " good"));
354
355     if (lore_ptr->flags3 & RF3_UNDEAD)
356         hook_c_roff(TERM_VIOLET, _("アンデッドの", " undead"));
357
358     if (lore_ptr->flags3 & RF3_AMBERITE)
359         hook_c_roff(TERM_VIOLET, _("アンバーの王族の", " Amberite"));
360 }
361
362 void display_monster_exp(player_type *player_ptr, lore_type *lore_ptr)
363 {
364 #ifdef JP
365     hooked_roff("を倒すことは");
366 #endif
367     long exp_integer = (long)lore_ptr->r_ptr->mexp * lore_ptr->r_ptr->level / (player_ptr->max_plv + 2) * 3 / 2;
368     long exp_decimal
369         = ((((long)lore_ptr->r_ptr->mexp * lore_ptr->r_ptr->level % (player_ptr->max_plv + 2) * 3 / 2) * (long)1000 / (player_ptr->max_plv + 2) + 5) / 10);
370
371 #ifdef JP
372     hooked_roff(format(" %d レベルのキャラクタにとって 約%ld.%02ld ポイントの経験となる。", player_ptr->lev, (long)exp_integer, (long)exp_decimal));
373 #else
374     hooked_roff(format(" is worth about %ld.%02ld point%s", (long)exp_integer, (long)exp_decimal, ((exp_integer == 1) && (exp_decimal == 0)) ? "" : "s"));
375
376     char *ordinal;
377     ordinal = "th";
378     exp_integer = player_ptr->lev % 10;
379     if ((player_ptr->lev / 10) != 1) {
380         if (exp_integer == 1)
381             ordinal = "st";
382         else if (exp_integer == 2)
383             ordinal = "nd";
384         else if (exp_integer == 3)
385             ordinal = "rd";
386     }
387
388     char *vowel;
389     vowel = "";
390     exp_integer = player_ptr->lev;
391     if ((exp_integer == 8) || (exp_integer == 11) || (exp_integer == 18))
392         vowel = "n";
393
394     hooked_roff(format(" for a%s %lu%s level character.  ", vowel, (long)exp_integer, ordinal));
395 #endif
396 }
397
398 void display_monster_aura(lore_type *lore_ptr)
399 {
400     if ((lore_ptr->flags2 & RF2_AURA_FIRE) && (lore_ptr->flags2 & RF2_AURA_ELEC) && (lore_ptr->flags3 & RF3_AURA_COLD))
401         hook_c_roff(
402             TERM_VIOLET, format(_("%^sは炎と氷とスパークに包まれている。", "%^s is surrounded by flames, ice and electricity.  "), wd_he[lore_ptr->msex]));
403     else if ((lore_ptr->flags2 & RF2_AURA_FIRE) && (lore_ptr->flags2 & RF2_AURA_ELEC))
404         hook_c_roff(TERM_L_RED, format(_("%^sは炎とスパークに包まれている。", "%^s is surrounded by flames and electricity.  "), wd_he[lore_ptr->msex]));
405     else if ((lore_ptr->flags2 & RF2_AURA_FIRE) && (lore_ptr->flags3 & RF3_AURA_COLD))
406         hook_c_roff(TERM_BLUE, format(_("%^sは炎と氷に包まれている。", "%^s is surrounded by flames and ice.  "), wd_he[lore_ptr->msex]));
407     else if ((lore_ptr->flags3 & RF3_AURA_COLD) && (lore_ptr->flags2 & RF2_AURA_ELEC))
408         hook_c_roff(TERM_L_GREEN, format(_("%^sは氷とスパークに包まれている。", "%^s is surrounded by ice and electricity.  "), wd_he[lore_ptr->msex]));
409     else if (lore_ptr->flags2 & RF2_AURA_FIRE)
410         hook_c_roff(TERM_RED, format(_("%^sは炎に包まれている。", "%^s is surrounded by flames.  "), wd_he[lore_ptr->msex]));
411     else if (lore_ptr->flags3 & RF3_AURA_COLD)
412         hook_c_roff(TERM_BLUE, format(_("%^sは氷に包まれている。", "%^s is surrounded by ice.  "), wd_he[lore_ptr->msex]));
413     else if (lore_ptr->flags2 & RF2_AURA_ELEC)
414         hook_c_roff(TERM_L_BLUE, format(_("%^sはスパークに包まれている。", "%^s is surrounded by electricity.  "), wd_he[lore_ptr->msex]));
415 }
416
417 void display_lore_this(player_type *player_ptr, lore_type *lore_ptr)
418 {
419     if ((lore_ptr->r_ptr->r_tkills == 0) && !lore_ptr->know_everything)
420         return;
421
422 #ifdef JP
423     hooked_roff("この");
424 #else
425     if (lore_ptr->flags1 & RF1_UNIQUE) {
426         hooked_roff("Killing this");
427     } else {
428         hooked_roff("A kill of this");
429     }
430 #endif
431
432     display_monster_alignment(lore_ptr);
433     display_monster_kind(lore_ptr);
434     display_monster_exp(player_ptr, lore_ptr);
435 }
436
437 static void display_monster_escort_contents(lore_type *lore_ptr)
438 {
439     if (!lore_ptr->reinforce)
440         return;
441
442     hooked_roff(_("護衛の構成は", "These escorts"));
443     if ((lore_ptr->flags1 & RF1_ESCORT) || (lore_ptr->flags1 & RF1_ESCORTS)) {
444         hooked_roff(_("少なくとも", " at the least"));
445     }
446
447 #ifdef JP
448 #else
449     hooked_roff(" contain ");
450 #endif
451
452     for (int n = 0; n < A_MAX; n++) {
453         bool is_reinforced = lore_ptr->r_ptr->reinforce_id[n] > 0;
454         is_reinforced &= lore_ptr->r_ptr->reinforce_dd[n] > 0;
455         is_reinforced &= lore_ptr->r_ptr->reinforce_ds[n] > 0;
456         if (!is_reinforced)
457             continue;
458
459         monster_race *rf_ptr = &r_info[lore_ptr->r_ptr->reinforce_id[n]];
460         if (rf_ptr->flags1 & RF1_UNIQUE) {
461             hooked_roff(format(_("、%s", ", %s"), r_name + rf_ptr->name));
462             continue;
463         }
464
465 #ifdef JP
466         hooked_roff(format("、 %dd%d 体の%s", lore_ptr->r_ptr->reinforce_dd[n], lore_ptr->r_ptr->reinforce_ds[n], r_name + rf_ptr->name));
467 #else
468         bool plural = (lore_ptr->r_ptr->reinforce_dd[n] * lore_ptr->r_ptr->reinforce_ds[n] > 1);
469         GAME_TEXT name[MAX_NLEN];
470         strcpy(name, r_name + rf_ptr->name);
471         if (plural)
472             plural_aux(name);
473         hooked_roff(format(",%dd%d %s", lore_ptr->r_ptr->reinforce_dd[n], lore_ptr->r_ptr->reinforce_ds[n], name));
474 #endif
475     }
476
477     hooked_roff(_("で成り立っている。", "."));
478 }
479
480 void display_monster_collective(lore_type *lore_ptr)
481 {
482     if ((lore_ptr->flags1 & RF1_ESCORT) || (lore_ptr->flags1 & RF1_ESCORTS) || lore_ptr->reinforce) {
483         hooked_roff(format(_("%^sは通常護衛を伴って現れる。", "%^s usually appears with escorts.  "), wd_he[lore_ptr->msex]));
484         display_monster_escort_contents(lore_ptr);
485     }
486     else if (lore_ptr->flags1 & RF1_FRIENDS) {
487         hooked_roff(format(_("%^sは通常集団で現れる。", "%^s usually appears in groups.  "), wd_he[lore_ptr->msex]));
488     }
489 }
490
491 void display_monster_launching(player_type *player_ptr, lore_type *lore_ptr)
492 {
493     if (lore_ptr->flags4 & RF4_ROCKET) {
494         set_damage(player_ptr, lore_ptr->r_idx, (MS_ROCKET), _("ロケット%sを発射する", "shoot a rocket%s"), lore_ptr->tmp_msg[lore_ptr->vn]);
495         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
496         lore_ptr->color[lore_ptr->vn++] = TERM_UMBER;
497     }
498
499     if ((lore_ptr->flags4 & RF4_SHOOT) == 0)
500         return;
501
502     for (int m = 0; m < 4; m++) {
503         if (lore_ptr->r_ptr->blow[m].method != RBM_SHOOT)
504             continue;
505
506         if (know_armour(lore_ptr->r_idx))
507             sprintf(lore_ptr->tmp_msg[lore_ptr->vn], _("威力 %dd%d の射撃をする", "fire an arrow (Power:%dd%d)"), lore_ptr->r_ptr->blow[m].d_side,
508                 lore_ptr->r_ptr->blow[m].d_dice);
509         else
510             sprintf(lore_ptr->tmp_msg[lore_ptr->vn], _("射撃をする", "fire an arrow"));
511         lore_ptr->vp[lore_ptr->vn] = lore_ptr->tmp_msg[lore_ptr->vn];
512         lore_ptr->color[lore_ptr->vn++] = TERM_UMBER;
513         break;
514     }
515 }
516
517 void display_monster_sometimes(lore_type *lore_ptr)
518 {
519     if (lore_ptr->vn <= 0)
520         return;
521
522     hooked_roff(format(_("%^sは", "%^s"), wd_he[lore_ptr->msex]));
523     for (int n = 0; n < lore_ptr->vn; n++) {
524 #ifdef JP
525         if (n != lore_ptr->vn - 1) {
526             jverb(lore_ptr->vp[n], lore_ptr->jverb_buf, JVERB_OR);
527             hook_c_roff(lore_ptr->color[n], lore_ptr->jverb_buf);
528             hook_c_roff(lore_ptr->color[n], "り");
529             hooked_roff("、");
530         } else
531             hook_c_roff(lore_ptr->color[n], lore_ptr->vp[n]);
532 #else
533         if (n == 0)
534             hooked_roff(" may ");
535         else if (n < lore_ptr->vn - 1)
536             hooked_roff(", ");
537         else
538             hooked_roff(" or ");
539
540         hook_c_roff(lore_ptr->color[n], lore_ptr->vp[n]);
541 #endif
542     }
543
544     hooked_roff(_("ことがある。", ".  "));
545 }
546
547 void display_monster_guardian(lore_type *lore_ptr)
548 {
549     bool is_kingpin = (lore_ptr->flags1 & RF1_QUESTOR) != 0;
550     is_kingpin &= lore_ptr->r_ptr->r_sights > 0;
551     is_kingpin &= lore_ptr->r_ptr->max_num > 0;
552     is_kingpin &= (lore_ptr->r_idx == MON_OBERON) || (lore_ptr->r_idx == MON_SERPENT);
553     if (is_kingpin) {
554         hook_c_roff(TERM_VIOLET, _("あなたはこのモンスターを殺したいという強い欲望を感じている...", "You feel an intense desire to kill this monster...  "));
555     } else if (lore_ptr->flags7 & RF7_GUARDIAN) {
556         hook_c_roff(TERM_L_RED, _("このモンスターはダンジョンの主である。", "This monster is the master of a dungeon."));
557     }
558
559     hooked_roff("\n");
560 }