OSDN Git Service

[Refactor] #38997 cave_valid_bold() に player_type * 引数を追加. / Add player_type * argume...
[hengband/hengband.git] / src / floor.c
1 #include "angband.h"
2 #include "floor.h"
3 #include "floor-save.h"
4 #include "grid.h"
5 #include "dungeon.h"
6 #include "rooms.h"
7 #include "quest.h"
8 #include "object-hook.h"
9
10 /*
11  * The array of floor [MAX_WID][MAX_HGT].
12  * Not completely allocated, that would be inefficient
13  * Not completely hardcoded, that would overflow memory
14  */
15 floor_type floor_info;
16
17 /*
18  * The array of saved floors
19  */
20 saved_floor_type saved_floors[MAX_SAVED_FLOORS];
21
22 /*!
23 * @brief 鍵のかかったドアを配置する
24 * @param y 配置したいフロアのY座標
25 * @param x 配置したいフロアのX座標
26 * @return なし
27 */
28 void place_locked_door(floor_type *floor_ptr, POSITION y, POSITION x)
29 {
30         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
31         {
32                 place_floor_bold(floor_ptr, y, x);
33         }
34         else
35         {
36                 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));
37                 floor_ptr->grid_array[y][x].info &= ~(CAVE_FLOOR);
38                 delete_monster(y, x);
39         }
40 }
41
42
43 /*!
44 * @brief 隠しドアを配置する
45 * @param y 配置したいフロアのY座標
46 * @param x 配置したいフロアのX座標
47 * @param type DOOR_DEFAULT / DOOR_DOOR / DOOR_GLASS_DOOR / DOOR_CURTAIN のいずれか
48 * @return なし
49 */
50 void place_secret_door(floor_type *floor_ptr, POSITION y, POSITION x, int type)
51 {
52         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
53         {
54                 place_floor_bold(floor_ptr, y, x);
55         }
56         else
57         {
58                 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
59
60                 if (type == DOOR_DEFAULT)
61                 {
62                         type = ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
63                                 one_in_((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
64                                 ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
65                 }
66
67                 /* Create secret door */
68                 place_closed_door(y, x, type);
69
70                 if (type != DOOR_CURTAIN)
71                 {
72                         /* Hide by inner wall because this is used in rooms only */
73                         g_ptr->mimic = feat_wall_inner;
74
75                         /* Floor type terrain cannot hide a door */
76                         if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
77                         {
78                                 if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
79                                 {
80                                         g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
81                                 }
82                                 g_ptr->mimic = 0;
83                         }
84                 }
85
86                 g_ptr->info &= ~(CAVE_FLOOR);
87                 delete_monster(y, x);
88         }
89 }
90
91 static int scent_when = 0;
92
93 /*
94  * Characters leave scent trails for perceptive monsters to track.
95  *
96  * Smell is rather more limited than sound.  Many creatures cannot use
97  * it at all, it doesn't extend very far outwards from the character's
98  * current position, and monsters can use it to home in the character,
99  * but not to run away from him.
100  *
101  * Smell is valued according to age.  When a character takes his turn,
102  * scent is aged by one, and new scent of the current age is laid down.
103  * Speedy characters leave more scent, true, but it also ages faster,
104  * which makes it harder to hunt them down.
105  *
106  * Whenever the age count loops, most of the scent trail is erased and
107  * the age of the remainder is recalculated.
108  */
109 void update_smell(floor_type *floor_ptr, player_type *subject_ptr)
110 {
111         POSITION i, j;
112         POSITION y, x;
113
114         /* Create a table that controls the spread of scent */
115         const int scent_adjust[5][5] =
116         {
117                 { -1, 0, 0, 0,-1 },
118                 {  0, 1, 1, 1, 0 },
119                 {  0, 1, 2, 1, 0 },
120                 {  0, 1, 1, 1, 0 },
121                 { -1, 0, 0, 0,-1 },
122         };
123
124         /* Loop the age and adjust scent values when necessary */
125         if (++scent_when == 254)
126         {
127                 /* Scan the entire dungeon */
128                 for (y = 0; y < floor_ptr->height; y++)
129                 {
130                         for (x = 0; x < floor_ptr->width; x++)
131                         {
132                                 int w = floor_ptr->grid_array[y][x].when;
133                                 floor_ptr->grid_array[y][x].when = (w > 128) ? (w - 128) : 0;
134                         }
135                 }
136
137                 /* Restart */
138                 scent_when = 126;
139         }
140
141
142         /* Lay down new scent */
143         for (i = 0; i < 5; i++)
144         {
145                 for (j = 0; j < 5; j++)
146                 {
147                         grid_type *g_ptr;
148
149                         /* Translate table to map grids */
150                         y = i + subject_ptr->y - 2;
151                         x = j + subject_ptr->x - 2;
152
153                         /* Check Bounds */
154                         if (!in_bounds(floor_ptr, y, x)) continue;
155
156                         g_ptr = &floor_ptr->grid_array[y][x];
157
158                         /* Walls, water, and lava cannot hold scent. */
159                         if (!cave_have_flag_grid(g_ptr, FF_MOVE) && !is_closed_door(g_ptr->feat)) continue;
160
161                         /* Grid must not be blocked by walls from the character */
162                         if (!player_has_los_bold(subject_ptr, y, x)) continue;
163
164                         /* Note grids that are too far away */
165                         if (scent_adjust[i][j] == -1) continue;
166
167                         /* Mark the grid with new scent */
168                         g_ptr->when = scent_when + scent_adjust[i][j];
169                 }
170         }
171 }
172
173
174 /*
175  * Hack -- forget the "flow" information
176  */
177 void forget_flow(floor_type *floor_ptr)
178 {
179         POSITION x, y;
180
181         /* Check the entire dungeon */
182         for (y = 0; y < floor_ptr->height; y++)
183         {
184                 for (x = 0; x < floor_ptr->width; x++)
185                 {
186                         /* Forget the old data */
187                         floor_ptr->grid_array[y][x].dist = 0;
188                         floor_ptr->grid_array[y][x].cost = 0;
189                         floor_ptr->grid_array[y][x].when = 0;
190                 }
191         }
192 }
193
194 /*
195  * Routine used by the random vault creators to add a door to a location
196  * Note that range checking has to be done in the calling routine.
197  *
198  * The doors must be INSIDE the allocated region.
199  */
200 void add_door(floor_type* floor_ptr, POSITION x, POSITION y)
201 {
202         /* Need to have a wall in the center square */
203         if (!is_outer_bold(floor_ptr, y, x)) return;
204
205         /* look at:
206         *  x#x
207         *  .#.
208         *  x#x
209         *
210         *  where x=don't care
211         *  .=floor, #=wall
212         */
213
214         if (is_floor_bold(floor_ptr, y - 1, x) && is_floor_bold(floor_ptr, y + 1, x) &&
215                 (is_outer_bold(floor_ptr, y, x - 1) && is_outer_bold(floor_ptr, y, x + 1)))
216         {
217                 /* secret door */
218                 place_secret_door(floor_ptr, y, x, DOOR_DEFAULT);
219
220                 /* set boundarys so don't get wide doors */
221                 place_solid_bold(y, x - 1);
222                 place_solid_bold(y, x + 1);
223         }
224
225
226         /* look at:
227         *  x#x
228         *  .#.
229         *  x#x
230         *
231         *  where x = don't care
232         *  .=floor, #=wall
233         */
234         if (is_outer_bold(floor_ptr, y - 1, x) && is_outer_bold(floor_ptr, y + 1, x) &&
235                 is_floor_bold(floor_ptr, y, x - 1) && is_floor_bold(floor_ptr, y, x + 1))
236         {
237                 /* secret door */
238                 place_secret_door(floor_ptr, y, x, DOOR_DEFAULT);
239
240                 /* set boundarys so don't get wide doors */
241                 place_solid_bold(y - 1, x);
242                 place_solid_bold(y + 1, x);
243         }
244 }
245
246 /*!
247  * @brief 所定の位置に上り階段か下り階段を配置する / Place an up/down staircase at given location
248  * @param y 配置を試みたいマスのY座標
249  * @param x 配置を試みたいマスのX座標
250  * @return なし
251  */
252 void place_random_stairs(floor_type *floor_ptr, POSITION y, POSITION x)
253 {
254         bool up_stairs = TRUE;
255         bool down_stairs = TRUE;
256         grid_type *g_ptr;
257         g_ptr = &floor_ptr->grid_array[y][x];
258         if (!is_floor_grid(g_ptr) || g_ptr->o_idx) return;
259
260         if (!floor_ptr->dun_level) up_stairs = FALSE;
261         if (ironman_downward) up_stairs = FALSE;
262         if (floor_ptr->dun_level >= d_info[p_ptr->dungeon_idx].maxdepth) down_stairs = FALSE;
263         if (quest_number(floor_ptr->dun_level) && (floor_ptr->dun_level > 1)) down_stairs = FALSE;
264
265         /* We can't place both */
266         if (down_stairs && up_stairs)
267         {
268                 /* Choose a staircase randomly */
269                 if (randint0(100) < 50) up_stairs = FALSE;
270                 else down_stairs = FALSE;
271         }
272
273         /* Place the stairs */
274         if (up_stairs) set_cave_feat(floor_ptr, y, x, feat_up_stair);
275         else if (down_stairs) set_cave_feat(floor_ptr, y, x, feat_down_stair);
276 }
277
278 /*!
279  * @brief LOS(Line Of Sight / 視線が通っているか)の判定を行う。
280  * @param y1 始点のy座標
281  * @param x1 始点のx座標
282  * @param y2 終点のy座標
283  * @param x2 終点のx座標
284  * @return LOSが通っているならTRUEを返す。
285  * @details
286  * A simple, fast, integer-based line-of-sight algorithm.  By Joseph Hall,\n
287  * 4116 Brewster Drive, Raleigh NC 27606.  Email to jnh@ecemwl.ncsu.edu.\n
288  *\n
289  * Returns TRUE if a line of sight can be traced from (x1,y1) to (x2,y2).\n
290  *\n
291  * The LOS begins at the center of the tile (x1,y1) and ends at the center of\n
292  * the tile (x2,y2).  If los() is to return TRUE, all of the tiles this line\n
293  * passes through must be floor tiles, except for (x1,y1) and (x2,y2).\n
294  *\n
295  * We assume that the "mathematical corner" of a non-floor tile does not\n
296  * block line of sight.\n
297  *\n
298  * Because this function uses (short) ints for all calculations, overflow may\n
299  * occur if dx and dy exceed 90.\n
300  *\n
301  * Once all the degenerate cases are eliminated, the values "qx", "qy", and\n
302  * "m" are multiplied by a scale factor "f1 = abs(dx * dy * 2)", so that\n
303  * we can use integer arithmetic.\n
304  *\n
305  * We travel from start to finish along the longer axis, starting at the border\n
306  * between the first and second tiles, where the y offset = .5 * slope, taking\n
307  * into account the scale factor.  See below.\n
308  *\n
309  * Also note that this function and the "move towards target" code do NOT\n
310  * share the same properties.  Thus, you can see someone, target them, and\n
311  * then fire a bolt at them, but the bolt may hit a wall, not them.  However\n,
312  * by clever choice of target locations, you can sometimes throw a "curve".\n
313  *\n
314  * Note that "line of sight" is not "reflexive" in all cases.\n
315  *\n
316  * Use the "projectable()" routine to test "spell/missile line of sight".\n
317  *\n
318  * Use the "update_view()" function to determine player line-of-sight.\n
319  */
320 bool los(floor_type *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
321 {
322         /* Delta */
323         POSITION dx, dy;
324
325         /* Absolute */
326         POSITION ax, ay;
327
328         /* Signs */
329         POSITION sx, sy;
330
331         /* Fractions */
332         POSITION qx, qy;
333
334         /* Scanners */
335         POSITION tx, ty;
336
337         /* Scale factors */
338         POSITION f1, f2;
339
340         /* Slope, or 1/Slope, of LOS */
341         POSITION m;
342
343
344         /* Extract the offset */
345         dy = y2 - y1;
346         dx = x2 - x1;
347
348         /* Extract the absolute offset */
349         ay = ABS(dy);
350         ax = ABS(dx);
351
352
353         /* Handle adjacent (or identical) grids */
354         if ((ax < 2) && (ay < 2)) return TRUE;
355
356
357         /* Paranoia -- require "safe" origin */
358         /* if (!in_bounds(floor_ptr, y1, x1)) return FALSE; */
359         /* if (!in_bounds(floor_ptr, y2, x2)) return FALSE; */
360
361
362         /* Directly South/North */
363         if (!dx)
364         {
365                 /* South -- check for walls */
366                 if (dy > 0)
367                 {
368                         for (ty = y1 + 1; ty < y2; ty++)
369                         {
370                                 if (!cave_los_bold(floor_ptr, ty, x1)) return FALSE;
371                         }
372                 }
373
374                 /* North -- check for walls */
375                 else
376                 {
377                         for (ty = y1 - 1; ty > y2; ty--)
378                         {
379                                 if (!cave_los_bold(floor_ptr, ty, x1)) return FALSE;
380                         }
381                 }
382
383                 /* Assume los */
384                 return TRUE;
385         }
386
387         /* Directly East/West */
388         if (!dy)
389         {
390                 /* East -- check for walls */
391                 if (dx > 0)
392                 {
393                         for (tx = x1 + 1; tx < x2; tx++)
394                         {
395                                 if (!cave_los_bold(floor_ptr, y1, tx)) return FALSE;
396                         }
397                 }
398
399                 /* West -- check for walls */
400                 else
401                 {
402                         for (tx = x1 - 1; tx > x2; tx--)
403                         {
404                                 if (!cave_los_bold(floor_ptr, y1, tx)) return FALSE;
405                         }
406                 }
407
408                 /* Assume los */
409                 return TRUE;
410         }
411
412
413         /* Extract some signs */
414         sx = (dx < 0) ? -1 : 1;
415         sy = (dy < 0) ? -1 : 1;
416
417
418         /* Vertical "knights" */
419         if (ax == 1)
420         {
421                 if (ay == 2)
422                 {
423                         if (cave_los_bold(floor_ptr, y1 + sy, x1)) return TRUE;
424                 }
425         }
426
427         /* Horizontal "knights" */
428         else if (ay == 1)
429         {
430                 if (ax == 2)
431                 {
432                         if (cave_los_bold(floor_ptr, y1, x1 + sx)) return TRUE;
433                 }
434         }
435
436
437         /* Calculate scale factor div 2 */
438         f2 = (ax * ay);
439
440         /* Calculate scale factor */
441         f1 = f2 << 1;
442
443
444         /* Travel horizontally */
445         if (ax >= ay)
446         {
447                 /* Let m = dy / dx * 2 * (dy * dx) = 2 * dy * dy */
448                 qy = ay * ay;
449                 m = qy << 1;
450
451                 tx = x1 + sx;
452
453                 /* Consider the special case where slope == 1. */
454                 if (qy == f2)
455                 {
456                         ty = y1 + sy;
457                         qy -= f1;
458                 }
459                 else
460                 {
461                         ty = y1;
462                 }
463
464                 /* Note (below) the case (qy == f2), where */
465                 /* the LOS exactly meets the corner of a tile. */
466                 while (x2 - tx)
467                 {
468                         if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
469
470                         qy += m;
471
472                         if (qy < f2)
473                         {
474                                 tx += sx;
475                         }
476                         else if (qy > f2)
477                         {
478                                 ty += sy;
479                                 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
480                                 qy -= f1;
481                                 tx += sx;
482                         }
483                         else
484                         {
485                                 ty += sy;
486                                 qy -= f1;
487                                 tx += sx;
488                         }
489                 }
490         }
491
492         /* Travel vertically */
493         else
494         {
495                 /* Let m = dx / dy * 2 * (dx * dy) = 2 * dx * dx */
496                 qx = ax * ax;
497                 m = qx << 1;
498
499                 ty = y1 + sy;
500
501                 if (qx == f2)
502                 {
503                         tx = x1 + sx;
504                         qx -= f1;
505                 }
506                 else
507                 {
508                         tx = x1;
509                 }
510
511                 /* Note (below) the case (qx == f2), where */
512                 /* the LOS exactly meets the corner of a tile. */
513                 while (y2 - ty)
514                 {
515                         if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
516
517                         qx += m;
518
519                         if (qx < f2)
520                         {
521                                 ty += sy;
522                         }
523                         else if (qx > f2)
524                         {
525                                 tx += sx;
526                                 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
527                                 qx -= f1;
528                                 ty += sy;
529                         }
530                         else
531                         {
532                                 tx += sx;
533                                 qx -= f1;
534                                 ty += sy;
535                         }
536                 }
537         }
538
539         /* Assume los */
540         return TRUE;
541 }
542
543
544 /*
545  * Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive
546  * at the final destination, assuming no monster gets in the way.
547  *
548  * This is slightly (but significantly) different from "los(y1,x1,y2,x2)".
549  */
550 bool projectable(floor_type *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
551 {
552         POSITION y, x;
553
554         int grid_n = 0;
555         u16b grid_g[512];
556
557         /* Check the projection path */
558         grid_n = project_path(grid_g, (project_length ? project_length : MAX_RANGE), y1, x1, y2, x2, 0);
559
560         /* Identical grid */
561         if (!grid_n) return TRUE;
562
563         /* Final grid */
564         y = GRID_Y(grid_g[grid_n - 1]);
565         x = GRID_X(grid_g[grid_n - 1]);
566
567         /* May not end in an unrequested grid */
568         if ((y != y2) || (x != x2)) return (FALSE);
569
570         /* Assume okay */
571         return (TRUE);
572 }
573
574
575 /*!
576  * @brief 特殊な部屋地形向けにモンスターを配置する / Hack -- Place some sleeping monsters near the given location
577  * @param y1 モンスターを配置したいマスの中心Y座標
578  * @param x1 モンスターを配置したいマスの中心X座標
579  * @param num 配置したいモンスターの数
580  * @return なし
581  * @details
582  * Only really called by some of the "vault" routines.
583  */
584 void vault_monsters(floor_type *floor_ptr, POSITION y1, POSITION x1, int num)
585 {
586         int k, i;
587         POSITION y, x;
588         grid_type *g_ptr;
589
590         /* Try to summon "num" monsters "near" the given location */
591         for (k = 0; k < num; k++)
592         {
593                 /* Try nine locations */
594                 for (i = 0; i < 9; i++)
595                 {
596                         int d = 1;
597
598                         /* Pick a nearby location */
599                         scatter(&y, &x, y1, x1, d, 0);
600
601                         /* Require "empty" floor grids */
602                         g_ptr = &floor_ptr->grid_array[y][x];
603                         if (!cave_empty_grid(g_ptr)) continue;
604
605                         /* Place the monster (allow groups) */
606                         floor_ptr->monster_level = floor_ptr->base_level + 2;
607                         (void)place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
608                         floor_ptr->monster_level = floor_ptr->base_level;
609                 }
610         }
611 }
612
613
614 /*!
615  * @brief 指定された座標が地震や階段生成の対象となるマスかを返す。 / Determine if a given location may be "destroyed"
616  * @param y y座標
617  * @param x x座標
618  * @return 各種の変更が可能ならTRUEを返す。
619  * @details
620  * 条件は永久地形でなく、なおかつ該当のマスにアーティファクトが存在しないか、である。英語の旧コメントに反して*破壊*の抑止判定には現在使われていない。
621  */
622 bool cave_valid_bold(floor_type *floor_ptr, POSITION y, POSITION x)
623 {
624         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
625         OBJECT_IDX this_o_idx, next_o_idx = 0;
626
627         /* Forbid perma-grids */
628         if (cave_perma_grid(g_ptr)) return (FALSE);
629
630         /* Check objects */
631         for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
632         {
633                 object_type *o_ptr;
634                 o_ptr = &floor_ptr->o_list[this_o_idx];
635                 next_o_idx = o_ptr->next_o_idx;
636
637                 /* Forbid artifact grids */
638                 if (object_is_artifact(o_ptr)) return (FALSE);
639         }
640
641         /* Accept */
642         return (TRUE);
643 }
644
645