Data Structures | Macros | Functions | Variables
project.c File Reference

The project() function and helpers. More...

#include "angband.h"
#include "cave.h"
#include "game-event.h"
#include "game-input.h"
#include "generate.h"
#include "init.h"
#include "mon-util.h"
#include "player-timed.h"
#include "project.h"
#include "list-elements.h"
#include "list-project-environs.h"
#include "list-project-monsters.h"

Data Structures

struct  gf_type
GF type info needed for projections More...


#define ELEM(a, b, c, d, e, f, g, col)   { c, d, e, FALSE, col },
#define RV(b, x, y, m)   {b, x, y, m}
#define PROJ_ENV(a, col)   { NULL, 0, {0, 0, 0, 0}, FALSE, col },
#define PROJ_MON(a, obv)   { NULL, 0, {0, 0, 0, 0}, obv, COLOUR_WHITE },
#define ELEM(a, b, c, d, e, f, g, col)   #a,
#define PROJ_ENV(a, col)   #a,
#define PROJ_MON(a, obv)   #a,


int project_path (struct loc *gp, int range, int y1, int x1, int y2, int x2, int flg)
 Determine the path taken by a projection.
bool projectable (struct chunk *c, int y1, int x1, int y2, int x2, int flg)
 Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive at the final destination, assuming that no monster gets in the way, using the project_path() function to check the projection path.
bool gf_force_obvious (int type)
int gf_color (int type)
int gf_num (int type)
random_value gf_denom (int type)
const char * gf_desc (int type)
int gf_name_to_idx (const char *name)
const char * gf_idx_to_name (int type)
bool project (int who, int rad, int y, int x, int dam, int typ, int flg, int degrees_of_arc, byte diameter_of_source)

The main project() function and its helpers


byte gf_to_attr [GF_MAX][BOLT_MAX]
wchar_t gf_to_char [GF_MAX][BOLT_MAX]
static struct gf_type gf_table []
static const char * gf_name_list []

Detailed Description

The project() function and helpers.

Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke

This work is free software; you can redistribute it and/or modify it under the terms of either:

a) the GNU General Public License as published by the Free Software Foundation, version 2, or

b) the "Angband licence": This software may be copied and distributed for educational, research, and not for profit purposes provided that this copyright and statement are included in all such copies. Other copyrights may also apply.

Macro Definition Documentation

#define ELEM (   a,
)    { c, d, e, FALSE, col },
#define ELEM (   a,
)    #a,
#define PROJ_ENV (   a,
)    { NULL, 0, {0, 0, 0, 0}, FALSE, col },
#define PROJ_ENV (   a,
)    #a,
#define PROJ_MON (   a,
)    { NULL, 0, {0, 0, 0, 0}, obv, COLOUR_WHITE },
#define PROJ_MON (   a,
)    #a,
#define RV (   b,
)    {b, x, y, m}

Function Documentation

int gf_color ( int  type)

References gf_type::color, COLOUR_WHITE, GF_MAX, gf_table, and type.

Referenced by bolt_pict(), and gf_display().

random_value gf_denom ( int  type)

References gf_type::denom, GF_MAX, gf_table, and type.

Referenced by adjust_dam().

const char* gf_desc ( int  type)

References gf_type::desc, GF_MAX, gf_table, and type.

Referenced by project_p().

bool gf_force_obvious ( int  type)

References FALSE, gf_type::force_obvious, GF_MAX, gf_table, and type.

Referenced by project_m().

const char* gf_idx_to_name ( int  type)

References GF_MAX, gf_name_list, and type.

Referenced by gf_display().

int gf_name_to_idx ( const char *  name)

References gf_name_list, i, and my_stricmp().

Referenced by effect_param(), and parse_prefs_gf().

int gf_num ( int  type)

References GF_MAX, gf_table, gf_type::num, and type.

Referenced by adjust_dam().

bool project ( int  who,
int  rad,
int  y,
int  x,
int  dam,
int  typ,
int  flg,
int  degrees_of_arc,
byte  diameter_of_source 

The main project() function and its helpers

Generic "beam"/"bolt"/"ball" projection routine. -BEN-, some changes by -LM-

who,:Index of "source" monster (negative for the character)
rad,:Radius of explosion (0 = beam/bolt, 1 to 20 = ball), or maximum length of arc from the source.
x,:Target location (or location to travel towards)
dam,:Base damage to apply to monsters, terrain, objects, or player
typ,:Type of projection (fire, frost, dispel demons etc.)
flg,:Extra bit flags that control projection behavior
degrees_of_arc,:How wide an arc spell is (in degrees).
diameter_of_source,:how wide the source diameter is.
TRUE if any effects of the projection were observed, else FALSE

At present, there are five major types of projections:

Point-effect projection: (no PROJECT_BEAM flag, radius of zero, and either jumps directly to target or has a single source and target grid) A point-effect projection has no line of projection, and only affects one grid. It is used for most area-effect spells (like dispel evil) and pinpoint strikes like the monster Holding prayer.

Bolt: (no PROJECT_BEAM flag, radius of zero, has to travel from source to target) A bolt travels from source to target and affects only the final grid in its projection path. If given the PROJECT_STOP flag, it is stopped by any monster or character in its path (at present, all bolts use this flag).

Beam: (PROJECT_BEAM) A beam travels from source to target, affecting all grids passed through with full damage. It is never stopped by monsters in its path. Beams may never be combined with any other projection type.

Ball: (positive radius, unless the PROJECT_ARC flag is set) A ball travels from source towards the target, and always explodes. Unless specified, it does not affect wall grids, but otherwise affects any grids in LOS from the center of the explosion. If used with a direction, a ball will explode on the first occupied grid in its path. If given a target, it will explode on that target. If a wall is in the way, it will explode against the wall. If a ball reaches z_info->max_range without hitting anything or reaching its target, it will explode at that point.

Arc: (positive radius, with the PROJECT_ARC flag set) An arc is a portion of a source-centered ball that explodes outwards towards the target grid. Like a ball, it affects all non-wall grids in LOS of the source in the explosion area. The width of arc spells is con- trolled by degrees_of_arc. An arc is created by rejecting all grids that form the endpoints of lines whose angular difference (in degrees) from the centerline of the arc is greater than one-half the input "degrees_of_arc". See the table "get_ angle_to_grid" in "util.c" for more information. Note: An arc with a value for degrees_of_arc of zero is actually a beam of defined length.

Projections that effect all monsters in LOS are handled through the use of the PROJECT_LOS effect, which applies a single-grid projection to individual monsters. Projections that light up rooms or affect all monsters on the level are more efficiently handled through special functions.


PROJECT_STOP forces a path of projection to stop at the first occupied grid it hits. This is used with bolts, and also by ball spells travelling in a specific direction rather than towards a target.

PROJECT_THRU allows a path of projection towards a target to continue past that target. It also allows a spell to affect wall grids adjacent to a grid in LOS of the center of the explosion.

PROJECT_JUMP allows a projection to immediately set the source of the pro- jection to the target. This is used for all area effect spells (like dispel evil), and can also be used for bombardments.

PROJECT_HIDE erases all graphical effects, making the projection invisible.

PROJECT_GRID allows projections to affect terrain features.

PROJECT_ITEM allows projections to affect objects on the ground.

PROJECT_KILL allows projections to affect monsters.

PROJECT_PLAY allows projections to affect the player.

degrees_of_arc controls the width of arc spells. With a value for degrees_of_arc of zero, arcs act like beams of defined length.

diameter_of_source controls how quickly explosions lose strength with dis- tance from the target. Most ball spells have a source diameter of 10, which means that they do 1/2 damage at range 1, 1/3 damage at range 2, and so on. Caster-centered balls usually have a source diameter of 20, which allows them to do full damage to all adjacent grids. Arcs have source diameters ranging up to 20, which allows the spell designer to fine-tune how quickly a breath loses strength outwards from the breather. It is expected, but not required, that wide arcs lose strength more quickly over distance.

Implementation notes:

If the source grid is not the same as the target, we project along the path between them. Bolts stop if they hit anything, beams stop if they hit a wall, and balls and arcs may exhibit either bahavior. When they reach the final grid in the path, balls and arcs explode. We do not allow beams to be combined with explosions. Balls affect all floor grids in LOS (optionally, also wall grids adjacent to a grid in LOS) within their radius. Arcs do the same, but only within their cone of projection. Because affected grids are only scanned once, and it is really helpful to have explosions that travel outwards from the source, they are sorted by distance. For each distance, an adjusted damage is calculated. In successive passes, the code then displays explosion graphics, erases these graphics, marks terrain for possible later changes, affects objects, monsters, the character, and finally changes features and teleports monsters and characters in marked grids.

Usage and graphics notes:

Only 256 grids can be affected per projection, limiting the effective radius of standard ball attacks to nine units (diameter nineteen). Arcs can have larger radii; an arc capable of going out to range 20 should not be wider than 70 degrees.

Balls must explode BEFORE hitting walls, or they would affect monsters on both sides of a wall.

Note that for consistency, we pretend that the bolt actually takes time to move from point A to point B, even if the player cannot see part of the projection path. Note that in general, the player will always see part of the path, since it either starts at the player or ends on the player.

Hack – we assume that every "projection" is "self-illuminating".

Hack – when only a single monster is affected, we automatically track (and recall) that monster, unless "PROJECT_JUMP" is used.

Note that we must call "handle_stuff()" after affecting terrain features in the blast radius, in case the illumination of the grid was changed, and "update_view()" and "update_monsters()" need to be called.

References ABS, cave, cave_monster(), ddx_ddd, ddy_ddd, distance(), EVENT_BOLT, EVENT_EXPLOSION, event_signal_blast(), event_signal_bolt(), FALSE, get_angle_to_grid, handle_stuff(), health_track(), i, square::info, loc(), los(), angband_constants::max_range, monster::mflag, mflag_has, square::mon, monster_race_track(), ox, oy, panel_contains(), player_has_los_bold(), PROJECT_ARC, PROJECT_BEAM, project_f(), PROJECT_GRID, PROJECT_HIDE, PROJECT_ITEM, PROJECT_JUMP, PROJECT_KILL, project_m(), project_m_n, project_m_x, project_m_y, project_o(), project_p(), project_path(), PROJECT_PLAY, PROJECT_THRU, player::px, player::py, monster::race, sqinfo_off, sqinfo_on, square_in_bounds(), square_ispassable(), square_isproject(), square_isprojectable(), square_monster(), chunk::squares, player::timed, TRUE, player_upkeep::update, update_stuff(), player::upkeep, loc::x, loc::y, and z_info.

Referenced by effect_handler_BALL(), effect_handler_BIZARRE(), effect_handler_BREATH(), effect_handler_DARKEN_AREA(), effect_handler_LIGHT_AREA(), effect_handler_PROJECT_LOS(), effect_handler_STAR(), effect_handler_STAR_BALL(), effect_handler_SWARM(), project_aimed(), and project_touch().

int project_path ( struct loc gp,
int  range,
int  y1,
int  x1,
int  y2,
int  x2,
int  flg 

Determine the path taken by a projection.

The projection will always start from the grid (y1,x1), and will travel towards the grid (y2,x2), touching one grid per unit of distance along the major axis, and stopping when it enters the destination grid or a wall grid, or has travelled the maximum legal distance of "range".

Note that "distance" in this function (as in the "update_view()" code) is defined as "MAX(dy,dx) + MIN(dy,dx)/2", which means that the player actually has an "octagon of projection" not a "circle of projection".

The path grids are saved into the grid array pointed to by "gp", and there should be room for at least "range" grids in "gp". Note that due to the way in which distance is calculated, this function normally uses fewer than "range" grids for the projection path, so the result of this function should never be compared directly to "range". Note that the initial grid (y1,x1) is never saved into the grid array, not even if the initial grid is also the final grid. XXX XXX XXX

The "flg" flags can be used to modify the behavior of this function.

In particular, the "PROJECT_STOP" and "PROJECT_THRU" flags have the same semantics as they do for the "project" function, namely, that the path will stop as soon as it hits a monster, or that the path will continue through the destination grid, respectively.

The "PROJECT_JUMP" flag, which for the "project()" function means to start at a special grid (which makes no sense in this function), means that the path should be "angled" slightly if needed to avoid any wall grids, allowing the player to "target" any grid which is in "view". This flag is non-trivial and has not yet been implemented, but could perhaps make use of the "vinfo" array (above). XXX XXX XXX

This function returns the number of grids (if any) in the path. This function will return zero if and only if (y1,x1) and (y2,x2) are equal.

This algorithm is similar to, but slightly different from, the one used by "update_view_los()", and very different from the one used by "los()".

References cave, loc(), square::mon, PROJECT_STOP, PROJECT_THRU, square_isprojectable(), and chunk::squares.

Referenced by project(), projectable(), ranged_helper(), and target_set_interactive().

bool projectable ( struct chunk c,
int  y1,
int  x1,
int  y2,
int  x2,
int  flg 

Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive at the final destination, assuming that no monster gets in the way, using the project_path() function to check the projection path.

Note that no grid is ever projectable() from itself.

This function is used to determine if the player can (easily) target a given grid, and if a monster can target the player.

References FALSE, angband_constants::max_range, project_path(), square_ispassable(), TRUE, loc::x, loc::y, and z_info.

Referenced by find_hiding(), make_attack_spell(), monster_list_collect(), near_permwall(), and target_able().

Variable Documentation

const char* gf_name_list[]

Referenced by gf_idx_to_name(), and gf_name_to_idx().

struct gf_type gf_table[]
byte gf_to_attr[GF_MAX][BOLT_MAX]
wchar_t gf_to_char[GF_MAX][BOLT_MAX]