OSDN Git Service

695369608a2cd60a24238ab8c4bb4317a509bcb8
[hengband/hengband.git] / src / floor / wild.c
1 /*!
2  * @file wild.c
3  * @brief 荒野マップの生成とルール管理 / Wilderness generation
4  * @date 2014/02/13
5  * @author
6  * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke\n
7  * This software may be copied and distributed for educational, research, and\n
8  * not for profit purposes provided that this copyright and statement are\n
9  * included in all such copies.\n
10  * 2013 Deskull rearranged comment for Doxygen.
11  */
12
13 #include "floor/wild.h"
14 #include "core/asking-player.h"
15 #include "dungeon/dungeon-flag-types.h"
16 #include "dungeon/dungeon.h"
17 #include "dungeon/quest.h"
18 #include "floor/cave.h"
19 #include "floor/floor-town.h"
20 #include "game-option/birth-options.h"
21 #include "game-option/map-screen-options.h"
22 #include "grid/feature.h"
23 #include "grid/grid.h"
24 #include "info-reader/fixed-map-parser.h"
25 #include "info-reader/parse-error-types.h"
26 #include "io/files-util.h"
27 #include "io/tokenizer.h"
28 #include "main/init.h"
29 #include "monster-floor/monster-generator.h"
30 #include "monster-floor/monster-remover.h"
31 #include "monster-floor/monster-summon.h"
32 #include "monster-floor/place-monster-types.h"
33 #include "monster/monster-info.h"
34 #include "monster/monster-status.h"
35 #include "monster/monster-util.h"
36 #include "player/attack-defense-types.h"
37 #include "player/player-status.h"
38 #include "realm/realm-names-table.h"
39 #include "spell-realm/spells-hex.h"
40 #include "status/action-setter.h"
41 #include "system/floor-type-definition.h"
42 #include "system/system-variables.h"
43 #include "util/bit-flags-calculator.h"
44 #include "view/display-messages.h"
45 #include "window/main-window-util.h"
46 #include "world/world.h"
47
48 #define MAX_FEAT_IN_TERRAIN 18
49
50 /*
51  * Wilderness
52  */
53 wilderness_type **wilderness;
54
55 bool generate_encounter;
56
57 typedef struct border_type {
58     s16b north[MAX_WID];
59     s16b south[MAX_WID];
60     s16b east[MAX_HGT];
61     s16b west[MAX_HGT];
62     s16b north_west;
63     s16b north_east;
64     s16b south_west;
65     s16b south_east;
66 } border_type;
67
68 /*!
69  * @brief 地形生成確率を決める要素100の配列を確率テーブルから作成する
70  * @param feat_type 非一様確率を再現するための要素数100の配列
71  * @param prob 元の確率テーブル
72  * @return なし
73  */
74 static void set_floor_and_wall_aux(s16b feat_type[100], feat_prob prob[DUNGEON_FEAT_PROB_NUM])
75 {
76     int lim[DUNGEON_FEAT_PROB_NUM], cur = 0, i;
77
78     lim[0] = prob[0].percent;
79     for (i = 1; i < DUNGEON_FEAT_PROB_NUM; i++)
80         lim[i] = lim[i - 1] + prob[i].percent;
81     if (lim[DUNGEON_FEAT_PROB_NUM - 1] < 100)
82         lim[DUNGEON_FEAT_PROB_NUM - 1] = 100;
83
84     for (i = 0; i < 100; i++) {
85         while (i == lim[cur])
86             cur++;
87         feat_type[i] = prob[cur].feat;
88     }
89 }
90
91 /*!
92  * @brief ダンジョンの地形を指定確率に応じて各マスへランダムに敷き詰める
93  * / Fill the arrays of floors and walls in the good proportions
94  * @param type ダンジョンID
95  * @return なし
96  */
97 void set_floor_and_wall(DUNGEON_IDX type)
98 {
99     DUNGEON_IDX cur_type = 255;
100     dungeon_type *d_ptr;
101
102     /* Already filled */
103     if (cur_type == type)
104         return;
105
106     cur_type = type;
107     d_ptr = &d_info[type];
108
109     set_floor_and_wall_aux(feat_ground_type, d_ptr->floor);
110     set_floor_and_wall_aux(feat_wall_type, d_ptr->fill);
111
112     feat_wall_outer = d_ptr->outer_wall;
113     feat_wall_inner = d_ptr->inner_wall;
114     feat_wall_solid = d_ptr->outer_wall;
115 }
116
117 /*!
118  * @brief プラズマフラクタル的地形生成の再帰中間処理
119  * / Helper for plasma generation.
120  * @param x1 左上端の深み
121  * @param x2 右上端の深み
122  * @param x3 左下端の深み
123  * @param x4 右下端の深み
124  * @param xmid 中央座標X
125  * @param ymid 中央座標Y
126  * @param rough ランダム幅
127  * @param depth_max 深みの最大値
128  * @return なし
129  */
130 static void perturb_point_mid(
131     floor_type *floor_ptr, FEAT_IDX x1, FEAT_IDX x2, FEAT_IDX x3, FEAT_IDX x4, POSITION xmid, POSITION ymid, FEAT_IDX rough, FEAT_IDX depth_max)
132 {
133     /*
134      * Average the four corners & perturb it a bit.
135      * tmp is a random int +/- rough
136      */
137     FEAT_IDX tmp2 = rough * 2 + 1;
138     FEAT_IDX tmp = randint1(tmp2) - (rough + 1);
139
140     FEAT_IDX avg = ((x1 + x2 + x3 + x4) / 4) + tmp;
141
142     /* Division always rounds down, so we round up again */
143     if (((x1 + x2 + x3 + x4) % 4) > 1)
144         avg++;
145
146     /* Normalize */
147     if (avg < 0)
148         avg = 0;
149     if (avg > depth_max)
150         avg = depth_max;
151
152     /* Set the new value. */
153     floor_ptr->grid_array[ymid][xmid].feat = (FEAT_IDX)avg;
154 }
155
156 /*!
157  * @brief プラズマフラクタル的地形生成の再帰末端処理
158  * / Helper for plasma generation.
159  * @param x1 中間末端部1の重み
160  * @param x2 中間末端部2の重み
161  * @param x3 中間末端部3の重み
162  * @param xmid 最終末端部座標X
163  * @param ymid 最終末端部座標Y
164  * @param rough ランダム幅
165  * @param depth_max 深みの最大値
166  * @return なし
167  */
168 static void perturb_point_end(floor_type *floor_ptr, FEAT_IDX x1, FEAT_IDX x2, FEAT_IDX x3, POSITION xmid, POSITION ymid, FEAT_IDX rough, FEAT_IDX depth_max)
169 {
170     /*
171      * Average the three corners & perturb it a bit.
172      * tmp is a random int +/- rough
173      */
174     FEAT_IDX tmp2 = rough * 2 + 1;
175     FEAT_IDX tmp = randint0(tmp2) - rough;
176
177     FEAT_IDX avg = ((x1 + x2 + x3) / 3) + tmp;
178
179     /* Division always rounds down, so we round up again */
180     if ((x1 + x2 + x3) % 3)
181         avg++;
182
183     /* Normalize */
184     if (avg < 0)
185         avg = 0;
186     if (avg > depth_max)
187         avg = depth_max;
188
189     /* Set the new value. */
190     floor_ptr->grid_array[ymid][xmid].feat = (FEAT_IDX)avg;
191 }
192
193 /*!
194  * @brief プラズマフラクタル的地形生成の開始処理
195  * / Helper for plasma generation.
196  * @param x1 処理範囲の左上X座標
197  * @param y1 処理範囲の左上Y座標
198  * @param x2 処理範囲の右下X座標
199  * @param y2 処理範囲の右下Y座標
200  * @param depth_max 深みの最大値
201  * @param rough ランダム幅
202  * @return なし
203  * @details
204  * <pre>
205  * A generic function to generate the plasma fractal.
206  * Note that it uses ``cave_feat'' as temporary storage.
207  * The values in ``cave_feat'' after this function
208  * are NOT actual features; They are raw heights which
209  * need to be converted to features.
210  * </pre>
211  */
212 static void plasma_recursive(floor_type *floor_ptr, POSITION x1, POSITION y1, POSITION x2, POSITION y2, FEAT_IDX depth_max, FEAT_IDX rough)
213 {
214     /* Find middle */
215     POSITION xmid = (x2 - x1) / 2 + x1;
216     POSITION ymid = (y2 - y1) / 2 + y1;
217
218     /* Are we done? */
219     if (x1 + 1 == x2)
220         return;
221
222     perturb_point_mid(floor_ptr, floor_ptr->grid_array[y1][x1].feat, floor_ptr->grid_array[y2][x1].feat, floor_ptr->grid_array[y1][x2].feat,
223         floor_ptr->grid_array[y2][x2].feat, xmid, ymid, rough, depth_max);
224
225     perturb_point_end(
226         floor_ptr, floor_ptr->grid_array[y1][x1].feat, floor_ptr->grid_array[y1][x2].feat, floor_ptr->grid_array[ymid][xmid].feat, xmid, y1, rough, depth_max);
227
228     perturb_point_end(
229         floor_ptr, floor_ptr->grid_array[y1][x2].feat, floor_ptr->grid_array[y2][x2].feat, floor_ptr->grid_array[ymid][xmid].feat, x2, ymid, rough, depth_max);
230
231     perturb_point_end(
232         floor_ptr, floor_ptr->grid_array[y2][x2].feat, floor_ptr->grid_array[y2][x1].feat, floor_ptr->grid_array[ymid][xmid].feat, xmid, y2, rough, depth_max);
233
234     perturb_point_end(
235         floor_ptr, floor_ptr->grid_array[y2][x1].feat, floor_ptr->grid_array[y1][x1].feat, floor_ptr->grid_array[ymid][xmid].feat, x1, ymid, rough, depth_max);
236
237     /* Recurse the four quadrants */
238     plasma_recursive(floor_ptr, x1, y1, xmid, ymid, depth_max, rough);
239     plasma_recursive(floor_ptr, xmid, y1, x2, ymid, depth_max, rough);
240     plasma_recursive(floor_ptr, x1, ymid, xmid, y2, depth_max, rough);
241     plasma_recursive(floor_ptr, xmid, ymid, x2, y2, depth_max, rough);
242 }
243
244 /*
245  * The default table in terrain level generation.
246  */
247 static s16b terrain_table[MAX_WILDERNESS][MAX_FEAT_IN_TERRAIN];
248
249 /*!
250  * @brief 荒野フロア生成のサブルーチン
251  * @param terrain 荒野地形ID
252  * @param seed 乱数の固定シード
253  * @param border 未使用
254  * @param corner 広域マップの角部分としての生成ならばTRUE
255  * @return なし
256  */
257 static void generate_wilderness_area(floor_type *floor_ptr, int terrain, u32b seed, bool corner)
258 {
259     /* The outer wall is easy */
260     if (terrain == TERRAIN_EDGE) {
261         /* Create level background */
262         for (POSITION y1 = 0; y1 < MAX_HGT; y1++) {
263             for (POSITION x1 = 0; x1 < MAX_WID; x1++) {
264                 floor_ptr->grid_array[y1][x1].feat = feat_permanent;
265             }
266         }
267
268         return;
269     }
270
271     /* Hack -- Backup the RNG state */
272     u32b state_backup[4];
273     Rand_state_backup(state_backup);
274
275     /* Hack -- Induce consistant flavors */
276     Rand_state_set(seed);
277
278     int table_size = sizeof(terrain_table[0]) / sizeof(s16b);
279     if (!corner) {
280         /* Create level background */
281         for (POSITION y1 = 0; y1 < MAX_HGT; y1++) {
282             for (POSITION x1 = 0; x1 < MAX_WID; x1++) {
283                 floor_ptr->grid_array[y1][x1].feat = table_size / 2;
284             }
285         }
286     }
287
288     /*
289      * Initialize the four corners
290      * ToDo: calculate the medium height of the adjacent
291      * terrains for every corner.
292      */
293     floor_ptr->grid_array[1][1].feat = (s16b)randint0(table_size);
294     floor_ptr->grid_array[MAX_HGT - 2][1].feat = (s16b)randint0(table_size);
295     floor_ptr->grid_array[1][MAX_WID - 2].feat = (s16b)randint0(table_size);
296     floor_ptr->grid_array[MAX_HGT - 2][MAX_WID - 2].feat = (s16b)randint0(table_size);
297
298     /* Hack -- only four corners */
299     if (corner) {
300         floor_ptr->grid_array[1][1].feat = terrain_table[terrain][floor_ptr->grid_array[1][1].feat];
301         floor_ptr->grid_array[MAX_HGT - 2][1].feat = terrain_table[terrain][floor_ptr->grid_array[MAX_HGT - 2][1].feat];
302         floor_ptr->grid_array[1][MAX_WID - 2].feat = terrain_table[terrain][floor_ptr->grid_array[1][MAX_WID - 2].feat];
303         floor_ptr->grid_array[MAX_HGT - 2][MAX_WID - 2].feat = terrain_table[terrain][floor_ptr->grid_array[MAX_HGT - 2][MAX_WID - 2].feat];
304         Rand_state_restore(state_backup);
305         return;
306     }
307
308     /* Hack -- preserve four corners */
309     s16b north_west = floor_ptr->grid_array[1][1].feat;
310     s16b south_west = floor_ptr->grid_array[MAX_HGT - 2][1].feat;
311     s16b north_east = floor_ptr->grid_array[1][MAX_WID - 2].feat;
312     s16b south_east = floor_ptr->grid_array[MAX_HGT - 2][MAX_WID - 2].feat;
313
314     /* x1, y1, x2, y2, num_depths, roughness */
315     FEAT_IDX roughness = 1; /* The roughness of the level. */
316     plasma_recursive(floor_ptr, 1, 1, MAX_WID - 2, MAX_HGT - 2, table_size - 1, roughness);
317
318     /* Hack -- copyback four corners */
319     floor_ptr->grid_array[1][1].feat = north_west;
320     floor_ptr->grid_array[MAX_HGT - 2][1].feat = south_west;
321     floor_ptr->grid_array[1][MAX_WID - 2].feat = north_east;
322     floor_ptr->grid_array[MAX_HGT - 2][MAX_WID - 2].feat = south_east;
323
324     for (POSITION y1 = 1; y1 < MAX_HGT - 1; y1++) {
325         for (POSITION x1 = 1; x1 < MAX_WID - 1; x1++) {
326             floor_ptr->grid_array[y1][x1].feat = terrain_table[terrain][floor_ptr->grid_array[y1][x1].feat];
327         }
328     }
329
330     Rand_state_restore(state_backup);
331 }
332
333 /*!
334  * @brief 荒野フロア生成のメインルーチン /
335  * Load a town or generate a terrain level using "plasma" fractals.
336  * @param player_ptr プレーヤーへの参照ポインタ
337  * @param y 広域Y座標
338  * @param x 広域X座標
339  * @param border 広域マップの辺部分としての生成ならばTRUE
340  * @param corner 広域マップの角部分としての生成ならばTRUE
341  * @return なし
342  * @details
343  * <pre>
344  * x and y are the coordinates of the area in the wilderness.
345  * Border and corner are optimization flags to speed up the
346  * generation of the fractal terrain.
347  * If border is set then only the border of the terrain should
348  * be generated (for initializing the border structure).
349  * If corner is set then only the corners of the area are needed.
350  * </pre>
351  */
352 static void generate_area(player_type *player_ptr, POSITION y, POSITION x, bool border, bool corner)
353 {
354     /* Number of the town (if any) */
355     player_ptr->town_num = wilderness[y][x].town;
356
357     /* Set the base level */
358     floor_type *floor_ptr = player_ptr->current_floor_ptr;
359     floor_ptr->base_level = wilderness[y][x].level;
360
361     /* Set the dungeon level */
362     floor_ptr->dun_level = 0;
363
364     /* Set the monster generation level */
365     floor_ptr->monster_level = floor_ptr->base_level;
366
367     /* Set the object generation level */
368     floor_ptr->object_level = floor_ptr->base_level;
369
370     /* Create the town */
371     if (player_ptr->town_num) {
372         /* Reset the buildings */
373         init_buildings();
374
375         /* Initialize the town */
376         if (border | corner)
377             init_flags = INIT_CREATE_DUNGEON | INIT_ONLY_FEATURES;
378         else
379             init_flags = INIT_CREATE_DUNGEON;
380
381         parse_fixed_map(player_ptr, "t_info.txt", 0, 0, MAX_HGT, MAX_WID);
382
383         if (!corner && !border)
384             player_ptr->visit |= (1L << (player_ptr->town_num - 1));
385     } else {
386         int terrain = wilderness[y][x].terrain;
387         u32b seed = wilderness[y][x].seed;
388
389         generate_wilderness_area(floor_ptr, terrain, seed, corner);
390     }
391
392     if (!corner && !wilderness[y][x].town) {
393         /*
394          * Place roads in the wilderness
395          * ToDo: make the road a bit more interresting
396          */
397         if (wilderness[y][x].road) {
398             floor_ptr->grid_array[MAX_HGT / 2][MAX_WID / 2].feat = feat_floor;
399
400             POSITION x1, y1;
401             if (wilderness[y - 1][x].road) {
402                 /* North road */
403                 for (y1 = 1; y1 < MAX_HGT / 2; y1++) {
404                     x1 = MAX_WID / 2;
405                     floor_ptr->grid_array[y1][x1].feat = feat_floor;
406                 }
407             }
408
409             if (wilderness[y + 1][x].road) {
410                 /* North road */
411                 for (y1 = MAX_HGT / 2; y1 < MAX_HGT - 1; y1++) {
412                     x1 = MAX_WID / 2;
413                     floor_ptr->grid_array[y1][x1].feat = feat_floor;
414                 }
415             }
416
417             if (wilderness[y][x + 1].road) {
418                 /* East road */
419                 for (x1 = MAX_WID / 2; x1 < MAX_WID - 1; x1++) {
420                     y1 = MAX_HGT / 2;
421                     floor_ptr->grid_array[y1][x1].feat = feat_floor;
422                 }
423             }
424
425             if (wilderness[y][x - 1].road) {
426                 /* West road */
427                 for (x1 = 1; x1 < MAX_WID / 2; x1++) {
428                     y1 = MAX_HGT / 2;
429                     floor_ptr->grid_array[y1][x1].feat = feat_floor;
430                 }
431             }
432         }
433     }
434
435     /*
436      * 本来は '> 0'で良いと思われるがエンバグするのも怖いので'!= 0'と記載する
437      * 問題なければ'> 0'へ置き換えること
438      */
439     bool is_winner = wilderness[y][x].entrance != 0;
440     is_winner &= !wilderness[y][x].town != 0;
441     bool is_wild_winner = (d_info[wilderness[y][x].entrance].flags1 & DF1_WINNER) == 0;
442     is_winner &= ((current_world_ptr->total_winner != 0) || is_wild_winner);
443     if (!is_winner)
444         return;
445
446     /* Hack -- Backup the RNG state */
447     u32b state_backup[4];
448     Rand_state_backup(state_backup);
449
450     /* Hack -- Induce consistant flavors */
451     Rand_state_set(wilderness[y][x].seed);
452
453     int dy = rand_range(6, floor_ptr->height - 6);
454     int dx = rand_range(6, floor_ptr->width - 6);
455
456     floor_ptr->grid_array[dy][dx].feat = feat_entrance;
457     floor_ptr->grid_array[dy][dx].special = wilderness[y][x].entrance;
458
459     /* Hack -- Restore the RNG state */
460     Rand_state_restore(state_backup);
461 }
462
463 /*
464  * Border of the wilderness area
465  */
466 static border_type border;
467
468 /*!
469  * @brief 広域マップの生成 /
470  * Build the wilderness area outside of the town.
471  * @todo 広域マップは恒常生成にする予定、player_typeによる処理分岐は最終的に排除する。
472  * @param creature_ptr プレーヤーへの参照ポインタ
473  * @return なし
474  */
475 void wilderness_gen(player_type *creature_ptr)
476 {
477     /* Big town */
478     floor_type *floor_ptr = creature_ptr->current_floor_ptr;
479     floor_ptr->height = MAX_HGT;
480     floor_ptr->width = MAX_WID;
481
482     /* Assume illegal panel */
483     panel_row_min = floor_ptr->height;
484     panel_col_min = floor_ptr->width;
485
486     parse_fixed_map(creature_ptr, "w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x);
487     POSITION x = creature_ptr->wilderness_x;
488     POSITION y = creature_ptr->wilderness_y;
489     get_mon_num_prep(creature_ptr, get_monster_hook(creature_ptr), NULL);
490
491     /* North border */
492     generate_area(creature_ptr, y - 1, x, TRUE, FALSE);
493
494     for (int i = 1; i < MAX_WID - 1; i++) {
495         border.north[i] = floor_ptr->grid_array[MAX_HGT - 2][i].feat;
496     }
497
498     /* South border */
499     generate_area(creature_ptr, y + 1, x, TRUE, FALSE);
500
501     for (int i = 1; i < MAX_WID - 1; i++) {
502         border.south[i] = floor_ptr->grid_array[1][i].feat;
503     }
504
505     /* West border */
506     generate_area(creature_ptr, y, x - 1, TRUE, FALSE);
507
508     for (int i = 1; i < MAX_HGT - 1; i++) {
509         border.west[i] = floor_ptr->grid_array[i][MAX_WID - 2].feat;
510     }
511
512     /* East border */
513     generate_area(creature_ptr, y, x + 1, TRUE, FALSE);
514
515     for (int i = 1; i < MAX_HGT - 1; i++) {
516         border.east[i] = floor_ptr->grid_array[i][1].feat;
517     }
518
519     /* North west corner */
520     generate_area(creature_ptr, y - 1, x - 1, FALSE, TRUE);
521     border.north_west = floor_ptr->grid_array[MAX_HGT - 2][MAX_WID - 2].feat;
522
523     /* North east corner */
524     generate_area(creature_ptr, y - 1, x + 1, FALSE, TRUE);
525     border.north_east = floor_ptr->grid_array[MAX_HGT - 2][1].feat;
526
527     /* South west corner */
528     generate_area(creature_ptr, y + 1, x - 1, FALSE, TRUE);
529     border.south_west = floor_ptr->grid_array[1][MAX_WID - 2].feat;
530
531     /* South east corner */
532     generate_area(creature_ptr, y + 1, x + 1, FALSE, TRUE);
533     border.south_east = floor_ptr->grid_array[1][1].feat;
534
535     /* Create terrain of the current area */
536     generate_area(creature_ptr, y, x, FALSE, FALSE);
537
538     /* Special boundary walls -- North */
539     for (int i = 0; i < MAX_WID; i++) {
540         floor_ptr->grid_array[0][i].feat = feat_permanent;
541         floor_ptr->grid_array[0][i].mimic = border.north[i];
542     }
543
544     /* Special boundary walls -- South */
545     for (int i = 0; i < MAX_WID; i++) {
546         floor_ptr->grid_array[MAX_HGT - 1][i].feat = feat_permanent;
547         floor_ptr->grid_array[MAX_HGT - 1][i].mimic = border.south[i];
548     }
549
550     /* Special boundary walls -- West */
551     for (int i = 0; i < MAX_HGT; i++) {
552         floor_ptr->grid_array[i][0].feat = feat_permanent;
553         floor_ptr->grid_array[i][0].mimic = border.west[i];
554     }
555
556     /* Special boundary walls -- East */
557     for (int i = 0; i < MAX_HGT; i++) {
558         floor_ptr->grid_array[i][MAX_WID - 1].feat = feat_permanent;
559         floor_ptr->grid_array[i][MAX_WID - 1].mimic = border.east[i];
560     }
561
562     floor_ptr->grid_array[0][0].mimic = border.north_west;
563     floor_ptr->grid_array[0][MAX_WID - 1].mimic = border.north_east;
564     floor_ptr->grid_array[MAX_HGT - 1][0].mimic = border.south_west;
565     floor_ptr->grid_array[MAX_HGT - 1][MAX_WID - 1].mimic = border.south_east;
566
567     /* Light up or darken the area */
568     for (y = 0; y < floor_ptr->height; y++) {
569         for (x = 0; x < floor_ptr->width; x++) {
570             grid_type *g_ptr;
571             g_ptr = &floor_ptr->grid_array[y][x];
572
573             if (is_daytime()) {
574                 /* Assume lit */
575                 g_ptr->info |= CAVE_GLOW;
576
577                 /* Hack -- Memorize lit grids if allowed */
578                 if (view_perma_grids)
579                     g_ptr->info |= CAVE_MARK;
580                 continue;
581             }
582
583             /* Feature code (applying "mimic" field) */
584             feature_type *f_ptr;
585             f_ptr = &f_info[get_feat_mimic(g_ptr)];
586
587             if (!is_mirror_grid(g_ptr) && !have_flag(f_ptr->flags, FF_QUEST_ENTER) && !have_flag(f_ptr->flags, FF_ENTRANCE)) {
588                 /* Assume dark */
589                 g_ptr->info &= ~(CAVE_GLOW);
590
591                 /* Darken "boring" features */
592                 if (!have_flag(f_ptr->flags, FF_REMEMBER)) {
593                     /* Forget the grid */
594                     g_ptr->info &= ~(CAVE_MARK);
595                 }
596
597                 continue;
598             }
599
600             if (!have_flag(f_ptr->flags, FF_ENTRANCE))
601                 continue;
602
603             g_ptr->info |= CAVE_GLOW;
604
605             /* Hack -- Memorize lit grids if allowed */
606             if (view_perma_grids)
607                 g_ptr->info |= CAVE_MARK;
608         }
609     }
610
611     if (creature_ptr->teleport_town) {
612         for (y = 0; y < floor_ptr->height; y++) {
613             for (x = 0; x < floor_ptr->width; x++) {
614                 grid_type *g_ptr;
615                 g_ptr = &floor_ptr->grid_array[y][x];
616
617                 /* Seeing true feature code (ignore mimic) */
618                 feature_type *f_ptr;
619                 f_ptr = &f_info[g_ptr->feat];
620
621                 if (!have_flag(f_ptr->flags, FF_BLDG))
622                     continue;
623
624                 if ((f_ptr->subtype != 4) && !((creature_ptr->town_num == 1) && (f_ptr->subtype == 0)))
625                     continue;
626
627                 if (g_ptr->m_idx) {
628                     delete_monster_idx(creature_ptr, g_ptr->m_idx);
629                 }
630
631                 creature_ptr->oldpy = y;
632                 creature_ptr->oldpx = x;
633             }
634         }
635
636         creature_ptr->teleport_town = FALSE;
637     } else if (creature_ptr->leaving_dungeon) {
638         for (y = 0; y < floor_ptr->height; y++) {
639             for (x = 0; x < floor_ptr->width; x++) {
640                 grid_type *g_ptr;
641                 g_ptr = &floor_ptr->grid_array[y][x];
642
643                 if (!cave_have_flag_grid(g_ptr, FF_ENTRANCE))
644                     continue;
645
646                 if (g_ptr->m_idx) {
647                     delete_monster_idx(creature_ptr, g_ptr->m_idx);
648                 }
649
650                 creature_ptr->oldpy = y;
651                 creature_ptr->oldpx = x;
652             }
653         }
654
655         creature_ptr->teleport_town = FALSE;
656     }
657
658     player_place(creature_ptr, creature_ptr->oldpy, creature_ptr->oldpx);
659     int lim = (generate_encounter == TRUE) ? 40 : MIN_M_ALLOC_TN;
660
661     /* Make some residents */
662     for (int i = 0; i < lim; i++) {
663         BIT_FLAGS mode = 0;
664
665         if (!(generate_encounter || (one_in_(2) && (!creature_ptr->town_num))))
666             mode |= PM_ALLOW_SLEEP;
667
668         /* Make a resident */
669         (void)alloc_monster(creature_ptr, generate_encounter ? 0 : 3, mode, summon_specific);
670     }
671
672     if (generate_encounter)
673         creature_ptr->ambush_flag = TRUE;
674     generate_encounter = FALSE;
675
676     /* Fill the arrays of floors and walls in the good proportions */
677     set_floor_and_wall(0);
678
679     /* Set rewarded quests to finished */
680     for (int i = 0; i < max_q_idx; i++) {
681         if (quest[i].status == QUEST_STATUS_REWARDED)
682             quest[i].status = QUEST_STATUS_FINISHED;
683     }
684 }
685
686 static s16b conv_terrain2feat[MAX_WILDERNESS];
687
688 /*!
689  * @brief 広域マップの生成(簡易処理版) /
690  * Build the wilderness area. -DG-
691  * @return なし
692  */
693 void wilderness_gen_small(player_type *creature_ptr)
694 {
695     /* To prevent stupid things */
696     floor_type *floor_ptr = creature_ptr->current_floor_ptr;
697     for (int i = 0; i < MAX_WID; i++) {
698         for (int j = 0; j < MAX_HGT; j++) {
699             floor_ptr->grid_array[j][i].feat = feat_permanent;
700         }
701     }
702
703     parse_fixed_map(creature_ptr, "w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x);
704
705     /* Fill the map */
706     for (int i = 0; i < current_world_ptr->max_wild_x; i++) {
707         for (int j = 0; j < current_world_ptr->max_wild_y; j++) {
708             if (wilderness[j][i].town && (wilderness[j][i].town != NO_TOWN)) {
709                 floor_ptr->grid_array[j][i].feat = (s16b)feat_town;
710                 floor_ptr->grid_array[j][i].special = (s16b)wilderness[j][i].town;
711                 floor_ptr->grid_array[j][i].info |= (CAVE_GLOW | CAVE_MARK);
712                 continue;
713             }
714
715             if (wilderness[j][i].road) {
716                 floor_ptr->grid_array[j][i].feat = feat_floor;
717                 floor_ptr->grid_array[j][i].info |= (CAVE_GLOW | CAVE_MARK);
718                 continue;
719             }
720
721             if (wilderness[j][i].entrance && (current_world_ptr->total_winner || !(d_info[wilderness[j][i].entrance].flags1 & DF1_WINNER))) {
722                 floor_ptr->grid_array[j][i].feat = feat_entrance;
723                 floor_ptr->grid_array[j][i].special = (byte)wilderness[j][i].entrance;
724                 floor_ptr->grid_array[j][i].info |= (CAVE_GLOW | CAVE_MARK);
725                 continue;
726             }
727
728             floor_ptr->grid_array[j][i].feat = conv_terrain2feat[wilderness[j][i].terrain];
729             floor_ptr->grid_array[j][i].info |= (CAVE_GLOW | CAVE_MARK);
730         }
731     }
732
733     floor_ptr->height = (s16b)current_world_ptr->max_wild_y;
734     floor_ptr->width = (s16b)current_world_ptr->max_wild_x;
735
736     if (floor_ptr->height > MAX_HGT)
737         floor_ptr->height = MAX_HGT;
738     if (floor_ptr->width > MAX_WID)
739         floor_ptr->width = MAX_WID;
740
741     /* Assume illegal panel */
742     panel_row_min = floor_ptr->height;
743     panel_col_min = floor_ptr->width;
744
745     creature_ptr->x = creature_ptr->wilderness_x;
746     creature_ptr->y = creature_ptr->wilderness_y;
747     creature_ptr->town_num = 0;
748 }
749
750 typedef struct wilderness_grid wilderness_grid;
751
752 struct wilderness_grid {
753     int terrain; /* Terrain type */
754     TOWN_IDX town; /* Town number */
755     DEPTH level; /* Level of the wilderness */
756     byte road; /* Road */
757     char name[32]; /* Name of the town/wilderness */
758 };
759
760 static wilderness_grid w_letter[255];
761
762 /*!
763  * @brief w_info.txtのデータ解析 /
764  * Parse a sub-file of the "extra info"
765  * @param buf 読み取ったデータ行のバッファ
766  * @param ymin 未使用
767  * @param xmin 広域地形マップを読み込みたいx座標の開始位置
768  * @param ymax 未使用
769  * @param xmax 広域地形マップを読み込みたいx座標の終了位置
770  * @param y 広域マップの高さを返す参照ポインタ
771  * @param x 広域マップの幅を返す参照ポインタ
772  * @return なし
773  */
774 errr parse_line_wilderness(player_type *creature_ptr, char *buf, int xmin, int xmax, int *y, int *x)
775 {
776     if (!(buf[0] == 'W'))
777         return (PARSE_ERROR_GENERIC);
778
779     int num;
780     char *zz[33];
781     switch (buf[2]) {
782         /* Process "W:F:<letter>:<terrain>:<town>:<road>:<name> */
783 #ifdef JP
784     case 'E':
785         return 0;
786     case 'F':
787     case 'J':
788 #else
789     case 'J':
790         return 0;
791     case 'F':
792     case 'E':
793 #endif
794     {
795         if ((num = tokenize(buf + 4, 6, zz, 0)) > 1) {
796             int index = zz[0][0];
797
798             if (num > 1)
799                 w_letter[index].terrain = atoi(zz[1]);
800             else
801                 w_letter[index].terrain = 0;
802
803             if (num > 2)
804                 w_letter[index].level = (s16b)atoi(zz[2]);
805             else
806                 w_letter[index].level = 0;
807
808             if (num > 3)
809                 w_letter[index].town = (TOWN_IDX)atoi(zz[3]);
810             else
811                 w_letter[index].town = 0;
812
813             if (num > 4)
814                 w_letter[index].road = (byte)atoi(zz[4]);
815             else
816                 w_letter[index].road = 0;
817
818             if (num > 5)
819                 strcpy(w_letter[index].name, zz[5]);
820             else
821                 w_letter[index].name[0] = 0;
822         } else {
823             /* Failure */
824             return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
825         }
826
827         break;
828     }
829
830     /* Process "W:D:<layout> */
831     /* Layout of the wilderness */
832     case 'D': {
833         char *s = buf + 4;
834         int len = strlen(s);
835         int i;
836         for (*x = xmin, i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++) {
837             int id = s[0];
838             wilderness[*y][*x].terrain = w_letter[id].terrain;
839             wilderness[*y][*x].level = w_letter[id].level;
840             wilderness[*y][*x].town = w_letter[id].town;
841             wilderness[*y][*x].road = w_letter[id].road;
842             strcpy(town_info[w_letter[id].town].name, w_letter[id].name);
843         }
844
845         (*y)++;
846         break;
847     }
848
849     /* Process "W:P:<x>:<y> - starting position in the wilderness */
850     case 'P': {
851         bool is_corner = creature_ptr->wilderness_x == 0;
852         is_corner = creature_ptr->wilderness_y == 0;
853         if (!is_corner)
854             break;
855
856         if (tokenize(buf + 4, 2, zz, 0) != 2) {
857             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
858         }
859
860         creature_ptr->wilderness_y = atoi(zz[0]);
861         creature_ptr->wilderness_x = atoi(zz[1]);
862
863         if ((creature_ptr->wilderness_x < 1) || (creature_ptr->wilderness_x > current_world_ptr->max_wild_x) || (creature_ptr->wilderness_y < 1)
864             || (creature_ptr->wilderness_y > current_world_ptr->max_wild_y)) {
865             return PARSE_ERROR_OUT_OF_BOUNDS;
866         }
867
868         break;
869     }
870
871     default:
872         return PARSE_ERROR_UNDEFINED_DIRECTIVE;
873     }
874
875     for (int i = 1; i < current_world_ptr->max_d_idx; i++) {
876         if (!d_info[i].maxdepth)
877             continue;
878         wilderness[d_info[i].dy][d_info[i].dx].entrance = (byte)i;
879         if (!wilderness[d_info[i].dy][d_info[i].dx].town) {
880             wilderness[d_info[i].dy][d_info[i].dx].level = d_info[i].mindepth;
881         }
882     }
883
884     return 0;
885 }
886
887 /*!
888  * @brief ゲーム開始時に各荒野フロアの乱数シードを指定する /
889  * Generate the random seeds for the wilderness
890  * @return なし
891  */
892 void seed_wilderness(void)
893 {
894     for (POSITION x = 0; x < current_world_ptr->max_wild_x; x++) {
895         for (POSITION y = 0; y < current_world_ptr->max_wild_y; y++) {
896             wilderness[y][x].seed = randint0(0x10000000);
897             wilderness[y][x].entrance = 0;
898         }
899     }
900 }
901
902 /*
903  * Pointer to wilderness_type
904  */
905 typedef wilderness_type *wilderness_type_ptr;
906
907 /*!
908  * @brief ゲーム開始時の荒野初期化メインルーチン /
909  * Initialize wilderness array
910  * @return エラーコード
911  */
912 errr init_wilderness(void)
913 {
914     /* Allocate the wilderness (two-dimension array) */
915     C_MAKE(wilderness, current_world_ptr->max_wild_y, wilderness_type_ptr);
916     C_MAKE(wilderness[0], current_world_ptr->max_wild_x * current_world_ptr->max_wild_y, wilderness_type);
917
918     /* Init the other pointers */
919     for (int i = 1; i < current_world_ptr->max_wild_y; i++) {
920         wilderness[i] = wilderness[0] + i * current_world_ptr->max_wild_x;
921     }
922
923     generate_encounter = FALSE;
924     return 0;
925 }
926
927 /*!
928  * @brief 荒野の地勢設定を初期化する /
929  * Initialize wilderness array
930  * @param terrain 初期化したい地勢ID
931  * @param feat_global 基本的な地形ID
932  * @param fmt 地勢内の地形数を参照するための独自フォーマット
933  * @return なし
934  */
935 static void init_terrain_table(int terrain, s16b feat_global, concptr fmt, ...)
936 {
937     /* Begin the varargs stuff */
938     va_list vp;
939     va_start(vp, fmt);
940
941     /* Wilderness terrains on global map */
942     conv_terrain2feat[terrain] = feat_global;
943
944     /* Wilderness terrains on local map */
945     int cur = 0;
946     char check = 'a';
947     for (concptr p = fmt; *p; p++) {
948         if (*p != check) {
949             plog_fmt("Format error");
950             continue;
951         }
952
953         FEAT_IDX feat = (s16b)va_arg(vp, int);
954         int num = va_arg(vp, int);
955         int lim = cur + num;
956
957         for (; (cur < lim) && (cur < MAX_FEAT_IN_TERRAIN); cur++) {
958             terrain_table[terrain][cur] = feat;
959         }
960
961         if (cur >= MAX_FEAT_IN_TERRAIN)
962             break;
963
964         check++;
965     }
966
967     if (cur < MAX_FEAT_IN_TERRAIN) {
968         plog_fmt("Too few parameters");
969     }
970
971     va_end(vp);
972 }
973
974 /*!
975  * @brief 荒野の地勢設定全体を初期化するメインルーチン /
976  * Initialize arrays for wilderness terrains
977  * @return なし
978  */
979 void init_wilderness_terrains(void)
980 {
981     init_terrain_table(TERRAIN_EDGE, feat_permanent, "a", feat_permanent, MAX_FEAT_IN_TERRAIN);
982
983     init_terrain_table(TERRAIN_TOWN, feat_town, "a", feat_floor, MAX_FEAT_IN_TERRAIN);
984
985     init_terrain_table(TERRAIN_DEEP_WATER, feat_deep_water, "ab", feat_deep_water, 12, feat_shallow_water, MAX_FEAT_IN_TERRAIN - 12);
986
987     init_terrain_table(TERRAIN_SHALLOW_WATER, feat_shallow_water, "abcde", feat_deep_water, 3, feat_shallow_water, 12, feat_floor, 1, feat_dirt, 1, feat_grass,
988         MAX_FEAT_IN_TERRAIN - 17);
989
990     init_terrain_table(TERRAIN_SWAMP, feat_swamp, "abcdef", feat_dirt, 2, feat_grass, 3, feat_tree, 1, feat_brake, 1, feat_shallow_water, 4, feat_swamp,
991         MAX_FEAT_IN_TERRAIN - 11);
992
993     init_terrain_table(
994         TERRAIN_DIRT, feat_dirt, "abcdef", feat_floor, 3, feat_dirt, 10, feat_flower, 1, feat_brake, 1, feat_grass, 1, feat_tree, MAX_FEAT_IN_TERRAIN - 16);
995
996     init_terrain_table(
997         TERRAIN_GRASS, feat_grass, "abcdef", feat_floor, 2, feat_dirt, 2, feat_grass, 9, feat_flower, 1, feat_brake, 2, feat_tree, MAX_FEAT_IN_TERRAIN - 16);
998
999     init_terrain_table(TERRAIN_TREES, feat_tree, "abcde", feat_floor, 2, feat_dirt, 1, feat_tree, 11, feat_brake, 2, feat_grass, MAX_FEAT_IN_TERRAIN - 16);
1000
1001     init_terrain_table(TERRAIN_DESERT, feat_dirt, "abc", feat_floor, 2, feat_dirt, 13, feat_grass, MAX_FEAT_IN_TERRAIN - 15);
1002
1003     init_terrain_table(TERRAIN_SHALLOW_LAVA, feat_shallow_lava, "abc", feat_shallow_lava, 14, feat_deep_lava, 3, feat_mountain, MAX_FEAT_IN_TERRAIN - 17);
1004
1005     init_terrain_table(
1006         TERRAIN_DEEP_LAVA, feat_deep_lava, "abcd", feat_dirt, 3, feat_shallow_lava, 3, feat_deep_lava, 10, feat_mountain, MAX_FEAT_IN_TERRAIN - 16);
1007
1008     init_terrain_table(TERRAIN_MOUNTAIN, feat_mountain, "abcdef", feat_floor, 1, feat_brake, 1, feat_grass, 2, feat_dirt, 2, feat_tree, 2, feat_mountain,
1009         MAX_FEAT_IN_TERRAIN - 8);
1010 }
1011
1012 /*!
1013  * @brief 荒野から広域マップへの切り替え処理 /
1014  * Initialize arrays for wilderness terrains
1015  * @param encount 襲撃時TRUE
1016  * @return 切り替えが行われた場合はTRUEを返す。
1017  */
1018 bool change_wild_mode(player_type *creature_ptr, bool encount)
1019 {
1020     generate_encounter = encount;
1021
1022     /* It is in the middle of changing map */
1023     if (creature_ptr->leaving)
1024         return FALSE;
1025
1026     if (lite_town || vanilla_town) {
1027         msg_print(_("荒野なんてない。", "No global map."));
1028         return FALSE;
1029     }
1030
1031     if (creature_ptr->wild_mode) {
1032         /* Save the location in the global map */
1033         creature_ptr->wilderness_x = creature_ptr->x;
1034         creature_ptr->wilderness_y = creature_ptr->y;
1035
1036         /* Give first move to the player */
1037         creature_ptr->energy_need = 0;
1038
1039         /* Go back to the ordinary map */
1040         creature_ptr->wild_mode = FALSE;
1041         creature_ptr->leaving = TRUE;
1042         return TRUE;
1043     }
1044
1045     bool have_pet = FALSE;
1046     for (int i = 1; i < creature_ptr->current_floor_ptr->m_max; i++) {
1047         monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[i];
1048
1049         if (!monster_is_valid(m_ptr))
1050             continue;
1051         if (is_pet(m_ptr) && i != creature_ptr->riding)
1052             have_pet = TRUE;
1053         if (monster_csleep_remaining(m_ptr))
1054             continue;
1055         if (m_ptr->cdis > MAX_SIGHT)
1056             continue;
1057         if (!is_hostile(m_ptr))
1058             continue;
1059         msg_print(_("敵がすぐ近くにいるときは広域マップに入れない!", "You cannot enter global map, since there is some monsters nearby!"));
1060         free_turn(creature_ptr);
1061         return FALSE;
1062     }
1063
1064     if (have_pet) {
1065         concptr msg = _("ペットを置いて広域マップに入りますか?", "Do you leave your pets behind? ");
1066
1067         if (!get_check_strict(creature_ptr, msg, CHECK_OKAY_CANCEL)) {
1068             free_turn(creature_ptr);
1069             return FALSE;
1070         }
1071     }
1072
1073     take_turn(creature_ptr, 1000);
1074
1075     /* Remember the position */
1076     creature_ptr->oldpx = creature_ptr->x;
1077     creature_ptr->oldpy = creature_ptr->y;
1078
1079     /* Cancel hex spelling */
1080     if (hex_spelling_any(creature_ptr))
1081         stop_hex_spell_all(creature_ptr);
1082
1083     /* Cancel any special action */
1084     set_action(creature_ptr, ACTION_NONE);
1085
1086     /* Go into the global map */
1087     creature_ptr->wild_mode = TRUE;
1088     creature_ptr->leaving = TRUE;
1089     return TRUE;
1090 }