OSDN Git Service

[feature] ソースファイルをC++に対応
[hengbandforosx/hengbandosx.git] / src / cmd-action / cmd-mind.c
1 /*!
2  * @brief 各職業の特殊技能実装 / Special magics
3  * @date 2014/01/15
4  * @author
5  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n
6  * This software may be copied and distributed for educational, research,\n
7  * and not for profit purposes provided that this copyright and statement\n
8  * are included in all such copies.  Other copyrights may also apply.\n
9  * 2005 henkma \n
10  * 2014 Deskull rearranged comment for Doxygen.\n
11  */
12
13 #include "cmd-action/cmd-mind.h"
14 #include "action/action-limited.h"
15 #include "core/asking-player.h"
16 #include "core/player-redraw-types.h"
17 #include "core/window-redrawer.h"
18 #include "effect/effect-characteristics.h"
19 #include "effect/effect-processor.h"
20 #include "game-option/disturbance-options.h"
21 #include "game-option/input-options.h"
22 #include "grid/grid.h"
23 #include "inventory/inventory-slot-types.h"
24 #include "io/input-key-acceptor.h"
25 #include "main/sound-definitions-table.h"
26 #include "main/sound-of-music.h"
27 #include "mind/mind-berserker.h"
28 #include "mind/mind-explanations-table.h"
29 #include "mind/mind-force-trainer.h"
30 #include "mind/mind-mindcrafter.h"
31 #include "mind/mind-mirror-master.h"
32 #include "mind/mind-ninja.h"
33 #include "mind/mind-numbers.h"
34 #include "mind/mind-power-getter.h"
35 #include "mind/mind-types.h"
36 #include "player/player-class.h"
37 #include "player/player-damage.h"
38 #include "player/player-status-table.h"
39 #include "spell-kind/spells-teleport.h"
40 #include "spell/spell-types.h"
41 #include "status/bad-status-setter.h"
42 #include "status/base-status.h"
43 #include "system/floor-type-definition.h"
44 #include "term/screen-processor.h"
45 #include "util/buffer-shaper.h"
46 #include "view/display-messages.h"
47
48 typedef struct cm_type {
49     mind_kind_type use_mind;
50     concptr mind_explanation;
51     SPELL_IDX n;
52     int b;
53     PERCENTAGE chance;
54     PERCENTAGE minfail;
55     PLAYER_LEVEL plev;
56     int old_csp;
57     mind_type spell;
58     bool cast;
59     int mana_cost;
60     bool on_mirror;
61 } cm_type;
62
63 static cm_type *initialize_cm_type(player_type *caster_ptr, cm_type *cm_ptr)
64 {
65     cm_ptr->n = 0;
66     cm_ptr->b = 0;
67     cm_ptr->minfail = 0;
68     cm_ptr->plev = caster_ptr->lev;
69     cm_ptr->old_csp = caster_ptr->csp;
70     cm_ptr->on_mirror = FALSE;
71     return cm_ptr;
72 }
73
74 static void switch_mind_kind(player_type *caster_ptr, cm_type *cm_ptr)
75 {
76     switch (caster_ptr->pclass) {
77     case CLASS_MINDCRAFTER:
78         cm_ptr->use_mind = MIND_MINDCRAFTER;
79         cm_ptr->mind_explanation = _("精神", "skill");
80         break;
81     case CLASS_FORCETRAINER:
82         cm_ptr->use_mind = MIND_KI;
83         cm_ptr->mind_explanation = _("気", "skill");
84         break;
85     case CLASS_BERSERKER:
86         cm_ptr->use_mind = MIND_BERSERKER;
87         cm_ptr->mind_explanation = _("怒り", "skill");
88         break;
89     case CLASS_MIRROR_MASTER:
90         cm_ptr->use_mind = MIND_MIRROR_MASTER;
91         cm_ptr->mind_explanation = _("鏡魔法", "skill");
92         break;
93     case CLASS_NINJA:
94         cm_ptr->use_mind = MIND_NINJUTSU;
95         cm_ptr->mind_explanation = _("精神", "skill");
96         break;
97     default:
98         cm_ptr->use_mind = (mind_kind_type)0;
99         cm_ptr->mind_explanation = _("超能力", "skill");
100         break;
101     }
102 }
103
104 static void decide_mind_ki_chance(player_type *caster_ptr, cm_type *cm_ptr)
105 {
106     if (cm_ptr->use_mind != MIND_KI)
107         return;
108
109     if (heavy_armor(caster_ptr))
110         cm_ptr->chance += 20;
111
112     if (caster_ptr->icky_wield[0])
113         cm_ptr->chance += 20;
114     else if (has_melee_weapon(caster_ptr, INVEN_MAIN_HAND))
115         cm_ptr->chance += 10;
116
117     if (caster_ptr->icky_wield[1])
118         cm_ptr->chance += 20;
119     else if (has_melee_weapon(caster_ptr, INVEN_SUB_HAND))
120         cm_ptr->chance += 10;
121
122     if (cm_ptr->n == 5)
123         for (int j = 0; j < get_current_ki(caster_ptr) / 50; j++)
124             cm_ptr->mana_cost += (j + 1) * 3 / 2;
125 }
126
127 static bool check_mind_hp_mp_sufficiency(player_type *caster_ptr, cm_type *cm_ptr)
128 {
129     if ((cm_ptr->use_mind == MIND_BERSERKER) || (cm_ptr->use_mind == MIND_NINJUTSU)) {
130         if (cm_ptr->mana_cost > caster_ptr->chp) {
131             msg_print(_("HPが足りません。", "You do not have enough hp to use this power."));
132             return FALSE;
133         }
134
135         return TRUE;
136     }
137
138     if (cm_ptr->mana_cost <= caster_ptr->csp)
139         return TRUE;
140
141     msg_print(_("MPが足りません。", "You do not have enough mana to use this power."));
142     if (!over_exert)
143         return FALSE;
144
145     return get_check(_("それでも挑戦しますか? ", "Attempt it anyway? "));
146 }
147
148 static void decide_mind_chance(player_type *caster_ptr, cm_type *cm_ptr)
149 {
150     if (cm_ptr->chance == 0)
151         return;
152
153     cm_ptr->chance -= 3 * (cm_ptr->plev - cm_ptr->spell.min_lev);
154     cm_ptr->chance += caster_ptr->to_m_chance;
155     cm_ptr->chance -= 3 * (adj_mag_stat[caster_ptr->stat_ind[mp_ptr->spell_stat]] - 1);
156     if ((cm_ptr->mana_cost > caster_ptr->csp) && (cm_ptr->use_mind != MIND_BERSERKER) && (cm_ptr->use_mind != MIND_NINJUTSU))
157         cm_ptr->chance += 5 * (cm_ptr->mana_cost - caster_ptr->csp);
158
159     cm_ptr->minfail = adj_mag_fail[caster_ptr->stat_ind[mp_ptr->spell_stat]];
160     if (cm_ptr->chance < cm_ptr->minfail)
161         cm_ptr->chance = cm_ptr->minfail;
162
163     if (caster_ptr->stun > 50)
164         cm_ptr->chance += 25;
165     else if (caster_ptr->stun)
166         cm_ptr->chance += 15;
167
168     if (cm_ptr->use_mind != MIND_KI)
169         return;
170
171     if (heavy_armor(caster_ptr))
172         cm_ptr->chance += 5;
173
174     if (caster_ptr->icky_wield[0])
175         cm_ptr->chance += 5;
176
177     if (caster_ptr->icky_wield[1])
178         cm_ptr->chance += 5;
179 }
180
181 static void check_mind_mindcrafter(player_type *caster_ptr, cm_type *cm_ptr)
182 {
183     if (cm_ptr->use_mind != MIND_MINDCRAFTER)
184         return;
185
186     if (cm_ptr->b < 5) {
187         msg_print(_("なんてこった!頭の中が真っ白になった!", "Oh, no! Your mind has gone blank!"));
188         lose_all_info(caster_ptr);
189         return;
190     }
191
192     if (cm_ptr->b < 15) {
193         msg_print(_("奇妙な光景が目の前で踊っている...", "Weird visions seem to dance before your eyes..."));
194         set_image(caster_ptr, caster_ptr->image + 5 + randint1(10));
195         return;
196     }
197
198     if (cm_ptr->b < 45) {
199         msg_print(_("あなたの頭は混乱した!", "Your brain is addled!"));
200         set_confused(caster_ptr, caster_ptr->confused + randint1(8));
201         return;
202     }
203
204     if (cm_ptr->b < 90) {
205         set_stun(caster_ptr, caster_ptr->stun + randint1(8));
206         return;
207     }
208
209     msg_format(_("%sの力が制御できない氾流となって解放された!", "Your mind unleashes its power in an uncontrollable storm!"), cm_ptr->mind_explanation);
210     project(caster_ptr, PROJECT_WHO_UNCTRL_POWER, 2 + cm_ptr->plev / 10, caster_ptr->y, caster_ptr->x, cm_ptr->plev * 2, GF_MANA,
211         PROJECT_JUMP | PROJECT_KILL | PROJECT_GRID | PROJECT_ITEM, -1);
212     caster_ptr->csp = MAX(0, caster_ptr->csp - cm_ptr->plev * MAX(1, cm_ptr->plev / 10));
213 }
214
215 static void check_mind_mirror_master(player_type *caster_ptr, cm_type *cm_ptr)
216 {
217     if (cm_ptr->use_mind != MIND_MIRROR_MASTER)
218         return;
219
220     if (cm_ptr->b < 51)
221         return;
222
223     if (cm_ptr->b < 81) {
224         msg_print(_("鏡の世界の干渉を受けた!", "Weird visions seem to dance before your eyes..."));
225         teleport_player(caster_ptr, 10, TELEPORT_PASSIVE);
226         return;
227     }
228
229     if (cm_ptr->b < 96) {
230         msg_print(_("まわりのものがキラキラ輝いている!", "Your brain is addled!"));
231         set_image(caster_ptr, caster_ptr->image + 5 + randint1(10));
232         return;
233     }
234
235     msg_format(_("%sの力が制御できない氾流となって解放された!", "Your mind unleashes its power in an uncontrollable storm!"), cm_ptr->mind_explanation);
236     project(caster_ptr, PROJECT_WHO_UNCTRL_POWER, 2 + cm_ptr->plev / 10, caster_ptr->y, caster_ptr->x, cm_ptr->plev * 2, GF_MANA,
237         PROJECT_JUMP | PROJECT_KILL | PROJECT_GRID | PROJECT_ITEM, -1);
238     caster_ptr->csp = MAX(0, caster_ptr->csp - cm_ptr->plev * MAX(1, cm_ptr->plev / 10));
239 }
240
241 static void check_mind_class(player_type *caster_ptr, cm_type *cm_ptr)
242 {
243     if ((cm_ptr->use_mind == MIND_BERSERKER) || (cm_ptr->use_mind == MIND_NINJUTSU))
244         return;
245
246     if ((cm_ptr->use_mind == MIND_KI) && (cm_ptr->n != 5) && get_current_ki(caster_ptr)) {
247         msg_print(_("気が散ってしまった...", "Your improved Force has gone away..."));
248         set_current_ki(caster_ptr, TRUE, 0);
249     }
250
251     if (randint1(100) >= (cm_ptr->chance / 2))
252         return;
253
254     cm_ptr->b = randint1(100);
255     check_mind_mindcrafter(caster_ptr, cm_ptr);
256     check_mind_mirror_master(caster_ptr, cm_ptr);
257 }
258
259 static bool switch_mind_class(player_type *caster_ptr, cm_type *cm_ptr)
260 {
261     switch (cm_ptr->use_mind) {
262     case MIND_MINDCRAFTER:
263         cm_ptr->cast = cast_mindcrafter_spell(caster_ptr, static_cast<mind_mindcrafter_type>(cm_ptr->n));
264         return TRUE;
265     case MIND_KI:
266         cm_ptr->cast = cast_force_spell(caster_ptr, static_cast<mind_force_trainer_type>(cm_ptr->n));
267         return TRUE;
268     case MIND_BERSERKER:
269         cm_ptr->cast = cast_berserk_spell(caster_ptr, static_cast<mind_berserker_type>(cm_ptr->n));
270         return TRUE;
271     case MIND_MIRROR_MASTER:
272         if (is_mirror_grid(&caster_ptr->current_floor_ptr->grid_array[caster_ptr->y][caster_ptr->x]))
273             cm_ptr->on_mirror = TRUE;
274
275         cm_ptr->cast = cast_mirror_spell(caster_ptr, static_cast<mind_mirror_master_type>(cm_ptr->n));
276         return TRUE;
277     case MIND_NINJUTSU:
278         cm_ptr->cast = cast_ninja_spell(caster_ptr, static_cast<mind_ninja_type>(cm_ptr->n));
279         return TRUE;
280     default:
281         msg_format(_("謎の能力:%d, %d", "Mystery power:%d, %d"), cm_ptr->use_mind, cm_ptr->n);
282         return FALSE;
283     }
284 }
285
286 static void mind_turn_passing(player_type *caster_ptr, cm_type *cm_ptr)
287 {
288     if (cm_ptr->on_mirror && (caster_ptr->pclass == CLASS_MIRROR_MASTER)) {
289         if (cm_ptr->n == 3 || cm_ptr->n == 5 || cm_ptr->n == 7 || cm_ptr->n == 16) {
290             take_turn(caster_ptr, 50);
291             return;
292         }
293     }
294
295     take_turn(caster_ptr, 100);
296 }
297
298 static bool judge_mind_chance(player_type *caster_ptr, cm_type *cm_ptr)
299 {
300     if (randint0(100) >= cm_ptr->chance) {
301         sound(SOUND_ZAP);
302         return switch_mind_class(caster_ptr, cm_ptr) && cm_ptr->cast;
303     }
304
305     if (flush_failure)
306         flush();
307
308     msg_format(_("%sの集中に失敗した!", "You failed to concentrate hard enough for %s!"), cm_ptr->mind_explanation);
309     sound(SOUND_FAIL);
310     check_mind_class(caster_ptr, cm_ptr);
311     return TRUE;
312 }
313
314 static void mind_reflection(player_type *caster_ptr, cm_type *cm_ptr)
315 {
316     int oops = cm_ptr->mana_cost - cm_ptr->old_csp;
317     if ((caster_ptr->csp - cm_ptr->mana_cost) < 0)
318         caster_ptr->csp_frac = 0;
319
320     caster_ptr->csp = MAX(0, caster_ptr->csp - cm_ptr->mana_cost);
321     msg_format(_("%sを集中しすぎて気を失ってしまった!", "You faint from the effort!"), cm_ptr->mind_explanation);
322     (void)set_paralyzed(caster_ptr, caster_ptr->paralyzed + randint1(5 * oops + 1));
323     if (randint0(100) >= 50)
324         return;
325
326     bool perm = randint0(100) < 25;
327     msg_print(_("自分の精神を攻撃してしまった!", "You have damaged your mind!"));
328     (void)dec_stat(caster_ptr, A_WIS, 15 + randint1(10), perm);
329 }
330
331 static void process_hard_concentration(player_type *caster_ptr, cm_type *cm_ptr)
332 {
333     if ((cm_ptr->use_mind == MIND_BERSERKER) || (cm_ptr->use_mind == MIND_NINJUTSU)) {
334         take_hit(caster_ptr, DAMAGE_USELIFE, cm_ptr->mana_cost, _("過度の集中", "concentrating too hard"), -1);
335         caster_ptr->redraw |= PR_HP;
336         return;
337     }
338
339     if (cm_ptr->mana_cost > cm_ptr->old_csp) {
340         mind_reflection(caster_ptr, cm_ptr);
341         return;
342     }
343
344     caster_ptr->csp -= cm_ptr->mana_cost;
345     if (caster_ptr->csp < 0)
346         caster_ptr->csp = 0;
347
348     if ((cm_ptr->use_mind == MIND_MINDCRAFTER) && (cm_ptr->n == 13)) {
349         caster_ptr->csp = 0;
350         caster_ptr->csp_frac = 0;
351     }
352 }
353
354 /*!
355  * @brief 特殊技能コマンドのメインルーチン /
356  * @return なし
357  */
358 void do_cmd_mind(player_type *caster_ptr)
359 {
360     cm_type tmp_cm;
361     cm_type *cm_ptr = initialize_cm_type(caster_ptr, &tmp_cm);
362     if (cmd_limit_confused(caster_ptr) || !get_mind_power(caster_ptr, &cm_ptr->n, FALSE))
363         return;
364
365     switch_mind_kind(caster_ptr, cm_ptr);
366     cm_ptr->spell = mind_powers[cm_ptr->use_mind].info[cm_ptr->n];
367     cm_ptr->chance = cm_ptr->spell.fail;
368     cm_ptr->mana_cost = cm_ptr->spell.mana_cost;
369     decide_mind_ki_chance(caster_ptr, cm_ptr);
370     if (!check_mind_hp_mp_sufficiency(caster_ptr, cm_ptr))
371         return;
372
373     decide_mind_chance(caster_ptr, cm_ptr);
374     if (cm_ptr->chance > 95)
375         cm_ptr->chance = 95;
376
377     if (!judge_mind_chance(caster_ptr, cm_ptr))
378         return;
379
380     mind_turn_passing(caster_ptr, cm_ptr);
381     process_hard_concentration(caster_ptr, cm_ptr);
382     caster_ptr->redraw |= PR_MANA;
383     caster_ptr->window_flags |= PW_PLAYER;
384     caster_ptr->window_flags |= PW_SPELL;
385 }
386
387 static mind_kind_type decide_use_mind_browse(player_type *caster_ptr)
388 {
389     switch (caster_ptr->pclass) {
390     case CLASS_MINDCRAFTER:
391         return MIND_MINDCRAFTER;
392     case CLASS_FORCETRAINER:
393         return MIND_KI;
394     case CLASS_BERSERKER:
395         return MIND_BERSERKER;
396     case CLASS_NINJA:
397         return MIND_NINJUTSU;
398     case CLASS_MIRROR_MASTER:
399         return MIND_MIRROR_MASTER;
400     default:
401         return (mind_kind_type)0; // 実質CLASS_MINDCRAFTERと同じ.
402     }
403 }
404
405 /*!
406  * @brief 現在プレイヤーが使用可能な特殊技能の一覧表示 /
407  * @return なし
408  */
409 void do_cmd_mind_browse(player_type *caster_ptr)
410 {
411     SPELL_IDX n = 0;
412     char temp[62 * 5];
413     mind_kind_type use_mind = decide_use_mind_browse(caster_ptr);
414     screen_save();
415     while (TRUE) {
416         if (!get_mind_power(caster_ptr, &n, TRUE)) {
417             screen_load();
418             return;
419         }
420
421         term_erase(12, 21, 255);
422         term_erase(12, 20, 255);
423         term_erase(12, 19, 255);
424         term_erase(12, 18, 255);
425         term_erase(12, 17, 255);
426         term_erase(12, 16, 255);
427         shape_buffer(mind_tips[use_mind][n], 62, temp, sizeof(temp));
428         for (int j = 0, line = 17; temp[j]; j += (1 + strlen(&temp[j]))) {
429             prt(&temp[j], line, 15);
430             line++;
431         }
432
433         switch (use_mind) {
434         case MIND_MIRROR_MASTER:
435         case MIND_NINJUTSU:
436             prt(_("何かキーを押して下さい。", "Hit any key."), 0, 0);
437             (void)inkey();
438             break;
439         default:
440             break;
441         }
442     }
443 }