OSDN Git Service

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