OSDN Git Service

[Refactor] monster_idxと0との比較を関数化する
[hengbandforosx/hengbandosx.git] / src / room / vault-builder.cpp
1 #include "room/vault-builder.h"
2 #include "floor/cave.h"
3 #include "floor/floor-generator-util.h"
4 #include "floor/floor-util.h"
5 #include "game-option/cheat-options.h"
6 #include "grid/feature-flag-types.h"
7 #include "grid/object-placer.h"
8 #include "grid/trap.h"
9 #include "monster-floor/monster-generator.h"
10 #include "monster-floor/place-monster-types.h"
11 #include "monster/monster-util.h"
12 #include "system/floor-type-definition.h"
13 #include "system/grid-type-definition.h"
14 #include "system/player-type-definition.h"
15 #include "view/display-messages.h"
16
17 /*
18  * Grid based version of "creature_bold()"
19  */
20 static bool player_grid(PlayerType *player_ptr, Grid *g_ptr)
21 {
22     return g_ptr == &player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x];
23 }
24
25 /*
26  * Grid based version of "cave_empty_bold()"
27  */
28 static bool is_cave_empty_grid(PlayerType *player_ptr, Grid *g_ptr)
29 {
30     bool is_empty_grid = g_ptr->cave_has_flag(TerrainCharacteristics::PLACE);
31     is_empty_grid &= !is_monster(g_ptr->m_idx);
32     is_empty_grid &= !player_grid(player_ptr, g_ptr);
33     return is_empty_grid;
34 }
35
36 /*!
37  * @brief 特殊な部屋地形向けにモンスターを配置する / Place some sleeping monsters near the given location
38  * @param player_ptr プレイヤーへの参照ポインタ
39  * @param y1 モンスターを配置したいマスの中心Y座標
40  * @param x1 モンスターを配置したいマスの中心X座標
41  * @param num 配置したいモンスターの数
42  * @details
43  * Only really called by some of the "vault" routines.
44  */
45 void vault_monsters(PlayerType *player_ptr, POSITION y1, POSITION x1, int num)
46 {
47     auto *floor_ptr = player_ptr->current_floor_ptr;
48     for (int k = 0; k < num; k++) {
49         for (int i = 0; i < 9; i++) {
50             int d = 1;
51             POSITION y, x;
52             scatter(player_ptr, &y, &x, y1, x1, d, 0);
53             Grid *g_ptr;
54             g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
55             if (!is_cave_empty_grid(player_ptr, g_ptr)) {
56                 continue;
57             }
58
59             floor_ptr->monster_level = floor_ptr->base_level + 2;
60             (void)place_random_monster(player_ptr, y, x, PM_ALLOW_SLEEP | PM_ALLOW_GROUP);
61             floor_ptr->monster_level = floor_ptr->base_level;
62         }
63     }
64 }
65
66 /*!
67  * @brief 特殊な部屋向けに各種アイテムを配置する / Create up to "num" objects near the given coordinates
68  * @param player_ptr プレイヤーへの参照ポインタ
69  * @param y 配置したい中心マスのY座標
70  * @param x 配置したい中心マスのX座標
71  * @param num 配置したい数
72  * @details
73  * Only really called by some of the "vault" routines.
74  */
75 void vault_objects(PlayerType *player_ptr, POSITION y, POSITION x, int num)
76 {
77     auto *floor_ptr = player_ptr->current_floor_ptr;
78     for (; num > 0; --num) {
79         int j = y, k = x;
80         int dummy = 0;
81         for (int i = 0; i < 11; ++i) {
82             while (dummy < SAFE_MAX_ATTEMPTS) {
83                 j = rand_spread(y, 2);
84                 k = rand_spread(x, 3);
85                 dummy++;
86                 if (!in_bounds(floor_ptr, j, k)) {
87                     continue;
88                 }
89                 break;
90             }
91
92             if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room) {
93                 msg_print(_("警告!地下室のアイテムを配置できません!", "Warning! Could not place vault object!"));
94             }
95
96             Grid *g_ptr;
97             g_ptr = &floor_ptr->grid_array[j][k];
98             if (!g_ptr->is_floor() || !g_ptr->o_idx_list.empty()) {
99                 continue;
100             }
101
102             if (randint0(100) < 75) {
103                 place_object(player_ptr, j, k, 0L);
104             } else {
105                 place_gold(player_ptr, j, k);
106             }
107
108             break;
109         }
110     }
111 }
112
113 /*!
114  * @brief 特殊な部屋向けに各種アイテムを配置する(vault_trapのサブセット) / Place a trap with a given displacement of point
115  * @param y トラップを配置したいマスの中心Y座標
116  * @param x トラップを配置したいマスの中心X座標
117  * @param yd Y方向の配置分散マス数
118  * @param xd X方向の配置分散マス数
119  * @details
120  * Only really called by some of the "vault" routines.
121  */
122 static void vault_trap_aux(FloorType *floor_ptr, POSITION y, POSITION x, POSITION yd, POSITION xd)
123 {
124     Grid *g_ptr;
125     int y1 = y, x1 = x;
126     int dummy = 0;
127     for (int count = 0; count <= 5; count++) {
128         while (dummy < SAFE_MAX_ATTEMPTS) {
129             y1 = rand_spread(y, yd);
130             x1 = rand_spread(x, xd);
131             dummy++;
132             if (!in_bounds(floor_ptr, y1, x1)) {
133                 continue;
134             }
135             break;
136         }
137
138         if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room) {
139             msg_print(_("警告!地下室のトラップを配置できません!", "Warning! Could not place vault trap!"));
140         }
141
142         g_ptr = &floor_ptr->grid_array[y1][x1];
143         if (!g_ptr->is_floor() || !g_ptr->o_idx_list.empty() || is_monster(g_ptr->m_idx)) {
144             continue;
145         }
146
147         place_trap(floor_ptr, y1, x1);
148         break;
149     }
150 }
151
152 /*!
153  * @brief 特殊な部屋向けに各種アイテムを配置する(メインルーチン) / Place some traps with a given displacement of given location
154  * @param player_ptr プレイヤーへの参照ポインタ
155  * @param y トラップを配置したいマスの中心Y座標
156  * @param x トラップを配置したいマスの中心X座標
157  * @param yd Y方向の配置分散マス数
158  * @param xd X方向の配置分散マス数
159  * @param num 配置したいトラップの数
160  * @details
161  * Only really called by some of the "vault" routines.
162  * @todo rooms-normal からしか呼ばれていない、要調整
163  */
164 void vault_traps(FloorType *floor_ptr, POSITION y, POSITION x, POSITION yd, POSITION xd, int num)
165 {
166     for (int i = 0; i < num; i++) {
167         vault_trap_aux(floor_ptr, y, x, yd, xd);
168     }
169 }