OSDN Git Service

Merge pull request #716 from sikabane-works/release/3.0.0Alpha16
[hengbandforosx/hengbandosx.git] / src / core / player-processor.cpp
1 #include "core/player-processor.h"
2 #include "action/run-execution.h"
3 #include "action/travel-execution.h"
4 #include "core/disturbance.h"
5 #include "core/player-redraw-types.h"
6 #include "core/player-update-types.h"
7 #include "core/special-internal-keys.h"
8 #include "core/speed-table.h"
9 #include "core/stuff-handler.h"
10 #include "core/window-redrawer.h"
11 #include "floor/floor-save-util.h"
12 #include "floor/floor-util.h"
13 #include "floor/wild.h"
14 #include "game-option/disturbance-options.h"
15 #include "game-option/map-screen-options.h"
16 #include "grid/grid.h"
17 #include "inventory/pack-overflow.h"
18 #include "io/cursor.h"
19 #include "io/input-key-acceptor.h"
20 #include "io/input-key-processor.h"
21 #include "io/input-key-requester.h"
22 #include "mind/mind-force-trainer.h"
23 #include "mind/mind-sniper.h"
24 #include "monster-floor/monster-generator.h"
25 #include "monster-floor/place-monster-types.h"
26 #include "monster-race/monster-race-hook.h"
27 #include "monster-race/monster-race.h"
28 #include "monster-race/race-flags1.h"
29 #include "monster/monster-describer.h"
30 #include "monster/monster-flag-types.h"
31 #include "monster/monster-list.h"
32 #include "monster/monster-status-setter.h"
33 #include "monster/monster-status.h"
34 #include "monster/monster-update.h"
35 #include "monster/monster-util.h"
36 #include "mutation/mutation-investor-remover.h"
37 #include "player/attack-defense-types.h"
38 #include "player/eldritch-horror.h"
39 #include "player/player-skill.h"
40 #include "player/special-defense-types.h"
41 #include "spell-kind/spells-random.h"
42 #include "spell-realm/spells-hex.h"
43 #include "spell-realm/spells-song.h"
44 #include "status/action-setter.h"
45 #include "system/floor-type-definition.h"
46 #include "term/screen-processor.h"
47 #include "util/bit-flags-calculator.h"
48 #include "view/display-messages.h"
49 #include "window/display-sub-windows.h"
50 #include "world/world-turn-processor.h"
51
52 bool load = TRUE;
53 bool can_save = FALSE;
54
55 static void process_fishing(player_type *creature_ptr)
56 {
57     term_xtra(TERM_XTRA_DELAY, 10);
58     if (one_in_(1000)) {
59         MONRACE_IDX r_idx;
60         bool success = FALSE;
61         get_mon_num_prep(creature_ptr, monster_is_fishing_target, NULL);
62         r_idx = get_mon_num(creature_ptr, 0,
63             is_in_dungeon(creature_ptr) ? creature_ptr->current_floor_ptr->dun_level
64                                                        : wilderness[creature_ptr->wilderness_y][creature_ptr->wilderness_x].level,
65             0);
66         msg_print(NULL);
67         if (r_idx && one_in_(2)) {
68             POSITION y, x;
69             y = creature_ptr->y + ddy[creature_ptr->fishing_dir];
70             x = creature_ptr->x + ddx[creature_ptr->fishing_dir];
71             if (place_monster_aux(creature_ptr, 0, y, x, r_idx, PM_NO_KAGE)) {
72                 GAME_TEXT m_name[MAX_NLEN];
73                 monster_desc(creature_ptr, m_name, &creature_ptr->current_floor_ptr->m_list[creature_ptr->current_floor_ptr->grid_array[y][x].m_idx], 0);
74                 msg_format(_("%sが釣れた!", "You have a good catch!"), m_name);
75                 success = TRUE;
76             }
77         }
78
79         if (!success) {
80             msg_print(_("餌だけ食われてしまった!くっそ~!", "Damn!  The fish stole your bait!"));
81         }
82
83         disturb(creature_ptr, FALSE, TRUE);
84     }
85 }
86
87 bool continuous_action_running(player_type *creature_ptr)
88 {
89     return creature_ptr->running || travel.run || command_rep || (creature_ptr->action == ACTION_REST) || (creature_ptr->action == ACTION_FISH);
90 }
91
92 /*!
93  * @brief プレイヤーの行動処理 / Process the player
94  * @return なし
95  * @note
96  * Notice the annoying code to handle "pack overflow", which\n
97  * must come first just in case somebody manages to corrupt\n
98  * the savefiles by clever use of menu commands or something.\n
99  */
100 void process_player(player_type *creature_ptr)
101 {
102     if (creature_ptr->hack_mutation) {
103         msg_print(_("何か変わった気がする!", "You feel different!"));
104         (void)gain_mutation(creature_ptr, 0);
105         creature_ptr->hack_mutation = FALSE;
106     }
107
108     if (creature_ptr->invoking_midnight_curse) {
109         int count = 0;
110         activate_ty_curse(creature_ptr, FALSE, &count);
111         creature_ptr->invoking_midnight_curse = FALSE;
112     }
113
114     if (creature_ptr->phase_out) {
115         for (MONSTER_IDX m_idx = 1; m_idx < creature_ptr->current_floor_ptr->m_max; m_idx++) {
116             monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[m_idx];
117             if (!monster_is_valid(m_ptr))
118                 continue;
119
120             m_ptr->mflag2.set({MFLAG2::MARK, MFLAG2::SHOW});
121             update_monster(creature_ptr, m_idx, FALSE);
122         }
123
124         print_time(creature_ptr);
125     } else if (!(load && creature_ptr->energy_need <= 0)) {
126         creature_ptr->energy_need -= SPEED_TO_ENERGY(creature_ptr->pspeed);
127     }
128
129     if (creature_ptr->energy_need > 0)
130         return;
131     if (!command_rep) {
132         print_time(creature_ptr);
133     }
134
135     if (fresh_once && (continuous_action_running(creature_ptr) || !command_rep)) {
136         stop_term_fresh();
137     }
138
139     if (creature_ptr->resting < 0) {
140         if (creature_ptr->resting == COMMAND_ARG_REST_FULL_HEALING) {
141             if ((creature_ptr->chp == creature_ptr->mhp) && (creature_ptr->csp >= creature_ptr->msp)) {
142                 set_action(creature_ptr, ACTION_NONE);
143             }
144         } else if (creature_ptr->resting == COMMAND_ARG_REST_UNTIL_DONE) {
145             if ((creature_ptr->chp == creature_ptr->mhp) && (creature_ptr->csp >= creature_ptr->msp) && !creature_ptr->blind && !creature_ptr->confused
146                 && !creature_ptr->poisoned && !creature_ptr->afraid && !creature_ptr->stun && !creature_ptr->cut && !creature_ptr->slow
147                 && !creature_ptr->paralyzed && !creature_ptr->image && !creature_ptr->word_recall && !creature_ptr->alter_reality) {
148                 set_action(creature_ptr, ACTION_NONE);
149             }
150         }
151     }
152
153     if (creature_ptr->action == ACTION_FISH)
154         process_fishing(creature_ptr);
155
156     if (check_abort) {
157         if (continuous_action_running(creature_ptr)) {
158             inkey_scan = TRUE;
159             if (inkey()) {
160                 flush();
161                 disturb(creature_ptr, FALSE, TRUE);
162                 msg_print(_("中断しました。", "Canceled."));
163             }
164         }
165     }
166
167     if (creature_ptr->riding && !creature_ptr->confused && !creature_ptr->blind) {
168         monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[creature_ptr->riding];
169         monster_race *r_ptr = &r_info[m_ptr->r_idx];
170         if (monster_csleep_remaining(m_ptr)) {
171             GAME_TEXT m_name[MAX_NLEN];
172             (void)set_monster_csleep(creature_ptr, creature_ptr->riding, 0);
173             monster_desc(creature_ptr, m_name, m_ptr, 0);
174             msg_format(_("%^sを起こした。", "You have woken %s up."), m_name);
175         }
176
177         if (monster_stunned_remaining(m_ptr)) {
178             if (set_monster_stunned(creature_ptr, creature_ptr->riding,
179                     (randint0(r_ptr->level) < creature_ptr->skill_exp[GINOU_RIDING]) ? 0 : (monster_stunned_remaining(m_ptr) - 1))) {
180                 GAME_TEXT m_name[MAX_NLEN];
181                 monster_desc(creature_ptr, m_name, m_ptr, 0);
182                 msg_format(_("%^sを朦朧状態から立ち直らせた。", "%^s is no longer stunned."), m_name);
183             }
184         }
185
186         if (monster_confused_remaining(m_ptr)) {
187             if (set_monster_confused(creature_ptr, creature_ptr->riding,
188                     (randint0(r_ptr->level) < creature_ptr->skill_exp[GINOU_RIDING]) ? 0 : (monster_confused_remaining(m_ptr) - 1))) {
189                 GAME_TEXT m_name[MAX_NLEN];
190                 monster_desc(creature_ptr, m_name, m_ptr, 0);
191                 msg_format(_("%^sを混乱状態から立ち直らせた。", "%^s is no longer confused."), m_name);
192             }
193         }
194
195         if (monster_fear_remaining(m_ptr)) {
196             if (set_monster_monfear(creature_ptr, creature_ptr->riding,
197                     (randint0(r_ptr->level) < creature_ptr->skill_exp[GINOU_RIDING]) ? 0 : (monster_fear_remaining(m_ptr) - 1))) {
198                 GAME_TEXT m_name[MAX_NLEN];
199                 monster_desc(creature_ptr, m_name, m_ptr, 0);
200                 msg_format(_("%^sを恐怖から立ち直らせた。", "%^s is no longer afraid."), m_name);
201             }
202         }
203
204         handle_stuff(creature_ptr);
205     }
206
207     load = FALSE;
208     if (creature_ptr->lightspeed)
209         set_lightspeed(creature_ptr, creature_ptr->lightspeed - 1, TRUE);
210
211     if ((creature_ptr->pclass == CLASS_FORCETRAINER) && get_current_ki(creature_ptr)) {
212         if (get_current_ki(creature_ptr) < 40)
213             set_current_ki(creature_ptr, TRUE, 0);
214         else
215             set_current_ki(creature_ptr, FALSE, -40);
216         creature_ptr->update |= (PU_BONUS);
217     }
218
219     if (creature_ptr->action == ACTION_LEARN) {
220         s32b cost = 0L;
221         u32b cost_frac = (creature_ptr->msp + 30L) * 256L;
222         s64b_lshift(&cost, &cost_frac, 16);
223         if (s64b_cmp(creature_ptr->csp, creature_ptr->csp_frac, cost, cost_frac) < 0) {
224             creature_ptr->csp = 0;
225             creature_ptr->csp_frac = 0;
226             set_action(creature_ptr, ACTION_NONE);
227         } else {
228             s64b_sub(&(creature_ptr->csp), &(creature_ptr->csp_frac), cost, cost_frac);
229         }
230
231         creature_ptr->redraw |= PR_MANA;
232     }
233
234     if (creature_ptr->special_defense & KATA_MASK) {
235         if (creature_ptr->special_defense & KATA_MUSOU) {
236             if (creature_ptr->csp < 3) {
237                 set_action(creature_ptr, ACTION_NONE);
238             } else {
239                 creature_ptr->csp -= 2;
240                 creature_ptr->redraw |= (PR_MANA);
241             }
242         }
243     }
244
245     /*** Handle actual user input ***/
246     while (creature_ptr->energy_need <= 0) {
247         creature_ptr->window_flags |= PW_PLAYER;
248         creature_ptr->sutemi = FALSE;
249         creature_ptr->counter = FALSE;
250         creature_ptr->now_damaged = FALSE;
251
252         update_monsters(creature_ptr, FALSE);
253         handle_stuff(creature_ptr);
254         move_cursor_relative(creature_ptr->y, creature_ptr->x);
255         if (fresh_before)
256             term_fresh_force();
257
258         pack_overflow(creature_ptr);
259         if (!command_new)
260             command_see = FALSE;
261
262         free_turn(creature_ptr);
263         if (creature_ptr->phase_out) {
264             move_cursor_relative(creature_ptr->y, creature_ptr->x);
265             command_cmd = SPECIAL_KEY_BUILDING;
266             process_command(creature_ptr);
267         } else if (creature_ptr->paralyzed || (creature_ptr->stun >= 100)) {
268             take_turn(creature_ptr, 100);
269         } else if (creature_ptr->action == ACTION_REST) {
270             if (creature_ptr->resting > 0) {
271                 creature_ptr->resting--;
272                 if (!creature_ptr->resting)
273                     set_action(creature_ptr, ACTION_NONE);
274                 creature_ptr->redraw |= (PR_STATE);
275             }
276
277             take_turn(creature_ptr, 100);
278         } else if (creature_ptr->action == ACTION_FISH) {
279             take_turn(creature_ptr, 100);
280         } else if (creature_ptr->running) {
281             run_step(creature_ptr, 0);
282         } else if (travel.run) {
283             travel_step(creature_ptr);
284         } else if (command_rep) {
285             command_rep--;
286             creature_ptr->redraw |= (PR_STATE);
287             handle_stuff(creature_ptr);
288             msg_flag = FALSE;
289             prt("", 0, 0);
290             process_command(creature_ptr);
291         } else {
292             move_cursor_relative(creature_ptr->y, creature_ptr->x);
293
294             creature_ptr->window_flags |= PW_MONSTER_LIST;
295             window_stuff(creature_ptr);
296
297             can_save = TRUE;
298             request_command(creature_ptr, FALSE);
299             can_save = FALSE;
300             process_command(creature_ptr);
301         }
302
303         pack_overflow(creature_ptr);
304         if (creature_ptr->energy_use) {
305             if (creature_ptr->timewalk || creature_ptr->energy_use > 400) {
306                 creature_ptr->energy_need += creature_ptr->energy_use * TURNS_PER_TICK / 10;
307             } else {
308                 creature_ptr->energy_need += (s16b)((s32b)creature_ptr->energy_use * ENERGY_NEED() / 100L);
309             }
310
311             if (creature_ptr->image)
312                 creature_ptr->redraw |= (PR_MAP);
313
314             for (MONSTER_IDX m_idx = 1; m_idx < creature_ptr->current_floor_ptr->m_max; m_idx++) {
315                 monster_type *m_ptr;
316                 monster_race *r_ptr;
317                 m_ptr = &creature_ptr->current_floor_ptr->m_list[m_idx];
318                 if (!monster_is_valid(m_ptr))
319                     continue;
320
321                 r_ptr = &r_info[m_ptr->ap_r_idx];
322
323                 // モンスターのシンボル/カラーの更新
324                 if (m_ptr->ml && any_bits(r_ptr->flags1, (RF1_ATTR_MULTI | RF1_SHAPECHANGER))) {
325                     lite_spot(creature_ptr, m_ptr->fy, m_ptr->fx);
326                 }
327
328                 // 出現して即魔法を使わないようにするフラグを落とす処理
329                 if (m_ptr->mflag.has(MFLAG::PREVENT_MAGIC)) {
330                     m_ptr->mflag.reset(MFLAG::PREVENT_MAGIC);
331                 }
332
333                 if (m_ptr->mflag.has(MFLAG::SANITY_BLAST)) {
334                     m_ptr->mflag.reset(MFLAG::SANITY_BLAST);
335                     sanity_blast(creature_ptr, m_ptr, FALSE);
336                 }
337
338                 // 感知中のモンスターのフラグを落とす処理
339                 // 感知したターンはMFLAG2_SHOWを落とし、次のターンに感知中フラグのMFLAG2_MARKを落とす
340                 if (m_ptr->mflag2.has(MFLAG2::MARK)) {
341                     if (m_ptr->mflag2.has(MFLAG2::SHOW)) {
342                         m_ptr->mflag2.reset(MFLAG2::SHOW);
343                     } else {
344                         m_ptr->mflag2.reset(MFLAG2::MARK);
345                         m_ptr->ml = FALSE;
346                         update_monster(creature_ptr, m_idx, FALSE);
347                         if (creature_ptr->health_who == m_idx)
348                             creature_ptr->redraw |= (PR_HEALTH);
349                         if (creature_ptr->riding == m_idx)
350                             creature_ptr->redraw |= (PR_UHEALTH);
351
352                         lite_spot(creature_ptr, m_ptr->fy, m_ptr->fx);
353                     }
354                 }
355             }
356
357             if (creature_ptr->pclass == CLASS_IMITATOR) {
358                 if (creature_ptr->mane_num > (creature_ptr->lev > 44 ? 3 : creature_ptr->lev > 29 ? 2 : 1)) {
359                     creature_ptr->mane_num--;
360                     for (int j = 0; j < creature_ptr->mane_num; j++) {
361                         creature_ptr->mane_spell[j] = creature_ptr->mane_spell[j + 1];
362                         creature_ptr->mane_dam[j] = creature_ptr->mane_dam[j + 1];
363                     }
364                 }
365
366                 creature_ptr->new_mane = FALSE;
367                 creature_ptr->redraw |= (PR_IMITATION);
368             }
369
370             if (creature_ptr->action == ACTION_LEARN) {
371                 creature_ptr->new_mane = FALSE;
372                 creature_ptr->redraw |= (PR_STATE);
373             }
374
375             if (creature_ptr->timewalk && (creature_ptr->energy_need > -1000)) {
376                 creature_ptr->redraw |= (PR_MAP);
377                 creature_ptr->update |= (PU_MONSTERS);
378                 creature_ptr->window_flags |= (PW_OVERHEAD | PW_DUNGEON);
379
380                 msg_print(_("「時は動きだす…」", "You feel time flowing around you once more."));
381                 msg_print(NULL);
382                 creature_ptr->timewalk = FALSE;
383                 creature_ptr->energy_need = ENERGY_NEED();
384
385                 handle_stuff(creature_ptr);
386             }
387         }
388
389         if (!creature_ptr->playing || creature_ptr->is_dead) {
390             creature_ptr->timewalk = FALSE;
391             break;
392         }
393
394         if (creature_ptr->energy_use && creature_ptr->reset_concent)
395             reset_concentration(creature_ptr, TRUE);
396
397         if (creature_ptr->leaving)
398             break;
399     }
400
401     update_smell(creature_ptr->current_floor_ptr, creature_ptr);
402 }
403
404 /*!
405  * @brief プレイヤーの行動エネルギーが充填される(=プレイヤーのターンが回る)毎に行われる処理  / process the effects per 100 energy at player speed.
406  * @return なし
407  */
408 void process_upkeep_with_speed(player_type *creature_ptr)
409 {
410     if (!load && creature_ptr->enchant_energy_need > 0 && !creature_ptr->leaving) {
411         creature_ptr->enchant_energy_need -= SPEED_TO_ENERGY(creature_ptr->pspeed);
412     }
413
414     if (creature_ptr->enchant_energy_need > 0)
415         return;
416
417     while (creature_ptr->enchant_energy_need <= 0) {
418         if (!load)
419             check_music(creature_ptr);
420         if (!load)
421             check_hex(creature_ptr);
422         if (!load)
423             revenge_spell(creature_ptr);
424
425         creature_ptr->enchant_energy_need += ENERGY_NEED();
426     }
427 }