3 #include "dungeon/dungeon-flag-types.h"
4 #include "dungeon/dungeon.h"
5 #include "effect/effect-characteristics.h"
6 #include "effect/effect-processor.h"
7 #include "floor/cave.h"
8 #include "floor/floor-util.h"
9 #include "game-option/map-screen-options.h"
10 #include "grid/grid.h"
11 #include "mind/mind-ninja.h"
12 #include "monster-race/monster-race.h"
13 #include "monster-race/race-flags2.h"
14 #include "monster/monster-describer.h"
15 #include "monster/monster-status-setter.h"
16 #include "monster/monster-status.h"
17 #include "monster/monster-update.h"
18 #include "player/special-defense-types.h"
19 #include "spell-kind/spells-launcher.h"
20 #include "spell-kind/spells-lite.h"
21 #include "spell/spell-types.h"
22 #include "system/floor-type-definition.h"
23 #include "target/projection-path-calculator.h"
24 #include "util/bit-flags-calculator.h"
25 #include "view/display-messages.h"
26 #include "world/world.h"
31 Point(const int y, const int x)
38 using PassBoldFunc = bool (*)(floor_type *, POSITION, POSITION);
41 * @brief 指定した座標全てを照らす。
42 * @param caster_ptr プレーヤーへの参照ポインタ
43 * @param points 明るくすべき座標たち
46 * This routine clears the entire "temp" set.
47 * This routine will Perma-Lite all "temp" grids.
48 * This routine is used (only) by "lite_room()"
49 * Dark grids are illuminated.
50 * Also, process all affected monsters.
52 * SMART monsters always wake up when illuminated
53 * NORMAL monsters wake up 1/4 the time when illuminated
54 * STUPID monsters wake up 1/10 the time when illuminated
56 * @todo この辺、xとyが引数になっているが、caster_ptr->xとcaster_ptr->yで全て置き換えが効くはず……
58 static void cave_temp_room_lite(player_type *caster_ptr, const std::vector<Point> &points)
60 for (const auto &point : points) {
61 const POSITION y = point.y;
62 const POSITION x = point.x;
64 grid_type *g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
65 g_ptr->info &= ~(CAVE_TEMP);
66 g_ptr->info |= (CAVE_GLOW);
68 PERCENTAGE chance = 25;
69 monster_type *m_ptr = &caster_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
70 monster_race *r_ptr = &r_info[m_ptr->r_idx];
71 update_monster(caster_ptr, g_ptr->m_idx, FALSE);
72 if (r_ptr->flags2 & (RF2_STUPID))
74 if (r_ptr->flags2 & (RF2_SMART))
77 if (monster_csleep_remaining(m_ptr) && (randint0(100) < chance)) {
78 (void)set_monster_csleep(caster_ptr, g_ptr->m_idx, 0);
80 GAME_TEXT m_name[MAX_NLEN];
81 monster_desc(caster_ptr, m_name, m_ptr, 0);
82 msg_format(_("%^sが目を覚ました。", "%^s wakes up."), m_name);
87 note_spot(caster_ptr, y, x);
88 lite_spot(caster_ptr, y, x);
89 update_local_illumination(caster_ptr, y, x);
94 * @brief 指定した座標全てを暗くする。
95 * @param caster_ptr プレーヤーへの参照ポインタ
96 * @param points 暗くすべき座標たち
99 * This routine clears the entire "temp" set.
100 * This routine will "darken" all "temp" grids.
101 * In addition, some of these grids will be "unmarked".
102 * This routine is used (only) by "unlite_room()"
103 * Also, process all affected monsters
105 * @todo この辺、xとyが引数になっているが、caster_ptr->xとcaster_ptr->yで全て置き換えが効くはず……
107 static void cave_temp_room_unlite(player_type *caster_ptr, const std::vector<Point> &points)
109 for (const auto &point : points) {
110 const POSITION y = point.y;
111 const POSITION x = point.x;
113 grid_type *g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
114 bool do_dark = !is_mirror_grid(g_ptr);
115 g_ptr->info &= ~(CAVE_TEMP);
119 if (caster_ptr->current_floor_ptr->dun_level || !is_daytime()) {
120 for (int j = 0; j < 9; j++) {
121 POSITION by = y + ddy_ddd[j];
122 POSITION bx = x + ddx_ddd[j];
124 if (in_bounds2(caster_ptr->current_floor_ptr, by, bx)) {
125 grid_type *cc_ptr = &caster_ptr->current_floor_ptr->grid_array[by][bx];
127 if (has_flag(f_info[get_feat_mimic(cc_ptr)].flags, FF_GLOW)) {
138 g_ptr->info &= ~(CAVE_GLOW);
139 if (!has_flag(f_info[get_feat_mimic(g_ptr)].flags, FF_REMEMBER)) {
140 if (!view_torch_grids)
141 g_ptr->info &= ~(CAVE_MARK);
142 note_spot(caster_ptr, y, x);
146 update_monster(caster_ptr, g_ptr->m_idx, FALSE);
149 lite_spot(caster_ptr, y, x);
150 update_local_illumination(caster_ptr, y, x);
155 * @brief 周辺に関数ポインタの条件に該当する地形がいくつあるかを計算する / Determine how much contiguous open space this grid is next to
156 * @param floor_ptr 配置するフロアの参照ポインタ
159 * @param pass_bold 地形条件を返す関数ポインタ
162 static int next_to_open(floor_type *floor_ptr, const POSITION cy, const POSITION cx, const PassBoldFunc pass_bold)
166 for (int i = 0; i < 16; i++) {
167 POSITION y = cy + ddy_cdd[i % 8];
168 POSITION x = cx + ddx_cdd[i % 8];
169 if (!pass_bold(floor_ptr, y, x)) {
180 return MAX(len, blen);
184 * @brief 周辺に関数ポインタの条件に該当する地形がいくつあるかを計算する / Determine how much contiguous open space this grid is next to
185 * @param floor_ptr 配置するフロアの参照ポインタ
188 * @param pass_bold 地形条件を返す関数ポインタ
191 static int next_to_walls_adj(floor_type *floor_ptr, const POSITION cy, const POSITION cx, const PassBoldFunc pass_bold)
195 for (DIRECTION i = 0; i < 8; i++) {
199 if (!pass_bold(floor_ptr, y, x))
207 * @brief (y,x) が指定条件を満たすなら points に加える
208 * @param caster_ptr プレーヤーへの参照ポインタ
209 * @param points 座標記録用配列
212 * @param only_room 部屋内地形のみをチェック対象にするならば TRUE
213 * @param pass_bold 地形条件を返す関数ポインタ
215 static void cave_temp_room_aux(
216 player_type *caster_ptr, std::vector<Point> &points, const POSITION y, const POSITION x, const bool only_room, const PassBoldFunc pass_bold)
218 floor_type *floor_ptr = caster_ptr->current_floor_ptr;
219 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
221 // 既に points に追加済みなら何もしない。
222 if (g_ptr->info & (CAVE_TEMP))
225 if (!(g_ptr->info & (CAVE_ROOM))) {
228 if (!in_bounds2(floor_ptr, y, x))
230 if (distance(caster_ptr->y, caster_ptr->x, y, x) > get_max_range(caster_ptr))
233 /* Verify this grid */
235 * The reason why it is ==6 instead of >5 is that 8 is impossible
236 * due to the check for cave_bold above.
237 * 7 lights dead-end corridors (you need to do this for the
238 * checkboard interesting rooms, so that the boundary is lit
240 * This leaves only a check for 6 bounding walls!
242 if (in_bounds(floor_ptr, y, x) && pass_bold(floor_ptr, y, x) && (next_to_walls_adj(floor_ptr, y, x, pass_bold) == 6)
243 && (next_to_open(floor_ptr, y, x, pass_bold) <= 1))
247 // (y,x) を points に追加し、追加済みフラグを立てる。
248 points.emplace_back(y, x);
249 g_ptr->info |= (CAVE_TEMP);
253 * @brief (y,x) が明るくすべきマスなら points に加える
254 * @param caster_ptr プレーヤーへの参照ポインタ
255 * @param points 座標記録用配列
259 static void cave_temp_lite_room_aux(player_type *caster_ptr, std::vector<Point> &points, const POSITION y, const POSITION x)
261 cave_temp_room_aux(caster_ptr, points, y, x, FALSE, cave_los_bold);
265 * @brief 指定のマスが光を通さず射線のみを通すかを返す。 / Aux function -- see below
266 * @param floor_ptr 配置するフロアの参照ポインタ
269 * @return 射線を通すならばtrueを返す。
271 static bool cave_pass_dark_bold(floor_type *floor_ptr, POSITION y, POSITION x) { return cave_has_flag_bold(floor_ptr, y, x, FF_PROJECT); }
274 * @brief (y,x) が暗くすべきマスなら points に加える
275 * @param caster_ptr プレーヤーへの参照ポインタ
279 static void cave_temp_unlite_room_aux(player_type *caster_ptr, std::vector<Point> &points, const POSITION y, const POSITION x)
281 cave_temp_room_aux(caster_ptr, points, y, x, TRUE, cave_pass_dark_bold);
285 * @brief (y1,x1) を含む全ての部屋を照らす。 / Illuminate any room containing the given location.
286 * @param caster_ptr プレーヤーへの参照ポインタ
292 void lite_room(player_type *caster_ptr, const POSITION y1, const POSITION x1)
295 std::vector<Point> points;
297 floor_type *floor_ptr = caster_ptr->current_floor_ptr;
299 // (y1,x1) を起点として明るくするマスを記録していく。
301 cave_temp_lite_room_aux(caster_ptr, points, y1, x1);
302 for (size_t i = 0; i < size(points); i++) {
303 const auto &point = points[i];
304 const POSITION y = point.y;
305 const POSITION x = point.x;
307 if (!cave_los_bold(floor_ptr, y, x))
310 cave_temp_lite_room_aux(caster_ptr, points, y + 1, x);
311 cave_temp_lite_room_aux(caster_ptr, points, y - 1, x);
312 cave_temp_lite_room_aux(caster_ptr, points, y, x + 1);
313 cave_temp_lite_room_aux(caster_ptr, points, y, x - 1);
315 cave_temp_lite_room_aux(caster_ptr, points, y + 1, x + 1);
316 cave_temp_lite_room_aux(caster_ptr, points, y - 1, x - 1);
317 cave_temp_lite_room_aux(caster_ptr, points, y - 1, x + 1);
318 cave_temp_lite_room_aux(caster_ptr, points, y + 1, x - 1);
322 cave_temp_room_lite(caster_ptr, points);
325 if (caster_ptr->special_defense & NINJA_S_STEALTH) {
326 if (floor_ptr->grid_array[caster_ptr->y][caster_ptr->x].info & CAVE_GLOW)
327 set_superstealth(caster_ptr, FALSE);
332 * @brief (y1,x1) を含む全ての部屋を暗くする。 / Darken all rooms containing the given location
333 * @param caster_ptr プレーヤーへの参照ポインタ
337 void unlite_room(player_type *caster_ptr, const POSITION y1, const POSITION x1)
340 std::vector<Point> points;
342 floor_type *floor_ptr = caster_ptr->current_floor_ptr;
344 // (y1,x1) を起点として暗くするマスを記録していく。
346 cave_temp_unlite_room_aux(caster_ptr, points, y1, x1);
347 for (size_t i = 0; i < size(points); i++) {
348 const auto &point = points[i];
349 const POSITION y = point.y;
350 const POSITION x = point.x;
352 if (!cave_pass_dark_bold(floor_ptr, y, x))
355 cave_temp_unlite_room_aux(caster_ptr, points, y + 1, x);
356 cave_temp_unlite_room_aux(caster_ptr, points, y - 1, x);
357 cave_temp_unlite_room_aux(caster_ptr, points, y, x + 1);
358 cave_temp_unlite_room_aux(caster_ptr, points, y, x - 1);
360 cave_temp_unlite_room_aux(caster_ptr, points, y + 1, x + 1);
361 cave_temp_unlite_room_aux(caster_ptr, points, y - 1, x - 1);
362 cave_temp_unlite_room_aux(caster_ptr, points, y - 1, x + 1);
363 cave_temp_unlite_room_aux(caster_ptr, points, y + 1, x - 1);
367 cave_temp_room_unlite(caster_ptr, points);
371 * @brief スターライトの効果を発生させる
372 * @param caster_ptr プレーヤーへの参照ポインタ
373 * @param magic 魔法による効果であればTRUE、スターライトの杖による効果であればFALSE
376 bool starlight(player_type *caster_ptr, bool magic)
378 if (!caster_ptr->blind && !magic) {
379 msg_print(_("杖の先が明るく輝いた...", "The end of the staff glows brightly..."));
382 HIT_POINT num = damroll(5, 3);
384 POSITION y = 0, x = 0;
385 for (int k = 0; k < num; k++) {
389 scatter(caster_ptr, &y, &x, caster_ptr->y, caster_ptr->x, 4, PROJECT_LOS);
390 if (!cave_has_flag_bold(caster_ptr->current_floor_ptr, y, x, FF_PROJECT))
392 if (!player_bold(caster_ptr, y, x))
396 project(caster_ptr, 0, 0, y, x, damroll(6 + caster_ptr->lev / 8, 10), GF_LITE_WEAK,
397 (PROJECT_BEAM | PROJECT_THRU | PROJECT_GRID | PROJECT_KILL | PROJECT_LOS), -1);
404 * @brief プレイヤー位置を中心にLITE_WEAK属性を通じた照明処理を行う / Hack -- call light around the player Affect all monsters in the projection radius
405 * @param caster_ptr プレーヤーへの参照ポインタ
408 * @return 作用が実際にあった場合TRUEを返す
410 bool lite_area(player_type *caster_ptr, HIT_POINT dam, POSITION rad)
412 if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) {
413 msg_print(_("ダンジョンが光を吸収した。", "The darkness of this dungeon absorbs your light."));
417 if (!caster_ptr->blind) {
418 msg_print(_("白い光が辺りを覆った。", "You are surrounded by a white light."));
421 BIT_FLAGS flg = PROJECT_GRID | PROJECT_KILL;
422 (void)project(caster_ptr, 0, rad, caster_ptr->y, caster_ptr->x, dam, GF_LITE_WEAK, flg, -1);
424 lite_room(caster_ptr, caster_ptr->y, caster_ptr->x);
430 * @brief プレイヤー位置を中心にLITE_DARK属性を通じた消灯処理を行う / Hack -- call light around the player Affect all monsters in the projection radius
431 * @param caster_ptr プレーヤーへの参照ポインタ
434 * @return 作用が実際にあった場合TRUEを返す
436 bool unlite_area(player_type *caster_ptr, HIT_POINT dam, POSITION rad)
438 if (!caster_ptr->blind) {
439 msg_print(_("暗闇が辺りを覆った。", "Darkness surrounds you."));
442 BIT_FLAGS flg = PROJECT_GRID | PROJECT_KILL;
443 (void)project(caster_ptr, 0, rad, caster_ptr->y, caster_ptr->x, dam, GF_DARK_WEAK, flg, -1);
445 unlite_room(caster_ptr, caster_ptr->y, caster_ptr->x);
451 * @brief LITE_WEAK属性による光源ビーム処理
452 * @param caster_ptr プレーヤーへの参照ポインタ
453 * @param dir 方向(5ならばグローバル変数 target_col/target_row の座標を目標にする)
455 * @return 作用が実際にあった場合TRUEを返す
457 bool lite_line(player_type *caster_ptr, DIRECTION dir, HIT_POINT dam)
459 BIT_FLAGS flg = PROJECT_BEAM | PROJECT_GRID | PROJECT_KILL;
460 return (project_hook(caster_ptr, GF_LITE_WEAK, dir, dam, flg));