OSDN Git Service

eba38a0029f602fb772f0305729aedce13f678a1
[hengband/hengband.git] / src / floor.c
1 #include "angband.h"
2 #include "floor.h"
3 #include "floor-save.h"
4 #include "floor-generate.h"
5 #include "grid.h"
6 #include "dungeon.h"
7 #include "rooms.h"
8 #include "quest.h"
9 #include "object-hook.h"
10 #include "world.h"
11 #include "player-effects.h"
12 #include "object.h"
13 #include "object-hook.h"
14 #include "artifact.h"
15 #include "objectkind.h"
16 #include "trap.h"
17
18 /*
19  * The array of floor [MAX_WID][MAX_HGT].
20  * Not completely allocated, that would be inefficient
21  * Not completely hardcoded, that would overflow memory
22  */
23 floor_type floor_info;
24
25 /*
26  * The array of saved floors
27  */
28 saved_floor_type saved_floors[MAX_SAVED_FLOORS];
29
30 /*!
31 * @brief 鍵のかかったドアを配置する
32 * @param y 配置したいフロアのY座標
33 * @param x 配置したいフロアのX座標
34 * @return なし
35 */
36 void place_locked_door(floor_type *floor_ptr, POSITION y, POSITION x)
37 {
38         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
39         {
40                 place_floor_bold(floor_ptr, y, x);
41         }
42         else
43         {
44                 set_cave_feat(floor_ptr, y, x, feat_locked_door_random((d_info[p_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR));
45                 floor_ptr->grid_array[y][x].info &= ~(CAVE_FLOOR);
46                 delete_monster(floor_ptr, y, x);
47         }
48 }
49
50
51 /*!
52 * @brief 隠しドアを配置する
53 * @param y 配置したいフロアのY座標
54 * @param x 配置したいフロアのX座標
55 * @param type DOOR_DEFAULT / DOOR_DOOR / DOOR_GLASS_DOOR / DOOR_CURTAIN のいずれか
56 * @return なし
57 */
58 void place_secret_door(floor_type *floor_ptr, POSITION y, POSITION x, int type)
59 {
60         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
61         {
62                 place_floor_bold(floor_ptr, y, x);
63         }
64         else
65         {
66                 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
67
68                 if (type == DOOR_DEFAULT)
69                 {
70                         type = ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
71                                 one_in_((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
72                                 ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
73                 }
74
75                 /* Create secret door */
76                 place_closed_door(floor_ptr, y, x, type);
77
78                 if (type != DOOR_CURTAIN)
79                 {
80                         /* Hide by inner wall because this is used in rooms only */
81                         g_ptr->mimic = feat_wall_inner;
82
83                         /* Floor type terrain cannot hide a door */
84                         if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
85                         {
86                                 if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
87                                 {
88                                         g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
89                                 }
90                                 g_ptr->mimic = 0;
91                         }
92                 }
93
94                 g_ptr->info &= ~(CAVE_FLOOR);
95                 delete_monster(floor_ptr, y, x);
96         }
97 }
98
99 static int scent_when = 0;
100
101 /*
102  * Characters leave scent trails for perceptive monsters to track.
103  *
104  * Smell is rather more limited than sound.  Many creatures cannot use
105  * it at all, it doesn't extend very far outwards from the character's
106  * current position, and monsters can use it to home in the character,
107  * but not to run away from him.
108  *
109  * Smell is valued according to age.  When a character takes his turn,
110  * scent is aged by one, and new scent of the current age is laid down.
111  * Speedy characters leave more scent, true, but it also ages faster,
112  * which makes it harder to hunt them down.
113  *
114  * Whenever the age count loops, most of the scent trail is erased and
115  * the age of the remainder is recalculated.
116  */
117 void update_smell(floor_type *floor_ptr, player_type *subject_ptr)
118 {
119         POSITION i, j;
120         POSITION y, x;
121
122         /* Create a table that controls the spread of scent */
123         const int scent_adjust[5][5] =
124         {
125                 { -1, 0, 0, 0,-1 },
126                 {  0, 1, 1, 1, 0 },
127                 {  0, 1, 2, 1, 0 },
128                 {  0, 1, 1, 1, 0 },
129                 { -1, 0, 0, 0,-1 },
130         };
131
132         /* Loop the age and adjust scent values when necessary */
133         if (++scent_when == 254)
134         {
135                 /* Scan the entire dungeon */
136                 for (y = 0; y < floor_ptr->height; y++)
137                 {
138                         for (x = 0; x < floor_ptr->width; x++)
139                         {
140                                 int w = floor_ptr->grid_array[y][x].when;
141                                 floor_ptr->grid_array[y][x].when = (w > 128) ? (w - 128) : 0;
142                         }
143                 }
144
145                 /* Restart */
146                 scent_when = 126;
147         }
148
149
150         /* Lay down new scent */
151         for (i = 0; i < 5; i++)
152         {
153                 for (j = 0; j < 5; j++)
154                 {
155                         grid_type *g_ptr;
156
157                         /* Translate table to map grids */
158                         y = i + subject_ptr->y - 2;
159                         x = j + subject_ptr->x - 2;
160
161                         /* Check Bounds */
162                         if (!in_bounds(floor_ptr, y, x)) continue;
163
164                         g_ptr = &floor_ptr->grid_array[y][x];
165
166                         /* Walls, water, and lava cannot hold scent. */
167                         if (!cave_have_flag_grid(g_ptr, FF_MOVE) && !is_closed_door(g_ptr->feat)) continue;
168
169                         /* Grid must not be blocked by walls from the character */
170                         if (!player_has_los_bold(subject_ptr, y, x)) continue;
171
172                         /* Note grids that are too far away */
173                         if (scent_adjust[i][j] == -1) continue;
174
175                         /* Mark the grid with new scent */
176                         g_ptr->when = scent_when + scent_adjust[i][j];
177                 }
178         }
179 }
180
181
182 /*
183  * Hack -- forget the "flow" information
184  */
185 void forget_flow(floor_type *floor_ptr)
186 {
187         POSITION x, y;
188
189         /* Check the entire dungeon */
190         for (y = 0; y < floor_ptr->height; y++)
191         {
192                 for (x = 0; x < floor_ptr->width; x++)
193                 {
194                         /* Forget the old data */
195                         floor_ptr->grid_array[y][x].dist = 0;
196                         floor_ptr->grid_array[y][x].cost = 0;
197                         floor_ptr->grid_array[y][x].when = 0;
198                 }
199         }
200 }
201
202 /*
203  * Routine used by the random vault creators to add a door to a location
204  * Note that range checking has to be done in the calling routine.
205  *
206  * The doors must be INSIDE the allocated region.
207  */
208 void add_door(floor_type* floor_ptr, POSITION x, POSITION y)
209 {
210         /* Need to have a wall in the center square */
211         if (!is_outer_bold(floor_ptr, y, x)) return;
212
213         /* look at:
214         *  x#x
215         *  .#.
216         *  x#x
217         *
218         *  where x=don't care
219         *  .=floor, #=wall
220         */
221
222         if (is_floor_bold(floor_ptr, y - 1, x) && is_floor_bold(floor_ptr, y + 1, x) &&
223                 (is_outer_bold(floor_ptr, y, x - 1) && is_outer_bold(floor_ptr, y, x + 1)))
224         {
225                 /* secret door */
226                 place_secret_door(floor_ptr, y, x, DOOR_DEFAULT);
227
228                 /* set boundarys so don't get wide doors */
229                 place_solid_bold(floor_ptr, y, x - 1);
230                 place_solid_bold(floor_ptr, y, x + 1);
231         }
232
233
234         /* look at:
235         *  x#x
236         *  .#.
237         *  x#x
238         *
239         *  where x = don't care
240         *  .=floor, #=wall
241         */
242         if (is_outer_bold(floor_ptr, y - 1, x) && is_outer_bold(floor_ptr, y + 1, x) &&
243                 is_floor_bold(floor_ptr, y, x - 1) && is_floor_bold(floor_ptr, y, x + 1))
244         {
245                 /* secret door */
246                 place_secret_door(floor_ptr, y, x, DOOR_DEFAULT);
247
248                 /* set boundarys so don't get wide doors */
249                 place_solid_bold(floor_ptr, y - 1, x);
250                 place_solid_bold(floor_ptr, y + 1, x);
251         }
252 }
253
254 /*!
255  * @brief 所定の位置に上り階段か下り階段を配置する / Place an up/down staircase at given location
256  * @param y 配置を試みたいマスのY座標
257  * @param x 配置を試みたいマスのX座標
258  * @return なし
259  */
260 void place_random_stairs(floor_type *floor_ptr, POSITION y, POSITION x)
261 {
262         bool up_stairs = TRUE;
263         bool down_stairs = TRUE;
264         grid_type *g_ptr;
265         g_ptr = &floor_ptr->grid_array[y][x];
266         if (!is_floor_grid(g_ptr) || g_ptr->o_idx) return;
267
268         if (!floor_ptr->dun_level) up_stairs = FALSE;
269         if (ironman_downward) up_stairs = FALSE;
270         if (floor_ptr->dun_level >= d_info[p_ptr->dungeon_idx].maxdepth) down_stairs = FALSE;
271         if (quest_number(floor_ptr->dun_level) && (floor_ptr->dun_level > 1)) down_stairs = FALSE;
272
273         /* We can't place both */
274         if (down_stairs && up_stairs)
275         {
276                 /* Choose a staircase randomly */
277                 if (randint0(100) < 50) up_stairs = FALSE;
278                 else down_stairs = FALSE;
279         }
280
281         /* Place the stairs */
282         if (up_stairs) set_cave_feat(floor_ptr, y, x, feat_up_stair);
283         else if (down_stairs) set_cave_feat(floor_ptr, y, x, feat_down_stair);
284 }
285
286 /*!
287  * @brief LOS(Line Of Sight / 視線が通っているか)の判定を行う。
288  * @param y1 始点のy座標
289  * @param x1 始点のx座標
290  * @param y2 終点のy座標
291  * @param x2 終点のx座標
292  * @return LOSが通っているならTRUEを返す。
293  * @details
294  * A simple, fast, integer-based line-of-sight algorithm.  By Joseph Hall,\n
295  * 4116 Brewster Drive, Raleigh NC 27606.  Email to jnh@ecemwl.ncsu.edu.\n
296  *\n
297  * Returns TRUE if a line of sight can be traced from (x1,y1) to (x2,y2).\n
298  *\n
299  * The LOS begins at the center of the tile (x1,y1) and ends at the center of\n
300  * the tile (x2,y2).  If los() is to return TRUE, all of the tiles this line\n
301  * passes through must be floor tiles, except for (x1,y1) and (x2,y2).\n
302  *\n
303  * We assume that the "mathematical corner" of a non-floor tile does not\n
304  * block line of sight.\n
305  *\n
306  * Because this function uses (short) ints for all calculations, overflow may\n
307  * occur if dx and dy exceed 90.\n
308  *\n
309  * Once all the degenerate cases are eliminated, the values "qx", "qy", and\n
310  * "m" are multiplied by a scale factor "f1 = abs(dx * dy * 2)", so that\n
311  * we can use integer arithmetic.\n
312  *\n
313  * We travel from start to finish along the longer axis, starting at the border\n
314  * between the first and second tiles, where the y offset = .5 * slope, taking\n
315  * into account the scale factor.  See below.\n
316  *\n
317  * Also note that this function and the "move towards target" code do NOT\n
318  * share the same properties.  Thus, you can see someone, target them, and\n
319  * then fire a bolt at them, but the bolt may hit a wall, not them.  However\n,
320  * by clever choice of target locations, you can sometimes throw a "curve".\n
321  *\n
322  * Note that "line of sight" is not "reflexive" in all cases.\n
323  *\n
324  * Use the "projectable()" routine to test "spell/missile line of sight".\n
325  *\n
326  * Use the "update_view()" function to determine player line-of-sight.\n
327  */
328 bool los(floor_type *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
329 {
330         /* Delta */
331         POSITION dx, dy;
332
333         /* Absolute */
334         POSITION ax, ay;
335
336         /* Signs */
337         POSITION sx, sy;
338
339         /* Fractions */
340         POSITION qx, qy;
341
342         /* Scanners */
343         POSITION tx, ty;
344
345         /* Scale factors */
346         POSITION f1, f2;
347
348         /* Slope, or 1/Slope, of LOS */
349         POSITION m;
350
351
352         /* Extract the offset */
353         dy = y2 - y1;
354         dx = x2 - x1;
355
356         /* Extract the absolute offset */
357         ay = ABS(dy);
358         ax = ABS(dx);
359
360
361         /* Handle adjacent (or identical) grids */
362         if ((ax < 2) && (ay < 2)) return TRUE;
363
364
365         /* Paranoia -- require "safe" origin */
366         /* if (!in_bounds(floor_ptr, y1, x1)) return FALSE; */
367         /* if (!in_bounds(floor_ptr, y2, x2)) return FALSE; */
368
369
370         /* Directly South/North */
371         if (!dx)
372         {
373                 /* South -- check for walls */
374                 if (dy > 0)
375                 {
376                         for (ty = y1 + 1; ty < y2; ty++)
377                         {
378                                 if (!cave_los_bold(floor_ptr, ty, x1)) return FALSE;
379                         }
380                 }
381
382                 /* North -- check for walls */
383                 else
384                 {
385                         for (ty = y1 - 1; ty > y2; ty--)
386                         {
387                                 if (!cave_los_bold(floor_ptr, ty, x1)) return FALSE;
388                         }
389                 }
390
391                 /* Assume los */
392                 return TRUE;
393         }
394
395         /* Directly East/West */
396         if (!dy)
397         {
398                 /* East -- check for walls */
399                 if (dx > 0)
400                 {
401                         for (tx = x1 + 1; tx < x2; tx++)
402                         {
403                                 if (!cave_los_bold(floor_ptr, y1, tx)) return FALSE;
404                         }
405                 }
406
407                 /* West -- check for walls */
408                 else
409                 {
410                         for (tx = x1 - 1; tx > x2; tx--)
411                         {
412                                 if (!cave_los_bold(floor_ptr, y1, tx)) return FALSE;
413                         }
414                 }
415
416                 /* Assume los */
417                 return TRUE;
418         }
419
420
421         /* Extract some signs */
422         sx = (dx < 0) ? -1 : 1;
423         sy = (dy < 0) ? -1 : 1;
424
425
426         /* Vertical "knights" */
427         if (ax == 1)
428         {
429                 if (ay == 2)
430                 {
431                         if (cave_los_bold(floor_ptr, y1 + sy, x1)) return TRUE;
432                 }
433         }
434
435         /* Horizontal "knights" */
436         else if (ay == 1)
437         {
438                 if (ax == 2)
439                 {
440                         if (cave_los_bold(floor_ptr, y1, x1 + sx)) return TRUE;
441                 }
442         }
443
444
445         /* Calculate scale factor div 2 */
446         f2 = (ax * ay);
447
448         /* Calculate scale factor */
449         f1 = f2 << 1;
450
451
452         /* Travel horizontally */
453         if (ax >= ay)
454         {
455                 /* Let m = dy / dx * 2 * (dy * dx) = 2 * dy * dy */
456                 qy = ay * ay;
457                 m = qy << 1;
458
459                 tx = x1 + sx;
460
461                 /* Consider the special case where slope == 1. */
462                 if (qy == f2)
463                 {
464                         ty = y1 + sy;
465                         qy -= f1;
466                 }
467                 else
468                 {
469                         ty = y1;
470                 }
471
472                 /* Note (below) the case (qy == f2), where */
473                 /* the LOS exactly meets the corner of a tile. */
474                 while (x2 - tx)
475                 {
476                         if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
477
478                         qy += m;
479
480                         if (qy < f2)
481                         {
482                                 tx += sx;
483                         }
484                         else if (qy > f2)
485                         {
486                                 ty += sy;
487                                 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
488                                 qy -= f1;
489                                 tx += sx;
490                         }
491                         else
492                         {
493                                 ty += sy;
494                                 qy -= f1;
495                                 tx += sx;
496                         }
497                 }
498         }
499
500         /* Travel vertically */
501         else
502         {
503                 /* Let m = dx / dy * 2 * (dx * dy) = 2 * dx * dx */
504                 qx = ax * ax;
505                 m = qx << 1;
506
507                 ty = y1 + sy;
508
509                 if (qx == f2)
510                 {
511                         tx = x1 + sx;
512                         qx -= f1;
513                 }
514                 else
515                 {
516                         tx = x1;
517                 }
518
519                 /* Note (below) the case (qx == f2), where */
520                 /* the LOS exactly meets the corner of a tile. */
521                 while (y2 - ty)
522                 {
523                         if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
524
525                         qx += m;
526
527                         if (qx < f2)
528                         {
529                                 ty += sy;
530                         }
531                         else if (qx > f2)
532                         {
533                                 tx += sx;
534                                 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
535                                 qx -= f1;
536                                 ty += sy;
537                         }
538                         else
539                         {
540                                 tx += sx;
541                                 qx -= f1;
542                                 ty += sy;
543                         }
544                 }
545         }
546
547         /* Assume los */
548         return TRUE;
549 }
550
551
552 /*
553  * Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive
554  * at the final destination, assuming no monster gets in the way.
555  *
556  * This is slightly (but significantly) different from "los(y1,x1,y2,x2)".
557  */
558 bool projectable(floor_type *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
559 {
560         POSITION y, x;
561
562         int grid_n = 0;
563         u16b grid_g[512];
564
565         /* Check the projection path */
566         grid_n = project_path(floor_ptr, grid_g, (project_length ? project_length : MAX_RANGE), y1, x1, y2, x2, 0);
567
568         /* Identical grid */
569         if (!grid_n) return TRUE;
570
571         /* Final grid */
572         y = GRID_Y(grid_g[grid_n - 1]);
573         x = GRID_X(grid_g[grid_n - 1]);
574
575         /* May not end in an unrequested grid */
576         if ((y != y2) || (x != x2)) return FALSE;
577
578         /* Assume okay */
579         return TRUE;
580 }
581
582
583 /*!
584  * @brief 特殊な部屋地形向けにモンスターを配置する / Hack -- Place some sleeping monsters near the given location
585  * @param y1 モンスターを配置したいマスの中心Y座標
586  * @param x1 モンスターを配置したいマスの中心X座標
587  * @param num 配置したいモンスターの数
588  * @return なし
589  * @details
590  * Only really called by some of the "vault" routines.
591  */
592 void vault_monsters(floor_type *floor_ptr, POSITION y1, POSITION x1, int num)
593 {
594         int k, i;
595         POSITION y, x;
596         grid_type *g_ptr;
597
598         /* Try to summon "num" monsters "near" the given location */
599         for (k = 0; k < num; k++)
600         {
601                 /* Try nine locations */
602                 for (i = 0; i < 9; i++)
603                 {
604                         int d = 1;
605
606                         /* Pick a nearby location */
607                         scatter(floor_ptr, &y, &x, y1, x1, d, 0);
608
609                         /* Require "empty" floor grids */
610                         g_ptr = &floor_ptr->grid_array[y][x];
611                         if (!cave_empty_grid(g_ptr)) continue;
612
613                         /* Place the monster (allow groups) */
614                         floor_ptr->monster_level = floor_ptr->base_level + 2;
615                         (void)place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
616                         floor_ptr->monster_level = floor_ptr->base_level;
617                 }
618         }
619 }
620
621
622 /*!
623  * @brief 指定された座標が地震や階段生成の対象となるマスかを返す。 / Determine if a given location may be "destroyed"
624  * @param y y座標
625  * @param x x座標
626  * @return 各種の変更が可能ならTRUEを返す。
627  * @details
628  * 条件は永久地形でなく、なおかつ該当のマスにアーティファクトが存在しないか、である。英語の旧コメントに反して*破壊*の抑止判定には現在使われていない。
629  */
630 bool cave_valid_bold(floor_type *floor_ptr, POSITION y, POSITION x)
631 {
632         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
633         OBJECT_IDX this_o_idx, next_o_idx = 0;
634
635         /* Forbid perma-grids */
636         if (cave_perma_grid(g_ptr)) return FALSE;
637
638         /* Check objects */
639         for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
640         {
641                 object_type *o_ptr;
642                 o_ptr = &floor_ptr->o_list[this_o_idx];
643                 next_o_idx = o_ptr->next_o_idx;
644
645                 /* Forbid artifact grids */
646                 if (object_is_artifact(o_ptr)) return FALSE;
647         }
648
649         /* Accept */
650         return TRUE;
651 }
652
653 /*
654  * Change the "feat" flag for a grid, and notice/redraw the grid
655  */
656 void cave_set_feat(floor_type *floor_ptr, POSITION y, POSITION x, FEAT_IDX feat)
657 {
658         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
659         feature_type *f_ptr = &f_info[feat];
660         bool old_los, old_mirror;
661
662         if (!current_world_ptr->character_dungeon)
663         {
664                 /* Clear mimic type */
665                 g_ptr->mimic = 0;
666
667                 /* Change the feature */
668                 g_ptr->feat = feat;
669
670                 /* Hack -- glow the GLOW terrain */
671                 if (have_flag(f_ptr->flags, FF_GLOW) && !(d_info[floor_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
672                 {
673                         DIRECTION i;
674                         POSITION yy, xx;
675
676                         for (i = 0; i < 9; i++)
677                         {
678                                 yy = y + ddy_ddd[i];
679                                 xx = x + ddx_ddd[i];
680                                 if (!in_bounds2(floor_ptr, yy, xx)) continue;
681                                 floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
682                         }
683                 }
684
685                 return;
686         }
687
688         old_los = cave_have_flag_bold(floor_ptr, y, x, FF_LOS);
689         old_mirror = is_mirror_grid(g_ptr);
690
691         /* Clear mimic type */
692         g_ptr->mimic = 0;
693
694         /* Change the feature */
695         g_ptr->feat = feat;
696
697         /* Remove flag for mirror/glyph */
698         g_ptr->info &= ~(CAVE_OBJECT);
699
700         if (old_mirror && (d_info[floor_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
701         {
702                 g_ptr->info &= ~(CAVE_GLOW);
703                 if (!view_torch_grids) g_ptr->info &= ~(CAVE_MARK);
704
705                 update_local_illumination(p_ptr, y, x);
706         }
707
708         /* Check for change to boring grid */
709         if (!have_flag(f_ptr->flags, FF_REMEMBER)) g_ptr->info &= ~(CAVE_MARK);
710         if (g_ptr->m_idx) update_monster(p_ptr, g_ptr->m_idx, FALSE);
711
712         note_spot(y, x);
713         lite_spot(y, x);
714
715         /* Check if los has changed */
716         if (old_los ^ have_flag(f_ptr->flags, FF_LOS))
717         {
718
719 #ifdef COMPLEX_WALL_ILLUMINATION /* COMPLEX_WALL_ILLUMINATION */
720
721                 update_local_illumination(p_ptr, y, x);
722
723 #endif /* COMPLEX_WALL_ILLUMINATION */
724
725                 /* Update the visuals */
726                 p_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE | PU_MONSTERS);
727         }
728
729         /* Hack -- glow the GLOW terrain */
730         if (have_flag(f_ptr->flags, FF_GLOW) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
731         {
732                 DIRECTION i;
733                 POSITION yy, xx;
734                 grid_type *cc_ptr;
735
736                 for (i = 0; i < 9; i++)
737                 {
738                         yy = y + ddy_ddd[i];
739                         xx = x + ddx_ddd[i];
740                         if (!in_bounds2(floor_ptr, yy, xx)) continue;
741                         cc_ptr = &floor_ptr->grid_array[yy][xx];
742                         cc_ptr->info |= CAVE_GLOW;
743
744                         if (player_has_los_grid(cc_ptr))
745                         {
746                                 if (cc_ptr->m_idx) update_monster(p_ptr, cc_ptr->m_idx, FALSE);
747                                 note_spot(yy, xx);
748                                 lite_spot(yy, xx);
749                         }
750
751                         update_local_illumination(p_ptr, yy, xx);
752                 }
753
754                 if (p_ptr->special_defense & NINJA_S_STEALTH)
755                 {
756                         if (floor_ptr->grid_array[p_ptr->y][p_ptr->x].info & CAVE_GLOW) set_superstealth(p_ptr, FALSE);
757                 }
758         }
759 }
760
761
762 /*!
763  * @brief 所定の位置にさまざまな状態や種類のドアを配置する / Place a random type of door at the given location
764  * @param y ドアの配置を試みたいマスのY座標
765  * @param x ドアの配置を試みたいマスのX座標
766  * @param room 部屋に接している場合向けのドア生成か否か
767  * @return なし
768  */
769 void place_random_door(floor_type *floor_ptr, POSITION y, POSITION x, bool room)
770 {
771         int tmp, type;
772         FEAT_IDX feat = feat_none;
773         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
774
775         /* Initialize mimic info */
776         g_ptr->mimic = 0;
777
778         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
779         {
780                 place_floor_bold(floor_ptr, y, x);
781                 return;
782         }
783
784         type = ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
785                 one_in_((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
786                 ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
787
788         /* Choose an object */
789         tmp = randint0(1000);
790
791         /* Open doors (300/1000) */
792         if (tmp < 300)
793         {
794                 /* Create open door */
795                 feat = feat_door[type].open;
796         }
797
798         /* Broken doors (100/1000) */
799         else if (tmp < 400)
800         {
801                 /* Create broken door */
802                 feat = feat_door[type].broken;
803         }
804
805         /* Secret doors (200/1000) */
806         else if (tmp < 600)
807         {
808                 /* Create secret door */
809                 place_closed_door(floor_ptr, y, x, type);
810
811                 if (type != DOOR_CURTAIN)
812                 {
813                         /* Hide. If on the edge of room, use outer wall. */
814                         g_ptr->mimic = room ? feat_wall_outer : feat_wall_type[randint0(100)];
815
816                         /* Floor type terrain cannot hide a door */
817                         if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
818                         {
819                                 if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
820                                 {
821                                         g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
822                                 }
823                                 g_ptr->mimic = 0;
824                         }
825                 }
826         }
827
828         /* Closed, locked, or stuck doors (400/1000) */
829         else place_closed_door(floor_ptr, y, x, type);
830
831         if (tmp < 400)
832         {
833                 if (feat != feat_none)
834                 {
835                         set_cave_feat(floor_ptr, y, x, feat);
836                 }
837                 else
838                 {
839                         place_floor_bold(floor_ptr, y, x);
840                 }
841         }
842
843         delete_monster(floor_ptr, y, x);
844 }
845
846
847
848 /*!
849  * @brief グローバルオブジェクト配列を初期化する /
850  * Delete all the items when player leaves the level
851  * @note we do NOT visually reflect these (irrelevant) changes
852  * @details
853  * Hack -- we clear the "g_ptr->o_idx" field for every grid,
854  * and the "m_ptr->next_o_idx" field for every monster, since
855  * we know we are clearing every object.  Technically, we only
856  * clear those fields for grids/monsters containing objects,
857  * and we clear it once for every such object.
858  * @return なし
859  */
860 void wipe_o_list(floor_type *floor_ptr)
861 {
862         int i;
863
864         /* Delete the existing objects */
865         for (i = 1; i < floor_ptr->o_max; i++)
866         {
867                 object_type *o_ptr = &floor_ptr->o_list[i];
868
869                 if (!OBJECT_IS_VALID(o_ptr)) continue;
870
871                 /* Mega-Hack -- preserve artifacts */
872                 if (!current_world_ptr->character_dungeon || preserve_mode)
873                 {
874                         /* Hack -- Preserve unknown artifacts */
875                         if (object_is_fixed_artifact(o_ptr) && !object_is_known(o_ptr))
876                         {
877                                 /* Mega-Hack -- Preserve the artifact */
878                                 a_info[o_ptr->name1].cur_num = 0;
879                         }
880                 }
881
882                 if (OBJECT_IS_HELD_MONSTER(o_ptr))
883                 {
884                         monster_type *m_ptr;
885                         m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
886
887                         /* Hack -- see above */
888                         m_ptr->hold_o_idx = 0;
889                 }
890
891                 /* Dungeon */
892                 else
893                 {
894                         grid_type *g_ptr;
895
896                         /* Access location */
897                         POSITION y = o_ptr->iy;
898                         POSITION x = o_ptr->ix;
899
900                         /* Access grid */
901                         g_ptr = &floor_ptr->grid_array[y][x];
902
903                         /* Hack -- see above */
904                         g_ptr->o_idx = 0;
905                 }
906                 object_wipe(o_ptr);
907         }
908
909         /* Reset "floor_ptr->o_max" */
910         floor_ptr->o_max = 1;
911
912         /* Reset "floor_ptr->o_cnt" */
913         floor_ptr->o_cnt = 0;
914 }
915
916
917 /*!
918  * @brief 所定の位置に各種の閉じたドアを配置する / Place a random type of normal door at the given location.
919  * @param y ドアの配置を試みたいマスのY座標
920  * @param x ドアの配置を試みたいマスのX座標
921  * @param type ドアの地形ID
922  * @return なし
923  */
924 void place_closed_door(floor_type *floor_ptr, POSITION y, POSITION x, int type)
925 {
926         int tmp;
927         FEAT_IDX feat = feat_none;
928
929         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
930         {
931                 place_floor_bold(floor_ptr, y, x);
932                 return;
933         }
934
935         /* Choose an object */
936         tmp = randint0(400);
937
938         /* Closed doors (300/400) */
939         if (tmp < 300)
940         {
941                 /* Create closed door */
942                 feat = feat_door[type].closed;
943         }
944
945         /* Locked doors (99/400) */
946         else if (tmp < 399)
947         {
948                 /* Create locked door */
949                 feat = feat_locked_door_random(type);
950         }
951
952         /* Stuck doors (1/400) */
953         else
954         {
955                 /* Create jammed door */
956                 feat = feat_jammed_door_random(type);
957         }
958
959         if (feat != feat_none)
960         {
961                 cave_set_feat(floor_ptr, y, x, feat);
962
963                 /* Now it is not floor */
964                 floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
965         }
966         else
967         {
968                 place_floor_bold(floor_ptr, y, x);
969         }
970 }
971
972 /*!
973  * @brief 特殊な部屋向けに各種アイテムを配置する(vault_trapのサブセット) / Place a trap with a given displacement of point
974  * @param y トラップを配置したいマスの中心Y座標
975  * @param x トラップを配置したいマスの中心X座標
976  * @param yd Y方向の配置分散マス数
977  * @param xd X方向の配置分散マス数
978  * @return なし
979  * @details
980  * Only really called by some of the "vault" routines.
981  */
982 void vault_trap_aux(floor_type *floor_ptr, POSITION y, POSITION x, POSITION yd, POSITION xd)
983 {
984         int count = 0, y1 = y, x1 = x;
985         int dummy = 0;
986
987         grid_type *g_ptr;
988
989         /* Place traps */
990         for (count = 0; count <= 5; count++)
991         {
992                 /* Get a location */
993                 while (dummy < SAFE_MAX_ATTEMPTS)
994                 {
995                         y1 = rand_spread(y, yd);
996                         x1 = rand_spread(x, xd);
997                         dummy++;
998                         if (!in_bounds(floor_ptr, y1, x1)) continue;
999                         break;
1000                 }
1001
1002                 if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room)
1003                 {
1004                         msg_print(_("警告!地下室のトラップを配置できません!", "Warning! Could not place vault trap!"));
1005                 }
1006
1007                 /* Require "naked" floor grids */
1008                 g_ptr = &floor_ptr->grid_array[y1][x1];
1009                 if (!is_floor_grid(g_ptr) || g_ptr->o_idx || g_ptr->m_idx) continue;
1010
1011                 /* Place the trap */
1012                 place_trap(floor_ptr, y1, x1);
1013
1014                 break;
1015         }
1016 }
1017
1018 /*!
1019  * @brief 指定のマスが床系地形であるかを返す / Function that sees if a square is a floor.  (Includes range checking.)
1020  * @param x チェックするマスのX座標
1021  * @param y チェックするマスのY座標
1022  * @return 床系地形ならばTRUE
1023  */
1024 bool get_is_floor(floor_type *floor_ptr, POSITION x, POSITION y)
1025 {
1026         if (!in_bounds(floor_ptr, y, x))
1027         {
1028                 /* Out of bounds */
1029                 return FALSE;
1030         }
1031
1032         /* Do the real check */
1033         if (is_floor_bold(floor_ptr, y, x)) return TRUE;
1034
1035         return FALSE;
1036 }
1037
1038 /*!
1039 * @brief 隣接4マスに存在する通路の数を返す / Count the number of "corridor" grids adjacent to the given grid.
1040 * @param y1 基準となるマスのY座標
1041 * @param x1 基準となるマスのX座標
1042 * @return 通路の数
1043 * @note Assumes "in_bounds(y1, x1)"
1044 * @details
1045 * XXX XXX This routine currently only counts actual "empty floor"\n
1046 * grids which are not in rooms.  We might want to also count stairs,\n
1047 * open doors, closed doors, etc.
1048 */
1049 static int next_to_corr(floor_type *floor_ptr, POSITION y1, POSITION x1)
1050 {
1051         int i, k = 0;
1052         POSITION y, x;
1053
1054         grid_type *g_ptr;
1055
1056         /* Scan adjacent grids */
1057         for (i = 0; i < 4; i++)
1058         {
1059                 y = y1 + ddy_ddd[i];
1060                 x = x1 + ddx_ddd[i];
1061                 g_ptr = &floor_ptr->grid_array[y][x];
1062
1063                 /* Skip non floors */
1064                 if (cave_have_flag_grid(g_ptr, FF_WALL)) continue;
1065
1066                 /* Skip non "empty floor" grids */
1067                 if (!is_floor_grid(g_ptr))
1068                         continue;
1069
1070                 /* Skip grids inside rooms */
1071                 if (g_ptr->info & (CAVE_ROOM)) continue;
1072
1073                 /* Count these grids */
1074                 k++;
1075         }
1076
1077         /* Return the number of corridors */
1078         return (k);
1079 }
1080
1081 /*!
1082 * @brief ドアを設置可能な地形かを返す / Determine if the given location is "between" two walls, and "next to" two corridor spaces.
1083 * @param y 判定を行いたいマスのY座標
1084 * @param x 判定を行いたいマスのX座標
1085 * @return ドアを設置可能ならばTRUEを返す
1086 * @note Assumes "in_bounds()"
1087 * @details
1088 * \n
1089 * Assumes "in_bounds()"\n
1090 */
1091 static bool possible_doorway(floor_type *floor_ptr, POSITION y, POSITION x)
1092 {
1093         /* Count the adjacent corridors */
1094         if (next_to_corr(floor_ptr, y, x) >= 2)
1095         {
1096                 /* Check Vertical */
1097                 if (cave_have_flag_bold(floor_ptr, y - 1, x, FF_WALL) &&
1098                         cave_have_flag_bold(floor_ptr, y + 1, x, FF_WALL))
1099                 {
1100                         return TRUE;
1101                 }
1102
1103                 /* Check Horizontal */
1104                 if (cave_have_flag_bold(floor_ptr, y, x - 1, FF_WALL) &&
1105                         cave_have_flag_bold(floor_ptr, y, x + 1, FF_WALL))
1106                 {
1107                         return TRUE;
1108                 }
1109         }
1110
1111         /* No doorway */
1112         return FALSE;
1113 }
1114
1115 /*!
1116 * @brief ドアの設置を試みる / Places door at y, x position if at least 2 walls found
1117 * @param y 設置を行いたいマスのY座標
1118 * @param x 設置を行いたいマスのX座標
1119 * @return なし
1120 */
1121 void try_door(floor_type *floor_ptr, POSITION y, POSITION x)
1122 {
1123         if (!in_bounds(floor_ptr, y, x)) return;
1124
1125         /* Ignore walls */
1126         if (cave_have_flag_bold(floor_ptr, y, x, FF_WALL)) return;
1127
1128         /* Ignore room grids */
1129         if (floor_ptr->grid_array[y][x].info & (CAVE_ROOM)) return;
1130
1131         /* Occasional door (if allowed) */
1132         if ((randint0(100) < dun_tun_jct) && possible_doorway(floor_ptr, y, x) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_DOORS))
1133         {
1134                 /* Place a door */
1135                 place_random_door(floor_ptr, y, x, FALSE);
1136         }
1137 }
1138
1139
1140 FEAT_IDX conv_dungeon_feat(floor_type *floor_ptr, FEAT_IDX newfeat)
1141 {
1142         feature_type *f_ptr = &f_info[newfeat];
1143
1144         if (have_flag(f_ptr->flags, FF_CONVERT))
1145         {
1146                 switch (f_ptr->subtype)
1147                 {
1148                 case CONVERT_TYPE_FLOOR:
1149                         return feat_ground_type[randint0(100)];
1150                 case CONVERT_TYPE_WALL:
1151                         return feat_wall_type[randint0(100)];
1152                 case CONVERT_TYPE_INNER:
1153                         return feat_wall_inner;
1154                 case CONVERT_TYPE_OUTER:
1155                         return feat_wall_outer;
1156                 case CONVERT_TYPE_SOLID:
1157                         return feat_wall_solid;
1158                 case CONVERT_TYPE_STREAM1:
1159                         return d_info[floor_ptr->dungeon_idx].stream1;
1160                 case CONVERT_TYPE_STREAM2:
1161                         return d_info[floor_ptr->dungeon_idx].stream2;
1162                 default:
1163                         return newfeat;
1164                 }
1165         }
1166         else return newfeat;
1167 }
1168
1169
1170 /*!
1171  * @brief 特殊な部屋向けに各種アイテムを配置する / Create up to "num" objects near the given coordinates
1172  * @param player_ptr プレーヤーへの参照ポインタ
1173  * @param y 配置したい中心マスのY座標
1174  * @param x 配置したい中心マスのX座標
1175  * @param num 配置したい数
1176  * @return なし
1177  * @details
1178  * Only really called by some of the "vault" routines.
1179  */
1180 void vault_objects(player_type *player_ptr, POSITION y, POSITION x, int num)
1181 {
1182         int dummy = 0;
1183         int i = 0, j = y, k = x;
1184
1185         grid_type *g_ptr;
1186         floor_type *floor_ptr = player_ptr->current_floor_ptr;
1187
1188         /* Attempt to place 'num' objects */
1189         for (; num > 0; --num)
1190         {
1191                 /* Try up to 11 spots looking for empty space */
1192                 for (i = 0; i < 11; ++i)
1193                 {
1194                         /* Pick a random location */
1195                         while (dummy < SAFE_MAX_ATTEMPTS)
1196                         {
1197                                 j = rand_spread(y, 2);
1198                                 k = rand_spread(x, 3);
1199                                 dummy++;
1200                                 if (!in_bounds(floor_ptr, j, k)) continue;
1201                                 break;
1202                         }
1203
1204                         if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room)
1205                         {
1206                                 msg_print(_("警告!地下室のアイテムを配置できません!", "Warning! Could not place vault object!"));
1207                         }
1208
1209                         /* Require "clean" floor space */
1210                         g_ptr = &floor_ptr->grid_array[j][k];
1211                         if (!is_floor_grid(g_ptr) || g_ptr->o_idx) continue;
1212
1213                         if (randint0(100) < 75)
1214                         {
1215                                 place_object(player_ptr, j, k, 0L);
1216                         }
1217                         else
1218                         {
1219                                 place_gold(floor_ptr, j, k);
1220                         }
1221
1222                         /* Placement accomplished */
1223                         break;
1224                 }
1225         }
1226 }
1227
1228 /*!
1229  * @brief 始点から終点への直線経路を返す /
1230  * Determine the path taken by a projection.
1231  * @param gp 経路座標リストを返す参照ポインタ
1232  * @param range 距離
1233  * @param y1 始点Y座標
1234  * @param x1 始点X座標
1235  * @param y2 終点Y座標
1236  * @param x2 終点X座標
1237  * @param flg フラグID
1238  * @return リストの長さ
1239  * @details
1240  * <pre>
1241  * The projection will always start from the grid (y1,x1), and will travel
1242  * towards the grid (y2,x2), touching one grid per unit of distance along
1243  * the major axis, and stopping when it enters the destination grid or a
1244  * wall grid, or has travelled the maximum legal distance of "range".
1245  *
1246  * Note that "distance" in this function (as in the "update_view()" code)
1247  * is defined as "MAX(dy,dx) + MIN(dy,dx)/2", which means that the player
1248  * actually has an "octagon of projection" not a "circle of projection".
1249  *
1250  * The path grids are saved into the grid array pointed to by "gp", and
1251  * there should be room for at least "range" grids in "gp".  Note that
1252  * due to the way in which distance is calculated, this function normally
1253  * uses fewer than "range" grids for the projection path, so the result
1254  * of this function should never be compared directly to "range".  Note
1255  * that the initial grid (y1,x1) is never saved into the grid array, not
1256  * even if the initial grid is also the final grid.
1257  *
1258  * The "flg" flags can be used to modify the behavior of this function.
1259  *
1260  * In particular, the "PROJECT_STOP" and "PROJECT_THRU" flags have the same
1261  * semantics as they do for the "project" function, namely, that the path
1262  * will stop as soon as it hits a monster, or that the path will continue
1263  * through the destination grid, respectively.
1264  *
1265  * The "PROJECT_JUMP" flag, which for the "project()" function means to
1266  * start at a special grid (which makes no sense in this function), means
1267  * that the path should be "angled" slightly if needed to avoid any wall
1268  * grids, allowing the player to "target" any grid which is in "view".
1269  * This flag is non-trivial and has not yet been implemented, but could
1270  * perhaps make use of the "vinfo" array (above).
1271  *
1272  * This function returns the number of grids (if any) in the path.  This
1273  * function will return zero if and only if (y1,x1) and (y2,x2) are equal.
1274  *
1275  * This algorithm is similar to, but slightly different from, the one used
1276  * by "update_view_los()", and very different from the one used by "los()".
1277  * </pre>
1278  */
1279 sint project_path(floor_type *floor_ptr, u16b *gp, POSITION range, POSITION y1, POSITION x1, POSITION y2, POSITION x2, BIT_FLAGS flg)
1280 {
1281         POSITION y, x;
1282
1283         int n = 0;
1284         int k = 0;
1285
1286         /* Absolute */
1287         POSITION ay, ax;
1288
1289         /* Offsets */
1290         POSITION sy, sx;
1291
1292         /* Fractions */
1293         int frac;
1294
1295         /* Scale factors */
1296         int full, half;
1297
1298         /* Slope */
1299         int m;
1300
1301         /* No path necessary (or allowed) */
1302         if ((x1 == x2) && (y1 == y2)) return (0);
1303
1304
1305         /* Analyze "dy" */
1306         if (y2 < y1)
1307         {
1308                 ay = (y1 - y2);
1309                 sy = -1;
1310         }
1311         else
1312         {
1313                 ay = (y2 - y1);
1314                 sy = 1;
1315         }
1316
1317         /* Analyze "dx" */
1318         if (x2 < x1)
1319         {
1320                 ax = (x1 - x2);
1321                 sx = -1;
1322         }
1323         else
1324         {
1325                 ax = (x2 - x1);
1326                 sx = 1;
1327         }
1328
1329
1330         /* Number of "units" in one "half" grid */
1331         half = (ay * ax);
1332
1333         /* Number of "units" in one "full" grid */
1334         full = half << 1;
1335
1336         /* Vertical */
1337         if (ay > ax)
1338         {
1339                 /* Let m = ((dx/dy) * full) = (dx * dx * 2) */
1340                 m = ax * ax * 2;
1341
1342                 /* Start */
1343                 y = y1 + sy;
1344                 x = x1;
1345
1346                 frac = m;
1347
1348                 if (frac > half)
1349                 {
1350                         /* Advance (X) part 2 */
1351                         x += sx;
1352
1353                         /* Advance (X) part 3 */
1354                         frac -= full;
1355
1356                         /* Track distance */
1357                         k++;
1358                 }
1359
1360                 /* Create the projection path */
1361                 while (1)
1362                 {
1363                         /* Save grid */
1364                         gp[n++] = GRID(y, x);
1365
1366                         /* Hack -- Check maximum range */
1367                         if ((n + (k >> 1)) >= range) break;
1368
1369                         /* Sometimes stop at destination grid */
1370                         if (!(flg & (PROJECT_THRU)))
1371                         {
1372                                 if ((x == x2) && (y == y2)) break;
1373                         }
1374
1375                         if (flg & (PROJECT_DISI))
1376                         {
1377                                 if ((n > 0) && cave_stop_disintegration(floor_ptr, y, x)) break;
1378                         }
1379                         else if (flg & (PROJECT_LOS))
1380                         {
1381                                 if ((n > 0) && !cave_los_bold(floor_ptr, y, x)) break;
1382                         }
1383                         else if (!(flg & (PROJECT_PATH)))
1384                         {
1385                                 /* Always stop at non-initial wall grids */
1386                                 if ((n > 0) && !cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT)) break;
1387                         }
1388
1389                         /* Sometimes stop at non-initial monsters/players */
1390                         if (flg & (PROJECT_STOP))
1391                         {
1392                                 if ((n > 0) &&
1393                                         (player_bold(p_ptr, y, x) || floor_ptr->grid_array[y][x].m_idx != 0))
1394                                         break;
1395                         }
1396
1397                         if (!in_bounds(floor_ptr, y, x)) break;
1398
1399                         /* Slant */
1400                         if (m)
1401                         {
1402                                 /* Advance (X) part 1 */
1403                                 frac += m;
1404
1405                                 /* Horizontal change */
1406                                 if (frac > half)
1407                                 {
1408                                         /* Advance (X) part 2 */
1409                                         x += sx;
1410
1411                                         /* Advance (X) part 3 */
1412                                         frac -= full;
1413
1414                                         /* Track distance */
1415                                         k++;
1416                                 }
1417                         }
1418
1419                         /* Advance (Y) */
1420                         y += sy;
1421                 }
1422         }
1423
1424         /* Horizontal */
1425         else if (ax > ay)
1426         {
1427                 /* Let m = ((dy/dx) * full) = (dy * dy * 2) */
1428                 m = ay * ay * 2;
1429
1430                 /* Start */
1431                 y = y1;
1432                 x = x1 + sx;
1433
1434                 frac = m;
1435
1436                 /* Vertical change */
1437                 if (frac > half)
1438                 {
1439                         /* Advance (Y) part 2 */
1440                         y += sy;
1441
1442                         /* Advance (Y) part 3 */
1443                         frac -= full;
1444
1445                         /* Track distance */
1446                         k++;
1447                 }
1448
1449                 /* Create the projection path */
1450                 while (1)
1451                 {
1452                         /* Save grid */
1453                         gp[n++] = GRID(y, x);
1454
1455                         /* Hack -- Check maximum range */
1456                         if ((n + (k >> 1)) >= range) break;
1457
1458                         /* Sometimes stop at destination grid */
1459                         if (!(flg & (PROJECT_THRU)))
1460                         {
1461                                 if ((x == x2) && (y == y2)) break;
1462                         }
1463
1464                         if (flg & (PROJECT_DISI))
1465                         {
1466                                 if ((n > 0) && cave_stop_disintegration(floor_ptr, y, x)) break;
1467                         }
1468                         else if (flg & (PROJECT_LOS))
1469                         {
1470                                 if ((n > 0) && !cave_los_bold(floor_ptr, y, x)) break;
1471                         }
1472                         else if (!(flg & (PROJECT_PATH)))
1473                         {
1474                                 /* Always stop at non-initial wall grids */
1475                                 if ((n > 0) && !cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT)) break;
1476                         }
1477
1478                         /* Sometimes stop at non-initial monsters/players */
1479                         if (flg & (PROJECT_STOP))
1480                         {
1481                                 if ((n > 0) &&
1482                                         (player_bold(p_ptr, y, x) || floor_ptr->grid_array[y][x].m_idx != 0))
1483                                         break;
1484                         }
1485
1486                         if (!in_bounds(floor_ptr, y, x)) break;
1487
1488                         /* Slant */
1489                         if (m)
1490                         {
1491                                 /* Advance (Y) part 1 */
1492                                 frac += m;
1493
1494                                 /* Vertical change */
1495                                 if (frac > half)
1496                                 {
1497                                         /* Advance (Y) part 2 */
1498                                         y += sy;
1499
1500                                         /* Advance (Y) part 3 */
1501                                         frac -= full;
1502
1503                                         /* Track distance */
1504                                         k++;
1505                                 }
1506                         }
1507
1508                         /* Advance (X) */
1509                         x += sx;
1510                 }
1511         }
1512
1513         /* Diagonal */
1514         else
1515         {
1516                 /* Start */
1517                 y = y1 + sy;
1518                 x = x1 + sx;
1519
1520                 /* Create the projection path */
1521                 while (1)
1522                 {
1523                         /* Save grid */
1524                         gp[n++] = GRID(y, x);
1525
1526                         /* Hack -- Check maximum range */
1527                         if ((n + (n >> 1)) >= range) break;
1528
1529                         /* Sometimes stop at destination grid */
1530                         if (!(flg & (PROJECT_THRU)))
1531                         {
1532                                 if ((x == x2) && (y == y2)) break;
1533                         }
1534
1535                         if (flg & (PROJECT_DISI))
1536                         {
1537                                 if ((n > 0) && cave_stop_disintegration(floor_ptr, y, x)) break;
1538                         }
1539                         else if (flg & (PROJECT_LOS))
1540                         {
1541                                 if ((n > 0) && !cave_los_bold(floor_ptr, y, x)) break;
1542                         }
1543                         else if (!(flg & (PROJECT_PATH)))
1544                         {
1545                                 /* Always stop at non-initial wall grids */
1546                                 if ((n > 0) && !cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT)) break;
1547                         }
1548
1549                         /* Sometimes stop at non-initial monsters/players */
1550                         if (flg & (PROJECT_STOP))
1551                         {
1552                                 if ((n > 0) &&
1553                                         (player_bold(p_ptr, y, x) || floor_ptr->grid_array[y][x].m_idx != 0))
1554                                         break;
1555                         }
1556
1557                         if (!in_bounds(floor_ptr, y, x)) break;
1558
1559                         /* Advance (Y) */
1560                         y += sy;
1561
1562                         /* Advance (X) */
1563                         x += sx;
1564                 }
1565         }
1566
1567         /* Length */
1568         return (n);
1569 }
1570
1571
1572 /*!
1573  * @brief 指定のマスを床地形に変える / Set a square to be floor.  (Includes range checking.)
1574  * @param x 地形を変えたいマスのX座標
1575  * @param y 地形を変えたいマスのY座標
1576  * @return なし
1577  */
1578 void set_floor(floor_type *floor_ptr, POSITION x, POSITION y)
1579 {
1580         if (!in_bounds(floor_ptr, y, x))
1581         {
1582                 /* Out of bounds */
1583                 return;
1584         }
1585
1586         if (floor_ptr->grid_array[y][x].info & CAVE_ROOM)
1587         {
1588                 /* A room border don't touch. */
1589                 return;
1590         }
1591
1592         /* Set to be floor if is a wall (don't touch lakes). */
1593         if (is_extra_bold(floor_ptr, y, x))
1594                 place_floor_bold(floor_ptr, y, x);
1595 }
1596
1597
1598 /*!
1599  * @brief フロアの指定位置に生成階に応じたベースアイテムの生成を行う。
1600  * Attempt to place an object (normal or good/great) at the given location.
1601  * @param owner_ptr プレーヤーへの参照ポインタ
1602  * @param y 配置したいフロアのY座標
1603  * @param x 配置したいフロアのX座標
1604  * @param mode オプションフラグ
1605  * @return 生成に成功したらTRUEを返す。
1606  * @details
1607  * This routine plays nasty games to generate the "special artifacts".\n
1608  * This routine uses "object_level" for the "generation level".\n
1609  * This routine requires a clean floor grid destination.\n
1610  */
1611 void place_object(player_type *owner_ptr, POSITION y, POSITION x, BIT_FLAGS mode)
1612 {
1613         floor_type *floor_ptr = owner_ptr->current_floor_ptr;
1614
1615         /* Acquire grid */
1616         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
1617
1618         object_type forge;
1619         object_type *q_ptr;
1620
1621         /* Paranoia -- check bounds */
1622         if (!in_bounds(floor_ptr, y, x)) return;
1623
1624         /* Require floor space */
1625         if (!cave_drop_bold(floor_ptr, y, x)) return;
1626
1627         /* Avoid stacking on other objects */
1628         if (g_ptr->o_idx) return;
1629
1630         q_ptr = &forge;
1631         object_wipe(q_ptr);
1632
1633         /* Make an object (if possible) */
1634         if (!make_object(owner_ptr, q_ptr, mode)) return;
1635
1636         OBJECT_IDX o_idx = o_pop(floor_ptr);
1637
1638         /* Success */
1639         if (o_idx)
1640         {
1641                 object_type *o_ptr;
1642                 o_ptr = &floor_ptr->o_list[o_idx];
1643
1644                 /* Structure Copy */
1645                 object_copy(o_ptr, q_ptr);
1646
1647                 o_ptr->iy = y;
1648                 o_ptr->ix = x;
1649
1650                 /* Build a stack */
1651                 o_ptr->next_o_idx = g_ptr->o_idx;
1652
1653                 g_ptr->o_idx = o_idx;
1654                 note_spot(y, x);
1655                 lite_spot(y, x);
1656         }
1657         else
1658         {
1659                 /* Hack -- Preserve artifacts */
1660                 if (object_is_fixed_artifact(q_ptr))
1661                 {
1662                         a_info[q_ptr->name1].cur_num = 0;
1663                 }
1664         }
1665 }
1666
1667
1668
1669 /*!
1670  * @brief フロアの指定位置に生成階に応じた財宝オブジェクトの生成を行う。
1671  * Places a treasure (Gold or Gems) at given location
1672  * @param floor_ptr 現在フロアへの参照ポインタ
1673  * @param y 配置したいフロアのY座標
1674  * @param x 配置したいフロアのX座標
1675  * @return 生成に成功したらTRUEを返す。
1676  * @details
1677  * The location must be a legal, clean, floor grid.
1678  */
1679 void place_gold(floor_type *floor_ptr, POSITION y, POSITION x)
1680 {
1681         OBJECT_IDX o_idx;
1682
1683         /* Acquire grid */
1684         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
1685
1686         object_type forge;
1687         object_type *q_ptr;
1688
1689
1690         /* Paranoia -- check bounds */
1691         if (!in_bounds(floor_ptr, y, x)) return;
1692
1693         /* Require floor space */
1694         if (!cave_drop_bold(floor_ptr, y, x)) return;
1695
1696         /* Avoid stacking on other objects */
1697         if (g_ptr->o_idx) return;
1698
1699         q_ptr = &forge;
1700         object_wipe(q_ptr);
1701
1702         /* Make some gold */
1703         if (!make_gold(floor_ptr, q_ptr)) return;
1704
1705         o_idx = o_pop(floor_ptr);
1706
1707         /* Success */
1708         if (o_idx)
1709         {
1710                 object_type *o_ptr;
1711                 o_ptr = &floor_ptr->o_list[o_idx];
1712                 object_copy(o_ptr, q_ptr);
1713
1714                 /* Save location */
1715                 o_ptr->iy = y;
1716                 o_ptr->ix = x;
1717
1718                 /* Build a stack */
1719                 o_ptr->next_o_idx = g_ptr->o_idx;
1720
1721                 g_ptr->o_idx = o_idx;
1722                 note_spot(y, x);
1723                 lite_spot(y, x);
1724         }
1725 }
1726
1727
1728 /*!
1729  * @brief 指定位置に存在するモンスターを削除する / Delete the monster, if any, at a given location
1730  * @param x 削除位置x座標
1731  * @param y 削除位置y座標
1732  * @return なし
1733  */
1734 void delete_monster(floor_type *floor_ptr, POSITION y, POSITION x)
1735 {
1736         grid_type *g_ptr;
1737         if (!in_bounds(floor_ptr, y, x)) return;
1738
1739         /* Check the grid */
1740         g_ptr = &floor_ptr->grid_array[y][x];
1741
1742         /* Delete the monster (if any) */
1743         if (g_ptr->m_idx) delete_monster_idx(g_ptr->m_idx);
1744 }
1745
1746
1747
1748 /*!
1749  * @brief グローバルオブジェクト配列に対し指定範囲のオブジェクトを整理してIDの若い順に寄せる /
1750  * Move an object from index i1 to index i2 in the object list
1751  * @param i1 整理したい配列の始点
1752  * @param i2 整理したい配列の終点
1753  * @return なし
1754  */
1755 static void compact_objects_aux(floor_type *floor_ptr, OBJECT_IDX i1, OBJECT_IDX i2)
1756 {
1757         OBJECT_IDX i;
1758         grid_type *g_ptr;
1759         object_type *o_ptr;
1760
1761         /* Do nothing */
1762         if (i1 == i2) return;
1763
1764         /* Repair objects */
1765         for (i = 1; i < floor_ptr->o_max; i++)
1766         {
1767                 o_ptr = &floor_ptr->o_list[i];
1768
1769                 /* Skip "dead" objects */
1770                 if (!o_ptr->k_idx) continue;
1771
1772                 /* Repair "next" pointers */
1773                 if (o_ptr->next_o_idx == i1)
1774                 {
1775                         /* Repair */
1776                         o_ptr->next_o_idx = i2;
1777                 }
1778         }
1779         o_ptr = &floor_ptr->o_list[i1];
1780
1781         if (OBJECT_IS_HELD_MONSTER(o_ptr))
1782         {
1783                 monster_type *m_ptr;
1784                 m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
1785
1786                 /* Repair monster */
1787                 if (m_ptr->hold_o_idx == i1)
1788                 {
1789                         /* Repair */
1790                         m_ptr->hold_o_idx = i2;
1791                 }
1792         }
1793
1794         /* Dungeon */
1795         else
1796         {
1797                 POSITION y, x;
1798
1799                 /* Acquire location */
1800                 y = o_ptr->iy;
1801                 x = o_ptr->ix;
1802
1803                 /* Acquire grid */
1804                 g_ptr = &floor_ptr->grid_array[y][x];
1805
1806                 /* Repair grid */
1807                 if (g_ptr->o_idx == i1)
1808                 {
1809                         /* Repair */
1810                         g_ptr->o_idx = i2;
1811                 }
1812         }
1813
1814         /* Structure copy */
1815         floor_ptr->o_list[i2] = floor_ptr->o_list[i1];
1816
1817         /* Wipe the hole */
1818         object_wipe(o_ptr);
1819 }
1820
1821 /*!
1822  * @brief グローバルオブジェクト配列から優先度の低いものを削除し、データを圧縮する。 /
1823  * Compact and Reorder the object list.
1824  * @param size 最低でも減らしたいオブジェクト数の水準
1825  * @return なし
1826  * @details
1827  * (危険なので使用には注意すること)
1828  * This function can be very dangerous, use with caution!\n
1829  *\n
1830  * When actually "compacting" objects, we base the saving throw on a\n
1831  * combination of object level, distance from player, and current\n
1832  * "desperation".\n
1833  *\n
1834  * After "compacting" (if needed), we "reorder" the objects into a more\n
1835  * compact order, and we reset the allocation info, and the "live" array.\n
1836  */
1837 void compact_objects(floor_type *floor_ptr, int size)
1838 {
1839         OBJECT_IDX i;
1840         POSITION y, x;
1841         int num, cnt;
1842         int cur_lev, cur_dis, chance;
1843         object_type *o_ptr;
1844
1845         /* Compact */
1846         if (size)
1847         {
1848                 msg_print(_("アイテム情報を圧縮しています...", "Compacting objects..."));
1849                 p_ptr->redraw |= (PR_MAP);
1850                 p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
1851         }
1852
1853
1854         /* Compact at least 'size' objects */
1855         for (num = 0, cnt = 1; num < size; cnt++)
1856         {
1857                 /* Get more vicious each iteration */
1858                 cur_lev = 5 * cnt;
1859
1860                 /* Get closer each iteration */
1861                 cur_dis = 5 * (20 - cnt);
1862
1863                 /* Examine the objects */
1864                 for (i = 1; i < floor_ptr->o_max; i++)
1865                 {
1866                         o_ptr = &floor_ptr->o_list[i];
1867
1868                         if (!OBJECT_IS_VALID(o_ptr)) continue;
1869
1870                         /* Hack -- High level objects start out "immune" */
1871                         if (k_info[o_ptr->k_idx].level > cur_lev) continue;
1872
1873                         if (OBJECT_IS_HELD_MONSTER(o_ptr))
1874                         {
1875                                 monster_type *m_ptr;
1876                                 m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
1877
1878                                 y = m_ptr->fy;
1879                                 x = m_ptr->fx;
1880
1881                                 /* Monsters protect their objects */
1882                                 if (randint0(100) < 90) continue;
1883                         }
1884
1885                         /* Dungeon */
1886                         else
1887                         {
1888                                 y = o_ptr->iy;
1889                                 x = o_ptr->ix;
1890                         }
1891
1892                         /* Nearby objects start out "immune" */
1893                         if ((cur_dis > 0) && (distance(p_ptr->y, p_ptr->x, y, x) < cur_dis)) continue;
1894
1895                         /* Saving throw */
1896                         chance = 90;
1897
1898                         /* Hack -- only compact artifacts in emergencies */
1899                         if ((object_is_fixed_artifact(o_ptr) || o_ptr->art_name) &&
1900                                 (cnt < 1000)) chance = 100;
1901
1902                         /* Apply the saving throw */
1903                         if (randint0(100) < chance) continue;
1904
1905                         delete_object_idx(floor_ptr, i);
1906
1907                         /* Count it */
1908                         num++;
1909                 }
1910         }
1911
1912
1913         /* Excise dead objects (backwards!) */
1914         for (i = floor_ptr->o_max - 1; i >= 1; i--)
1915         {
1916                 o_ptr = &floor_ptr->o_list[i];
1917
1918                 /* Skip real objects */
1919                 if (o_ptr->k_idx) continue;
1920
1921                 /* Move last object into open hole */
1922                 compact_objects_aux(floor_ptr, floor_ptr->o_max - 1, i);
1923
1924                 /* Compress "floor_ptr->o_max" */
1925                 floor_ptr->o_max--;
1926         }
1927 }
1928
1929 /*!
1930  * @brief 特殊な部屋向けに各種アイテムを配置する(メインルーチン) / Place some traps with a given displacement of given location
1931  * @param y トラップを配置したいマスの中心Y座標
1932  * @param x トラップを配置したいマスの中心X座標
1933  * @param yd Y方向の配置分散マス数
1934  * @param xd X方向の配置分散マス数
1935  * @param num 配置したいトラップの数
1936  * @return なし
1937  * @details
1938  * Only really called by some of the "vault" routines.
1939  */
1940 void vault_traps(floor_type *floor_ptr, POSITION y, POSITION x, POSITION yd, POSITION xd, int num)
1941 {
1942         int i;
1943
1944         for (i = 0; i < num; i++)
1945         {
1946                 vault_trap_aux(floor_ptr, y, x, yd, xd);
1947         }
1948 }
1949
1950
1951 /*
1952  * Standard "find me a location" function
1953  *
1954  * Obtains a legal location within the given distance of the initial
1955  * location, and with "los()" from the source to destination location.
1956  *
1957  * This function is often called from inside a loop which searches for
1958  * locations while increasing the "d" distance.
1959  *
1960  * Currently the "m" parameter is unused.
1961  */
1962 void scatter(floor_type *floor_ptr, POSITION *yp, POSITION *xp, POSITION y, POSITION x, POSITION d, BIT_FLAGS mode)
1963 {
1964         POSITION nx, ny;
1965
1966         /* Pick a location */
1967         while (TRUE)
1968         {
1969                 /* Pick a new location */
1970                 ny = rand_spread(y, d);
1971                 nx = rand_spread(x, d);
1972
1973                 /* Ignore annoying locations */
1974                 if (!in_bounds(floor_ptr, ny, nx)) continue;
1975
1976                 /* Ignore "excessively distant" locations */
1977                 if ((d > 1) && (distance(y, x, ny, nx) > d)) continue;
1978
1979                 if (mode & PROJECT_LOS)
1980                 {
1981                         if (los(floor_ptr, y, x, ny, nx)) break;
1982                 }
1983                 else
1984                 {
1985                         if (projectable(floor_ptr, y, x, ny, nx)) break;
1986                 }
1987
1988         }
1989
1990         /* Save the location */
1991         (*yp) = ny;
1992         (*xp) = nx;
1993 }