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 m_ptr モンスターの参照ポインタ
23 * @return std::string 要求されたモンスターの説明を含む文字列
25 std::string monster_desc(PlayerType *player_ptr, 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_random_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");
150 /* Handle visible monsters, "reflexive" request */
151 if ((mode & (MD_POSSESSIVE | MD_OBJECTIVE)) == (MD_POSSESSIVE | MD_OBJECTIVE)) {
152 /* The monster is visible, so use its gender */
153 if (r_ptr->flags1 & (RF1_FEMALE)) {
154 return _("彼女自身", "herself");
155 } else if (r_ptr->flags1 & (RF1_MALE)) {
156 return _("彼自身", "himself");
158 return _("それ自身", "itself");
162 /* Handle all other visible monster requests */
165 if (m_ptr->is_pet() && !m_ptr->is_original_ap()) {
171 while (strncmp(t, "』", 2) && *t) {
176 desc = format("%s?』", buf);
178 desc = format("%s?", name);
181 desc = format("%s?", name);
184 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE) && !(is_hallucinated && !(mode & MD_IGNORE_HALLU))) {
185 if (m_ptr->mflag2.has(MonsterConstantFlagType::CHAMELEON) && !(mode & MD_TRUE_NAME)) {
191 while (strncmp(t, "』", 2) && *t) {
196 desc = format("%s?』", buf);
198 desc = format("%s?", name);
201 desc = format("%s?", name);
203 } else if (player_ptr->phase_out && !(player_ptr->riding && (&floor_ptr->m_list[player_ptr->riding] == m_ptr))) {
204 desc = format(_("%sもどき", "fake %s"), name);
208 } else if (mode & MD_INDEF_VISIBLE) {
210 desc = is_a_vowel(name[0]) ? "an " : "a ";
214 if (m_ptr->is_pet()) {
215 desc = _("あなたの", "your ");
217 desc = _("", "the ");
224 if (m_ptr->is_named()) {
225 desc.append(_("「", " called ")).append(m_ptr->nickname).append(_("」", ""));
228 if (player_ptr->riding && (&floor_ptr->m_list[player_ptr->riding] == m_ptr)) {
229 desc.append(_("(乗馬中)", "(riding)"));
232 if ((mode & MD_IGNORE_HALLU) && m_ptr->mflag2.has(MonsterConstantFlagType::CHAMELEON)) {
233 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
234 desc.append(_("(カメレオンの王)", "(Chameleon Lord)"));
236 desc.append(_("(カメレオン)", "(Chameleon)"));
240 if ((mode & MD_IGNORE_HALLU) && !m_ptr->is_original_ap()) {
241 desc.append("(").append(monraces_info[m_ptr->r_idx].name).append(")");
244 /* Handle the Possessive as a special afterthought */
245 if (mode & MD_POSSESSIVE) {
246 desc.append(_("の", "'s"));
253 * @brief ダメージを受けたモンスターの様子を記述する / Dump a message describing a monster's reaction to damage
254 * @param player_ptr プレイヤーへの参照ポインタ
255 * @param m_idx モンスター情報ID
258 * Technically should attempt to treat "Beholder"'s as jelly's
260 void message_pain(PlayerType *player_ptr, MONSTER_IDX m_idx, int dam)
262 auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
263 auto *r_ptr = &monraces_info[m_ptr->r_idx];
265 const auto m_name = monster_desc(player_ptr, m_ptr, 0);
269 msg_format(_("%^sはダメージを受けていない。", "%^s is unharmed."), m_name.data());
274 int newhp = m_ptr->hp;
275 int oldhp = newhp + dam;
276 int tmp = (newhp * 100L) / oldhp;
277 PERCENTAGE percentage = tmp;
279 if (angband_strchr(",ejmvwQ", r_ptr->d_char)) {
280 if (percentage > 95) {
281 msg_format(_("%^sはほとんど気にとめていない。", "%^s barely notices."), m_name.data());
282 } else if (percentage > 75) {
283 msg_format(_("%^sはしり込みした。", "%^s flinches."), m_name.data());
284 } else if (percentage > 50) {
285 msg_format(_("%^sは縮こまった。", "%^s squelches."), m_name.data());
286 } else if (percentage > 35) {
287 msg_format(_("%^sは痛みに震えた。", "%^s quivers in pain."), m_name.data());
288 } else if (percentage > 20) {
289 msg_format(_("%^sは身もだえした。", "%^s writhes about."), m_name.data());
290 } else if (percentage > 10) {
291 msg_format(_("%^sは苦痛で身もだえした。", "%^s writhes in agony."), m_name.data());
293 msg_format(_("%^sはぐにゃぐにゃと痙攣した。", "%^s jerks limply."), m_name.data());
298 if (angband_strchr("l", r_ptr->d_char)) {
299 if (percentage > 95) {
300 msg_format(_("%^sはほとんど気にとめていない。", "%^s barely notices."), m_name.data());
301 } else if (percentage > 75) {
302 msg_format(_("%^sはしり込みした。", "%^s flinches."), m_name.data());
303 } else if (percentage > 50) {
304 msg_format(_("%^sは躊躇した。", "%^s hesitates."), m_name.data());
305 } else if (percentage > 35) {
306 msg_format(_("%^sは痛みに震えた。", "%^s quivers in pain."), m_name.data());
307 } else if (percentage > 20) {
308 msg_format(_("%^sは身もだえした。", "%^s writhes about."), m_name.data());
309 } else if (percentage > 10) {
310 msg_format(_("%^sは苦痛で身もだえした。", "%^s writhes in agony."), m_name.data());
312 msg_format(_("%^sはぐにゃぐにゃと痙攣した。", "%^s jerks limply."), m_name.data());
317 if (angband_strchr("g#+<>", r_ptr->d_char)) {
318 if (percentage > 95) {
319 msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name.data());
320 } else if (percentage > 75) {
321 msg_format(_("%sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name.data());
322 } else if (percentage > 50) {
323 msg_format(_("%^sは雷鳴のように吠えた。", "%^s roars thunderously."), m_name.data());
324 } else if (percentage > 35) {
325 msg_format(_("%^sは苦しげに吠えた。", "%^s rumbles."), m_name.data());
326 } else if (percentage > 20) {
327 msg_format(_("%^sはうめいた。", "%^s grunts."), m_name.data());
328 } else if (percentage > 10) {
329 msg_format(_("%^sは躊躇した。", "%^s hesitates."), m_name.data());
331 msg_format(_("%^sはくしゃくしゃになった。", "%^s crumples."), m_name.data());
336 if (angband_strchr("JMR", r_ptr->d_char) || !isalpha(r_ptr->d_char)) {
337 if (percentage > 95) {
338 msg_format(_("%^sはほとんど気にとめていない。", "%^s barely notices."), m_name.data());
339 } else if (percentage > 75) {
340 msg_format(_("%^sはシーッと鳴いた。", "%^s hisses."), m_name.data());
341 } else if (percentage > 50) {
342 msg_format(_("%^sは怒って頭を上げた。", "%^s rears up in anger."), m_name.data());
343 } else if (percentage > 35) {
344 msg_format(_("%^sは猛然と威嚇した。", "%^s hisses furiously."), m_name.data());
345 } else if (percentage > 20) {
346 msg_format(_("%^sは身もだえした。", "%^s writhes about."), m_name.data());
347 } else if (percentage > 10) {
348 msg_format(_("%^sは苦痛で身もだえした。", "%^s writhes in agony."), m_name.data());
350 msg_format(_("%^sはぐにゃぐにゃと痙攣した。", "%^s jerks limply."), m_name.data());
355 if (angband_strchr("f", r_ptr->d_char)) {
356 if (percentage > 95) {
357 msg_format(_("%sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name.data());
358 } else if (percentage > 75) {
359 msg_format(_("%^sは吠えた。", "%^s roars."), m_name.data());
360 } else if (percentage > 50) {
361 msg_format(_("%^sは怒って吠えた。", "%^s growls angrily."), m_name.data());
362 } else if (percentage > 35) {
363 msg_format(_("%^sは痛みでシーッと鳴いた。", "%^s hisses with pain."), m_name.data());
364 } else if (percentage > 20) {
365 msg_format(_("%^sは痛みで弱々しく鳴いた。", "%^s mewls in pain."), m_name.data());
366 } else if (percentage > 10) {
367 msg_format(_("%^sは苦痛にうめいた。", "%^s hisses in agony."), m_name.data());
369 msg_format(_("%sは哀れな鳴き声を出した。", "%^s mewls pitifully."), m_name.data());
374 if (angband_strchr("acFIKS", r_ptr->d_char)) {
375 if (percentage > 95) {
376 msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name.data());
377 } else if (percentage > 75) {
378 msg_format(_("%^sはキーキー鳴いた。", "%^s chitters."), m_name.data());
379 } else if (percentage > 50) {
380 msg_format(_("%^sはヨロヨロ逃げ回った。", "%^s scuttles about."), m_name.data());
381 } else if (percentage > 35) {
382 msg_format(_("%^sはうるさく鳴いた。", "%^s twitters."), m_name.data());
383 } else if (percentage > 20) {
384 msg_format(_("%^sは痛みに痙攣した。", "%^s jerks in pain."), m_name.data());
385 } else if (percentage > 10) {
386 msg_format(_("%^sは苦痛で痙攣した。", "%^s jerks in agony."), m_name.data());
388 msg_format(_("%^sはピクピクひきつった。", "%^s twitches."), m_name.data());
393 if (angband_strchr("B", r_ptr->d_char)) {
394 if (percentage > 95) {
395 msg_format(_("%^sはさえずった。", "%^s chirps."), m_name.data());
396 } else if (percentage > 75) {
397 msg_format(_("%^sはピーピー鳴いた。", "%^s twitters."), m_name.data());
398 } else if (percentage > 50) {
399 msg_format(_("%^sはギャーギャー鳴いた。", "%^s squawks."), m_name.data());
400 } else if (percentage > 35) {
401 msg_format(_("%^sはギャーギャー鳴きわめいた。", "%^s chatters."), m_name.data());
402 } else if (percentage > 20) {
403 msg_format(_("%^sは苦しんだ。", "%^s jeers."), m_name.data());
404 } else if (percentage > 10) {
405 msg_format(_("%^sはのたうち回った。", "%^s flutters about."), m_name.data());
407 msg_format(_("%^sはキーキーと鳴き叫んだ。", "%^s squeaks."), m_name.data());
412 if (angband_strchr("duDLUW", r_ptr->d_char)) {
413 if (percentage > 95) {
414 msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name.data());
415 } else if (percentage > 75) {
416 msg_format(_("%^sはしり込みした。", "%^s flinches."), m_name.data());
417 } else if (percentage > 50) {
418 msg_format(_("%^sは痛みでシーッと鳴いた。", "%^s hisses in pain."), m_name.data());
419 } else if (percentage > 35) {
420 msg_format(_("%^sは痛みでうなった。", "%^s snarls with pain."), m_name.data());
421 } else if (percentage > 20) {
422 msg_format(_("%^sは痛みに吠えた。", "%^s roars with pain."), m_name.data());
423 } else if (percentage > 10) {
424 msg_format(_("%^sは苦しげに叫んだ。", "%^s gasps."), m_name.data());
426 msg_format(_("%^sは弱々しくうなった。", "%^s snarls feebly."), m_name.data());
431 if (angband_strchr("s", r_ptr->d_char)) {
432 if (percentage > 95) {
433 msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name.data());
434 } else if (percentage > 75) {
435 msg_format(_("%sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name.data());
436 } else if (percentage > 50) {
437 msg_format(_("%^sはカタカタと笑った。", "%^s rattles."), m_name.data());
438 } else if (percentage > 35) {
439 msg_format(_("%^sはよろめいた。", "%^s stumbles."), m_name.data());
440 } else if (percentage > 20) {
441 msg_format(_("%^sはカタカタ言った。", "%^s rattles."), m_name.data());
442 } else if (percentage > 10) {
443 msg_format(_("%^sはよろめいた。", "%^s staggers."), m_name.data());
445 msg_format(_("%^sはガタガタ言った。", "%^s clatters."), m_name.data());
450 if (angband_strchr("z", r_ptr->d_char)) {
451 if (percentage > 95) {
452 msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name.data());
453 } else if (percentage > 75) {
454 msg_format(_("%sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name.data());
455 } else if (percentage > 50) {
456 msg_format(_("%^sはうめいた。", "%^s groans."), m_name.data());
457 } else if (percentage > 35) {
458 msg_format(_("%sは苦しげにうめいた。", "%^s moans."), m_name.data());
459 } else if (percentage > 20) {
460 msg_format(_("%^sは躊躇した。", "%^s hesitates."), m_name.data());
461 } else if (percentage > 10) {
462 msg_format(_("%^sはうなった。", "%^s grunts."), m_name.data());
464 msg_format(_("%^sはよろめいた。", "%^s staggers."), m_name.data());
469 if (angband_strchr("G", r_ptr->d_char)) {
470 if (percentage > 95) {
471 msg_format(_("%sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name.data());
472 } else if (percentage > 75) {
473 msg_format(_("%sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name.data());
474 } else if (percentage > 50) {
475 msg_format(_("%sはうめいた。", "%^s moans."), m_name.data());
476 } else if (percentage > 35) {
477 msg_format(_("%^sは泣きわめいた。", "%^s wails."), m_name.data());
478 } else if (percentage > 20) {
479 msg_format(_("%^sは吠えた。", "%^s howls."), m_name.data());
480 } else if (percentage > 10) {
481 msg_format(_("%sは弱々しくうめいた。", "%^s moans softly."), m_name.data());
483 msg_format(_("%^sはかすかにうめいた。", "%^s sighs."), m_name.data());
488 if (angband_strchr("CZ", r_ptr->d_char)) {
489 if (percentage > 95) {
490 msg_format(_("%^sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name.data());
491 } else if (percentage > 75) {
492 msg_format(_("%^sは痛みでうなった。", "%^s snarls with pain."), m_name.data());
493 } else if (percentage > 50) {
494 msg_format(_("%^sは痛みでキャンキャン吠えた。", "%^s yelps in pain."), m_name.data());
495 } else if (percentage > 35) {
496 msg_format(_("%^sは痛みで鳴きわめいた。", "%^s howls in pain."), m_name.data());
497 } else if (percentage > 20) {
498 msg_format(_("%^sは苦痛のあまり鳴きわめいた。", "%^s howls in agony."), m_name.data());
499 } else if (percentage > 10) {
500 msg_format(_("%^sは苦痛でもだえ苦しんだ。", "%^s writhes in agony."), m_name.data());
502 msg_format(_("%^sは弱々しく吠えた。", "%^s yelps feebly."), m_name.data());
507 if (angband_strchr("Xbilqrt", r_ptr->d_char)) {
508 if (percentage > 95) {
509 msg_format(_("%^sは攻撃を気にとめていない。", "%^s ignores the attack."), m_name.data());
510 } else if (percentage > 75) {
511 msg_format(_("%^sは痛みでうなった。", "%^s grunts with pain."), m_name.data());
512 } else if (percentage > 50) {
513 msg_format(_("%^sは痛みで叫んだ。", "%^s squeals in pain."), m_name.data());
514 } else if (percentage > 35) {
515 msg_format(_("%^sは痛みで絶叫した。", "%^s shrieks in pain."), m_name.data());
516 } else if (percentage > 20) {
517 msg_format(_("%^sは苦痛のあまり絶叫した。", "%^s shrieks in agony."), m_name.data());
518 } else if (percentage > 10) {
519 msg_format(_("%^sは苦痛でもだえ苦しんだ。", "%^s writhes in agony."), m_name.data());
521 msg_format(_("%^sは弱々しく叫んだ。", "%^s cries out feebly."), m_name.data());
526 if (percentage > 95) {
527 msg_format(_("%^sは攻撃に肩をすくめた。", "%^s shrugs off the attack."), m_name.data());
528 } else if (percentage > 75) {
529 msg_format(_("%^sは痛みでうなった。", "%^s grunts with pain."), m_name.data());
530 } else if (percentage > 50) {
531 msg_format(_("%^sは痛みで叫んだ。", "%^s cries out in pain."), m_name.data());
532 } else if (percentage > 35) {
533 msg_format(_("%^sは痛みで絶叫した。", "%^s screams in pain."), m_name.data());
534 } else if (percentage > 20) {
535 msg_format(_("%^sは苦痛のあまり絶叫した。", "%^s screams in agony."), m_name.data());
536 } else if (percentage > 10) {
537 msg_format(_("%^sは苦痛でもだえ苦しんだ。", "%^s writhes in agony."), m_name.data());
539 msg_format(_("%^sは弱々しく叫んだ。", "%^s cries out feebly."), m_name.data());