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-entity.h"
11 #include "system/monster-race-info.h"
12 #include "system/player-type-definition.h"
13 #include "timed-effect/player-hallucination.h"
14 #include "timed-effect/timed-effects.h"
15 #include "util/quarks.h"
16 #include "util/string-processor.h"
17 #include "view/display-messages.h"
20 * @brief モンスターの呼称を作成する / Build a string describing a monster in some way.
21 * @param desc 記述出力先の文字列参照ポインタ
22 * @param m_ptr モンスターの参照ポインタ
25 void monster_desc(PlayerType *player_ptr, char *desc, MonsterEntity *m_ptr, BIT_FLAGS mode)
27 MonsterRaceInfo *r_ptr;
28 r_ptr = &monraces_info[m_ptr->ap_r_idx];
29 concptr name = (mode & MD_TRUE_NAME) ? m_ptr->get_real_r_ref().name.data() : r_ptr->name.data();
30 GAME_TEXT silly_name[1024];
32 auto is_hallucinated = player_ptr->effects()->hallucination()->is_hallucinated();
33 if (is_hallucinated && !(mode & MD_IGNORE_HALLU)) {
35 if (!get_rnd_line(_("silly_j.txt", "silly.txt"), enum2i(m_ptr->r_idx), silly_name)) {
41 MonsterRaceInfo *hallu_race;
44 auto r_idx = MonsterRace::pick_one_at_random();
45 hallu_race = &monraces_info[r_idx];
46 } while (hallu_race->name.empty() || hallu_race->kind_flags.has(MonsterKindType::UNIQUE));
48 strcpy(silly_name, (hallu_race->name.data()));
54 bool seen = (m_ptr && ((mode & MD_ASSUME_VISIBLE) || (!(mode & MD_ASSUME_HIDDEN) && m_ptr->ml)));
55 bool pron = (m_ptr && ((seen && (mode & MD_PRON_VISIBLE)) || (!seen && (mode & MD_PRON_HIDDEN))));
57 /* First, try using pronouns, or describing hidden monsters */
58 auto *floor_ptr = player_ptr->current_floor_ptr;
61 if (r_ptr->flags1 & (RF1_FEMALE)) {
63 } else if (r_ptr->flags1 & (RF1_MALE)) {
67 if (!m_ptr || !pron) {
71 concptr res = _("何か", "it");
72 switch (kind + (mode & (MD_INDEF_HIDDEN | MD_POSSESSIVE | MD_OBJECTIVE))) {
76 case 0x00 + (MD_OBJECTIVE):
79 case 0x00 + (MD_POSSESSIVE):
80 res = _("何かの", "its");
82 case 0x00 + (MD_POSSESSIVE | MD_OBJECTIVE):
83 res = _("何か自身", "itself");
85 case 0x00 + (MD_INDEF_HIDDEN):
86 res = _("何か", "something");
88 case 0x00 + (MD_INDEF_HIDDEN | MD_OBJECTIVE):
89 res = _("何か", "something");
91 case 0x00 + (MD_INDEF_HIDDEN | MD_POSSESSIVE):
92 res = _("何か", "something's");
94 case 0x00 + (MD_INDEF_HIDDEN | MD_POSSESSIVE | MD_OBJECTIVE):
95 res = _("それ自身", "itself");
100 case 0x10 + (MD_OBJECTIVE):
103 case 0x10 + (MD_POSSESSIVE):
104 res = _("彼の", "his");
106 case 0x10 + (MD_POSSESSIVE | MD_OBJECTIVE):
107 res = _("彼自身", "himself");
109 case 0x10 + (MD_INDEF_HIDDEN):
110 res = _("誰か", "someone");
112 case 0x10 + (MD_INDEF_HIDDEN | MD_OBJECTIVE):
113 res = _("誰か", "someone");
115 case 0x10 + (MD_INDEF_HIDDEN | MD_POSSESSIVE):
116 res = _("誰かの", "someone's");
118 case 0x10 + (MD_INDEF_HIDDEN | MD_POSSESSIVE | MD_OBJECTIVE):
119 res = _("彼自身", "himself");
122 res = _("彼女", "she");
124 case 0x20 + (MD_OBJECTIVE):
125 res = _("彼女", "her");
127 case 0x20 + (MD_POSSESSIVE):
128 res = _("彼女の", "her");
130 case 0x20 + (MD_POSSESSIVE | MD_OBJECTIVE):
131 res = _("彼女自身", "herself");
133 case 0x20 + (MD_INDEF_HIDDEN):
134 res = _("誰か", "someone");
136 case 0x20 + (MD_INDEF_HIDDEN | MD_OBJECTIVE):
137 res = _("誰か", "someone");
139 case 0x20 + (MD_INDEF_HIDDEN | MD_POSSESSIVE):
140 res = _("誰かの", "someone's");
142 case 0x20 + (MD_INDEF_HIDDEN | MD_POSSESSIVE | MD_OBJECTIVE):
143 res = _("彼女自身", "herself");
147 (void)strcpy(desc, res);
151 /* Handle visible monsters, "reflexive" request */
152 if ((mode & (MD_POSSESSIVE | MD_OBJECTIVE)) == (MD_POSSESSIVE | MD_OBJECTIVE)) {
153 /* The monster is visible, so use its gender */
154 if (r_ptr->flags1 & (RF1_FEMALE)) {
155 strcpy(desc, _("彼女自身", "herself"));
156 } else if (r_ptr->flags1 & (RF1_MALE)) {
157 strcpy(desc, _("彼自身", "himself"));
159 strcpy(desc, _("それ自身", "itself"));
164 /* Handle all other visible monster requests */
166 if (m_ptr->is_pet() && !m_ptr->is_original_ap()) {
172 while (strncmp(t, "』", 2) && *t) {
177 (void)sprintf(desc, "%s?』", buf);
179 (void)sprintf(desc, "%s?", name);
182 (void)sprintf(desc, "%s?", name);
185 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE) && !(is_hallucinated && !(mode & MD_IGNORE_HALLU))) {
186 if (m_ptr->mflag2.has(MonsterConstantFlagType::CHAMELEON) && !(mode & MD_TRUE_NAME)) {
192 while (strncmp(t, "』", 2) && *t) {
197 (void)sprintf(desc, "%s?』", buf);
199 (void)sprintf(desc, "%s?", name);
202 (void)sprintf(desc, "%s?", name);
204 } else if (player_ptr->phase_out && !(player_ptr->riding && (&floor_ptr->m_list[player_ptr->riding] == m_ptr))) {
205 (void)sprintf(desc, _("%sもどき", "fake %s"), name);
207 (void)strcpy(desc, name);
209 } else if (mode & MD_INDEF_VISIBLE) {
211 (void)strcpy(desc, "");
213 (void)strcpy(desc, is_a_vowel(name[0]) ? "an " : "a ");
215 (void)strcat(desc, name);
217 if (m_ptr->is_pet()) {
218 (void)strcpy(desc, _("あなたの", "your "));
220 (void)strcpy(desc, _("", "the "));
223 (void)strcat(desc, name);
227 if (m_ptr->nickname) {
228 std::string buf = _("「", " called ");
229 buf.append(quark_str(m_ptr->nickname)).append(_("」", ""));
230 strcat(desc, buf.data());
233 if (player_ptr->riding && (&floor_ptr->m_list[player_ptr->riding] == m_ptr)) {
234 strcat(desc, _("(乗馬中)", "(riding)"));
237 if ((mode & MD_IGNORE_HALLU) && m_ptr->mflag2.has(MonsterConstantFlagType::CHAMELEON)) {
238 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
239 strcat(desc, _("(カメレオンの王)", "(Chameleon Lord)"));
241 strcat(desc, _("(カメレオン)", "(Chameleon)"));
245 if ((mode & MD_IGNORE_HALLU) && !m_ptr->is_original_ap()) {
246 strcat(desc, format("(%s)", monraces_info[m_ptr->r_idx].name.data()));
249 /* Handle the Possessive as a special afterthought */
250 if (mode & MD_POSSESSIVE) {
251 (void)strcat(desc, _("の", "'s"));
256 * @brief ダメージを受けたモンスターの様子を記述する / Dump a message describing a monster's reaction to damage
257 * @param player_ptr プレイヤーへの参照ポインタ
258 * @param m_idx モンスター情報ID
261 * Technically should attempt to treat "Beholder"'s as jelly's
263 void message_pain(PlayerType *player_ptr, MONSTER_IDX m_idx, int dam)
265 auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
266 auto *r_ptr = &monraces_info[m_ptr->r_idx];
268 GAME_TEXT m_name[MAX_NLEN];
270 monster_desc(player_ptr, m_name, m_ptr, 0);
274 msg_format(_("%^sはダメージを受けていない。", "%^s is unharmed."), m_name);
279 int newhp = m_ptr->hp;
280 int oldhp = newhp + dam;
281 int tmp = (newhp * 100L) / oldhp;
282 PERCENTAGE percentage = tmp;
284 if (angband_strchr(",ejmvwQ", r_ptr->d_char)) {
285 if (percentage > 95) {
286 msg_format(_("%^sはほとんど気にとめていない。", "%^s barely notices."), m_name);
287 } else if (percentage > 75) {
288 msg_format(_("%^sはしり込みした。", "%^s flinches."), m_name);
289 } else if (percentage > 50) {
290 msg_format(_("%^sは縮こまった。", "%^s squelches."), m_name);
291 } else if (percentage > 35) {
292 msg_format(_("%^sは痛みに震えた。", "%^s quivers in pain."), m_name);
293 } else if (percentage > 20) {
294 msg_format(_("%^sは身もだえした。", "%^s writhes about."), m_name);
295 } else if (percentage > 10) {
296 msg_format(_("%^sは苦痛で身もだえした。", "%^s writhes in agony."), m_name);
298 msg_format(_("%^sはぐにゃぐにゃと痙攣した。", "%^s jerks limply."), m_name);
303 if (angband_strchr("l", r_ptr->d_char)) {
304 if (percentage > 95) {
305 msg_format(_("%^sはほとんど気にとめていない。", "%^s barely notices."), m_name);
306 } else if (percentage > 75) {
307 msg_format(_("%^sはしり込みした。", "%^s flinches."), m_name);
308 } else if (percentage > 50) {
309 msg_format(_("%^sは躊躇した。", "%^s hesitates."), m_name);
310 } else if (percentage > 35) {
311 msg_format(_("%^sは痛みに震えた。", "%^s quivers in pain."), m_name);
312 } else if (percentage > 20) {
313 msg_format(_("%^sは身もだえした。", "%^s writhes about."), m_name);
314 } else if (percentage > 10) {
315 msg_format(_("%^sは苦痛で身もだえした。", "%^s writhes in agony."), m_name);
317 msg_format(_("%^sはぐにゃぐにゃと痙攣した。", "%^s jerks limply."), m_name);
322 if (angband_strchr("g#+<>", r_ptr->d_char)) {
323 if (percentage > 95) {
324 msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name);
325 } else if (percentage > 75) {
326 msg_format(_("%sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name);
327 } else if (percentage > 50) {
328 msg_format(_("%^sは雷鳴のように吠えた。", "%^s roars thunderously."), m_name);
329 } else if (percentage > 35) {
330 msg_format(_("%^sは苦しげに吠えた。", "%^s rumbles."), m_name);
331 } else if (percentage > 20) {
332 msg_format(_("%^sはうめいた。", "%^s grunts."), m_name);
333 } else if (percentage > 10) {
334 msg_format(_("%^sは躊躇した。", "%^s hesitates."), m_name);
336 msg_format(_("%^sはくしゃくしゃになった。", "%^s crumples."), m_name);
341 if (angband_strchr("JMR", r_ptr->d_char) || !isalpha(r_ptr->d_char)) {
342 if (percentage > 95) {
343 msg_format(_("%^sはほとんど気にとめていない。", "%^s barely notices."), m_name);
344 } else if (percentage > 75) {
345 msg_format(_("%^sはシーッと鳴いた。", "%^s hisses."), m_name);
346 } else if (percentage > 50) {
347 msg_format(_("%^sは怒って頭を上げた。", "%^s rears up in anger."), m_name);
348 } else if (percentage > 35) {
349 msg_format(_("%^sは猛然と威嚇した。", "%^s hisses furiously."), m_name);
350 } else if (percentage > 20) {
351 msg_format(_("%^sは身もだえした。", "%^s writhes about."), m_name);
352 } else if (percentage > 10) {
353 msg_format(_("%^sは苦痛で身もだえした。", "%^s writhes in agony."), m_name);
355 msg_format(_("%^sはぐにゃぐにゃと痙攣した。", "%^s jerks limply."), m_name);
360 if (angband_strchr("f", r_ptr->d_char)) {
361 if (percentage > 95) {
362 msg_format(_("%sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name);
363 } else if (percentage > 75) {
364 msg_format(_("%^sは吠えた。", "%^s roars."), m_name);
365 } else if (percentage > 50) {
366 msg_format(_("%^sは怒って吠えた。", "%^s growls angrily."), m_name);
367 } else if (percentage > 35) {
368 msg_format(_("%^sは痛みでシーッと鳴いた。", "%^s hisses with pain."), m_name);
369 } else if (percentage > 20) {
370 msg_format(_("%^sは痛みで弱々しく鳴いた。", "%^s mewls in pain."), m_name);
371 } else if (percentage > 10) {
372 msg_format(_("%^sは苦痛にうめいた。", "%^s hisses in agony."), m_name);
374 msg_format(_("%sは哀れな鳴き声を出した。", "%^s mewls pitifully."), m_name);
379 if (angband_strchr("acFIKS", r_ptr->d_char)) {
380 if (percentage > 95) {
381 msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name);
382 } else if (percentage > 75) {
383 msg_format(_("%^sはキーキー鳴いた。", "%^s chitters."), m_name);
384 } else if (percentage > 50) {
385 msg_format(_("%^sはヨロヨロ逃げ回った。", "%^s scuttles about."), m_name);
386 } else if (percentage > 35) {
387 msg_format(_("%^sはうるさく鳴いた。", "%^s twitters."), m_name);
388 } else if (percentage > 20) {
389 msg_format(_("%^sは痛みに痙攣した。", "%^s jerks in pain."), m_name);
390 } else if (percentage > 10) {
391 msg_format(_("%^sは苦痛で痙攣した。", "%^s jerks in agony."), m_name);
393 msg_format(_("%^sはピクピクひきつった。", "%^s twitches."), m_name);
398 if (angband_strchr("B", r_ptr->d_char)) {
399 if (percentage > 95) {
400 msg_format(_("%^sはさえずった。", "%^s chirps."), m_name);
401 } else if (percentage > 75) {
402 msg_format(_("%^sはピーピー鳴いた。", "%^s twitters."), m_name);
403 } else if (percentage > 50) {
404 msg_format(_("%^sはギャーギャー鳴いた。", "%^s squawks."), m_name);
405 } else if (percentage > 35) {
406 msg_format(_("%^sはギャーギャー鳴きわめいた。", "%^s chatters."), m_name);
407 } else if (percentage > 20) {
408 msg_format(_("%^sは苦しんだ。", "%^s jeers."), m_name);
409 } else if (percentage > 10) {
410 msg_format(_("%^sはのたうち回った。", "%^s flutters about."), m_name);
412 msg_format(_("%^sはキーキーと鳴き叫んだ。", "%^s squeaks."), m_name);
417 if (angband_strchr("duDLUW", r_ptr->d_char)) {
418 if (percentage > 95) {
419 msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name);
420 } else if (percentage > 75) {
421 msg_format(_("%^sはしり込みした。", "%^s flinches."), m_name);
422 } else if (percentage > 50) {
423 msg_format(_("%^sは痛みでシーッと鳴いた。", "%^s hisses in pain."), m_name);
424 } else if (percentage > 35) {
425 msg_format(_("%^sは痛みでうなった。", "%^s snarls with pain."), m_name);
426 } else if (percentage > 20) {
427 msg_format(_("%^sは痛みに吠えた。", "%^s roars with pain."), m_name);
428 } else if (percentage > 10) {
429 msg_format(_("%^sは苦しげに叫んだ。", "%^s gasps."), m_name);
431 msg_format(_("%^sは弱々しくうなった。", "%^s snarls feebly."), m_name);
436 if (angband_strchr("s", r_ptr->d_char)) {
437 if (percentage > 95) {
438 msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name);
439 } else if (percentage > 75) {
440 msg_format(_("%sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name);
441 } else if (percentage > 50) {
442 msg_format(_("%^sはカタカタと笑った。", "%^s rattles."), m_name);
443 } else if (percentage > 35) {
444 msg_format(_("%^sはよろめいた。", "%^s stumbles."), m_name);
445 } else if (percentage > 20) {
446 msg_format(_("%^sはカタカタ言った。", "%^s rattles."), m_name);
447 } else if (percentage > 10) {
448 msg_format(_("%^sはよろめいた。", "%^s staggers."), m_name);
450 msg_format(_("%^sはガタガタ言った。", "%^s clatters."), m_name);
455 if (angband_strchr("z", r_ptr->d_char)) {
456 if (percentage > 95) {
457 msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name);
458 } else if (percentage > 75) {
459 msg_format(_("%sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name);
460 } else if (percentage > 50) {
461 msg_format(_("%^sはうめいた。", "%^s groans."), m_name);
462 } else if (percentage > 35) {
463 msg_format(_("%sは苦しげにうめいた。", "%^s moans."), m_name);
464 } else if (percentage > 20) {
465 msg_format(_("%^sは躊躇した。", "%^s hesitates."), m_name);
466 } else if (percentage > 10) {
467 msg_format(_("%^sはうなった。", "%^s grunts."), m_name);
469 msg_format(_("%^sはよろめいた。", "%^s staggers."), m_name);
474 if (angband_strchr("G", r_ptr->d_char)) {
475 if (percentage > 95) {
476 msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name);
477 } else if (percentage > 75) {
478 msg_format(_("%sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name);
479 } else if (percentage > 50) {
480 msg_format(_("%sはうめいた。", "%^s moans."), m_name);
481 } else if (percentage > 35) {
482 msg_format(_("%^sは泣きわめいた。", "%^s wails."), m_name);
483 } else if (percentage > 20) {
484 msg_format(_("%^sは吠えた。", "%^s howls."), m_name);
485 } else if (percentage > 10) {
486 msg_format(_("%sは弱々しくうめいた。", "%^s moans softly."), m_name);
488 msg_format(_("%^sはかすかにうめいた。", "%^s sighs."), m_name);
493 if (angband_strchr("CZ", r_ptr->d_char)) {
494 if (percentage > 95) {
495 msg_format(_("%^sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name);
496 } else if (percentage > 75) {
497 msg_format(_("%^sは痛みでうなった。", "%^s snarls with pain."), m_name);
498 } else if (percentage > 50) {
499 msg_format(_("%^sは痛みでキャンキャン吠えた。", "%^s yelps in pain."), m_name);
500 } else if (percentage > 35) {
501 msg_format(_("%^sは痛みで鳴きわめいた。", "%^s howls in pain."), m_name);
502 } else if (percentage > 20) {
503 msg_format(_("%^sは苦痛のあまり鳴きわめいた。", "%^s howls in agony."), m_name);
504 } else if (percentage > 10) {
505 msg_format(_("%^sは苦痛でもだえ苦しんだ。", "%^s writhes in agony."), m_name);
507 msg_format(_("%^sは弱々しく吠えた。", "%^s yelps feebly."), m_name);
512 if (angband_strchr("Xbilqrt", r_ptr->d_char)) {
513 if (percentage > 95) {
514 msg_format(_("%^sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name);
515 } else if (percentage > 75) {
516 msg_format(_("%^sは痛みでうなった。", "%^s grunts with pain."), m_name);
517 } else if (percentage > 50) {
518 msg_format(_("%^sは痛みで叫んだ。", "%^s squeals in pain."), m_name);
519 } else if (percentage > 35) {
520 msg_format(_("%^sは痛みで絶叫した。", "%^s shrieks in pain."), m_name);
521 } else if (percentage > 20) {
522 msg_format(_("%^sは苦痛のあまり絶叫した。", "%^s shrieks in agony."), m_name);
523 } else if (percentage > 10) {
524 msg_format(_("%^sは苦痛でもだえ苦しんだ。", "%^s writhes in agony."), m_name);
526 msg_format(_("%^sは弱々しく叫んだ。", "%^s cries out feebly."), m_name);
531 if (percentage > 95) {
532 msg_format(_("%^sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name);
533 } else if (percentage > 75) {
534 msg_format(_("%^sは痛みでうなった。", "%^s grunts with pain."), m_name);
535 } else if (percentage > 50) {
536 msg_format(_("%^sは痛みで叫んだ。", "%^s cries out in pain."), m_name);
537 } else if (percentage > 35) {
538 msg_format(_("%^sは痛みで絶叫した。", "%^s screams in pain."), m_name);
539 } else if (percentage > 20) {
540 msg_format(_("%^sは苦痛のあまり絶叫した。", "%^s screams in agony."), m_name);
541 } else if (percentage > 10) {
542 msg_format(_("%^sは苦痛でもだえ苦しんだ。", "%^s writhes in agony."), m_name);
544 msg_format(_("%^sは弱々しく叫んだ。", "%^s cries out feebly."), m_name);