2 * @brief フロアに影響のある魔法の処理
7 #include "spell-kind/spells-floor.h"
8 #include "action/travel-execution.h"
9 #include "cmd-io/cmd-dump.h"
10 #include "core/player-redraw-types.h"
11 #include "core/player-update-types.h"
12 #include "core/window-redrawer.h"
13 #include "dungeon/dungeon-flag-types.h"
14 #include "dungeon/dungeon.h"
15 #include "dungeon/quest.h"
16 #include "flavor/flavor-describer.h"
17 #include "flavor/object-flavor-types.h"
18 #include "floor/cave.h"
19 #include "floor/floor-object.h"
20 #include "floor/floor-save.h"
21 #include "floor/floor-util.h"
22 #include "game-option/birth-options.h"
23 #include "game-option/cheat-options.h"
24 #include "game-option/map-screen-options.h"
25 #include "game-option/play-record-options.h"
26 #include "grid/feature-flag-types.h"
27 #include "grid/grid.h"
28 #include "io/write-diary.h"
29 #include "mind/mind-ninja.h"
30 #include "monster-floor/monster-lite.h"
31 #include "monster-race/monster-race.h"
32 #include "monster-race/race-flags1.h"
33 #include "monster/monster-describer.h"
34 #include "monster/monster-description-types.h"
35 #include "monster/monster-info.h"
36 #include "monster/monster-status.h"
37 #include "monster/smart-learn-types.h"
38 #include "object-enchant/special-object-flags.h"
39 #include "object-hook/hook-checker.h"
40 #include "object-hook/hook-enchant.h"
41 #include "object/object-mark-types.h"
42 #include "perception/object-perception.h"
43 #include "player/special-defense-types.h"
44 #include "spell-kind/spells-teleport.h"
45 #include "spell/spell-types.h"
46 #include "status/bad-status-setter.h"
47 #include "system/artifact-type-definition.h"
48 #include "system/floor-type-definition.h"
49 #include "util/bit-flags-calculator.h"
50 #include "view/display-messages.h"
54 * @param caster_ptr プレーヤーへの参照ポインタ
58 void wiz_lite(player_type *caster_ptr, bool ninja)
60 /* Memorize objects */
61 for (OBJECT_IDX i = 1; i < caster_ptr->current_floor_ptr->o_max; i++) {
62 object_type *o_ptr = &caster_ptr->current_floor_ptr->o_list[i];
63 if (!object_is_valid(o_ptr))
65 if (object_is_held_monster(o_ptr))
67 o_ptr->marked |= OM_FOUND;
70 /* Scan all normal grids */
71 for (POSITION y = 1; y < caster_ptr->current_floor_ptr->height - 1; y++) {
72 /* Scan all normal grids */
73 for (POSITION x = 1; x < caster_ptr->current_floor_ptr->width - 1; x++) {
74 grid_type *g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
76 /* Memorize terrain of the grid */
77 g_ptr->info |= (CAVE_KNOWN);
79 /* Feature code (applying "mimic" field) */
80 FEAT_IDX feat = get_feat_mimic(g_ptr);
82 f_ptr = &f_info[feat];
84 /* Process all non-walls */
85 if (has_flag(f_ptr->flags, FF_WALL))
88 /* Scan all neighbors */
89 for (OBJECT_IDX i = 0; i < 9; i++) {
90 POSITION yy = y + ddy_ddd[i];
91 POSITION xx = x + ddx_ddd[i];
92 g_ptr = &caster_ptr->current_floor_ptr->grid_array[yy][xx];
94 /* Feature code (applying "mimic" field) */
95 f_ptr = &f_info[get_feat_mimic(g_ptr)];
97 /* Perma-lite the grid */
98 if (!(d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) && !ninja) {
99 g_ptr->info |= (CAVE_GLOW);
102 /* Memorize normal features */
103 if (has_flag(f_ptr->flags, FF_REMEMBER)) {
104 /* Memorize the grid */
105 g_ptr->info |= (CAVE_MARK);
108 /* Perma-lit grids (newly and previously) */
109 else if (g_ptr->info & CAVE_GLOW) {
110 /* Normally, memorize floors (see above) */
111 if (view_perma_grids && !view_torch_grids) {
112 /* Memorize the grid */
113 g_ptr->info |= (CAVE_MARK);
120 caster_ptr->update |= (PU_MONSTERS);
121 caster_ptr->redraw |= (PR_MAP);
122 caster_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
124 if (caster_ptr->special_defense & NINJA_S_STEALTH) {
125 if (caster_ptr->current_floor_ptr->grid_array[caster_ptr->y][caster_ptr->x].info & CAVE_GLOW)
126 set_superstealth(caster_ptr, FALSE);
131 * Forget the dungeon map (ala "Thinking of Maud...").
133 void wiz_dark(player_type *caster_ptr)
135 /* Forget every grid */
136 for (POSITION y = 1; y < caster_ptr->current_floor_ptr->height - 1; y++) {
137 for (POSITION x = 1; x < caster_ptr->current_floor_ptr->width - 1; x++) {
138 grid_type *g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
140 /* Process the grid */
141 g_ptr->info &= ~(CAVE_MARK | CAVE_IN_DETECT | CAVE_KNOWN);
142 g_ptr->info |= (CAVE_UNSAFE);
146 /* Forget every grid on horizontal edge */
147 for (POSITION x = 0; x < caster_ptr->current_floor_ptr->width; x++) {
148 caster_ptr->current_floor_ptr->grid_array[0][x].info &= ~(CAVE_MARK);
149 caster_ptr->current_floor_ptr->grid_array[caster_ptr->current_floor_ptr->height - 1][x].info &= ~(CAVE_MARK);
152 /* Forget every grid on vertical edge */
153 for (POSITION y = 1; y < (caster_ptr->current_floor_ptr->height - 1); y++) {
154 caster_ptr->current_floor_ptr->grid_array[y][0].info &= ~(CAVE_MARK);
155 caster_ptr->current_floor_ptr->grid_array[y][caster_ptr->current_floor_ptr->width - 1].info &= ~(CAVE_MARK);
158 /* Forget all objects */
159 for (OBJECT_IDX i = 1; i < caster_ptr->current_floor_ptr->o_max; i++) {
160 object_type *o_ptr = &caster_ptr->current_floor_ptr->o_list[i];
162 if (!object_is_valid(o_ptr))
164 if (object_is_held_monster(o_ptr))
167 /* Forget the object */
168 o_ptr->marked &= OM_TOUCHED;
171 /* Forget travel route when we have forgotten map */
172 forget_travel_flow(caster_ptr->current_floor_ptr);
174 caster_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
175 caster_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);
176 caster_ptr->update |= (PU_MONSTERS);
177 caster_ptr->redraw |= (PR_MAP);
178 caster_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
182 * Hack -- map the current panel (plus some) ala "magic mapping"
184 void map_area(player_type *caster_ptr, POSITION range)
186 if (d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
190 for (POSITION y = 1; y < caster_ptr->current_floor_ptr->height - 1; y++) {
191 for (POSITION x = 1; x < caster_ptr->current_floor_ptr->width - 1; x++) {
192 if (distance(caster_ptr->y, caster_ptr->x, y, x) > range)
196 g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
198 /* Memorize terrain of the grid */
199 g_ptr->info |= (CAVE_KNOWN);
201 /* Feature code (applying "mimic" field) */
202 FEAT_IDX feat = get_feat_mimic(g_ptr);
204 f_ptr = &f_info[feat];
206 /* All non-walls are "checked" */
207 if (has_flag(f_ptr->flags, FF_WALL))
210 /* Memorize normal features */
211 if (has_flag(f_ptr->flags, FF_REMEMBER)) {
212 /* Memorize the object */
213 g_ptr->info |= (CAVE_MARK);
216 /* Memorize known walls */
217 for (int i = 0; i < 8; i++) {
218 g_ptr = &caster_ptr->current_floor_ptr->grid_array[y + ddy_ddd[i]][x + ddx_ddd[i]];
220 /* Feature code (applying "mimic" field) */
221 feat = get_feat_mimic(g_ptr);
222 f_ptr = &f_info[feat];
224 /* Memorize walls (etc) */
225 if (has_flag(f_ptr->flags, FF_REMEMBER)) {
226 /* Memorize the walls */
227 g_ptr->info |= (CAVE_MARK);
233 caster_ptr->redraw |= (PR_MAP);
234 caster_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
238 * @brief *破壊*処理を行う / The spell of destruction
242 * @param in_generate ダンジョンフロア生成中の処理ならばTRUE
243 * @return 効力があった場合TRUEを返す
246 * This spell "deletes" monsters (instead of "killing" them).
248 * Later we may use one function for both "destruction" and
249 * "earthquake" by using the "full" to select "destruction".
252 bool destroy_area(player_type *caster_ptr, POSITION y1, POSITION x1, POSITION r, bool in_generate)
254 /* Prevent destruction of quest levels and town */
255 floor_type *floor_ptr = caster_ptr->current_floor_ptr;
256 if ((floor_ptr->inside_quest && is_fixed_quest_idx(floor_ptr->inside_quest)) || !floor_ptr->dun_level) {
260 /* Lose monster light */
262 clear_mon_lite(floor_ptr);
264 /* Big area of affect */
266 for (POSITION y = (y1 - r); y <= (y1 + r); y++) {
267 for (POSITION x = (x1 - r); x <= (x1 + r); x++) {
268 if (!in_bounds(floor_ptr, y, x))
271 /* Extract the distance */
272 int k = distance(y1, x1, y, x);
274 /* Stay in the circle of death */
278 g_ptr = &floor_ptr->grid_array[y][x];
280 /* Lose room and vault */
281 g_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
283 /* Lose light and knowledge */
284 g_ptr->info &= ~(CAVE_MARK | CAVE_GLOW | CAVE_KNOWN);
286 if (!in_generate) /* Normal */
289 g_ptr->info &= ~(CAVE_UNSAFE);
291 /* Hack -- Notice player affect */
292 if (player_bold(caster_ptr, y, x)) {
293 /* Hurt the player later */
296 /* Do not hurt this grid */
301 /* Hack -- Skip the epicenter */
302 if ((y == y1) && (x == x1))
306 monster_type *m_ptr = &floor_ptr->m_list[g_ptr->m_idx];
307 monster_race *r_ptr = &r_info[m_ptr->r_idx];
309 if (in_generate) /* In generation */
311 /* Delete the monster (if any) */
312 delete_monster(caster_ptr, y, x);
313 } else if (r_ptr->flags1 & RF1_QUESTOR) {
314 /* Heal the monster */
315 m_ptr->hp = m_ptr->maxhp;
317 /* Try to teleport away quest monsters */
318 if (!teleport_away(caster_ptr, g_ptr->m_idx, (r * 2) + 1, TELEPORT_DEC_VALOUR))
321 if (record_named_pet && is_pet(m_ptr) && m_ptr->nickname) {
322 GAME_TEXT m_name[MAX_NLEN];
324 monster_desc(caster_ptr, m_name, m_ptr, MD_INDEF_VISIBLE);
325 exe_write_diary(caster_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_DESTROY, m_name);
328 /* Delete the monster (if any) */
329 delete_monster(caster_ptr, y, x);
333 /* During generation, destroyed artifacts are "preserved" */
334 if (preserve_mode || in_generate) {
335 OBJECT_IDX this_o_idx, next_o_idx = 0;
337 /* Scan all objects in the grid */
338 for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) {
340 o_ptr = &floor_ptr->o_list[this_o_idx];
341 next_o_idx = o_ptr->next_o_idx;
343 /* Hack -- Preserve unknown artifacts */
344 if (object_is_fixed_artifact(o_ptr) && (!object_is_known(o_ptr) || in_generate)) {
345 /* Mega-Hack -- Preserve the artifact */
346 a_info[o_ptr->name1].cur_num = 0;
348 if (in_generate && cheat_peek) {
349 GAME_TEXT o_name[MAX_NLEN];
350 describe_flavor(caster_ptr, o_name, o_ptr, (OD_NAME_ONLY | OD_STORE));
351 msg_format(_("伝説のアイテム (%s) は生成中に*破壊*された。", "Artifact (%s) was *destroyed* during generation."), o_name);
353 } else if (in_generate && cheat_peek && o_ptr->art_name) {
355 _("ランダム・アーティファクトの1つは生成中に*破壊*された。", "One of the random artifacts was *destroyed* during generation."));
360 delete_all_items_from_floor(caster_ptr, y, x);
362 /* Destroy "non-permanent" grids */
363 if (cave_has_flag_grid(g_ptr, FF_PERMANENT))
366 /* Wall (or floor) type */
367 int t = randint0(200);
369 if (!in_generate) /* Normal */
372 /* Create granite wall */
373 cave_set_feat(caster_ptr, y, x, feat_granite);
375 /* Create quartz vein */
376 cave_set_feat(caster_ptr, y, x, feat_quartz_vein);
377 } else if (t < 100) {
378 /* Create magma vein */
379 cave_set_feat(caster_ptr, y, x, feat_magma_vein);
382 cave_set_feat(caster_ptr, y, x, feat_ground_type[randint0(100)]);
389 /* Create granite wall */
390 place_grid(caster_ptr, g_ptr, GB_EXTRA);
392 /* Create quartz vein */
393 g_ptr->feat = feat_quartz_vein;
394 } else if (t < 100) {
395 /* Create magma vein */
396 g_ptr->feat = feat_magma_vein;
399 place_grid(caster_ptr, g_ptr, GB_FLOOR);
402 /* Clear garbage of hidden trap or door */
410 /* Process "re-glowing" */
411 for (POSITION y = (y1 - r); y <= (y1 + r); y++) {
412 for (POSITION x = (x1 - r); x <= (x1 + r); x++) {
413 if (!in_bounds(floor_ptr, y, x))
416 /* Extract the distance */
417 int k = distance(y1, x1, y, x);
419 /* Stay in the circle of death */
423 g_ptr = &floor_ptr->grid_array[y][x];
425 if (is_mirror_grid(g_ptr)) {
426 g_ptr->info |= CAVE_GLOW;
430 if ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
437 for (i = 0; i < 9; i++) {
440 if (!in_bounds2(floor_ptr, yy, xx))
442 cc_ptr = &floor_ptr->grid_array[yy][xx];
443 if (has_flag(f_info[get_feat_mimic(cc_ptr)].flags, FF_GLOW)) {
444 g_ptr->info |= CAVE_GLOW;
451 /* Hack -- Affect player */
453 msg_print(_("燃えるような閃光が発生した!", "There is a searing blast of light!"));
455 /* Blind the player */
456 if (!caster_ptr->resist_blind && !caster_ptr->resist_lite) {
458 (void)set_blind(caster_ptr, caster_ptr->blind + 10 + randint1(10));
462 forget_flow(floor_ptr);
464 /* Mega-Hack -- Forget the view and lite */
465 caster_ptr->update |= (PU_UN_VIEW | PU_UN_LITE | PU_VIEW | PU_LITE | PU_FLOW | PU_MON_LITE | PU_MONSTERS);
466 caster_ptr->redraw |= (PR_MAP);
467 caster_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
469 if (caster_ptr->special_defense & NINJA_S_STEALTH) {
470 if (floor_ptr->grid_array[caster_ptr->y][caster_ptr->x].info & CAVE_GLOW)
471 set_superstealth(caster_ptr, FALSE);