OSDN Git Service

Merge remote-tracking branch 'remotes/hengbandosx/english-market-edits' into feature...
[hengband/hengband.git] / src / floor / floor-changer.c
1 #include "floor/floor-changer.h"
2 #include "action/travel-execution.h"
3 #include "dungeon/dungeon.h"
4 #include "dungeon/quest-monster-placer.h"
5 #include "dungeon/quest.h"
6 #include "effect/effect-characteristics.h"
7 #include "floor/floor-generator.h"
8 #include "floor/floor-mode-changer.h"
9 #include "floor/floor-object.h"
10 #include "floor/floor-save-util.h"
11 #include "floor/floor-save.h"
12 #include "floor/floor-util.h"
13 #include "floor/wild.h"
14 #include "game-option/birth-options.h"
15 #include "game-option/play-record-options.h"
16 #include "grid/feature.h"
17 #include "grid/grid.h"
18 #include "io/write-diary.h"
19 #include "load/floor-loader.h"
20 #include "main/sound-of-music.h"
21 #include "monster-floor/monster-generator.h"
22 #include "monster-floor/monster-remover.h"
23 #include "monster-floor/monster-summon.h"
24 #include "monster-race/monster-race.h"
25 #include "monster-race/race-flags1.h"
26 #include "monster-race/race-flags2.h"
27 #include "monster-race/race-flags7.h"
28 #include "monster/monster-describer.h"
29 #include "monster/monster-description-types.h"
30 #include "monster/monster-flag-types.h"
31 #include "monster/monster-info.h"
32 #include "monster/monster-list.h"
33 #include "monster/monster-status-setter.h"
34 #include "monster/monster-status.h"
35 #include "monster/monster-update.h"
36 #include "object-hook/hook-checker.h"
37 #include "object-hook/hook-enchant.h"
38 #include "spell-kind/spells-floor.h"
39 #include "system/artifact-type-definition.h"
40 #include "system/floor-type-definition.h"
41 #include "system/object-type-definition.h"
42 #include "view/display-messages.h"
43 #include "window/main-window-util.h"
44 #include "world/world.h"
45
46 /*!
47  * @brief 階段移動先のフロアが生成できない時に簡単な行き止まりマップを作成する / Builds the dead end
48  * @return なし
49  */
50 static void build_dead_end(player_type *creature_ptr)
51 {
52     clear_cave(creature_ptr);
53     creature_ptr->x = creature_ptr->y = 0;
54     set_floor_and_wall(0);
55     creature_ptr->current_floor_ptr->height = SCREEN_HGT;
56     creature_ptr->current_floor_ptr->width = SCREEN_WID;
57     for (POSITION y = 0; y < MAX_HGT; y++)
58         for (POSITION x = 0; x < MAX_WID; x++)
59             place_bold(creature_ptr, y, x, GB_SOLID_PERM);
60
61     creature_ptr->y = creature_ptr->current_floor_ptr->height / 2;
62     creature_ptr->x = creature_ptr->current_floor_ptr->width / 2;
63     place_bold(creature_ptr, creature_ptr->y, creature_ptr->x, GB_FLOOR);
64     wipe_generate_random_floor_flags(creature_ptr->current_floor_ptr);
65 }
66
67 static MONSTER_IDX decide_pet_index(player_type *master_ptr, const int current_monster, POSITION *cy, POSITION *cx)
68 {
69     floor_type *floor_ptr = master_ptr->current_floor_ptr;
70     if (current_monster == 0) {
71         MONSTER_IDX m_idx = m_pop(floor_ptr);
72         master_ptr->riding = m_idx;
73         if (m_idx) {
74             *cy = master_ptr->y;
75             *cx = master_ptr->x;
76         }
77
78         return m_idx;
79     }
80
81     POSITION d;
82     for (d = 1; d < A_MAX; d++) {
83         int j;
84         for (j = 1000; j > 0; j--) {
85             scatter(master_ptr, cy, cx, master_ptr->y, master_ptr->x, d, PROJECT_NONE);
86             if (monster_can_enter(master_ptr, *cy, *cx, &r_info[party_mon[current_monster].r_idx], 0))
87                 break;
88         }
89
90         if (j != 0)
91             break;
92     }
93
94     return (d == 6) ? 0 : m_pop(floor_ptr);
95 }
96
97 static void set_pet_params(player_type *master_ptr, monster_race **r_ptr, const int current_monster, MONSTER_IDX m_idx, const POSITION cy, const POSITION cx)
98 {
99     monster_type *m_ptr = &master_ptr->current_floor_ptr->m_list[m_idx];
100     master_ptr->current_floor_ptr->grid_array[cy][cx].m_idx = m_idx;
101     m_ptr->r_idx = party_mon[current_monster].r_idx;
102     *m_ptr = party_mon[current_monster];
103     *r_ptr = real_r_ptr(m_ptr);
104     m_ptr->fy = cy;
105     m_ptr->fx = cx;
106     m_ptr->current_floor_ptr = master_ptr->current_floor_ptr;
107     m_ptr->ml = TRUE;
108     m_ptr->mtimed[MTIMED_CSLEEP] = 0;
109     m_ptr->hold_o_idx = 0;
110     m_ptr->target_y = 0;
111     if (((*r_ptr)->flags1 & RF1_FORCE_SLEEP) && !ironman_nightmare) {
112         m_ptr->mflag |= MFLAG_NICE;
113         repair_monsters = TRUE;
114     }
115 }
116
117 /*!
118  * @brief 移動先のフロアに伴ったペットを配置する / Place preserved pet monsters on new floor
119  * @param master_ptr プレーヤーへの参照ポインタ
120  * @return なし
121  */
122 static void place_pet(player_type *master_ptr)
123 {
124     int max_num = master_ptr->wild_mode ? 1 : MAX_PARTY_MON;
125     for (int current_monster = 0; current_monster < max_num; current_monster++) {
126         POSITION cy = 0;
127         POSITION cx = 0;
128         if (party_mon[current_monster].r_idx == 0)
129             continue;
130
131         MONSTER_IDX m_idx = decide_pet_index(master_ptr, current_monster, &cy, &cx);
132         if (m_idx != 0) {
133             monster_race *r_ptr;
134             set_pet_params(master_ptr, &r_ptr, current_monster, m_idx, cy, cx);
135             update_monster(master_ptr, m_idx, TRUE);
136             lite_spot(master_ptr, cy, cx);
137             if (r_ptr->flags2 & RF2_MULTIPLY)
138                 master_ptr->current_floor_ptr->num_repro++;
139         } else {
140             monster_type *m_ptr = &party_mon[current_monster];
141             monster_race *r_ptr = real_r_ptr(m_ptr);
142             GAME_TEXT m_name[MAX_NLEN];
143             monster_desc(master_ptr, m_name, m_ptr, 0);
144             msg_format(_("%sとはぐれてしまった。", "You have lost sight of %s."), m_name);
145             if (record_named_pet && m_ptr->nickname) {
146                 monster_desc(master_ptr, m_name, m_ptr, MD_INDEF_VISIBLE);
147                 exe_write_diary(master_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_LOST_SIGHT, m_name);
148             }
149
150             if (r_ptr->cur_num)
151                 r_ptr->cur_num--;
152         }
153     }
154
155     (void)C_WIPE(party_mon, MAX_PARTY_MON, monster_type);
156 }
157
158 /*!
159  * @brief ユニークモンスターやアーティファクトの所在フロアを更新する / Hack -- Update location of unique monsters and artifacts
160  * @param cur_floor_id 現在のフロアID
161  * @return なし
162  * @details
163  * The r_ptr->floor_id and a_ptr->floor_id are not updated correctly\n
164  * while new floor creation since dungeons may be re-created by\n
165  * auto-scum option.\n
166  */
167 static void update_unique_artifact(floor_type *floor_ptr, s16b cur_floor_id)
168 {
169     for (int i = 1; i < floor_ptr->m_max; i++) {
170         monster_race *r_ptr;
171         monster_type *m_ptr = &floor_ptr->m_list[i];
172         if (!monster_is_valid(m_ptr))
173             continue;
174
175         r_ptr = real_r_ptr(m_ptr);
176         if ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NAZGUL))
177             r_ptr->floor_id = cur_floor_id;
178     }
179
180     for (int i = 1; i < floor_ptr->o_max; i++) {
181         object_type *o_ptr = &floor_ptr->o_list[i];
182         if (!object_is_valid(o_ptr))
183             continue;
184
185         if (object_is_fixed_artifact(o_ptr))
186             a_info[o_ptr->name1].floor_id = cur_floor_id;
187     }
188 }
189
190 static void check_visited_floor(player_type *creature_ptr, saved_floor_type *sf_ptr, bool *loaded)
191 {
192     if ((sf_ptr->last_visit == 0) || !load_floor(creature_ptr, sf_ptr, 0))
193         return;
194
195     *loaded = TRUE;
196     if ((creature_ptr->change_floor_mode & CFM_NO_RETURN) == 0)
197         return;
198
199     grid_type *g_ptr = &creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x];
200     if (feat_uses_special(g_ptr->feat))
201         return;
202
203     if (creature_ptr->change_floor_mode & (CFM_DOWN | CFM_UP))
204         g_ptr->feat = feat_ground_type[randint0(100)];
205
206     g_ptr->special = 0;
207 }
208
209 static void update_floor_id(player_type *creature_ptr, saved_floor_type *sf_ptr)
210 {
211     if (creature_ptr->floor_id == 0) {
212         if (creature_ptr->change_floor_mode & CFM_UP)
213             sf_ptr->lower_floor_id = 0;
214         else if (creature_ptr->change_floor_mode & CFM_DOWN)
215             sf_ptr->upper_floor_id = 0;
216
217         return;
218     }
219
220     saved_floor_type *cur_sf_ptr = get_sf_ptr(creature_ptr->floor_id);
221     if (creature_ptr->change_floor_mode & CFM_UP) {
222         if (cur_sf_ptr->upper_floor_id == new_floor_id)
223             sf_ptr->lower_floor_id = creature_ptr->floor_id;
224
225         return;
226     }
227
228     if (((creature_ptr->change_floor_mode & CFM_DOWN) != 0) && (cur_sf_ptr->lower_floor_id == new_floor_id))
229         sf_ptr->upper_floor_id = creature_ptr->floor_id;
230 }
231
232 static void reset_unique_by_floor_change(player_type *creature_ptr)
233 {
234     floor_type *floor_ptr = creature_ptr->current_floor_ptr;
235     for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++) {
236         monster_race *r_ptr;
237         monster_type *m_ptr = &floor_ptr->m_list[i];
238         if (!monster_is_valid(m_ptr))
239             continue;
240
241         if (!is_pet(m_ptr)) {
242             m_ptr->hp = m_ptr->maxhp = m_ptr->max_maxhp;
243             (void)set_monster_fast(creature_ptr, i, 0);
244             (void)set_monster_slow(creature_ptr, i, 0);
245             (void)set_monster_stunned(creature_ptr, i, 0);
246             (void)set_monster_confused(creature_ptr, i, 0);
247             (void)set_monster_monfear(creature_ptr, i, 0);
248             (void)set_monster_invulner(creature_ptr, i, 0, FALSE);
249         }
250
251         r_ptr = real_r_ptr(m_ptr);
252         if (!(r_ptr->flags1 & RF1_UNIQUE) && !(r_ptr->flags7 & RF7_NAZGUL))
253             continue;
254
255         if (r_ptr->floor_id != new_floor_id)
256             delete_monster_idx(creature_ptr, i);
257     }
258 }
259
260 static void new_floor_allocation(player_type *creature_ptr, saved_floor_type *sf_ptr)
261 {
262     GAME_TURN tmp_last_visit = sf_ptr->last_visit;
263     int alloc_chance = d_info[creature_ptr->dungeon_idx].max_m_alloc_chance;
264     while (tmp_last_visit > current_world_ptr->game_turn)
265         tmp_last_visit -= TURNS_PER_TICK * TOWN_DAWN;
266
267     GAME_TURN absence_ticks = (current_world_ptr->game_turn - tmp_last_visit) / TURNS_PER_TICK;
268     reset_unique_by_floor_change(creature_ptr);
269     for (MONSTER_IDX i = 1; i < creature_ptr->current_floor_ptr->o_max; i++) {
270         object_type *o_ptr = &creature_ptr->current_floor_ptr->o_list[i];
271         if (!object_is_valid(o_ptr) || !object_is_fixed_artifact(o_ptr))
272             continue;
273
274         if (a_info[o_ptr->name1].floor_id == new_floor_id)
275             a_info[o_ptr->name1].cur_num = 1;
276         else
277             delete_object_idx(creature_ptr, i);
278     }
279
280     (void)place_quest_monsters(creature_ptr);
281     GAME_TURN alloc_times = absence_ticks / alloc_chance;
282     if (randint0(alloc_chance) < (absence_ticks % alloc_chance))
283         alloc_times++;
284
285     for (MONSTER_IDX i = 0; i < alloc_times; i++)
286         (void)alloc_monster(creature_ptr, 0, 0, summon_specific);
287 }
288
289 static void check_dead_end(player_type *creature_ptr, saved_floor_type *sf_ptr)
290 {
291     if (sf_ptr->last_visit == 0) {
292         generate_floor(creature_ptr);
293         return;
294     }
295
296     msg_print(_("階段は行き止まりだった。", "The staircases come to a dead end..."));
297     build_dead_end(creature_ptr);
298     if (creature_ptr->change_floor_mode & CFM_UP)
299         sf_ptr->upper_floor_id = 0;
300     else if (creature_ptr->change_floor_mode & CFM_DOWN)
301         sf_ptr->lower_floor_id = 0;
302 }
303
304 static void update_new_floor_feature(player_type *creature_ptr, saved_floor_type *sf_ptr, const bool loaded)
305 {
306     if (loaded) {
307         new_floor_allocation(creature_ptr, sf_ptr);
308         return;
309     }
310
311     check_dead_end(creature_ptr, sf_ptr);
312     sf_ptr->last_visit = current_world_ptr->game_turn;
313     sf_ptr->dun_level = creature_ptr->current_floor_ptr->dun_level;
314     if ((creature_ptr->change_floor_mode & CFM_NO_RETURN) != 0)
315         return;
316
317     grid_type *g_ptr = &creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x];
318     if ((creature_ptr->change_floor_mode & CFM_UP) && !quest_number(creature_ptr, creature_ptr->current_floor_ptr->dun_level))
319         g_ptr->feat = (creature_ptr->change_floor_mode & CFM_SHAFT) ? feat_state(creature_ptr, feat_down_stair, FF_SHAFT) : feat_down_stair;
320     else if ((creature_ptr->change_floor_mode & CFM_DOWN) && !ironman_downward)
321         g_ptr->feat = (creature_ptr->change_floor_mode & CFM_SHAFT) ? feat_state(creature_ptr, feat_up_stair, FF_SHAFT) : feat_up_stair;
322
323     g_ptr->mimic = 0;
324     g_ptr->special = creature_ptr->floor_id;
325 }
326
327 static void cut_off_the_upstair(player_type *creature_ptr)
328 {
329     if (creature_ptr->change_floor_mode & CFM_RAND_PLACE) {
330         (void)new_player_spot(creature_ptr);
331         return;
332     }
333     
334     if (((creature_ptr->change_floor_mode & CFM_NO_RETURN) == 0) || ((creature_ptr->change_floor_mode & (CFM_DOWN | CFM_UP)) == 0))
335         return;
336
337     if (!creature_ptr->blind)
338         msg_print(_("突然階段が塞がれてしまった。", "Suddenly the stairs is blocked!"));
339     else
340         msg_print(_("ゴトゴトと何か音がした。", "You hear some noises."));
341 }
342
343 static void update_floor(player_type *creature_ptr)
344 {
345     if (!(creature_ptr->change_floor_mode & CFM_SAVE_FLOORS) && !(creature_ptr->change_floor_mode & CFM_FIRST_FLOOR)) {
346         generate_floor(creature_ptr);
347         new_floor_id = 0;
348         return;
349     }
350
351     if (new_floor_id == 0)
352         new_floor_id = get_new_floor_id(creature_ptr);
353
354     saved_floor_type *sf_ptr;
355     bool loaded = FALSE;
356     sf_ptr = get_sf_ptr(new_floor_id);
357     check_visited_floor(creature_ptr, sf_ptr, &loaded);
358     update_floor_id(creature_ptr, sf_ptr);
359     update_new_floor_feature(creature_ptr, sf_ptr, loaded);
360     cut_off_the_upstair(creature_ptr);
361     sf_ptr->visit_mark = latest_visit_mark++;
362 }
363
364 /*!
365  * @brief フロアの切り替え処理 / Enter new floor.
366  * @param creature_ptr プレーヤーへの参照ポインタ
367  * @return なし
368  * @details
369  * If the floor is an old saved floor, it will be\n
370  * restored from the temporary file.  If the floor is new one, new floor\n
371  * will be generated.\n
372  */
373 void change_floor(player_type *creature_ptr)
374 {
375     current_world_ptr->character_dungeon = FALSE;
376     creature_ptr->dtrap = FALSE;
377     panel_row_min = 0;
378     panel_row_max = 0;
379     panel_col_min = 0;
380     panel_col_max = 0;
381     creature_ptr->ambush_flag = FALSE;
382     update_floor(creature_ptr);
383     place_pet(creature_ptr);
384     forget_travel_flow(creature_ptr->current_floor_ptr);
385     update_unique_artifact(creature_ptr->current_floor_ptr, new_floor_id);
386     creature_ptr->floor_id = new_floor_id;
387     current_world_ptr->character_dungeon = TRUE;
388     if (creature_ptr->pseikaku == PERSONALITY_MUNCHKIN)
389         wiz_lite(creature_ptr, (bool)(creature_ptr->pclass == CLASS_NINJA));
390
391     creature_ptr->current_floor_ptr->generated_turn = current_world_ptr->game_turn;
392     creature_ptr->feeling_turn = creature_ptr->current_floor_ptr->generated_turn;
393     creature_ptr->feeling = 0;
394     creature_ptr->change_floor_mode = 0L;
395     select_floor_music(creature_ptr);
396     creature_ptr->change_floor_mode = 0;
397 }