OSDN Git Service

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