1 /**
2  * \file project.c
3  * \brief The project() function and helpers
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-event.h"
22 #include "game-input.h"
23 #include "generate.h"
24 #include "init.h"
25 #include "mon-predicate.h"
26 #include "mon-util.h"
27 #include "player-calcs.h"
28 #include "player-timed.h"
29 #include "project.h"
30 #include "source.h"
31 #include "trap.h"
32 
33 struct projection *projections;
34 
35 /*
36  * Specify attr/char pairs for visual special effects for project()
37  * Ideally move these and PROJ-type colors to the UI - NRM
38  */
39 byte proj_to_attr[PROJ_MAX][BOLT_MAX];
40 wchar_t proj_to_char[PROJ_MAX][BOLT_MAX];
41 
42 /**
43  * ------------------------------------------------------------------------
44  * PROJ type info needed for projections
45  *
46  * Note that elements come first, so PROJ_ACID == ELEM_ACID, etc
47  * ------------------------------------------------------------------------ */
48 static const char *proj_name_list[] =
49 {
50 	#define ELEM(a) #a,
51 	#include "list-elements.h"
52 	#undef ELEM
53 	#define PROJ(a) #a,
54 	#include "list-projections.h"
55 	#undef PROJ
56 	"MAX",
57     NULL
58 };
59 
proj_name_to_idx(const char * name)60 int proj_name_to_idx(const char *name)
61 {
62     int i;
63     for (i = 0; proj_name_list[i]; i++) {
64         if (!my_stricmp(name, proj_name_list[i]))
65             return i;
66     }
67 
68     return -1;
69 }
70 
proj_idx_to_name(int type)71 const char *proj_idx_to_name(int type)
72 {
73     assert(type >= 0);
74     assert(type < PROJ_MAX);
75 
76     return proj_name_list[type];
77 }
78 
79 /**
80  * ------------------------------------------------------------------------
81  * Projection paths
82  * ------------------------------------------------------------------------ */
83 /**
84  * Determine the path taken by a projection.
85  *
86  * The projection will always start from the grid1, and will travel
87  * towards grid2, touching one grid per unit of distance along
88  * the major axis, and stopping when it enters the finish grid or a
89  * wall grid, or has travelled the maximum legal distance of "range".
90  *
91  * Note that "distance" in this function (as in the "update_view()" code)
92  * is defined as "MAX(dy,dx) + MIN(dy,dx)/2", which means that the player
93  * actually has an "octagon of projection" not a "circle of projection".
94  *
95  * The path grids are saved into the grid array pointed to by "gp", and
96  * there should be room for at least "range" grids in "gp".  Note that
97  * due to the way in which distance is calculated, this function normally
98  * uses fewer than "range" grids for the projection path, so the result
99  * of this function should never be compared directly to "range".  Note
100  * that the initial grid grid1 is never saved into the grid array, not
101  * even if the initial grid is also the final grid.  XXX XXX XXX
102  *
103  * The "flg" flags can be used to modify the behavior of this function.
104  *
105  * In particular, the "PROJECT_STOP" and "PROJECT_THRU" flags have the same
106  * semantics as they do for the "project" function, namely, that the path
107  * will stop as soon as it hits a monster, or that the path will continue
108  * through the finish grid, respectively.
109  *
110  * The "PROJECT_JUMP" flag, which for the "project()" function means to
111  * start at a special grid (which makes no sense in this function), means
112  * that the path should be "angled" slightly if needed to avoid any wall
113  * grids, allowing the player to "target" any grid which is in "view".
114  * This flag is non-trivial and has not yet been implemented, but could
115  * perhaps make use of the "vinfo" array (above).  XXX XXX XXX
116  *
117  * This function returns the number of grids (if any) in the path.  This
118  * function will return zero if and only if grid1 and grid2 are equal.
119  *
120  * This algorithm is similar to, but slightly different from, the one used
121  * by "update_view_los()", and very different from the one used by "los()".
122  */
project_path(struct loc * gp,int range,struct loc grid1,struct loc grid2,int flg)123 int project_path(struct loc *gp, int range, struct loc grid1, struct loc grid2,
124 				 int flg)
125 {
126 	int y, x;
127 
128 	int n = 0;
129 	int k = 0;
130 
131 	/* Absolute */
132 	int ay, ax;
133 
134 	/* Offsets */
135 	int sy, sx;
136 
137 	/* Fractions */
138 	int frac;
139 
140 	/* Scale factors */
141 	int full, half;
142 
143 	/* Slope */
144 	int m;
145 
146 	/* Possible decoy */
147 	struct loc decoy = cave_find_decoy(cave);
148 
149 	/* No path necessary (or allowed) */
150 	if (loc_eq(grid1, grid2)) return (0);
151 
152 
153 	/* Analyze "dy" */
154 	if (grid2.y < grid1.y) {
155 		ay = (grid1.y - grid2.y);
156 		sy = -1;
157 	} else {
158 		ay = (grid2.y - grid1.y);
159 		sy = 1;
160 	}
161 
162 	/* Analyze "dx" */
163 	if (grid2.x < grid1.x) {
164 		ax = (grid1.x - grid2.x);
165 		sx = -1;
166 	} else {
167 		ax = (grid2.x - grid1.x);
168 		sx = 1;
169 	}
170 
171 
172 	/* Number of "units" in one "half" grid */
173 	half = (ay * ax);
174 
175 	/* Number of "units" in one "full" grid */
176 	full = half << 1;
177 
178 
179 	/* Vertical */
180 	if (ay > ax) {
181 		/* Start at tile edge */
182 		frac = ax * ax;
183 
184 		/* Let m = ((dx/dy) * full) = (dx * dx * 2) = (frac * 2) */
185 		m = frac << 1;
186 
187 		/* Start */
188 		y = grid1.y + sy;
189 		x = grid1.x;
190 
191 		/* Create the projection path */
192 		while (1) {
193 			/* Save grid */
194 			gp[n++] = loc(x, y);
195 
196 			/* Hack -- Check maximum range */
197 			if ((n + (k >> 1)) >= range) break;
198 
199 			/* Sometimes stop at finish grid */
200 			if (!(flg & (PROJECT_THRU)))
201 				if (loc_eq(loc(x, y), grid2)) break;
202 
203 			/* Don't stop if making paths through rock for generation */
204 			if (!(flg & (PROJECT_ROCK))) {
205 				/* Stop at non-initial wall grids, except where that would
206 				 * leak info during targetting */
207 				if (!(flg & (PROJECT_INFO))) {
208 					if ((n > 0) && !square_isprojectable(cave, loc(x, y)))
209 						break;
210 				} else if ((n > 0) && square_isbelievedwall(cave, loc(x, y))) {
211 					break;
212 				}
213 			}
214 
215 			/* Sometimes stop at non-initial monsters/players, decoys */
216 			if (flg & (PROJECT_STOP)) {
217 				if ((n > 0) && (square(cave, loc(x, y))->mon != 0)) break;
218 				if (loc_eq(loc(x, y), decoy)) break;
219 			}
220 
221 			/* Slant */
222 			if (m) {
223 				/* Advance (X) part 1 */
224 				frac += m;
225 
226 				/* Horizontal change */
227 				if (frac >= half) {
228 					/* Advance (X) part 2 */
229 					x += sx;
230 
231 					/* Advance (X) part 3 */
232 					frac -= full;
233 
234 					/* Track distance */
235 					k++;
236 				}
237 			}
238 
239 			/* Advance (Y) */
240 			y += sy;
241 		}
242 	}
243 
244 	/* Horizontal */
245 	else if (ax > ay) {
246 		/* Start at tile edge */
247 		frac = ay * ay;
248 
249 		/* Let m = ((dy/dx) * full) = (dy * dy * 2) = (frac * 2) */
250 		m = frac << 1;
251 
252 		/* Start */
253 		y = grid1.y;
254 		x = grid1.x + sx;
255 
256 		/* Create the projection path */
257 		while (1) {
258 			/* Save grid */
259 			gp[n++] = loc(x, y);
260 
261 			/* Hack -- Check maximum range */
262 			if ((n + (k >> 1)) >= range) break;
263 
264 			/* Sometimes stop at finish grid */
265 			if (!(flg & (PROJECT_THRU)))
266 				if (loc_eq(loc(x, y), grid2)) break;
267 
268 			/* Don't stop if making paths through rock for generation */
269 			if (!(flg & (PROJECT_ROCK))) {
270 				/* Stop at non-initial wall grids, except where that would
271 				 * leak info during targetting */
272 				if (!(flg & (PROJECT_INFO))) {
273 					if ((n > 0) && !square_isprojectable(cave, loc(x, y)))
274 						break;
275 				} else if ((n > 0) && square_isbelievedwall(cave, loc(x, y))) {
276 					break;
277 				}
278 			}
279 
280 			/* Sometimes stop at non-initial monsters/players, decoys */
281 			if (flg & (PROJECT_STOP)) {
282 				if ((n > 0) && (square(cave, loc(x, y))->mon != 0)) break;
283 				if (loc_eq(loc(x, y), decoy)) break;
284 			}
285 
286 			/* Slant */
287 			if (m) {
288 				/* Advance (Y) part 1 */
289 				frac += m;
290 
291 				/* Vertical change */
292 				if (frac >= half) {
293 					/* Advance (Y) part 2 */
294 					y += sy;
295 
296 					/* Advance (Y) part 3 */
297 					frac -= full;
298 
299 					/* Track distance */
300 					k++;
301 				}
302 			}
303 
304 			/* Advance (X) */
305 			x += sx;
306 		}
307 	}
308 
309 	/* Diagonal */
310 	else {
311 		/* Start */
312 		y = grid1.y + sy;
313 		x = grid1.x + sx;
314 
315 		/* Create the projection path */
316 		while (1) {
317 			/* Save grid */
318 			gp[n++] = loc(x, y);
319 
320 			/* Hack -- Check maximum range */
321 			if ((n + (n >> 1)) >= range) break;
322 
323 			/* Sometimes stop at finish grid */
324 			if (!(flg & (PROJECT_THRU)))
325 				if (loc_eq(loc(x, y), grid2)) break;
326 
327 			/* Don't stop if making paths through rock for generation */
328 			if (!(flg & (PROJECT_ROCK))) {
329 				/* Stop at non-initial wall grids, except where that would
330 				 * leak info during targetting */
331 				if (!(flg & (PROJECT_INFO))) {
332 					if ((n > 0) && !square_isprojectable(cave, loc(x, y)))
333 						break;
334 				} else if ((n > 0) && square_isbelievedwall(cave, loc(x, y))) {
335 					break;
336 				}
337 			}
338 
339 			/* Sometimes stop at non-initial monsters/players, decoys */
340 			if (flg & (PROJECT_STOP)) {
341 				if ((n > 0) && (square(cave, loc(x, y))->mon != 0)) break;
342 				if (loc_eq(loc(x, y), decoy)) break;
343 			}
344 
345 			/* Advance */
346 			y += sy;
347 			x += sx;
348 		}
349 	}
350 
351 	/* Length */
352 	return (n);
353 }
354 
355 
356 /**
357  * Determine if a bolt spell cast from grid1 to grid2 will arrive
358  * at the final destination, assuming that no monster gets in the way,
359  * using the project_path() function to check the projection path.
360  *
361  * Note that no grid is ever projectable() from itself.
362  *
363  * This function is used to determine if the player can (easily) target
364  * a given grid, and if a monster can target the player.
365  */
projectable(struct chunk * c,struct loc grid1,struct loc grid2,int flg)366 bool projectable(struct chunk *c, struct loc grid1, struct loc grid2, int flg)
367 {
368 	struct loc grid_g[512];
369 	int grid_n = 0;
370 	int max_range = z_info->max_range;
371 
372 	/* Check for shortened projection range */
373 	if ((flg & PROJECT_SHORT) && player->timed[TMD_COVERTRACKS]) {
374 		max_range /= 4;
375 	}
376 
377 	/* Check the projection path */
378 	grid_n = project_path(grid_g, max_range, grid1, grid2, flg);
379 
380 	/* No grid is ever projectable from itself */
381 	if (!grid_n) return false;
382 
383 	/* May not end in a wall grid */
384 	if (!square_ispassable(c, grid_g[grid_n - 1])) return false;
385 
386 	/* May not end in an unrequested grid */
387 	if (!loc_eq(grid_g[grid_n - 1], grid2)) return false;
388 
389 	/* Assume okay */
390 	return (true);
391 }
392 
393 
394 
395 
396 /**
397  * ------------------------------------------------------------------------
398  * The main project() function and its helpers
399  * ------------------------------------------------------------------------ */
400 
401 /**
402  * Given an origin, find its coordinates and return them
403  *
404  * If there is no origin, return (-1, -1)
405  */
origin_get_loc(struct source origin)406 struct loc origin_get_loc(struct source origin)
407 {
408 	switch (origin.what) {
409 		case SRC_MONSTER: {
410 			struct monster *who = cave_monster(cave, origin.which.monster);
411 			return who ? who->grid : loc(-1, -1);
412 		}
413 
414 		case SRC_TRAP: {
415 			struct trap *trap = origin.which.trap;
416 			return trap->grid;
417 		}
418 
419 		case SRC_PLAYER:
420 		case SRC_OBJECT:	/* Currently only worn cursed objects use this */
421 		case SRC_CHEST_TRAP:
422 			return player->grid;
423 
424 		case SRC_NONE:
425 			return loc(-1, -1);
426 	}
427 
428 	return loc(-1, -1);
429 }
430 
431 /**
432  * Generic "beam"/"bolt"/"ball" projection routine.
433  *   -BEN-, some changes by -LM-
434  *
435  *   \param origin Origin of the projection
436  *   \param rad Radius of explosion (0 = beam/bolt, 1 to 20 = ball), or maximum
437  *	  length of arc from the source.
438  *   \param y Target location (or location to travel towards)
439  *   \param x Target location (or location to travel towards)
440  *   \param dam Base damage to apply to monsters, terrain, objects, or player
441  *   \param typ Type of projection (fire, frost, dispel demons etc.)
442  *   \param flg Extra bit flags that control projection behavior
443  *   \param degrees_of_arc How wide an arc spell is (in degrees).
444  *   \param diameter_of_source how wide the source diameter is.
445  *   \param obj An object that the projection ignores
446  *
447  *   \return true if any effects of the projection were observed, else false
448  *
449  *
450  * At present, there are five major types of projections:
451  *
452  * Point-effect projection:  (no PROJECT_BEAM flag, radius of zero, and either
453  *   jumps directly to target or has a single source and target grid)
454  * A point-effect projection has no line of projection, and only affects one
455  *   grid.  It is used for most area-effect spells (like dispel evil) and
456  *   pinpoint strikes like the monster Holding prayer.
457  *
458  * Bolt:  (no PROJECT_BEAM flag, radius of zero, has to travel from source to
459  *   target)
460  * A bolt travels from source to target and affects only the final grid in its
461  *   projection path.  If given the PROJECT_STOP flag, it is stopped by any
462  *   monster or character in its path (at present, all bolts use this flag).
463  *
464  * Beam:  (PROJECT_BEAM)
465  * A beam travels from source to target, affecting all grids passed through
466  *   with full damage.  It is never stopped by monsters in its path.  Beams
467  *   may never be combined with any other projection type.
468  *
469  * Ball:  (positive radius, unless the PROJECT_ARC flag is set)
470  * A ball travels from source towards the target, and always explodes.  Unless
471  *   specified, it does not affect wall grids, but otherwise affects any grids
472  *   in LOS from the center of the explosion.
473  * If used with a direction, a ball will explode on the first occupied grid in
474  *   its path.  If given a target, it will explode on that target.  If a
475  *   wall is in the way, it will explode against the wall.  If a ball reaches
476  *   z_info->max_range without hitting anything or reaching its target, it will
477  *   explode at that point.
478  *
479  * Arc:  (positive radius, with the PROJECT_ARC flag set)
480  * An arc is a portion of a source-centered ball that explodes outwards
481  *   towards the target grid.  Like a ball, it affects all non-wall grids in
482  *   LOS of the source in the explosion area.  The width of arc spells is con-
483  *   trolled by degrees_of_arc.
484  * An arc is created by rejecting all grids that form the endpoints of lines
485  *   whose angular difference (in degrees) from the centerline of the arc is
486  *   greater than one-half the input "degrees_of_arc".  See the table "get_
487  *   angle_to_grid" in "util.c" for more information.
488  * Note:  An arc with a value for degrees_of_arc of zero is actually a beam of
489  *   defined length.
490  *
491  * Projections that effect all monsters in LOS are handled through the use
492  *   of the PROJECT_LOS effect, which applies a single-grid projection to
493  *   individual monsters.  Projections that light up rooms or affect all
494  *   monsters on the level are more efficiently handled through special
495  *   functions.
496  *
497  *
498  * Variations:
499  *
500  * PROJECT_STOP forces a path of projection to stop at the first occupied grid
501  *   it hits.  This is used with bolts, and also by ball spells travelling in
502  *   a specific direction rather than towards a target.
503  *
504  * PROJECT_THRU allows a path of projection towards a target to continue
505  *   past that target.  It also allows a spell to affect wall grids adjacent
506  *   to a grid in LOS of the center of the explosion.
507  *
508  * PROJECT_JUMP allows a projection to immediately set the source of the pro-
509  *   jection to the target.  This is used for all area effect spells (like
510  *   dispel evil), and can also be used for bombardments.
511  *
512  * PROJECT_HIDE erases all graphical effects, making the projection invisible.
513  *
514  * PROJECT_GRID allows projections to affect terrain features.
515  *
516  * PROJECT_ITEM allows projections to affect objects on the ground.
517  *
518  * PROJECT_KILL allows projections to affect monsters.
519  *
520  * PROJECT_PLAY allows projections to affect the player.
521  *
522  * degrees_of_arc controls the width of arc spells.  With a value for
523  *   degrees_of_arc of zero, arcs act like beams of defined length.
524  *
525  * diameter_of_source controls how quickly explosions lose strength with dis-
526  *   tance from the target.  Most ball spells have a source diameter of 10,
527  *   which means that they do 1/2 damage at range 1, 1/3 damage at range 2,
528  *   and so on.   Caster-centered balls usually have a source diameter of 20,
529  *   which allows them to do full damage to all adjacent grids.   Arcs have
530  *   source diameters ranging up from 20, which allows the spell designer to
531  *   fine-tune how quickly a breath loses strength outwards from the breather.
532  *
533  *
534  * Implementation notes:
535  *
536  * If the source grid is not the same as the target, we project along the path
537  *   between them.  Bolts stop if they hit anything, beams stop if they hit a
538  *   wall, and balls and arcs may exhibit either bahavior.  When they reach
539  *   the final grid in the path, balls and arcs explode.  We do not allow
540  *   beams to be combined with explosions.
541  * Balls affect all floor grids in LOS (optionally, also wall grids adjacent
542  *   to a grid in LOS) within their radius.  Arcs do the same, but only within
543  *   their cone of projection.
544  * Because affected grids are only scanned once, and it is really helpful to
545  *   have explosions that travel outwards from the source, they are sorted by
546  *   distance.  For each distance, an adjusted damage is calculated.
547  * In successive passes, the code then displays explosion graphics, erases
548  *   these graphics, marks terrain for possible later changes, affects
549  *   objects, monsters, the character, and finally changes features and
550  *   teleports monsters and characters in marked grids.
551  *
552  *
553  * Usage and graphics notes:
554  *
555  * Only 256 grids can be affected per projection, limiting the effective
556  * radius of standard ball attacks to nine units (diameter nineteen).  Arcs
557  * can have larger radii; an arc capable of going out to range 20 should not
558  * be wider than 70 degrees.
559  *
560  * Balls must explode BEFORE hitting walls, or they would affect monsters on
561  * both sides of a wall.
562  *
563  * Note that for consistency, we pretend that the bolt actually takes time
564  * to move from point A to point B, even if the player cannot see part of the
565  * projection path.  Note that in general, the player will *always* see part
566  * of the path, since it either starts at the player or ends on the player.
567  *
568  * Hack -- we assume that every "projection" is "self-illuminating".
569  *
570  * Hack -- when only a single monster is affected, we automatically track
571  * (and recall) that monster, unless "PROJECT_JUMP" is used.
572  *
573  * Note that we must call "handle_stuff()" after affecting terrain features
574  * in the blast radius, in case the illumination of the grid was changed,
575  * and "update_view()" and "update_monsters()" need to be called.
576  */
project(struct source origin,int rad,struct loc finish,int dam,int typ,int flg,int degrees_of_arc,byte diameter_of_source,const struct object * obj)577 bool project(struct source origin, int rad, struct loc finish,
578 			 int dam, int typ, int flg,
579 			 int degrees_of_arc, byte diameter_of_source,
580 			 const struct object *obj)
581 {
582 	int i, j, k, dist_from_centre;
583 
584 	u32b dam_temp;
585 
586 	struct loc centre;
587 	struct loc start;
588 
589 	int n1y = 0;
590 	int n1x = 0;
591 
592 	/* Assume the player sees nothing */
593 	bool notice = false;
594 
595 	/* Notify the UI if it can draw this projection */
596 	bool drawing = false;
597 
598 	/* Is the player blind? */
599 	bool blind = (player->timed[TMD_BLIND] ? true : false);
600 
601 	/* Number of grids in the "path" */
602 	int num_path_grids = 0;
603 
604 	/* Actual grids in the "path" */
605 	struct loc path_grid[512];
606 
607 	/* Number of grids in the "blast area" (including the "beam" path) */
608 	int num_grids = 0;
609 
610 	/* Coordinates of the affected grids */
611 	struct loc blast_grid[256];
612 
613 	/* Distance to each of the affected grids. */
614 	int distance_to_grid[256];
615 
616 	/* Player visibility of each of the affected grids. */
617 	bool player_sees_grid[256];
618 
619 	/* Precalculated damage values for each distance. */
620 	int *dam_at_dist = malloc((z_info->max_range + 1) * sizeof(*dam_at_dist));
621 
622 	/* Flush any pending output */
623 	handle_stuff(player);
624 
625 	/* No projection path - jump to target */
626 	if (flg & PROJECT_JUMP) {
627 		start = finish;
628 
629 		/* Clear the flag */
630 		flg &= ~(PROJECT_JUMP);
631 	} else {
632 		start = origin_get_loc(origin);
633 
634 		/* Default to finish grid */
635 		if (start.y == -1 && start.x == -1) {
636 			start = finish;
637 		}
638 	}
639 
640 	/* Default center of explosion (if any) */
641 	centre = start;
642 
643 	/*
644 	 * An arc spell with no width and a non-zero radius is actually a
645 	 * beam of defined length.  Mark it as such.
646 	 */
647 	if ((flg & (PROJECT_ARC)) && (degrees_of_arc == 0) && (rad != 0)) {
648 		/* No longer an arc */
649 		flg &= ~(PROJECT_ARC);
650 
651 		/* Now considered a beam */
652 		flg |= (PROJECT_BEAM);
653 		flg |= (PROJECT_THRU);
654 	}
655 
656 	/*
657 	 * If a single grid is both start and finish (for example
658 	 * if PROJECT_JUMP is set), store it; otherwise, travel along the
659 	 * projection path.
660 	 */
661 	if (loc_eq(start, finish)) {
662 		blast_grid[num_grids] =  finish;
663 		centre = finish;
664 		distance_to_grid[num_grids] = 0;
665 		sqinfo_on(square(cave, finish)->info, SQUARE_PROJECT);
666 		num_grids++;
667 	} else {
668 		/* Start from caster */
669 		int y = start.y;
670 		int x = start.x;
671 
672 		/* Calculate the projection path */
673 		num_path_grids = project_path(path_grid, z_info->max_range, start,
674 									  finish, flg);
675 
676 		/* Some beams have limited length. */
677 		if (flg & (PROJECT_BEAM)) {
678 			/* Use length limit, if any is given. */
679 			if ((rad > 0) && (rad < num_path_grids)) {
680 				num_path_grids = rad;
681 			}
682 		}
683 
684 
685 		/* Project along the path (except for arcs) */
686 		if (!(flg & (PROJECT_ARC))) {
687 			for (i = 0; i < num_path_grids; ++i) {
688 				int oy = y;
689 				int ox = x;
690 
691 				int ny = path_grid[i].y;
692 				int nx = path_grid[i].x;
693 
694 				/* Hack -- Balls explode before reaching walls. */
695 				if (!square_ispassable(cave, path_grid[i]) && (rad > 0) &&
696 					!(flg & (PROJECT_BEAM)))
697 					break;
698 
699 				/* Advance */
700 				y = ny;
701 				x = nx;
702 
703 				/* Beams collect all grids in the path, all other methods
704 				 * collect only the final grid in the path. */
705 				if (flg & (PROJECT_BEAM)) {
706 					blast_grid[num_grids].y = y;
707 					blast_grid[num_grids].x = x;
708 					distance_to_grid[num_grids] = 0;
709 					sqinfo_on(square(cave, loc(x, y))->info, SQUARE_PROJECT);
710 					num_grids++;
711 				} else if (i == num_path_grids - 1) {
712 					blast_grid[num_grids].y = y;
713 					blast_grid[num_grids].x = x;
714 					distance_to_grid[num_grids] = 0;
715 					sqinfo_on(square(cave, loc(x, y))->info, SQUARE_PROJECT);
716 					num_grids++;
717 				}
718 
719 				/* Only do visuals if requested and within range limit. */
720 				if (!blind && !(flg & (PROJECT_HIDE))) {
721 					bool seen = square_isview(cave, loc(x, y));
722 					bool beam = flg & (PROJECT_BEAM);
723 
724 					/* Tell the UI to display the bolt */
725 					event_signal_bolt(EVENT_BOLT, typ, drawing, seen, beam, oy,
726 									  ox, y, x);
727 				}
728 			}
729 		}
730 
731 		/* Save the "blast epicenter" */
732 		centre.y = y;
733 		centre.x = x;
734 	}
735 
736 	/* Now check for explosions.  Beams have already stored all the grids they
737 	 * will affect; all non-beam projections with positive radius explode in
738 	 * some way */
739 	if ((rad > 0) && (!(flg & (PROJECT_BEAM)))) {
740 		int y, x;
741 
742 		/* Pre-calculate some things for arcs. */
743 		if ((flg & (PROJECT_ARC)) && (num_path_grids != 0)) {
744 			/* Explosion centers on the caster. */
745 			centre = start;
746 
747 			/* The radius of arcs cannot be more than 20 */
748 			if (rad > 20)
749 				rad = 20;
750 
751 			/* Ensure legal access into get_angle_to_grid table */
752 			if (num_path_grids < 21)
753 				i = num_path_grids - 1;
754 			else
755 				i = 20;
756 
757 			/* Reorient the grid forming the end of the arc's centerline. */
758 			n1y = path_grid[i].y - centre.y + 20;
759 			n1x = path_grid[i].x - centre.x + 20;
760 		}
761 
762 		/* If the explosion centre hasn't been saved already, save it now. */
763 		if (num_grids == 0) {
764 			blast_grid[num_grids] = centre;
765 			distance_to_grid[num_grids] = 0;
766 			sqinfo_on(square(cave, centre)->info, SQUARE_PROJECT);
767 			num_grids++;
768 		}
769 
770 		/* Scan every grid that might possibly be in the blast radius. */
771 		for (y = centre.y - rad; y <= centre.y + rad; y++) {
772 			for (x = centre.x - rad; x <= centre.x + rad; x++) {
773 				struct loc grid = loc(x, y);
774 				bool on_path = false;
775 
776 				/* Center grid has already been stored. */
777 				if (loc_eq(grid, centre))
778 					continue;
779 
780 				/* Precaution: Stay within area limit. */
781 				if (num_grids >= 255)
782 					break;
783 
784 				/* Ignore "illegal" locations */
785 				if (!square_in_bounds(cave, grid))
786 					continue;
787 
788 				/* Most explosions are immediately stopped by walls. If
789 				 * PROJECT_THRU is set, walls can be affected if adjacent to
790 				 * a grid visible from the explosion centre - note that as of
791 				 * Angband 3.5.0 there are no such explosions - NRM.
792 				 * All explosions can affect one layer of terrain which is
793 				 * passable but not projectable */
794 				if ((flg & (PROJECT_THRU)) || square_ispassable(cave, grid)) {
795 					/* If this is a wall grid, ... */
796 					if (!square_isprojectable(cave, grid)) {
797 						bool can_see_one = false;
798 						/* Check neighbors */
799 						for (i = 0; i < 8; i++) {
800 							struct loc adj_grid = loc_sum(grid, ddgrid_ddd[i]);
801 							if (los(cave, centre, adj_grid)) {
802 								can_see_one = true;
803 								break;
804 							}
805 						}
806 
807 						/* Require at least one adjacent grid in LOS. */
808 						if (!can_see_one)
809 							continue;
810 					}
811 				} else if (!square_isprojectable(cave, grid))
812 					continue;
813 
814 				/* Must be within maximum distance. */
815 				dist_from_centre  = (distance(centre, grid));
816 				if (dist_from_centre > rad)
817 					continue;
818 
819 				/* Mark grids which are on the projection path */
820 				for (i = 0; i < num_path_grids; i++) {
821 					if (loc_eq(grid, path_grid[i])) {
822 						on_path = true;
823 					}
824 				}
825 
826 				/* Do we need to consider a restricted angle? */
827 				if (flg & (PROJECT_ARC)) {
828 					/* Use angle comparison to delineate an arc. */
829 					int n2y, n2x, tmp, rotate, diff;
830 
831 					/* Reorient current grid for table access. */
832 					n2y = y - start.y + 20;
833 					n2x = x - start.x + 20;
834 
835 					/* Find the angular difference (/2) between the lines to
836 					 * the end of the arc's center-line and to the current grid.
837 					 */
838 					rotate = 90 - get_angle_to_grid[n1y][n1x];
839 					tmp = ABS(get_angle_to_grid[n2y][n2x] + rotate) % 180;
840 					diff = ABS(90 - tmp);
841 
842 					/* If difference is greater then that allowed, skip it,
843 					 * unless it's on the target path */
844 					if ((diff >= (degrees_of_arc + 6) / 4) && !on_path)
845 						continue;
846 				}
847 
848 				/* Accept remaining grids if in LOS or on the projection path */
849 				if (los(cave, centre, grid) || on_path) {
850 					blast_grid[num_grids].y = y;
851 					blast_grid[num_grids].x = x;
852 					distance_to_grid[num_grids] = dist_from_centre;
853 					sqinfo_on(square(cave, grid)->info, SQUARE_PROJECT);
854 					num_grids++;
855 				}
856 			}
857 		}
858 	}
859 
860 	/* Calculate and store the actual damage at each distance. */
861 	for (i = 0; i <= z_info->max_range; i++) {
862 		if (i > rad) {
863 			/* No damage outside the radius. */
864 			dam_temp = 0;
865 		} else if ((!diameter_of_source) || (i == 0)) {
866 			/* Standard damage calc. for 10' source diameters, or at origin. */
867 			dam_temp = (dam + i) / (i + 1);
868 		} else {
869 			/* If a particular diameter for the source of the explosion's
870 			 * energy is given, it is full strength to that diameter and
871 			 * then reduces */
872 			dam_temp = (diameter_of_source * dam) / (i + 1);
873 			if (dam_temp > (u32b) dam) {
874 				dam_temp = dam;
875 			}
876 		}
877 
878 		/* Store it. */
879 		dam_at_dist[i] = dam_temp;
880 	}
881 
882 
883 	/* Sort the blast grids by distance from the centre. */
884 	for (i = 0, k = 0; i <= rad; i++) {
885 		/* Collect all the grids of a given distance together. */
886 		for (j = k; j < num_grids; j++) {
887 			if (distance_to_grid[j] == i) {
888 				struct loc tmp;
889 				int tmp_d = distance_to_grid[k];
890 				tmp = blast_grid[k];
891 
892 				blast_grid[k] = blast_grid[j];
893 				distance_to_grid[k] = distance_to_grid[j];
894 
895 				blast_grid[j] = tmp;
896 				distance_to_grid[j] = tmp_d;
897 
898 				/* Write to next slot */
899 				k++;
900 			}
901 		}
902 	}
903 
904 	/* Establish which grids are visible - no blast visuals with PROJECT_HIDE */
905 	for (i = 0; i < num_grids; i++) {
906 		if (panel_contains(blast_grid[i].y, blast_grid[i].x) &&
907 			square_isview(cave, blast_grid[i]) &&
908 			!blind && !(flg & (PROJECT_HIDE))) {
909 			player_sees_grid[i] = true;
910 		} else {
911 			player_sees_grid[i] = false;
912 		}
913 	}
914 
915 	/* Tell the UI to display the blast */
916 	event_signal_blast(EVENT_EXPLOSION, typ, num_grids, distance_to_grid,
917 					   drawing, player_sees_grid, blast_grid, centre);
918 
919 	/* Affect objects on every relevant grid */
920 	if (flg & (PROJECT_ITEM)) {
921 		for (i = 0; i < num_grids; i++) {
922 			if (project_o(origin, distance_to_grid[i], blast_grid[i],
923 						  dam_at_dist[distance_to_grid[i]], typ, obj)) {
924 				notice = true;
925 			}
926 		}
927 	}
928 
929 	/* Check monsters */
930 	if (flg & (PROJECT_KILL)) {
931 		bool was_obvious = false;
932 		bool did_hit = false;
933 		int num_hit = 0;
934 		struct loc last_hit_grid = loc(0, 0);
935 
936 		/* Scan for monsters */
937 		for (i = 0; i < num_grids; i++) {
938 			struct monster *mon = NULL;
939 
940 			/* Check this monster hasn't been processed already */
941 			if (!square_isproject(cave, blast_grid[i]))
942 				continue;
943 
944 			/* Check there is actually a monster here */
945 			mon = square_monster(cave, blast_grid[i]);
946 			if (mon == NULL)
947 				continue;
948 
949 			/* Affect the monster in the grid */
950 			project_m(origin, distance_to_grid[i], blast_grid[i],
951 			          dam_at_dist[distance_to_grid[i]], typ, flg,
952 			          &did_hit, &was_obvious);
953 			if (was_obvious) {
954 				notice = true;
955 			}
956 			if (did_hit) {
957 				num_hit++;
958 
959 				/* Monster location may have been updated by project_m() */
960 				last_hit_grid = mon->grid;
961 			}
962 		}
963 
964 		/* Player affected one monster (without "jumping") */
965 		if (origin.what == SRC_PLAYER &&
966 				num_hit == 1 &&
967 				!(flg & PROJECT_JUMP)) {
968 			/* Location */
969 			int x = last_hit_grid.x;
970 			int y = last_hit_grid.y;
971 
972 			/* Track if possible */
973 			if (square(cave, loc(x, y))->mon > 0) {
974 				struct monster *mon = square_monster(cave, loc(x, y));
975 
976 				/* Recall and track */
977 				if (monster_is_visible(mon)) {
978 					monster_race_track(player->upkeep, mon->race);
979 					health_track(player->upkeep, mon);
980 				}
981 			}
982 		}
983 	}
984 
985 	/* Look for the player, affect them when found */
986 	if (flg & (PROJECT_PLAY)) {
987 		/* Set power */
988 		int power = 0;
989 		if (origin.what == SRC_MONSTER) {
990 			struct monster *mon = cave_monster(cave, origin.which.monster);
991 			power = mon->race->spell_power;
992 
993 			/* Breaths from powerful monsters get power effects as well */
994 			if (monster_is_powerful(mon))
995 				power = MAX(power, 80);
996 		}
997 		for (i = 0; i < num_grids; i++) {
998 			if (project_p(origin, distance_to_grid[i], blast_grid[i],
999 						  dam_at_dist[distance_to_grid[i]], typ, power,
1000 						  flg & PROJECT_SELF)) {
1001 				notice = true;
1002 				if (player->is_dead) {
1003 					free(dam_at_dist);
1004 					return notice;
1005 				}
1006 				break;
1007 			}
1008 		}
1009 	}
1010 
1011 	/* Affect features in every relevant grid */
1012 	if (flg & (PROJECT_GRID)) {
1013 		for (i = 0; i < num_grids; i++) {
1014 			if (project_f(origin, distance_to_grid[i], blast_grid[i],
1015 						  dam_at_dist[distance_to_grid[i]], typ)) {
1016 				notice = true;
1017 			}
1018 		}
1019 	}
1020 
1021 	/* Clear all the processing marks. */
1022 	for (i = 0; i < num_grids; i++) {
1023 		/* Clear the mark */
1024 		sqinfo_off(square(cave, blast_grid[i])->info, SQUARE_PROJECT);
1025 	}
1026 
1027 	/* Update stuff if needed */
1028 	if (player->upkeep->update) update_stuff(player);
1029 
1030 	free(dam_at_dist);
1031 
1032 	/* Return "something was noticed" */
1033 	return (notice);
1034 }
1035