1 /**
2 * \file cave-square.c
3 * \brief functions for dealing with individual squares
4 *
5 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
6 *
7 * This work is free software; you can redistribute it and/or modify it
8 * under the terms of either:
9 *
10 * a) the GNU General Public License as published by the Free Software
11 * Foundation, version 2, or
12 *
13 * b) the "Angband licence":
14 * This software may be copied and distributed for educational, research,
15 * and not for profit purposes provided that this copyright and statement
16 * are included in all such copies. Other copyrights may also apply.
17 */
18
19 #include "angband.h"
20 #include "cave.h"
21 #include "game-world.h"
22 #include "init.h"
23 #include "monster.h"
24 #include "obj-knowledge.h"
25 #include "obj-pile.h"
26 #include "obj-util.h"
27 #include "object.h"
28 #include "player-timed.h"
29 #include "trap.h"
30
31
32 /**
33 * FEATURE PREDICATES
34 *
35 * These functions test a terrain feature index for the obviously described
36 * type. They are used in the square feature predicates below, and
37 * occasionally on their own
38 */
39
40 /**
41 * True if the square is a magma wall.
42 */
feat_is_magma(int feat)43 bool feat_is_magma(int feat)
44 {
45 return tf_has(f_info[feat].flags, TF_MAGMA);
46 }
47
48 /**
49 * True if the square is a quartz wall.
50 */
feat_is_quartz(int feat)51 bool feat_is_quartz(int feat)
52 {
53 return tf_has(f_info[feat].flags, TF_QUARTZ);
54 }
55
56 /**
57 * True if the square is a granite wall.
58 */
feat_is_granite(int feat)59 bool feat_is_granite(int feat)
60 {
61 return tf_has(f_info[feat].flags, TF_GRANITE);
62 }
63
64 /**
65 * True if the square is a mineral wall with treasure (magma/quartz).
66 */
feat_is_treasure(int feat)67 bool feat_is_treasure(int feat)
68 {
69 return (tf_has(f_info[feat].flags, TF_GOLD));
70 }
71
72 /**
73 * True if the feature is a solid wall (not rubble).
74 */
feat_is_wall(int feat)75 bool feat_is_wall(int feat)
76 {
77 return tf_has(f_info[feat].flags, TF_WALL);
78 }
79
80 /**
81 * True if the feature is a floor.
82 */
feat_is_floor(int feat)83 bool feat_is_floor(int feat)
84 {
85 return tf_has(f_info[feat].flags, TF_FLOOR);
86 }
87
88 /**
89 * True if the feature can hold a trap.
90 */
feat_is_trap_holding(int feat)91 bool feat_is_trap_holding(int feat)
92 {
93 return tf_has(f_info[feat].flags, TF_TRAP);
94 }
95
96 /**
97 * True if the feature can hold an object.
98 */
feat_is_object_holding(int feat)99 bool feat_is_object_holding(int feat)
100 {
101 return tf_has(f_info[feat].flags, TF_OBJECT);
102 }
103
104 /**
105 * True if a monster can walk through the feature.
106 */
feat_is_monster_walkable(int feat)107 bool feat_is_monster_walkable(int feat)
108 {
109 return tf_has(f_info[feat].flags, TF_PASSABLE);
110 }
111
112 /**
113 * True if the feature is a shop entrance.
114 */
feat_is_shop(int feat)115 bool feat_is_shop(int feat)
116 {
117 return tf_has(f_info[feat].flags, TF_SHOP);
118 }
119
120 /**
121 * True if the feature is passable by the player.
122 */
feat_is_passable(int feat)123 bool feat_is_passable(int feat)
124 {
125 return tf_has(f_info[feat].flags, TF_PASSABLE);
126 }
127
128 /**
129 * True if any projectable can pass through the feature.
130 */
feat_is_projectable(int feat)131 bool feat_is_projectable(int feat)
132 {
133 return tf_has(f_info[feat].flags, TF_PROJECT);
134 }
135
136 /**
137 * True if the feature can be lit by light sources.
138 */
feat_is_torch(int feat)139 bool feat_is_torch(int feat)
140 {
141 return tf_has(f_info[feat].flags, TF_TORCH);
142 }
143
144 /**
145 * True if the feature is internally lit.
146 */
feat_is_bright(int feat)147 bool feat_is_bright(int feat)
148 {
149 return tf_has(f_info[feat].flags, TF_BRIGHT);
150 }
151
152 /**
153 * True if the feature is internally lit.
154 */
feat_is_fiery(int feat)155 bool feat_is_fiery(int feat)
156 {
157 return tf_has(f_info[feat].flags, TF_FIERY);
158 }
159
160 /**
161 * True if the feature doesn't carry monster flow information.
162 */
feat_is_no_flow(int feat)163 bool feat_is_no_flow(int feat)
164 {
165 return tf_has(f_info[feat].flags, TF_NO_FLOW);
166 }
167
168 /**
169 * True if the feature doesn't carry player scent.
170 */
feat_is_no_scent(int feat)171 bool feat_is_no_scent(int feat)
172 {
173 return tf_has(f_info[feat].flags, TF_NO_SCENT);
174 }
175
176 /**
177 * True if the feature should have smooth boundaries (for dungeon generation).
178 */
feat_is_smooth(int feat)179 bool feat_is_smooth(int feat)
180 {
181 return tf_has(f_info[feat].flags, TF_SMOOTH);
182 }
183
184 /**
185 * SQUARE FEATURE PREDICATES
186 *
187 * These functions are used to figure out what kind of square something is,
188 * via c->squares[y][x].feat (preferably accessed via square(c, grid)).
189 * All direct testing of square(c, grid)->feat should be rewritten
190 * in terms of these functions.
191 *
192 * It's often better to use square behavior predicates (written in terms of
193 * these functions) instead of these functions directly. For instance,
194 * square_isrock() will return false for a secret door, even though it will
195 * behave like a rock wall until the player determines it's a door.
196 *
197 * Use functions like square_isdiggable, square_iswall, etc. in these cases.
198 */
199
200 /**
201 * True if the square is normal open floor.
202 */
square_isfloor(struct chunk * c,struct loc grid)203 bool square_isfloor(struct chunk *c, struct loc grid)
204 {
205 return feat_is_floor(square(c, grid)->feat);
206 }
207
208 /**
209 * True if the square can hold a trap.
210 */
square_istrappable(struct chunk * c,struct loc grid)211 bool square_istrappable(struct chunk *c, struct loc grid)
212 {
213 return feat_is_trap_holding(square(c, grid)->feat);
214 }
215
216 /**
217 * True if the square can hold an object.
218 */
square_isobjectholding(struct chunk * c,struct loc grid)219 bool square_isobjectholding(struct chunk *c, struct loc grid)
220 {
221 return feat_is_object_holding(square(c, grid)->feat);
222 }
223
224 /**
225 * True if the square is a normal granite rock wall.
226 */
square_isrock(struct chunk * c,struct loc grid)227 bool square_isrock(struct chunk *c, struct loc grid)
228 {
229 return (tf_has(f_info[square(c, grid)->feat].flags, TF_GRANITE) &&
230 !tf_has(f_info[square(c, grid)->feat].flags, TF_DOOR_ANY));
231 }
232
233 /**
234 * True if the square is granite.
235 */
square_isgranite(struct chunk * c,struct loc grid)236 bool square_isgranite(struct chunk *c, struct loc grid)
237 {
238 return feat_is_granite(square(c, grid)->feat);
239 }
240
241 /**
242 * True if the square is a permanent wall.
243 */
square_isperm(struct chunk * c,struct loc grid)244 bool square_isperm(struct chunk *c, struct loc grid)
245 {
246 return (tf_has(f_info[square(c, grid)->feat].flags, TF_PERMANENT) &&
247 tf_has(f_info[square(c, grid)->feat].flags, TF_ROCK));
248 }
249
250 /**
251 * True if the square is a magma wall.
252 */
square_ismagma(struct chunk * c,struct loc grid)253 bool square_ismagma(struct chunk *c, struct loc grid)
254 {
255 return feat_is_magma(square(c, grid)->feat);
256 }
257
258 /**
259 * True if the square is a quartz wall.
260 */
square_isquartz(struct chunk * c,struct loc grid)261 bool square_isquartz(struct chunk *c, struct loc grid)
262 {
263 return feat_is_quartz(square(c, grid)->feat);
264 }
265
266 /**
267 * True if the square is a mineral wall (magma/quartz/granite).
268 */
square_ismineral(struct chunk * c,struct loc grid)269 bool square_ismineral(struct chunk *c, struct loc grid)
270 {
271 return square_isrock(c, grid) || square_ismagma(c, grid) ||
272 square_isquartz(c, grid);
273 }
274
square_hasgoldvein(struct chunk * c,struct loc grid)275 bool square_hasgoldvein(struct chunk *c, struct loc grid)
276 {
277 return tf_has(f_info[square(c, grid)->feat].flags, TF_GOLD);
278 }
279
280 /**
281 * True if the square is rubble.
282 */
square_isrubble(struct chunk * c,struct loc grid)283 bool square_isrubble(struct chunk *c, struct loc grid)
284 {
285 return (!tf_has(f_info[square(c, grid)->feat].flags, TF_WALL) &&
286 tf_has(f_info[square(c, grid)->feat].flags, TF_ROCK));
287 }
288
289 /**
290 * True if the square is a hidden secret door.
291 *
292 * These squares appear as if they were granite--when detected a secret door
293 * is replaced by a closed door.
294 */
square_issecretdoor(struct chunk * c,struct loc grid)295 bool square_issecretdoor(struct chunk *c, struct loc grid)
296 {
297 return (tf_has(f_info[square(c, grid)->feat].flags, TF_DOOR_ANY) &&
298 tf_has(f_info[square(c, grid)->feat].flags, TF_ROCK));
299 }
300
301 /**
302 * True if the square is an open door.
303 */
square_isopendoor(struct chunk * c,struct loc grid)304 bool square_isopendoor(struct chunk *c, struct loc grid)
305 {
306 return (tf_has(f_info[square(c, grid)->feat].flags, TF_CLOSABLE));
307 }
308
309 /**
310 * True if the square is a closed door (possibly locked or jammed).
311 */
square_iscloseddoor(struct chunk * c,struct loc grid)312 bool square_iscloseddoor(struct chunk *c, struct loc grid)
313 {
314 int feat = square(c, grid)->feat;
315 return tf_has(f_info[feat].flags, TF_DOOR_CLOSED);
316 }
317
square_isbrokendoor(struct chunk * c,struct loc grid)318 bool square_isbrokendoor(struct chunk *c, struct loc grid)
319 {
320 int feat = square(c, grid)->feat;
321 return (tf_has(f_info[feat].flags, TF_DOOR_ANY) &&
322 tf_has(f_info[feat].flags, TF_PASSABLE) &&
323 !tf_has(f_info[feat].flags, TF_CLOSABLE));
324 }
325
326 /**
327 * True if the square is a door.
328 *
329 * This includes open, closed, and hidden doors.
330 */
square_isdoor(struct chunk * c,struct loc grid)331 bool square_isdoor(struct chunk *c, struct loc grid)
332 {
333 int feat = square(c, grid)->feat;
334 return tf_has(f_info[feat].flags, TF_DOOR_ANY);
335 }
336
337 /**
338 * True if square is any stair
339 */
square_isstairs(struct chunk * c,struct loc grid)340 bool square_isstairs(struct chunk *c, struct loc grid)
341 {
342 int feat = square(c, grid)->feat;
343 return tf_has(f_info[feat].flags, TF_STAIR);
344 }
345
346 /**
347 * True if square is an up stair.
348 */
square_isupstairs(struct chunk * c,struct loc grid)349 bool square_isupstairs(struct chunk*c, struct loc grid)
350 {
351 int feat = square(c, grid)->feat;
352 return tf_has(f_info[feat].flags, TF_UPSTAIR);
353 }
354
355 /**
356 * True if square is a down stair.
357 */
square_isdownstairs(struct chunk * c,struct loc grid)358 bool square_isdownstairs(struct chunk *c, struct loc grid)
359 {
360 int feat = square(c, grid)->feat;
361 return tf_has(f_info[feat].flags, TF_DOWNSTAIR);
362 }
363
364 /**
365 * True if the square is a shop entrance.
366 */
square_isshop(struct chunk * c,struct loc grid)367 bool square_isshop(struct chunk *c, struct loc grid)
368 {
369 return feat_is_shop(square(c, grid)->feat);
370 }
371
372 /**
373 * True if the square contains the player
374 */
square_isplayer(struct chunk * c,struct loc grid)375 bool square_isplayer(struct chunk *c, struct loc grid) {
376 return square(c, grid)->mon < 0 ? true : false;
377 }
378
379 /**
380 * True if the square contains the player or a monster
381 */
square_isoccupied(struct chunk * c,struct loc grid)382 bool square_isoccupied(struct chunk *c, struct loc grid) {
383 return square(c, grid)->mon != 0 ? true : false;
384 }
385
386 /**
387 * True if the the player knows the terrain of the square
388 */
square_isknown(struct chunk * c,struct loc grid)389 bool square_isknown(struct chunk *c, struct loc grid) {
390 if (c != cave) return false;
391 if (player->cave == NULL) return false;
392 return square(player->cave, grid)->feat == FEAT_NONE ? false : true;
393 }
394
395 /**
396 * True if the the player's knowledge of the terrain of the square is wrong
397 * or missing
398 */
square_isnotknown(struct chunk * c,struct loc grid)399 bool square_isnotknown(struct chunk *c, struct loc grid) {
400 if (c != cave) return false;
401 if (player->cave == NULL) return true;
402 return square(player->cave, grid)->feat != square(c, grid)->feat;
403 }
404
405 /**
406 * SQUARE INFO PREDICATES
407 *
408 * These functions tell whether a square is marked with one of the SQUARE_*
409 * flags. These flags are mostly used to mark a square with some information
410 * about its location or status.
411 */
412
413 /**
414 * True if the square is marked
415 */
square_ismark(struct chunk * c,struct loc grid)416 bool square_ismark(struct chunk *c, struct loc grid) {
417 assert(square_in_bounds(c, grid));
418 return sqinfo_has(square(c, grid)->info, SQUARE_MARK);
419 }
420
421 /**
422 * True if the square is lit
423 */
square_isglow(struct chunk * c,struct loc grid)424 bool square_isglow(struct chunk *c, struct loc grid) {
425 assert(square_in_bounds(c, grid));
426 return sqinfo_has(square(c, grid)->info, SQUARE_GLOW);
427 }
428
429 /**
430 * True if the square is part of a vault.
431 *
432 * This doesn't say what kind of square it is, just that it is part of a vault.
433 */
square_isvault(struct chunk * c,struct loc grid)434 bool square_isvault(struct chunk *c, struct loc grid) {
435 assert(square_in_bounds(c, grid));
436 return sqinfo_has(square(c, grid)->info, SQUARE_VAULT);
437 }
438
439 /**
440 * True if the square is part of a room.
441 */
square_isroom(struct chunk * c,struct loc grid)442 bool square_isroom(struct chunk *c, struct loc grid) {
443 assert(square_in_bounds(c, grid));
444 return sqinfo_has(square(c, grid)->info, SQUARE_ROOM);
445 }
446
447 /**
448 * True if the square has been seen by the player
449 */
square_isseen(struct chunk * c,struct loc grid)450 bool square_isseen(struct chunk *c, struct loc grid) {
451 assert(square_in_bounds(c, grid));
452 return sqinfo_has(square(c, grid)->info, SQUARE_SEEN);
453 }
454
455 /**
456 * True if the cave square is currently viewable by the player
457 */
square_isview(struct chunk * c,struct loc grid)458 bool square_isview(struct chunk *c, struct loc grid) {
459 assert(square_in_bounds(c, grid));
460 return sqinfo_has(square(c, grid)->info, SQUARE_VIEW);
461 }
462
463 /**
464 * True if the cave square was seen before the current update
465 */
square_wasseen(struct chunk * c,struct loc grid)466 bool square_wasseen(struct chunk *c, struct loc grid) {
467 assert(square_in_bounds(c, grid));
468 return sqinfo_has(square(c, grid)->info, SQUARE_WASSEEN);
469 }
470
471 /**
472 * True if cave square is a feeling trigger square
473 */
square_isfeel(struct chunk * c,struct loc grid)474 bool square_isfeel(struct chunk *c, struct loc grid) {
475 assert(square_in_bounds(c, grid));
476 return sqinfo_has(square(c, grid)->info, SQUARE_FEEL);
477 }
478
479 /**
480 * True if the square has a known trap
481 */
square_istrap(struct chunk * c,struct loc grid)482 bool square_istrap(struct chunk *c, struct loc grid) {
483 assert(square_in_bounds(c, grid));
484 return sqinfo_has(square(c, grid)->info, SQUARE_TRAP);
485 }
486
487 /**
488 * True if the square has an unknown trap
489 */
square_isinvis(struct chunk * c,struct loc grid)490 bool square_isinvis(struct chunk *c, struct loc grid) {
491 assert(square_in_bounds(c, grid));
492 return sqinfo_has(square(c, grid)->info, SQUARE_INVIS);
493 }
494
495 /**
496 * True if cave square is an inner wall (generation)
497 */
square_iswall_inner(struct chunk * c,struct loc grid)498 bool square_iswall_inner(struct chunk *c, struct loc grid) {
499 assert(square_in_bounds(c, grid));
500 return sqinfo_has(square(c, grid)->info, SQUARE_WALL_INNER);
501 }
502
503 /**
504 * True if cave square is an outer wall (generation)
505 */
square_iswall_outer(struct chunk * c,struct loc grid)506 bool square_iswall_outer(struct chunk *c, struct loc grid) {
507 assert(square_in_bounds(c, grid));
508 return sqinfo_has(square(c, grid)->info, SQUARE_WALL_OUTER);
509 }
510
511 /**
512 * True if cave square is a solid wall (generation)
513 */
square_iswall_solid(struct chunk * c,struct loc grid)514 bool square_iswall_solid(struct chunk *c, struct loc grid) {
515 assert(square_in_bounds(c, grid));
516 return sqinfo_has(square(c, grid)->info, SQUARE_WALL_SOLID);
517 }
518
519 /**
520 * True if cave square has monster restrictions (generation)
521 */
square_ismon_restrict(struct chunk * c,struct loc grid)522 bool square_ismon_restrict(struct chunk *c, struct loc grid) {
523 assert(square_in_bounds(c, grid));
524 return sqinfo_has(square(c, grid)->info, SQUARE_MON_RESTRICT);
525 }
526
527 /**
528 * True if cave square can't be teleported from by the player
529 */
square_isno_teleport(struct chunk * c,struct loc grid)530 bool square_isno_teleport(struct chunk *c, struct loc grid) {
531 assert(square_in_bounds(c, grid));
532 return sqinfo_has(square(c, grid)->info, SQUARE_NO_TELEPORT);
533 }
534
535 /**
536 * True if cave square can't be magically mapped by the player
537 */
square_isno_map(struct chunk * c,struct loc grid)538 bool square_isno_map(struct chunk *c, struct loc grid) {
539 assert(square_in_bounds(c, grid));
540 return sqinfo_has(square(c, grid)->info, SQUARE_NO_MAP);
541 }
542
543 /**
544 * True if cave square can't be detected by player ESP
545 */
square_isno_esp(struct chunk * c,struct loc grid)546 bool square_isno_esp(struct chunk *c, struct loc grid) {
547 assert(square_in_bounds(c, grid));
548 return sqinfo_has(square(c, grid)->info, SQUARE_NO_ESP);
549 }
550
551 /**
552 * True if cave square is marked for projection processing
553 */
square_isproject(struct chunk * c,struct loc grid)554 bool square_isproject(struct chunk *c, struct loc grid) {
555 assert(square_in_bounds(c, grid));
556 return sqinfo_has(square(c, grid)->info, SQUARE_PROJECT);
557 }
558
559 /**
560 * True if cave square has been detected for traps
561 */
square_isdtrap(struct chunk * c,struct loc grid)562 bool square_isdtrap(struct chunk *c, struct loc grid) {
563 assert(square_in_bounds(c, grid));
564 return sqinfo_has(square(c, grid)->info, SQUARE_DTRAP);
565 }
566
567 /**
568 * True if cave square is inappropriate to place stairs
569 */
square_isno_stairs(struct chunk * c,struct loc grid)570 bool square_isno_stairs(struct chunk *c, struct loc grid) {
571 assert(square_in_bounds(c, grid));
572 return sqinfo_has(square(c, grid)->info, SQUARE_NO_STAIRS);
573 }
574
575
576 /**
577 * SQUARE BEHAVIOR PREDICATES
578 *
579 * These functions define how a given square behaves, e.g. whether it is
580 * passable by the player, whether it is diggable, contains items, etc.
581 *
582 * These functions use the SQUARE FEATURE PREDICATES (among other info) to
583 * make the determination.
584 */
585
586 /**
587 * True if the square is open (a floor square not occupied by a monster).
588 */
square_isopen(struct chunk * c,struct loc grid)589 bool square_isopen(struct chunk *c, struct loc grid) {
590 return square_isfloor(c, grid) && !square(c, grid)->mon;
591 }
592
593 /**
594 * True if the square is empty (an open square without any items).
595 */
square_isempty(struct chunk * c,struct loc grid)596 bool square_isempty(struct chunk *c, struct loc grid) {
597 if (square_isplayertrap(c, grid)) return false;
598 if (square_iswebbed(c, grid)) return false;
599 return square_isopen(c, grid) && !square_object(c, grid);
600 }
601
602 /**
603 * True if the square is empty (an open square without any items).
604 */
square_isarrivable(struct chunk * c,struct loc grid)605 bool square_isarrivable(struct chunk *c, struct loc grid) {
606 if (square(c, grid)->mon) return false;
607 if (square_isplayertrap(c, grid)) return false;
608 if (square_iswebbed(c, grid)) return false;
609 if (square_isfloor(c, grid)) return true;
610 if (square_isstairs(c, grid)) return true;
611 // maybe allow open doors or suchlike?
612 return false;
613 }
614
615 /**
616 * True if the square is an untrapped floor square without items.
617 */
square_canputitem(struct chunk * c,struct loc grid)618 bool square_canputitem(struct chunk *c, struct loc grid) {
619 if (!square_isobjectholding(c, grid)) return false;
620 if (square_istrap(c, grid)) return false;
621 return !square_object(c, grid);
622 }
623
624 /**
625 * True if the square can be dug: this includes rubble and non-permanent walls.
626 */
square_isdiggable(struct chunk * c,struct loc grid)627 bool square_isdiggable(struct chunk *c, struct loc grid) {
628 return (square_ismineral(c, grid) ||
629 square_issecretdoor(c, grid) ||
630 square_isrubble(c, grid));
631 }
632
633 /**
634 * True if the square is a floor with no traps.
635 */
square_iswebbable(struct chunk * c,struct loc grid)636 bool square_iswebbable(struct chunk *c, struct loc grid) {
637 if (square_trap(c, grid)) return false;
638 return square_isfloor(c, grid);
639 }
640
641 /**
642 * True if a monster can walk through the tile.
643 *
644 * This is needed for polymorphing. A monster may be on a feature that isn't
645 * an empty space, causing problems when it is replaced with a new monster.
646 */
square_is_monster_walkable(struct chunk * c,struct loc grid)647 bool square_is_monster_walkable(struct chunk *c, struct loc grid)
648 {
649 assert(square_in_bounds(c, grid));
650 return feat_is_monster_walkable(square(c, grid)->feat);
651 }
652
653 /**
654 * True if the square is passable by the player.
655 */
square_ispassable(struct chunk * c,struct loc grid)656 bool square_ispassable(struct chunk *c, struct loc grid) {
657 assert(square_in_bounds(c, grid));
658 return feat_is_passable(square(c, grid)->feat);
659 }
660
661 /**
662 * True if any projectable can pass through the square.
663 *
664 * This function is the logical negation of square_iswall().
665 */
square_isprojectable(struct chunk * c,struct loc grid)666 bool square_isprojectable(struct chunk *c, struct loc grid) {
667 if (!square_in_bounds(c, grid)) return false;
668 return feat_is_projectable(square(c, grid)->feat);
669 }
670
671 /**
672 * True if the square is a wall square (impedes the player).
673 *
674 * This function is the logical negation of square_isprojectable().
675 */
square_iswall(struct chunk * c,struct loc grid)676 bool square_iswall(struct chunk *c, struct loc grid) {
677 assert(square_in_bounds(c, grid));
678 return !square_isprojectable(c, grid);
679 }
680
681 /**
682 * True if the square is a permanent wall or one of the "stronger" walls.
683 *
684 * The stronger walls are granite, magma and quartz. This excludes things like
685 * secret doors and rubble.
686 */
square_isstrongwall(struct chunk * c,struct loc grid)687 bool square_isstrongwall(struct chunk *c, struct loc grid) {
688 assert(square_in_bounds(c, grid));
689 return square_ismineral(c, grid) || square_isperm(c, grid);
690 }
691
692 /**
693 * True if the cave square is internally lit.
694 */
square_isbright(struct chunk * c,struct loc grid)695 bool square_isbright(struct chunk *c, struct loc grid) {
696 assert(square_in_bounds(c, grid));
697 return feat_is_bright(square(c, grid)->feat);
698 }
699
700 /**
701 * True if the cave square is fire-based.
702 */
square_isfiery(struct chunk * c,struct loc grid)703 bool square_isfiery(struct chunk *c, struct loc grid) {
704 assert(square_in_bounds(c, grid));
705 return feat_is_fiery(square(c, grid)->feat);
706 }
707
708 /**
709 * True if the cave square is lit.
710 */
square_islit(struct chunk * c,struct loc grid)711 bool square_islit(struct chunk *c, struct loc grid) {
712 assert(square_in_bounds(c, grid));
713 return square_light(c, grid) > 0 ? true : false;
714 }
715
716 /**
717 * True if a lit wall should appear lit.
718 */
square_islitwall(struct chunk * c,struct loc grid)719 bool square_islitwall(struct chunk *c, struct loc grid) {
720 int d;
721 assert(square_in_bounds(c, grid));
722 for (d = 0; d < 8; d++) {
723 struct loc adj = loc_sum(grid, ddgrid_ddd[d]);
724 if (!square_in_bounds(c, adj)) continue;
725 if (!square_isfloor(c, adj)) continue;
726 if (!square_isroom(c, adj)) continue;
727 if (!square_isglow(c, adj)) continue;
728 if (!square_isseen(c, adj)) continue;
729 return true;
730 }
731
732 return false;
733 }
734
735 /**
736 * True if the cave square can damage the inhabitant - only lava so far
737 */
square_isdamaging(struct chunk * c,struct loc grid)738 bool square_isdamaging(struct chunk *c, struct loc grid) {
739 assert(square_in_bounds(c, grid));
740 return feat_is_fiery(square(c, grid)->feat);
741 }
742
743 /**
744 * True if the cave square doesn't allow monster flow information.
745 */
square_isnoflow(struct chunk * c,struct loc grid)746 bool square_isnoflow(struct chunk *c, struct loc grid) {
747 assert(square_in_bounds(c, grid));
748 return feat_is_no_flow(square(c, grid)->feat);
749 }
750
751 /**
752 * True if the cave square doesn't carry player scent.
753 */
square_isnoscent(struct chunk * c,struct loc grid)754 bool square_isnoscent(struct chunk *c, struct loc grid) {
755 assert(square_in_bounds(c, grid));
756 return feat_is_no_scent(square(c, grid)->feat);
757 }
758
square_iswarded(struct chunk * c,struct loc grid)759 bool square_iswarded(struct chunk *c, struct loc grid)
760 {
761 struct trap_kind *rune = lookup_trap("glyph of warding");
762 return square_trap_specific(c, grid, rune->tidx);
763 }
764
square_isdecoyed(struct chunk * c,struct loc grid)765 bool square_isdecoyed(struct chunk *c, struct loc grid)
766 {
767 struct trap_kind *glyph = lookup_trap("decoy");
768 return square_trap_specific(c, grid, glyph->tidx);
769 }
770
square_iswebbed(struct chunk * c,struct loc grid)771 bool square_iswebbed(struct chunk *c, struct loc grid)
772 {
773 struct trap_kind *web = lookup_trap("web");
774 return square_trap_specific(c, grid, web->tidx);
775 }
776
square_seemslikewall(struct chunk * c,struct loc grid)777 bool square_seemslikewall(struct chunk *c, struct loc grid)
778 {
779 return tf_has(f_info[square(c, grid)->feat].flags, TF_ROCK);
780 }
781
square_isinteresting(struct chunk * c,struct loc grid)782 bool square_isinteresting(struct chunk *c, struct loc grid)
783 {
784 int f = square(c, grid)->feat;
785 return tf_has(f_info[f].flags, TF_INTERESTING);
786 }
787
788 /**
789 * True if the square is a closed, locked door.
790 */
square_islockeddoor(struct chunk * c,struct loc grid)791 bool square_islockeddoor(struct chunk *c, struct loc grid)
792 {
793 return square_door_power(c, grid) > 0;
794 }
795
796 /**
797 * True if there is a player trap (known or unknown) in this square.
798 */
square_isplayertrap(struct chunk * c,struct loc grid)799 bool square_isplayertrap(struct chunk *c, struct loc grid)
800 {
801 return square_trap_flag(c, grid, TRF_TRAP);
802 }
803
804 /**
805 * True if there is a visible trap in this square.
806 */
square_isvisibletrap(struct chunk * c,struct loc grid)807 bool square_isvisibletrap(struct chunk *c, struct loc grid)
808 {
809 /* Look for a visible trap */
810 return square_trap_flag(c, grid, TRF_VISIBLE);
811 }
812 /**
813 * True if the square is an unknown player trap (it will appear as a floor tile)
814 */
square_issecrettrap(struct chunk * c,struct loc grid)815 bool square_issecrettrap(struct chunk *c, struct loc grid)
816 {
817 return !square_isvisibletrap(c, grid) && square_isplayertrap(c, grid);
818 }
819
820 /**
821 * True if the square is a known, disabled player trap.
822 */
square_isdisabledtrap(struct chunk * c,struct loc grid)823 bool square_isdisabledtrap(struct chunk *c, struct loc grid)
824 {
825 return square_isvisibletrap(c, grid) &&
826 (square_trap_timeout(c, grid, -1) > 0);
827 }
828
829 /**
830 * True if the square is a known, disarmable player trap.
831 */
square_isdisarmabletrap(struct chunk * c,struct loc grid)832 bool square_isdisarmabletrap(struct chunk *c, struct loc grid)
833 {
834 if (square_isdisabledtrap(c, grid)) return false;
835 return square_isvisibletrap(c, grid) && square_isplayertrap(c, grid);
836 }
837
838 /**
839 * Checks if a square is at the (inner) edge of a trap detect area
840 */
square_dtrap_edge(struct chunk * c,struct loc grid)841 bool square_dtrap_edge(struct chunk *c, struct loc grid)
842 {
843 /* Check if the square is a dtrap in the first place */
844 if (!square_isdtrap(c, grid)) return false;
845
846 /* Check for non-dtrap adjacent grids */
847 if (square_in_bounds_fully(c, next_grid(grid, DIR_S)) &&
848 (!square_isdtrap(c, next_grid(grid, DIR_S))))
849 return true;
850 if (square_in_bounds_fully(c, next_grid(grid, DIR_E)) &&
851 (!square_isdtrap(c, next_grid(grid, DIR_E))))
852 return true;
853 if (square_in_bounds_fully(c, next_grid(grid, DIR_N)) &&
854 (!square_isdtrap(c, next_grid(grid, DIR_N))))
855 return true;
856 if (square_in_bounds_fully(c, next_grid(grid, DIR_W)) &&
857 (!square_isdtrap(c, next_grid(grid, DIR_W))))
858 return true;
859
860 return false;
861 }
862
863 /**
864 * Determine if a given location may be "destroyed"
865 *
866 * Used by destruction spells, and for placing stairs, etc.
867 */
square_changeable(struct chunk * c,struct loc grid)868 bool square_changeable(struct chunk *c, struct loc grid)
869 {
870 struct object *obj;
871
872 /* Forbid perma-grids */
873 if (square_isperm(c, grid) || square_isshop(c, grid) ||
874 square_isstairs(c, grid))
875 return (false);
876
877 /* Check objects */
878 for (obj = square_object(c, grid); obj; obj = obj->next)
879 /* Forbid artifact grids */
880 if (obj->artifact) return (false);
881
882 /* Accept */
883 return (true);
884 }
885
886
square_in_bounds(struct chunk * c,struct loc grid)887 bool square_in_bounds(struct chunk *c, struct loc grid)
888 {
889 assert(c);
890 return grid.x >= 0 && grid.x < c->width &&
891 grid.y >= 0 && grid.y < c->height;
892 }
893
square_in_bounds_fully(struct chunk * c,struct loc grid)894 bool square_in_bounds_fully(struct chunk *c, struct loc grid)
895 {
896 assert(c);
897 return grid.x > 0 && grid.x < c->width - 1 &&
898 grid.y > 0 && grid.y < c->height - 1;
899 }
900
901 /**
902 * Checks if a square is thought by the player to block projections
903 */
square_isbelievedwall(struct chunk * c,struct loc grid)904 bool square_isbelievedwall(struct chunk *c, struct loc grid)
905 {
906 // the edge of the world is definitely gonna block things
907 if (!square_in_bounds_fully(c, grid)) return true;
908 // if we dont know assume its projectable
909 if (!square_isknown(c, grid)) return false;
910 // report what we think (we may be wrong)
911 return !square_isprojectable(player->cave, grid);
912 }
913
914 /**
915 * Checks if a square is in a cul-de-sac
916 */
square_suits_stairs_well(struct chunk * c,struct loc grid)917 bool square_suits_stairs_well(struct chunk *c, struct loc grid)
918 {
919 if (square_isvault(c, grid) || square_isno_stairs(c, grid)) return false;
920 return (square_num_walls_adjacent(c, grid) == 3) &&
921 (square_num_walls_diagonal(c, grid) == 4) && square_isempty(c, grid);
922 }
923
924 /**
925 * Checks if a square is in a corridor
926 */
square_suits_stairs_ok(struct chunk * c,struct loc grid)927 bool square_suits_stairs_ok(struct chunk *c, struct loc grid)
928 {
929 if (square_isvault(c, grid) || square_isno_stairs(c, grid)) return false;
930 return (square_num_walls_adjacent(c, grid) == 2) &&
931 (square_num_walls_diagonal(c, grid) == 4) && square_isempty(c, grid);
932 }
933
934
935
936 /**
937 * OTHER SQUARE FUNCTIONS
938 *
939 * Below are various square-specific functions which are not predicates
940 */
941
square(struct chunk * c,struct loc grid)942 const struct square *square(struct chunk *c, struct loc grid)
943 {
944 assert(square_in_bounds(c, grid));
945 return &c->squares[grid.y][grid.x];
946 }
947
square_feat(struct chunk * c,struct loc grid)948 struct feature *square_feat(struct chunk *c, struct loc grid)
949 {
950 assert(square_in_bounds(c, grid));
951 return &f_info[square(c, grid)->feat];
952 }
953
square_light(struct chunk * c,struct loc grid)954 int square_light(struct chunk *c, struct loc grid)
955 {
956 assert(square_in_bounds(c, grid));
957 return square(c, grid)->light;
958 }
959
960 /**
961 * Get a monster on the current level by its position.
962 */
square_monster(struct chunk * c,struct loc grid)963 struct monster *square_monster(struct chunk *c, struct loc grid)
964 {
965 if (!square_in_bounds(c, grid)) return NULL;
966 if (square(c, grid)->mon > 0) {
967 struct monster *mon = cave_monster(c, square(c, grid)->mon);
968 return mon && mon->race ? mon : NULL;
969 }
970
971 return NULL;
972 }
973
974 /**
975 * Get the top object of a pile on the current level by its position.
976 */
square_object(struct chunk * c,struct loc grid)977 struct object *square_object(struct chunk *c, struct loc grid) {
978 if (!square_in_bounds(c, grid)) return NULL;
979 return square(c, grid)->obj;
980 }
981
982 /**
983 * Get the first (and currently only) trap in a position on the current level.
984 */
square_trap(struct chunk * c,struct loc grid)985 struct trap *square_trap(struct chunk *c, struct loc grid)
986 {
987 if (!square_in_bounds(c, grid)) return NULL;
988 return square(c, grid)->trap;
989 }
990
991 /**
992 * Return true if the given object is on the floor at this grid
993 */
square_holds_object(struct chunk * c,struct loc grid,struct object * obj)994 bool square_holds_object(struct chunk *c, struct loc grid, struct object *obj) {
995 assert(square_in_bounds(c, grid));
996 return pile_contains(square_object(c, grid), obj);
997 }
998
999 /**
1000 * Excise an object from a floor pile, leaving it orphaned.
1001 */
square_excise_object(struct chunk * c,struct loc grid,struct object * obj)1002 void square_excise_object(struct chunk *c, struct loc grid, struct object *obj){
1003 assert(square_in_bounds(c, grid));
1004 pile_excise(&c->squares[grid.y][grid.x].obj, obj);
1005 }
1006
1007 /**
1008 * Excise an entire floor pile.
1009 */
square_excise_pile(struct chunk * c,struct loc grid)1010 void square_excise_pile(struct chunk *c, struct loc grid) {
1011 assert(square_in_bounds(c, grid));
1012 object_pile_free(square_object(c, grid));
1013 square_set_obj(c, grid, NULL);
1014 }
1015
1016 /**
1017 * Excise an object from a floor pile and delete it while doing the other
1018 * necessary bookkeeping. Normally, this is only called for the chunk
1019 * representing the true nature of the environment and not the one
1020 * representing the player's view of it. If do_note is true, call
1021 * square_note_spot(). If do_light is true, call square_light_spot().
1022 * Unless calling this on the player's view, those both would be true
1023 * except as an optimization/simplification when the caller would call
1024 * square_note_spot()/square_light_spot() anyways or knows that those aren't
1025 * necessary.
1026 */
square_delete_object(struct chunk * c,struct loc grid,struct object * obj,bool do_note,bool do_light)1027 void square_delete_object(struct chunk *c, struct loc grid, struct object *obj, bool do_note, bool do_light)
1028 {
1029 square_excise_object(c, grid, obj);
1030 delist_object(c, obj);
1031 object_delete(&obj);
1032 if (do_note) {
1033 square_note_spot(c, grid);
1034 }
1035 if (do_light) {
1036 square_light_spot(c, grid);
1037 }
1038 }
1039
1040 /**
1041 * Sense the existence of objects on a grid in the current level
1042 */
square_sense_pile(struct chunk * c,struct loc grid)1043 void square_sense_pile(struct chunk *c, struct loc grid)
1044 {
1045 struct object *obj;
1046
1047 if (c != cave) return;
1048
1049 /* Sense every item on this grid */
1050 for (obj = square_object(c, grid); obj; obj = obj->next) {
1051 object_sense(player, obj);
1052 }
1053 }
1054
1055 /**
1056 * Update the player's knowledge of the objects on a grid in the current level
1057 */
square_know_pile(struct chunk * c,struct loc grid)1058 void square_know_pile(struct chunk *c, struct loc grid)
1059 {
1060 struct object *obj;
1061
1062 if (c != cave) return;
1063
1064 object_lists_check_integrity(c, player->cave);
1065
1066 /* Know every item on this grid, greater knowledge for the player grid */
1067 for (obj = square_object(c, grid); obj; obj = obj->next) {
1068 object_see(player, obj);
1069 if (loc_eq(grid, player->grid)) {
1070 object_touch(player, obj);
1071 }
1072 }
1073
1074 /* Remove known location of anything not on this grid */
1075 obj = square_object(player->cave, grid);
1076 while (obj) {
1077 struct object *next = obj->next;
1078 assert(c->objects[obj->oidx]);
1079 if (!square_holds_object(c, grid, c->objects[obj->oidx])) {
1080 struct object *original = c->objects[obj->oidx];
1081 square_excise_object(player->cave, grid, obj);
1082 obj->grid = loc(0, 0);
1083
1084 /* Delete objects which no longer exist anywhere */
1085 if (obj->notice & OBJ_NOTICE_IMAGINED) {
1086 delist_object(player->cave, obj);
1087 object_delete(&obj);
1088 original->known = NULL;
1089 delist_object(c, original);
1090 object_delete(&original);
1091 }
1092 }
1093 obj = next;
1094 }
1095 }
1096
1097
1098 /**
1099 * Return how many cardinal directions around (x, y) contain walls.
1100 * \param c current chunk
1101 * \param y co-ordinates
1102 * \param x co-ordinates
1103 * \return the number of walls
1104 */
square_num_walls_adjacent(struct chunk * c,struct loc grid)1105 int square_num_walls_adjacent(struct chunk *c, struct loc grid)
1106 {
1107 int k = 0;
1108 assert(square_in_bounds(c, grid));
1109
1110 if (feat_is_wall(square(c, next_grid(grid, DIR_S))->feat)) k++;
1111 if (feat_is_wall(square(c, next_grid(grid, DIR_N))->feat)) k++;
1112 if (feat_is_wall(square(c, next_grid(grid, DIR_E))->feat)) k++;
1113 if (feat_is_wall(square(c, next_grid(grid, DIR_W))->feat)) k++;
1114
1115 return k;
1116 }
1117
1118 /**
1119 * Return how many diagonal directions around (x, y) contain walls.
1120 * \param c current chunk
1121 * \param y co-ordinates
1122 * \param x co-ordinates
1123 * \return the number of walls
1124 */
square_num_walls_diagonal(struct chunk * c,struct loc grid)1125 int square_num_walls_diagonal(struct chunk *c, struct loc grid)
1126 {
1127 int k = 0;
1128 assert(square_in_bounds(c, grid));
1129
1130 if (feat_is_wall(square(c, next_grid(grid, DIR_SE))->feat)) k++;
1131 if (feat_is_wall(square(c, next_grid(grid, DIR_NW))->feat)) k++;
1132 if (feat_is_wall(square(c, next_grid(grid, DIR_NE))->feat)) k++;
1133 if (feat_is_wall(square(c, next_grid(grid, DIR_SW))->feat)) k++;
1134
1135 return k;
1136 }
1137
1138
1139 /**
1140 * Set the terrain type for a square.
1141 *
1142 * This should be the only function that sets terrain, apart from the savefile
1143 * loading code.
1144 */
square_set_feat(struct chunk * c,struct loc grid,int feat)1145 void square_set_feat(struct chunk *c, struct loc grid, int feat)
1146 {
1147 int current_feat;
1148
1149 assert(square_in_bounds(c, grid));
1150 current_feat = square(c, grid)->feat;
1151
1152 /* Track changes */
1153 if (current_feat) c->feat_count[current_feat]--;
1154 if (feat) c->feat_count[feat]++;
1155
1156 /* Make the change */
1157 c->squares[grid.y][grid.x].feat = feat;
1158
1159 /* Light bright terrain */
1160 if (feat_is_bright(feat)) {
1161 sqinfo_on(square(c, grid)->info, SQUARE_GLOW);
1162 }
1163
1164 /* Make the new terrain feel at home */
1165 if (character_dungeon) {
1166 /* Remove traps if necessary */
1167 if (!square_player_trap_allowed(c, grid))
1168 square_destroy_trap(c, grid);
1169
1170 square_note_spot(c, grid);
1171 square_light_spot(c, grid);
1172 } else {
1173 /* Make sure no incorrect wall flags set for dungeon generation */
1174 sqinfo_off(square(c, grid)->info, SQUARE_WALL_INNER);
1175 sqinfo_off(square(c, grid)->info, SQUARE_WALL_OUTER);
1176 sqinfo_off(square(c, grid)->info, SQUARE_WALL_SOLID);
1177 }
1178 }
1179
1180 /**
1181 * Set the player-"known" terrain type for a square.
1182 */
square_set_known_feat(struct chunk * c,struct loc grid,int feat)1183 static void square_set_known_feat(struct chunk *c, struct loc grid, int feat)
1184 {
1185 if (c != cave) return;
1186 player->cave->squares[grid.y][grid.x].feat = feat;
1187 }
1188
1189 /**
1190 * Set the occupying monster for a square.
1191 */
square_set_mon(struct chunk * c,struct loc grid,int midx)1192 void square_set_mon(struct chunk *c, struct loc grid, int midx)
1193 {
1194 c->squares[grid.y][grid.x].mon = midx;
1195 }
1196
1197 /**
1198 * Set the (first) object for a square.
1199 */
square_set_obj(struct chunk * c,struct loc grid,struct object * obj)1200 void square_set_obj(struct chunk *c, struct loc grid, struct object *obj)
1201 {
1202 c->squares[grid.y][grid.x].obj = obj;
1203 }
1204
1205 /**
1206 * Set the (first) trap for a square.
1207 */
square_set_trap(struct chunk * c,struct loc grid,struct trap * trap)1208 void square_set_trap(struct chunk *c, struct loc grid, struct trap *trap)
1209 {
1210 c->squares[grid.y][grid.x].trap = trap;
1211 }
1212
square_add_trap(struct chunk * c,struct loc grid)1213 void square_add_trap(struct chunk *c, struct loc grid)
1214 {
1215 assert(square_in_bounds_fully(c, grid));
1216 place_trap(c, grid, -1, c->depth);
1217 }
1218
square_add_glyph(struct chunk * c,struct loc grid,int type)1219 void square_add_glyph(struct chunk *c, struct loc grid, int type)
1220 {
1221 struct trap_kind *glyph = NULL;
1222 switch (type) {
1223 case GLYPH_WARDING: {
1224 glyph = lookup_trap("glyph of warding");
1225 break;
1226 }
1227 case GLYPH_DECOY: {
1228 glyph = lookup_trap("decoy");
1229 c->decoy = grid;
1230 break;
1231 }
1232 default: {
1233 msg("Non-existent glyph requested. Please report this bug.");
1234 return;
1235 }
1236 }
1237 place_trap(c, grid, glyph->tidx, 0);
1238 }
1239
square_add_web(struct chunk * c,struct loc grid)1240 void square_add_web(struct chunk *c, struct loc grid)
1241 {
1242 struct trap_kind *web = lookup_trap("web");
1243 place_trap(c, grid, web->tidx, 0);
1244 }
1245
square_add_stairs(struct chunk * c,struct loc grid,int depth)1246 void square_add_stairs(struct chunk *c, struct loc grid, int depth) {
1247 int down = randint0(100) < 50;
1248 if (depth == 0)
1249 down = 1;
1250 else if (is_quest(depth) || depth >= z_info->max_depth - 1)
1251 down = 0;
1252
1253 square_set_feat(c, grid, down ? FEAT_MORE : FEAT_LESS);
1254 }
1255
square_add_door(struct chunk * c,struct loc grid,bool closed)1256 void square_add_door(struct chunk *c, struct loc grid, bool closed) {
1257 square_set_feat(c, grid, closed ? FEAT_CLOSED : FEAT_OPEN);
1258 }
1259
square_open_door(struct chunk * c,struct loc grid)1260 void square_open_door(struct chunk *c, struct loc grid)
1261 {
1262 square_remove_all_traps(c, grid);
1263 square_set_feat(c, grid, FEAT_OPEN);
1264 }
1265
square_close_door(struct chunk * c,struct loc grid)1266 void square_close_door(struct chunk *c, struct loc grid)
1267 {
1268 square_set_feat(c, grid, FEAT_CLOSED);
1269 }
1270
square_smash_door(struct chunk * c,struct loc grid)1271 void square_smash_door(struct chunk *c, struct loc grid)
1272 {
1273 square_remove_all_traps(c, grid);
1274 square_set_feat(c, grid, FEAT_BROKEN);
1275 }
1276
square_unlock_door(struct chunk * c,struct loc grid)1277 void square_unlock_door(struct chunk *c, struct loc grid) {
1278 assert(square_islockeddoor(c, grid));
1279 square_set_door_lock(c, grid, 0);
1280 }
1281
square_destroy_door(struct chunk * c,struct loc grid)1282 void square_destroy_door(struct chunk *c, struct loc grid) {
1283 assert(square_isdoor(c, grid));
1284 square_remove_all_traps(c, grid);
1285 square_set_feat(c, grid, FEAT_FLOOR);
1286 }
1287
square_destroy_trap(struct chunk * c,struct loc grid)1288 void square_destroy_trap(struct chunk *c, struct loc grid)
1289 {
1290 square_remove_all_traps(c, grid);
1291 }
1292
square_disable_trap(struct chunk * c,struct loc grid)1293 void square_disable_trap(struct chunk *c, struct loc grid)
1294 {
1295 if (!square_isplayertrap(c, grid)) return;
1296 square_set_trap_timeout(c, grid, false, -1, 10);
1297 }
1298
square_destroy_decoy(struct chunk * c,struct loc grid)1299 void square_destroy_decoy(struct chunk *c, struct loc grid)
1300 {
1301 square_remove_all_traps(c, grid);
1302 c->decoy = loc(0, 0);
1303 if (los(c, player->grid, grid) && !player->timed[TMD_BLIND]){
1304 msg("The decoy is destroyed!");
1305 }
1306 }
1307
square_tunnel_wall(struct chunk * c,struct loc grid)1308 void square_tunnel_wall(struct chunk *c, struct loc grid)
1309 {
1310 square_set_feat(c, grid, FEAT_FLOOR);
1311 }
1312
square_destroy_wall(struct chunk * c,struct loc grid)1313 void square_destroy_wall(struct chunk *c, struct loc grid)
1314 {
1315 square_set_feat(c, grid, FEAT_FLOOR);
1316 }
1317
square_smash_wall(struct chunk * c,struct loc grid)1318 void square_smash_wall(struct chunk *c, struct loc grid)
1319 {
1320 int i;
1321 square_set_feat(c, grid, FEAT_FLOOR);
1322
1323 for (i = 0; i < 8; i++) {
1324 /* Extract adjacent location */
1325 struct loc adj_grid = loc_sum(grid, ddgrid_ddd[i]);
1326
1327 /* Check legality */
1328 if (!square_in_bounds_fully(c, adj_grid)) continue;
1329
1330 /* Ignore permanent grids */
1331 if (square_isperm(c, adj_grid)) continue;
1332
1333 /* Ignore floors, but destroy decoys */
1334 if (square_isfloor(c, adj_grid)) {
1335 if (square_isdecoyed(c, adj_grid)) {
1336 square_destroy_decoy(c, adj_grid);
1337 }
1338 continue;
1339 }
1340
1341 /* Give this grid a chance to survive */
1342 if ((square_isgranite(c, adj_grid) && one_in_(4)) ||
1343 (square_isquartz(c, adj_grid) && one_in_(10)) ||
1344 (square_ismagma(c, adj_grid) && one_in_(20))) {
1345 continue;
1346 }
1347
1348 /* Remove it */
1349 square_set_feat(c, adj_grid, FEAT_FLOOR);
1350 }
1351 }
1352
square_destroy(struct chunk * c,struct loc grid)1353 void square_destroy(struct chunk *c, struct loc grid) {
1354 int feat = FEAT_FLOOR;
1355 int r = randint0(200);
1356
1357 if (r < 20)
1358 feat = FEAT_GRANITE;
1359 else if (r < 70)
1360 feat = FEAT_QUARTZ;
1361 else if (r < 100)
1362 feat = FEAT_MAGMA;
1363
1364 square_set_feat(c, grid, feat);
1365 }
1366
square_earthquake(struct chunk * c,struct loc grid)1367 void square_earthquake(struct chunk *c, struct loc grid) {
1368 int t = randint0(100);
1369 int f;
1370
1371 if (!square_ispassable(c, grid)) {
1372 square_set_feat(c, grid, FEAT_FLOOR);
1373 return;
1374 }
1375
1376 if (t < 20)
1377 f = FEAT_GRANITE;
1378 else if (t < 70)
1379 f = FEAT_QUARTZ;
1380 else
1381 f = FEAT_MAGMA;
1382 square_set_feat(c, grid, f);
1383 }
1384
1385 /**
1386 * Add visible treasure to a mineral square.
1387 */
square_upgrade_mineral(struct chunk * c,struct loc grid)1388 void square_upgrade_mineral(struct chunk *c, struct loc grid)
1389 {
1390 if (square(c, grid)->feat == FEAT_MAGMA)
1391 square_set_feat(c, grid, FEAT_MAGMA_K);
1392 if (square(c, grid)->feat == FEAT_QUARTZ)
1393 square_set_feat(c, grid, FEAT_QUARTZ_K);
1394 }
1395
square_destroy_rubble(struct chunk * c,struct loc grid)1396 void square_destroy_rubble(struct chunk *c, struct loc grid) {
1397 assert(square_isrubble(c, grid));
1398 square_set_feat(c, grid, FEAT_FLOOR);
1399 }
1400
square_force_floor(struct chunk * c,struct loc grid)1401 void square_force_floor(struct chunk *c, struct loc grid) {
1402 square_set_feat(c, grid, FEAT_FLOOR);
1403 }
1404
1405 /* Note that this returns the STORE_ index, which is one less than shopnum */
square_shopnum(struct chunk * c,struct loc grid)1406 int square_shopnum(struct chunk *c, struct loc grid) {
1407 if (square_isshop(c, grid))
1408 return f_info[square(c, grid)->feat].shopnum - 1;
1409 return -1;
1410 }
1411
square_digging(struct chunk * c,struct loc grid)1412 int square_digging(struct chunk *c, struct loc grid) {
1413 if (square_isdiggable(c, grid))
1414 return f_info[square(c, grid)->feat].dig;
1415 return 0;
1416 }
1417
square_apparent_name(struct chunk * c,struct player * p,struct loc grid)1418 const char *square_apparent_name(struct chunk *c, struct player *p, struct loc grid) {
1419 int actual = square(player->cave, grid)->feat;
1420 char *mimic_name = f_info[actual].mimic;
1421 int f = mimic_name ? lookup_feat(mimic_name) : actual;
1422 return f_info[f].name;
1423 }
1424
square_apparent_look_prefix(struct chunk * c,struct player * p,struct loc grid)1425 const char *square_apparent_look_prefix(struct chunk *c, struct player *p, struct loc grid) {
1426 int actual = square(player->cave, grid)->feat;
1427 char *mimic_name = f_info[actual].mimic;
1428 int f = mimic_name ? lookup_feat(mimic_name) : actual;
1429 return (f_info[f].look_prefix) ? f_info[f].look_prefix :
1430 (is_a_vowel(f_info[f].name[0]) ? "an " : "a ");
1431 }
1432
square_apparent_look_in_preposition(struct chunk * c,struct player * p,struct loc grid)1433 const char *square_apparent_look_in_preposition(struct chunk *c, struct player *p, struct loc grid) {
1434 int actual = square(player->cave, grid)->feat;
1435 char *mimic_name = f_info[actual].mimic;
1436 int f = mimic_name ? lookup_feat(mimic_name) : actual;
1437 return (f_info[f].look_in_preposition) ?
1438 f_info[f].look_in_preposition : "on ";
1439 }
1440
1441 /* Memorize the terrain */
square_memorize(struct chunk * c,struct loc grid)1442 void square_memorize(struct chunk *c, struct loc grid) {
1443 if (c != cave) return;
1444 square_set_known_feat(c, grid, square(c, grid)->feat);
1445 }
1446
1447 /* Forget the terrain */
square_forget(struct chunk * c,struct loc grid)1448 void square_forget(struct chunk *c, struct loc grid) {
1449 if (c != cave) return;
1450 square_set_known_feat(c, grid, FEAT_NONE);
1451 }
1452
square_mark(struct chunk * c,struct loc grid)1453 void square_mark(struct chunk *c, struct loc grid) {
1454 sqinfo_on(square(c, grid)->info, SQUARE_MARK);
1455 }
1456
square_unmark(struct chunk * c,struct loc grid)1457 void square_unmark(struct chunk *c, struct loc grid) {
1458 sqinfo_off(square(c, grid)->info, SQUARE_MARK);
1459 }
1460