OSDN Git Service

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