OSDN Git Service

86c646e9d2d4ffdbde3752f7b2b4dd7d06c05ef5
[hengbandforosx/hengbandosx.git] / src / monster / monster-describer.cpp
1 #include "monster/monster-describer.h"
2 #include "io/files-util.h"
3 #include "locale/english.h"
4 #include "monster-race/monster-race.h"
5 #include "monster-race/race-flags1.h"
6 #include "monster/monster-description-types.h"
7 #include "monster/monster-flag-types.h"
8 #include "monster/monster-info.h"
9 #include "system/floor-type-definition.h"
10 #include "system/monster-race-definition.h"
11 #include "system/monster-type-definition.h"
12 #include "system/player-type-definition.h"
13 #include "util/quarks.h"
14 #include "util/string-processor.h"
15 #include "view/display-messages.h"
16
17 /*!
18  * @brief モンスターの呼称を作成する / Build a string describing a monster in some way.
19  * @param desc 記述出力先の文字列参照ポインタ
20  * @param m_ptr モンスターの参照ポインタ
21  * @param mode 呼称オプション
22  */
23 void monster_desc(PlayerType *player_ptr, char *desc, monster_type *m_ptr, BIT_FLAGS mode)
24 {
25     monster_race *r_ptr;
26     r_ptr = &r_info[m_ptr->ap_r_idx];
27     concptr name = (mode & MD_TRUE_NAME) ? real_r_ptr(m_ptr)->name.c_str() : r_ptr->name.c_str();
28     GAME_TEXT silly_name[1024];
29     bool named = false;
30     if (player_ptr->hallucinated && !(mode & MD_IGNORE_HALLU)) {
31         if (one_in_(2)) {
32             if (!get_rnd_line(_("silly_j.txt", "silly.txt"), m_ptr->r_idx, silly_name))
33                 named = true;
34         }
35
36         if (!named) {
37             monster_race *hallu_race;
38
39             do {
40                 hallu_race = &r_info[randint1(r_info.size() - 1)];
41             } while (hallu_race->name.empty() || hallu_race->kind_flags.has(MonsterKindType::UNIQUE));
42
43             strcpy(silly_name, (hallu_race->name.c_str()));
44         }
45
46         name = silly_name;
47     }
48
49     bool seen = (m_ptr && ((mode & MD_ASSUME_VISIBLE) || (!(mode & MD_ASSUME_HIDDEN) && m_ptr->ml)));
50     bool pron = (m_ptr && ((seen && (mode & MD_PRON_VISIBLE)) || (!seen && (mode & MD_PRON_HIDDEN))));
51
52     /* First, try using pronouns, or describing hidden monsters */
53     auto *floor_ptr = player_ptr->current_floor_ptr;
54     if (!seen || pron) {
55         int kind = 0x00;
56         if (r_ptr->flags1 & (RF1_FEMALE))
57             kind = 0x20;
58         else if (r_ptr->flags1 & (RF1_MALE))
59             kind = 0x10;
60
61         if (!m_ptr || !pron)
62             kind = 0x00;
63
64         concptr res = _("何か", "it");
65         switch (kind + (mode & (MD_INDEF_HIDDEN | MD_POSSESSIVE | MD_OBJECTIVE))) {
66         case 0x00:
67             res = _("何か", "it");
68             break;
69         case 0x00 + (MD_OBJECTIVE):
70             res = _("何か", "it");
71             break;
72         case 0x00 + (MD_POSSESSIVE):
73             res = _("何かの", "its");
74             break;
75         case 0x00 + (MD_POSSESSIVE | MD_OBJECTIVE):
76             res = _("何か自身", "itself");
77             break;
78         case 0x00 + (MD_INDEF_HIDDEN):
79             res = _("何か", "something");
80             break;
81         case 0x00 + (MD_INDEF_HIDDEN | MD_OBJECTIVE):
82             res = _("何か", "something");
83             break;
84         case 0x00 + (MD_INDEF_HIDDEN | MD_POSSESSIVE):
85             res = _("何か", "something's");
86             break;
87         case 0x00 + (MD_INDEF_HIDDEN | MD_POSSESSIVE | MD_OBJECTIVE):
88             res = _("それ自身", "itself");
89             break;
90         case 0x10:
91             res = _("彼", "he");
92             break;
93         case 0x10 + (MD_OBJECTIVE):
94             res = _("彼", "him");
95             break;
96         case 0x10 + (MD_POSSESSIVE):
97             res = _("彼の", "his");
98             break;
99         case 0x10 + (MD_POSSESSIVE | MD_OBJECTIVE):
100             res = _("彼自身", "himself");
101             break;
102         case 0x10 + (MD_INDEF_HIDDEN):
103             res = _("誰か", "someone");
104             break;
105         case 0x10 + (MD_INDEF_HIDDEN | MD_OBJECTIVE):
106             res = _("誰か", "someone");
107             break;
108         case 0x10 + (MD_INDEF_HIDDEN | MD_POSSESSIVE):
109             res = _("誰かの", "someone's");
110             break;
111         case 0x10 + (MD_INDEF_HIDDEN | MD_POSSESSIVE | MD_OBJECTIVE):
112             res = _("彼自身", "himself");
113             break;
114         case 0x20:
115             res = _("彼女", "she");
116             break;
117         case 0x20 + (MD_OBJECTIVE):
118             res = _("彼女", "her");
119             break;
120         case 0x20 + (MD_POSSESSIVE):
121             res = _("彼女の", "her");
122             break;
123         case 0x20 + (MD_POSSESSIVE | MD_OBJECTIVE):
124             res = _("彼女自身", "herself");
125             break;
126         case 0x20 + (MD_INDEF_HIDDEN):
127             res = _("誰か", "someone");
128             break;
129         case 0x20 + (MD_INDEF_HIDDEN | MD_OBJECTIVE):
130             res = _("誰か", "someone");
131             break;
132         case 0x20 + (MD_INDEF_HIDDEN | MD_POSSESSIVE):
133             res = _("誰かの", "someone's");
134             break;
135         case 0x20 + (MD_INDEF_HIDDEN | MD_POSSESSIVE | MD_OBJECTIVE):
136             res = _("彼女自身", "herself");
137             break;
138         }
139
140         (void)strcpy(desc, res);
141         return;
142     }
143
144     /* Handle visible monsters, "reflexive" request */
145     if ((mode & (MD_POSSESSIVE | MD_OBJECTIVE)) == (MD_POSSESSIVE | MD_OBJECTIVE)) {
146         /* The monster is visible, so use its gender */
147         if (r_ptr->flags1 & (RF1_FEMALE))
148             strcpy(desc, _("彼女自身", "herself"));
149         else if (r_ptr->flags1 & (RF1_MALE))
150             strcpy(desc, _("彼自身", "himself"));
151         else
152             strcpy(desc, _("それ自身", "itself"));
153         return;
154     }
155
156     /* Handle all other visible monster requests */
157     /* Tanuki? */
158     if (is_pet(m_ptr) && !is_original_ap(m_ptr)) {
159 #ifdef JP
160         char *t;
161         char buf[128];
162         strcpy(buf, name);
163         t = buf;
164         while (strncmp(t, "』", 2) && *t)
165             t++;
166         if (*t) {
167             *t = '\0';
168             (void)sprintf(desc, "%s?』", buf);
169         } else
170             (void)sprintf(desc, "%s?", name);
171 #else
172         (void)sprintf(desc, "%s?", name);
173 #endif
174     } else {
175         if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE) && !(player_ptr->hallucinated && !(mode & MD_IGNORE_HALLU))) {
176             if (m_ptr->mflag2.has(MonsterConstantFlagType::CHAMELEON) && !(mode & MD_TRUE_NAME)) {
177 #ifdef JP
178                 char *t;
179                 char buf[128];
180                 strcpy(buf, name);
181                 t = buf;
182                 while (strncmp(t, "』", 2) && *t)
183                     t++;
184                 if (*t) {
185                     *t = '\0';
186                     (void)sprintf(desc, "%s?』", buf);
187                 } else
188                     (void)sprintf(desc, "%s?", name);
189 #else
190                 (void)sprintf(desc, "%s?", name);
191 #endif
192             } else if (player_ptr->phase_out && !(player_ptr->riding && (&floor_ptr->m_list[player_ptr->riding] == m_ptr))) {
193                 (void)sprintf(desc, _("%sもどき", "fake %s"), name);
194             } else {
195                 (void)strcpy(desc, name);
196             }
197         } else if (mode & MD_INDEF_VISIBLE) {
198 #ifdef JP
199             (void)strcpy(desc, "");
200 #else
201             (void)strcpy(desc, is_a_vowel(name[0]) ? "an " : "a ");
202 #endif
203             (void)strcat(desc, name);
204         } else {
205             if (is_pet(m_ptr))
206                 (void)strcpy(desc, _("あなたの", "your "));
207             else
208                 (void)strcpy(desc, _("", "the "));
209
210             (void)strcat(desc, name);
211         }
212     }
213
214     if (m_ptr->nickname) {
215         char buf[128];
216         sprintf(buf, _("「%s」", " called %s"), quark_str(m_ptr->nickname));
217         strcat(desc, buf);
218     }
219
220     if (player_ptr->riding && (&floor_ptr->m_list[player_ptr->riding] == m_ptr)) {
221         strcat(desc, _("(乗馬中)", "(riding)"));
222     }
223
224     if ((mode & MD_IGNORE_HALLU) && m_ptr->mflag2.has(MonsterConstantFlagType::CHAMELEON)) {
225         if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
226             strcat(desc, _("(カメレオンの王)", "(Chameleon Lord)"));
227         } else {
228             strcat(desc, _("(カメレオン)", "(Chameleon)"));
229         }
230     }
231
232     if ((mode & MD_IGNORE_HALLU) && !is_original_ap(m_ptr)) {
233         strcat(desc, format("(%s)", r_info[m_ptr->r_idx].name.c_str()));
234     }
235
236     /* Handle the Possessive as a special afterthought */
237     if (mode & MD_POSSESSIVE) {
238         (void)strcat(desc, _("の", "'s"));
239     }
240 }
241
242 /*!
243  * @brief ダメージを受けたモンスターの様子を記述する / Dump a message describing a monster's reaction to damage
244  * @param player_ptr プレイヤーへの参照ポインタ
245  * @param m_idx モンスター情報ID
246  * @param dam 与えたダメージ
247  * @details
248  * Technically should attempt to treat "Beholder"'s as jelly's
249  */
250 void message_pain(PlayerType *player_ptr, MONSTER_IDX m_idx, HIT_POINT dam)
251 {
252     auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
253     auto *r_ptr = &r_info[m_ptr->r_idx];
254
255     GAME_TEXT m_name[MAX_NLEN];
256
257     monster_desc(player_ptr, m_name, m_ptr, 0);
258
259     if (dam == 0) {
260         if (m_ptr->ml) {
261             msg_format(_("%^sはダメージを受けていない。", "%^s is unharmed."), m_name);
262         }
263         return;
264     }
265
266     HIT_POINT newhp = m_ptr->hp;
267     HIT_POINT oldhp = newhp + dam;
268     HIT_POINT tmp = (newhp * 100L) / oldhp;
269     PERCENTAGE percentage = tmp;
270
271     if (angband_strchr(",ejmvwQ", r_ptr->d_char)) {
272         if (percentage > 95)
273             msg_format(_("%^sはほとんど気にとめていない。", "%^s barely notices."), m_name);
274         else if (percentage > 75)
275             msg_format(_("%^sはしり込みした。", "%^s flinches."), m_name);
276         else if (percentage > 50)
277             msg_format(_("%^sは縮こまった。", "%^s squelches."), m_name);
278         else if (percentage > 35)
279             msg_format(_("%^sは痛みに震えた。", "%^s quivers in pain."), m_name);
280         else if (percentage > 20)
281             msg_format(_("%^sは身もだえした。", "%^s writhes about."), m_name);
282         else if (percentage > 10)
283             msg_format(_("%^sは苦痛で身もだえした。", "%^s writhes in agony."), m_name);
284         else
285             msg_format(_("%^sはぐにゃぐにゃと痙攣した。", "%^s jerks limply."), m_name);
286         return;
287     }
288
289     if (angband_strchr("l", r_ptr->d_char)) {
290         if (percentage > 95)
291             msg_format(_("%^sはほとんど気にとめていない。", "%^s barely notices."), m_name);
292         else if (percentage > 75)
293             msg_format(_("%^sはしり込みした。", "%^s flinches."), m_name);
294         else if (percentage > 50)
295             msg_format(_("%^sは躊躇した。", "%^s hesitates."), m_name);
296         else if (percentage > 35)
297             msg_format(_("%^sは痛みに震えた。", "%^s quivers in pain."), m_name);
298         else if (percentage > 20)
299             msg_format(_("%^sは身もだえした。", "%^s writhes about."), m_name);
300         else if (percentage > 10)
301             msg_format(_("%^sは苦痛で身もだえした。", "%^s writhes in agony."), m_name);
302         else
303             msg_format(_("%^sはぐにゃぐにゃと痙攣した。", "%^s jerks limply."), m_name);
304         return;
305     }
306
307     if (angband_strchr("g#+<>", r_ptr->d_char)) {
308         if (percentage > 95)
309             msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name);
310         else if (percentage > 75)
311             msg_format(_("%sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name);
312         else if (percentage > 50)
313             msg_format(_("%^sは雷鳴のように吠えた。", "%^s roars thunderously."), m_name);
314         else if (percentage > 35)
315             msg_format(_("%^sは苦しげに吠えた。", "%^s rumbles."), m_name);
316         else if (percentage > 20)
317             msg_format(_("%^sはうめいた。", "%^s grunts."), m_name);
318         else if (percentage > 10)
319             msg_format(_("%^sは躊躇した。", "%^s hesitates."), m_name);
320         else
321             msg_format(_("%^sはくしゃくしゃになった。", "%^s crumples."), m_name);
322         return;
323     }
324
325     if (angband_strchr("JMR", r_ptr->d_char) || !isalpha(r_ptr->d_char)) {
326         if (percentage > 95)
327             msg_format(_("%^sはほとんど気にとめていない。", "%^s barely notices."), m_name);
328         else if (percentage > 75)
329             msg_format(_("%^sはシーッと鳴いた。", "%^s hisses."), m_name);
330         else if (percentage > 50)
331             msg_format(_("%^sは怒って頭を上げた。", "%^s rears up in anger."), m_name);
332         else if (percentage > 35)
333             msg_format(_("%^sは猛然と威嚇した。", "%^s hisses furiously."), m_name);
334         else if (percentage > 20)
335             msg_format(_("%^sは身もだえした。", "%^s writhes about."), m_name);
336         else if (percentage > 10)
337             msg_format(_("%^sは苦痛で身もだえした。", "%^s writhes in agony."), m_name);
338         else
339             msg_format(_("%^sはぐにゃぐにゃと痙攣した。", "%^s jerks limply."), m_name);
340         return;
341     }
342
343     if (angband_strchr("f", r_ptr->d_char)) {
344         if (percentage > 95)
345             msg_format(_("%sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name);
346         else if (percentage > 75)
347             msg_format(_("%^sは吠えた。", "%^s roars."), m_name);
348         else if (percentage > 50)
349             msg_format(_("%^sは怒って吠えた。", "%^s growls angrily."), m_name);
350         else if (percentage > 35)
351             msg_format(_("%^sは痛みでシーッと鳴いた。", "%^s hisses with pain."), m_name);
352         else if (percentage > 20)
353             msg_format(_("%^sは痛みで弱々しく鳴いた。", "%^s mewls in pain."), m_name);
354         else if (percentage > 10)
355             msg_format(_("%^sは苦痛にうめいた。", "%^s hisses in agony."), m_name);
356         else
357             msg_format(_("%sは哀れな鳴き声を出した。", "%^s mewls pitifully."), m_name);
358         return;
359     }
360
361     if (angband_strchr("acFIKS", r_ptr->d_char)) {
362         if (percentage > 95)
363             msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name);
364         else if (percentage > 75)
365             msg_format(_("%^sはキーキー鳴いた。", "%^s chitters."), m_name);
366         else if (percentage > 50)
367             msg_format(_("%^sはヨロヨロ逃げ回った。", "%^s scuttles about."), m_name);
368         else if (percentage > 35)
369             msg_format(_("%^sはうるさく鳴いた。", "%^s twitters."), m_name);
370         else if (percentage > 20)
371             msg_format(_("%^sは痛みに痙攣した。", "%^s jerks in pain."), m_name);
372         else if (percentage > 10)
373             msg_format(_("%^sは苦痛で痙攣した。", "%^s jerks in agony."), m_name);
374         else
375             msg_format(_("%^sはピクピクひきつった。", "%^s twitches."), m_name);
376         return;
377     }
378
379     if (angband_strchr("B", r_ptr->d_char)) {
380         if (percentage > 95)
381             msg_format(_("%^sはさえずった。", "%^s chirps."), m_name);
382         else if (percentage > 75)
383             msg_format(_("%^sはピーピー鳴いた。", "%^s twitters."), m_name);
384         else if (percentage > 50)
385             msg_format(_("%^sはギャーギャー鳴いた。", "%^s squawks."), m_name);
386         else if (percentage > 35)
387             msg_format(_("%^sはギャーギャー鳴きわめいた。", "%^s chatters."), m_name);
388         else if (percentage > 20)
389             msg_format(_("%^sは苦しんだ。", "%^s jeers."), m_name);
390         else if (percentage > 10)
391             msg_format(_("%^sはのたうち回った。", "%^s flutters about."), m_name);
392         else
393             msg_format(_("%^sはキーキーと鳴き叫んだ。", "%^s squeaks."), m_name);
394         return;
395     }
396
397     if (angband_strchr("duDLUW", r_ptr->d_char)) {
398         if (percentage > 95)
399             msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name);
400         else if (percentage > 75)
401             msg_format(_("%^sはしり込みした。", "%^s flinches."), m_name);
402         else if (percentage > 50)
403             msg_format(_("%^sは痛みでシーッと鳴いた。", "%^s hisses in pain."), m_name);
404         else if (percentage > 35)
405             msg_format(_("%^sは痛みでうなった。", "%^s snarls with pain."), m_name);
406         else if (percentage > 20)
407             msg_format(_("%^sは痛みに吠えた。", "%^s roars with pain."), m_name);
408         else if (percentage > 10)
409             msg_format(_("%^sは苦しげに叫んだ。", "%^s gasps."), m_name);
410         else
411             msg_format(_("%^sは弱々しくうなった。", "%^s snarls feebly."), m_name);
412         return;
413     }
414
415     if (angband_strchr("s", r_ptr->d_char)) {
416         if (percentage > 95)
417             msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name);
418         else if (percentage > 75)
419             msg_format(_("%sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name);
420         else if (percentage > 50)
421             msg_format(_("%^sはカタカタと笑った。", "%^s rattles."), m_name);
422         else if (percentage > 35)
423             msg_format(_("%^sはよろめいた。", "%^s stumbles."), m_name);
424         else if (percentage > 20)
425             msg_format(_("%^sはカタカタ言った。", "%^s rattles."), m_name);
426         else if (percentage > 10)
427             msg_format(_("%^sはよろめいた。", "%^s staggers."), m_name);
428         else
429             msg_format(_("%^sはガタガタ言った。", "%^s clatters."), m_name);
430         return;
431     }
432
433     if (angband_strchr("z", r_ptr->d_char)) {
434         if (percentage > 95)
435             msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name);
436         else if (percentage > 75)
437             msg_format(_("%sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name);
438         else if (percentage > 50)
439             msg_format(_("%^sはうめいた。", "%^s groans."), m_name);
440         else if (percentage > 35)
441             msg_format(_("%sは苦しげにうめいた。", "%^s moans."), m_name);
442         else if (percentage > 20)
443             msg_format(_("%^sは躊躇した。", "%^s hesitates."), m_name);
444         else if (percentage > 10)
445             msg_format(_("%^sはうなった。", "%^s grunts."), m_name);
446         else
447             msg_format(_("%^sはよろめいた。", "%^s staggers."), m_name);
448         return;
449     }
450
451     if (angband_strchr("G", r_ptr->d_char)) {
452         if (percentage > 95)
453             msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name);
454         else if (percentage > 75)
455             msg_format(_("%sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name);
456         else if (percentage > 50)
457             msg_format(_("%sはうめいた。", "%^s moans."), m_name);
458         else if (percentage > 35)
459             msg_format(_("%^sは泣きわめいた。", "%^s wails."), m_name);
460         else if (percentage > 20)
461             msg_format(_("%^sは吠えた。", "%^s howls."), m_name);
462         else if (percentage > 10)
463             msg_format(_("%sは弱々しくうめいた。", "%^s moans softly."), m_name);
464         else
465             msg_format(_("%^sはかすかにうめいた。", "%^s sighs."), m_name);
466         return;
467     }
468
469     if (angband_strchr("CZ", r_ptr->d_char)) {
470         if (percentage > 95)
471             msg_format(_("%^sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name);
472         else if (percentage > 75)
473             msg_format(_("%^sは痛みでうなった。", "%^s snarls with pain."), m_name);
474         else if (percentage > 50)
475             msg_format(_("%^sは痛みでキャンキャン吠えた。", "%^s yelps in pain."), m_name);
476         else if (percentage > 35)
477             msg_format(_("%^sは痛みで鳴きわめいた。", "%^s howls in pain."), m_name);
478         else if (percentage > 20)
479             msg_format(_("%^sは苦痛のあまり鳴きわめいた。", "%^s howls in agony."), m_name);
480         else if (percentage > 10)
481             msg_format(_("%^sは苦痛でもだえ苦しんだ。", "%^s writhes in agony."), m_name);
482         else
483             msg_format(_("%^sは弱々しく吠えた。", "%^s yelps feebly."), m_name);
484         return;
485     }
486
487     if (angband_strchr("Xbilqrt", r_ptr->d_char)) {
488         if (percentage > 95)
489             msg_format(_("%^sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name);
490         else if (percentage > 75)
491             msg_format(_("%^sは痛みでうなった。", "%^s grunts with pain."), m_name);
492         else if (percentage > 50)
493             msg_format(_("%^sは痛みで叫んだ。", "%^s squeals in pain."), m_name);
494         else if (percentage > 35)
495             msg_format(_("%^sは痛みで絶叫した。", "%^s shrieks in pain."), m_name);
496         else if (percentage > 20)
497             msg_format(_("%^sは苦痛のあまり絶叫した。", "%^s shrieks in agony."), m_name);
498         else if (percentage > 10)
499             msg_format(_("%^sは苦痛でもだえ苦しんだ。", "%^s writhes in agony."), m_name);
500         else
501             msg_format(_("%^sは弱々しく叫んだ。", "%^s cries out feebly."), m_name);
502         return;
503     }
504
505     if (percentage > 95)
506         msg_format(_("%^sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name);
507     else if (percentage > 75)
508         msg_format(_("%^sは痛みでうなった。", "%^s grunts with pain."), m_name);
509     else if (percentage > 50)
510         msg_format(_("%^sは痛みで叫んだ。", "%^s cries out in pain."), m_name);
511     else if (percentage > 35)
512         msg_format(_("%^sは痛みで絶叫した。", "%^s screams in pain."), m_name);
513     else if (percentage > 20)
514         msg_format(_("%^sは苦痛のあまり絶叫した。", "%^s screams in agony."), m_name);
515     else if (percentage > 10)
516         msg_format(_("%^sは苦痛でもだえ苦しんだ。", "%^s writhes in agony."), m_name);
517     else
518         msg_format(_("%^sは弱々しく叫んだ。", "%^s cries out feebly."), m_name);
519 }