OSDN Git Service

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