OSDN Git Service

Merge branch 'master' of https://github.com/hengband/hengband
[hengbandforosx/hengbandosx.git] / src / player-info / self-info.cpp
1 /*!
2  * @brief 自己分析処理/ Self knowledge
3  * @date 2018/09/07
4  * @author deskull
5  * <pre>
6  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
7  * This software may be copied and distributed for educational, research,
8  * and not for profit purposes provided that this copyright and statement
9  * are included in all such copies.  Other copyrights may also apply.
10  * </pre>
11  */
12
13 #include "player-info/self-info.h"
14 #include "avatar/avatar.h"
15 #include "io/input-key-acceptor.h"
16 #include "object-enchant/trc-types.h"
17 #include "player-info/base-status-info.h"
18 #include "player-info/body-improvement-info.h"
19 #include "player-info/class-ability-info.h"
20 #include "player-info/mutation-info.h"
21 #include "player-info/race-ability-info.h"
22 #include "player-info/race-info.h"
23 #include "player-info/resistance-info.h"
24 #include "player-info/self-info-util.h"
25 #include "player-info/weapon-effect-info.h"
26 #include "player/attack-defense-types.h"
27 #include "player/player-status-flags.h"
28 #include "player/player-status.h"
29 #include "system/player-type-definition.h"
30 #include "term/gameterm.h"
31 #include "term/screen-processor.h"
32 #include "term/z-form.h"
33 #include "timed-effect/player-blindness.h"
34 #include "timed-effect/player-confusion.h"
35 #include "timed-effect/player-cut.h"
36 #include "timed-effect/player-fear.h"
37 #include "timed-effect/player-hallucination.h"
38 #include "timed-effect/player-poison.h"
39 #include "timed-effect/player-stun.h"
40 #include "timed-effect/timed-effects.h"
41 #include "view/display-self-info.h"
42
43 static void set_bad_status_info(PlayerType *player_ptr, self_info_type *self_ptr)
44 {
45     auto effects = player_ptr->effects();
46     if (effects->blindness()->is_blind()) {
47         self_ptr->info[self_ptr->line++] = _("あなたは目が見えない。", "You cannot see.");
48     }
49
50     if (effects->confusion()->is_confused()) {
51         self_ptr->info[self_ptr->line++] = _("あなたは混乱している。", "You are confused.");
52     }
53
54     if (effects->fear()->is_fearful()) {
55         self_ptr->info[self_ptr->line++] = _("あなたは恐怖に侵されている。", "You are terrified.");
56     }
57
58     if (effects->cut()->is_cut()) {
59         self_ptr->info[self_ptr->line++] = _("あなたは出血している。", "You are bleeding.");
60     }
61
62     if (effects->stun()->is_stunned()) {
63         self_ptr->info[self_ptr->line++] = _("あなたはもうろうとしている。", "You are stunned.");
64     }
65
66     if (effects->poison()->is_poisoned()) {
67         self_ptr->info[self_ptr->line++] = _("あなたは毒に侵されている。", "You are poisoned.");
68     }
69
70     if (effects->hallucination()->is_hallucinated()) {
71         self_ptr->info[self_ptr->line++] = _("あなたは幻覚を見ている。", "You are hallucinating.");
72     }
73 }
74
75 static void set_curse_info(PlayerType *player_ptr, self_info_type *self_ptr)
76 {
77     if (player_ptr->cursed.has(CurseTraitType::TY_CURSE)) {
78         self_ptr->info[self_ptr->line++] = _("あなたは邪悪な怨念に包まれている。", "You carry an ancient foul curse.");
79     }
80
81     if (has_aggravate(player_ptr)) {
82         self_ptr->info[self_ptr->line++] = _("あなたはモンスターを怒らせている。", "You aggravate monsters.");
83     }
84
85     if (player_ptr->cursed.has(CurseTraitType::DRAIN_EXP)) {
86         self_ptr->info[self_ptr->line++] = _("あなたは経験値を吸われている。", "You occasionally lose experience for no reason.");
87     }
88
89     if (player_ptr->cursed.has(CurseTraitType::SLOW_REGEN)) {
90         self_ptr->info[self_ptr->line++] = _("あなたの回復力は非常に遅い。", "You regenerate slowly.");
91     }
92
93     if (player_ptr->cursed.has(CurseTraitType::ADD_L_CURSE)) {
94         self_ptr->info[self_ptr->line++] = _("あなたの弱い呪いは増える。", "Your weak curses multiply.");
95     } /* 暫定的 -- henkma */
96
97     if (player_ptr->cursed.has(CurseTraitType::ADD_H_CURSE)) {
98         self_ptr->info[self_ptr->line++] = _("あなたの強い呪いは増える。", "Your heavy curses multiply.");
99     } /* 暫定的 -- henkma */
100
101     if (player_ptr->cursed.has(CurseTraitType::CALL_ANIMAL)) {
102         self_ptr->info[self_ptr->line++] = _("あなたは動物に狙われている。", "You attract animals.");
103     }
104
105     if (player_ptr->cursed.has(CurseTraitType::CALL_DEMON)) {
106         self_ptr->info[self_ptr->line++] = _("あなたは悪魔に狙われている。", "You attract demons.");
107     }
108
109     if (player_ptr->cursed.has(CurseTraitType::CALL_DRAGON)) {
110         self_ptr->info[self_ptr->line++] = _("あなたはドラゴンに狙われている。", "You attract dragons.");
111     }
112
113     if (player_ptr->cursed.has(CurseTraitType::COWARDICE)) {
114         self_ptr->info[self_ptr->line++] = _("あなたは時々臆病になる。", "You are subject to cowardice.");
115     }
116
117     if (player_ptr->cursed.has(CurseTraitType::BERS_RAGE)) {
118         self_ptr->info[self_ptr->line++] = _("あなたは狂戦士化の発作を起こす。", "You are subject to berserker fits.");
119     }
120
121     if (player_ptr->cursed.has(CurseTraitType::TELEPORT)) {
122         self_ptr->info[self_ptr->line++] = _("あなたの位置はひじょうに不安定だ。", "Your position is very uncertain.");
123     }
124
125     if (player_ptr->cursed.has(CurseTraitType::LOW_MELEE)) {
126         self_ptr->info[self_ptr->line++] = _("あなたの武器は攻撃を外しやすい。", "Your weapon causes you to miss blows.");
127     }
128
129     if (player_ptr->cursed.has(CurseTraitType::LOW_AC)) {
130         self_ptr->info[self_ptr->line++] = _("あなたは攻撃を受けやすい。", "You are subject to be hit.");
131     }
132
133     if (player_ptr->cursed.has(CurseTraitType::HARD_SPELL)) {
134         self_ptr->info[self_ptr->line++] = _("あなたは魔法を失敗しやすい。", "Your spells fail more frequently.");
135     }
136
137     if (player_ptr->cursed.has(CurseTraitType::FAST_DIGEST)) {
138         self_ptr->info[self_ptr->line++] = _("あなたはすぐお腹がへる。", "You have a good appetite.");
139     }
140
141     if (player_ptr->cursed.has(CurseTraitType::DRAIN_HP)) {
142         self_ptr->info[self_ptr->line++] = _("あなたは体力を吸われている。", "You occasionally lose hit points for no reason.");
143     }
144
145     if (player_ptr->cursed.has(CurseTraitType::DRAIN_MANA)) {
146         self_ptr->info[self_ptr->line++] = _("あなたは魔力を吸われている。", "You occasionally lose spell points for no reason.");
147     }
148 }
149
150 static void set_special_attack_info(PlayerType *player_ptr, self_info_type *self_ptr)
151 {
152     if (player_ptr->special_attack & ATTACK_CONFUSE) {
153         self_ptr->info[self_ptr->line++] = _("あなたの手は赤く輝いている。", "Your hands are glowing dull red.");
154     }
155
156     if (player_ptr->special_attack & ATTACK_FIRE) {
157         self_ptr->info[self_ptr->line++] = _("あなたの手は火炎に覆われている。", "You can strike the enemy with flame.");
158     }
159
160     if (player_ptr->special_attack & ATTACK_COLD) {
161         self_ptr->info[self_ptr->line++] = _("あなたの手は冷気に覆われている。", "You can strike the enemy with cold.");
162     }
163
164     if (player_ptr->special_attack & ATTACK_ACID) {
165         self_ptr->info[self_ptr->line++] = _("あなたの手は酸に覆われている。", "You can strike the enemy with acid.");
166     }
167
168     if (player_ptr->special_attack & ATTACK_ELEC) {
169         self_ptr->info[self_ptr->line++] = _("あなたの手は電撃に覆われている。", "You can strike the enemy with electoric shock.");
170     }
171
172     if (player_ptr->special_attack & ATTACK_POIS) {
173         self_ptr->info[self_ptr->line++] = _("あなたの手は毒に覆われている。", "You can strike the enemy with poison.");
174     }
175 }
176
177 static void set_esp_info(PlayerType *player_ptr, self_info_type *self_ptr)
178 {
179     if (player_ptr->telepathy) {
180         self_ptr->info[self_ptr->line++] = _("あなたはテレパシー能力を持っている。", "You have ESP.");
181     }
182
183     if (player_ptr->esp_animal) {
184         self_ptr->info[self_ptr->line++] = _("あなたは自然界の生物の存在を感じる能力を持っている。", "You sense natural creatures.");
185     }
186
187     if (player_ptr->esp_undead) {
188         self_ptr->info[self_ptr->line++] = _("あなたはアンデッドの存在を感じる能力を持っている。", "You sense undead.");
189     }
190
191     if (player_ptr->esp_demon) {
192         self_ptr->info[self_ptr->line++] = _("あなたは悪魔の存在を感じる能力を持っている。", "You sense demons.");
193     }
194
195     if (player_ptr->esp_orc) {
196         self_ptr->info[self_ptr->line++] = _("あなたはオークの存在を感じる能力を持っている。", "You sense orcs.");
197     }
198
199     if (player_ptr->esp_troll) {
200         self_ptr->info[self_ptr->line++] = _("あなたはトロルの存在を感じる能力を持っている。", "You sense trolls.");
201     }
202
203     if (player_ptr->esp_giant) {
204         self_ptr->info[self_ptr->line++] = _("あなたは巨人の存在を感じる能力を持っている。", "You sense giants.");
205     }
206
207     if (player_ptr->esp_dragon) {
208         self_ptr->info[self_ptr->line++] = _("あなたはドラゴンの存在を感じる能力を持っている。", "You sense dragons.");
209     }
210
211     if (player_ptr->esp_human) {
212         self_ptr->info[self_ptr->line++] = _("あなたは人間の存在を感じる能力を持っている。", "You sense humans.");
213     }
214
215     if (player_ptr->esp_evil) {
216         self_ptr->info[self_ptr->line++] = _("あなたは邪悪な生き物の存在を感じる能力を持っている。", "You sense evil creatures.");
217     }
218
219     if (player_ptr->esp_good) {
220         self_ptr->info[self_ptr->line++] = _("あなたは善良な生き物の存在を感じる能力を持っている。", "You sense good creatures.");
221     }
222
223     if (player_ptr->esp_nonliving) {
224         self_ptr->info[self_ptr->line++] = _("あなたは活動する無生物体の存在を感じる能力を持っている。", "You sense non-living creatures.");
225     }
226
227     if (player_ptr->esp_unique) {
228         self_ptr->info[self_ptr->line++] = _("あなたは特別な強敵の存在を感じる能力を持っている。", "You sense unique monsters.");
229     }
230 }
231
232 /*!
233  * @brief 自己分析処理(Nethackからのアイデア) / self-knowledge... idea from nethack.
234  * @details
235  * <pre>
236  * Useful for determining powers and
237  * resistences of items.  It saves the screen, clears it, then starts listing
238  * attributes, a screenful at a time.  (There are a LOT of attributes to
239  * list.  It will probably take 2 or 3 screens for a powerful character whose
240  * using several artifacts...) -CFT
241  *
242  * It is now a lot more efficient. -BEN-
243  *
244  * See also "identify_fully()".
245  *
246  * Use the "show_file()" method, perhaps.
247  * </pre>
248  */
249 void self_knowledge(PlayerType *player_ptr)
250 {
251     self_info_type tmp_si;
252     self_info_type *self_ptr = initialize_self_info_type(&tmp_si);
253     display_life_rating(player_ptr, self_ptr);
254     chg_virtue(player_ptr, Virtue::KNOWLEDGE, 1);
255     chg_virtue(player_ptr, Virtue::ENLIGHTEN, 1);
256     display_max_base_status(player_ptr, self_ptr);
257     display_virtue(player_ptr, self_ptr);
258     self_ptr->info[self_ptr->line++] = "";
259     if (player_ptr->mimic_form != MimicKindType::NONE) {
260         display_mimic_race_ability(player_ptr, self_ptr);
261     } else {
262         set_race_ability_info(player_ptr, self_ptr);
263     }
264
265     set_class_ability_info(player_ptr, self_ptr);
266     set_mutation_info(player_ptr, self_ptr);
267     set_bad_status_info(player_ptr, self_ptr);
268     set_curse_info(player_ptr, self_ptr);
269     set_body_improvement_info_1(player_ptr, self_ptr);
270     set_special_attack_info(player_ptr, self_ptr);
271     switch (player_ptr->action) {
272     case ACTION_SEARCH:
273         self_ptr->info[self_ptr->line++] = _("あなたはひじょうに注意深く周囲を見渡している。", "You are looking around very carefully.");
274         break;
275     }
276
277     set_body_improvement_info_2(player_ptr, self_ptr);
278     set_esp_info(player_ptr, self_ptr);
279     set_body_improvement_info_3(player_ptr, self_ptr);
280     set_element_resistance_info(player_ptr, self_ptr);
281     set_high_resistance_info(player_ptr, self_ptr);
282     set_body_improvement_info_4(player_ptr, self_ptr);
283     set_status_sustain_info(player_ptr, self_ptr);
284     set_equipment_influence(player_ptr, self_ptr);
285     set_weapon_effect_info(player_ptr, self_ptr);
286     display_self_info(self_ptr);
287 }
288
289 /*!
290  * @brief 魔法効果時間のターン数に基づいて表現IDを返す。
291  * @param dur 効果ターン数
292  * @return 効果時間の表現ID
293  */
294 static int report_magics_aux(int dur)
295 {
296     if (dur <= 5) {
297         return 0;
298     } else if (dur <= 10) {
299         return 1;
300     } else if (dur <= 20) {
301         return 2;
302     } else if (dur <= 50) {
303         return 3;
304     } else if (dur <= 100) {
305         return 4;
306     } else if (dur <= 200) {
307         return 5;
308     } else {
309         return 6;
310     }
311 }
312
313 static concptr report_magic_durations[] = { _("ごく短い間", "for a short time"), _("少しの間", "for a little while"), _("しばらくの間", "for a while"),
314     _("多少長い間", "for a long while"), _("長い間", "for a long time"), _("非常に長い間", "for a very long time"),
315     _("信じ難いほど長い間", "for an incredibly long time"), _("モンスターを攻撃するまで", "until you hit a monster") };
316
317 /*!
318  * @brief 現在の一時的効果一覧を返す / Report all currently active magical effects.
319  */
320 void report_magics(PlayerType *player_ptr)
321 {
322     int i = 0;
323     concptr info[128];
324     int info2[128];
325     const auto effects = player_ptr->effects();
326     const auto blindness = effects->blindness();
327     if (blindness->is_blind()) {
328         info2[i] = report_magics_aux(blindness->current());
329         info[i++] = _("あなたは目が見えない", "You cannot see");
330     }
331
332     const auto confusion = effects->confusion();
333     if (confusion->is_confused()) {
334         info2[i] = report_magics_aux(confusion->current());
335         info[i++] = _("あなたは混乱している", "You are confused");
336     }
337
338     if (effects->fear()->is_fearful()) {
339         info2[i] = report_magics_aux(effects->fear()->current());
340         info[i++] = _("あなたは恐怖に侵されている", "You are terrified");
341     }
342
343     const auto player_poison = effects->poison();
344     if (player_poison->is_poisoned()) {
345         info2[i] = report_magics_aux(player_poison->current());
346         info[i++] = _("あなたは毒に侵されている", "You are poisoned");
347     }
348
349     auto hallucination = effects->hallucination();
350     if (hallucination->is_hallucinated()) {
351         info2[i] = report_magics_aux(hallucination->current());
352         info[i++] = _("あなたは幻覚を見ている", "You are hallucinating");
353     }
354
355     if (player_ptr->blessed) {
356         info2[i] = report_magics_aux(player_ptr->blessed);
357         info[i++] = _("あなたは高潔さを感じている", "You feel rightous");
358     }
359
360     if (player_ptr->hero) {
361         info2[i] = report_magics_aux(player_ptr->hero);
362         info[i++] = _("あなたはヒーロー気分だ", "You feel heroic");
363     }
364
365     if (is_shero(player_ptr)) {
366         info2[i] = report_magics_aux(player_ptr->shero);
367         info[i++] = _("あなたは戦闘狂だ", "You are in a battle rage");
368     }
369
370     if (player_ptr->protevil) {
371         info2[i] = report_magics_aux(player_ptr->protevil);
372         info[i++] = _("あなたは邪悪なる存在から守られている", "You are protected from evil");
373     }
374
375     if (player_ptr->shield) {
376         info2[i] = report_magics_aux(player_ptr->shield);
377         info[i++] = _("あなたは神秘のシールドで守られている", "You are protected by a mystic shield");
378     }
379
380     if (player_ptr->invuln) {
381         info2[i] = report_magics_aux(player_ptr->invuln);
382         info[i++] = _("あなたは無敵だ", "You are invulnerable");
383     }
384
385     if (player_ptr->wraith_form) {
386         info2[i] = report_magics_aux(player_ptr->wraith_form);
387         info[i++] = _("あなたは幽体化している", "You are incorporeal");
388     }
389
390     if (player_ptr->special_attack & ATTACK_CONFUSE) {
391         info2[i] = 7;
392         info[i++] = _("あなたの手は赤く輝いている", "Your hands are glowing dull red.");
393     }
394
395     if (player_ptr->word_recall) {
396         info2[i] = report_magics_aux(player_ptr->word_recall);
397         info[i++] = _("この後帰還の詔が発動する", "You are waiting to be recalled");
398     }
399
400     if (player_ptr->alter_reality) {
401         info2[i] = report_magics_aux(player_ptr->alter_reality);
402         info[i++] = _("この後現実変容が発動する", "You waiting to be altered");
403     }
404
405     if (player_ptr->oppose_acid) {
406         info2[i] = report_magics_aux(player_ptr->oppose_acid);
407         info[i++] = _("あなたは酸への耐性を持っている", "You are resistant to acid");
408     }
409
410     if (player_ptr->oppose_elec) {
411         info2[i] = report_magics_aux(player_ptr->oppose_elec);
412         info[i++] = _("あなたは電撃への耐性を持っている", "You are resistant to lightning");
413     }
414
415     if (player_ptr->oppose_fire) {
416         info2[i] = report_magics_aux(player_ptr->oppose_fire);
417         info[i++] = _("あなたは火への耐性を持っている", "You are resistant to fire");
418     }
419
420     if (player_ptr->oppose_cold) {
421         info2[i] = report_magics_aux(player_ptr->oppose_cold);
422         info[i++] = _("あなたは冷気への耐性を持っている", "You are resistant to cold");
423     }
424
425     if (player_ptr->oppose_pois) {
426         info2[i] = report_magics_aux(player_ptr->oppose_pois);
427         info[i++] = _("あなたは毒への耐性を持っている", "You are resistant to poison");
428     }
429
430     screen_save();
431
432     /* Erase the screen */
433     for (int k = 1; k < MAIN_TERM_MIN_ROWS; k++) {
434         prt("", k, 13);
435     }
436
437     prt(_("    現在かかっている魔法     :", "     Your Current Magic:"), 1, 15);
438     int k = 2;
439     char buf[80];
440     for (int j = 0; j < i; j++) {
441         strnfmt(buf, sizeof(buf), _("%-28s : 期間 - %s ", "%s %s."), info[j], report_magic_durations[info2[j]]);
442         prt(buf, k++, 15);
443
444         /* Every 20 entries (lines 2 to 21), start over */
445         if ((k == 22) && (j + 1 < i)) {
446             prt(_("-- 続く --", "-- more --"), k, 15);
447             inkey();
448             for (; k > 2; k--) {
449                 prt("", k, 15);
450             }
451         }
452     }
453
454     prt(_("[何かキーを押すとゲームに戻ります]", "[Press any key to continue]"), k, 13);
455     inkey();
456     screen_load();
457 }