Angband
Functions | Variables
mon-move.c File Reference

Monster movement. More...

#include "angband.h"
#include "cave.h"
#include "game-world.h"
#include "init.h"
#include "monster.h"
#include "mon-attack.h"
#include "mon-desc.h"
#include "mon-lore.h"
#include "mon-make.h"
#include "mon-spell.h"
#include "mon-util.h"
#include "mon-timed.h"
#include "obj-desc.h"
#include "obj-ignore.h"
#include "obj-pile.h"
#include "obj-slays.h"
#include "obj-tval.h"
#include "obj-util.h"
#include "player-calcs.h"
#include "player-util.h"
#include "project.h"
#include "trap.h"

Functions

static void find_range (struct monster *mon)
 Calculate minimum and desired combat ranges. More...
 
bool multiply_monster (const struct monster *mon)
 Lets the given monster attempt to reproduce. More...
 
static bool near_permwall (const struct monster *mon, struct chunk *c)
 
static bool get_moves_flow (struct chunk *c, struct monster *mon)
 Choose the best direction for "flowing". More...
 
static bool get_moves_fear (struct chunk *c, struct monster *mon)
 Provide a location to flee to, but give the player a wide berth. More...
 
static bool find_safety (struct chunk *c, struct monster *mon)
 Choose a "safe" location near a monster for it to run toward. More...
 
static bool find_hiding (struct chunk *c, struct monster *mon)
 Choose a good hiding place near a monster for it to run toward. More...
 
static int choose_direction (int dy, int dx)
 Choose the basic direction of movement, and whether to bias left or right if the main direction is blocked. More...
 
static bool get_moves (struct chunk *c, struct monster *mon, int *dir)
 Choose "logical" directions for monster movement. More...
 
static bool monster_can_flow (struct chunk *c, struct monster *mon)
 
static bool monster_check_active (struct chunk *c, struct monster *mon)
 Determine whether a monster is active or passive. More...
 
static bool process_monster_timed (struct chunk *c, struct monster *mon)
 Process a monster's timed effects, e.g. More...
 
static bool process_monster_multiply (struct chunk *c, struct monster *mon)
 Attempt to reproduce, if possible. More...
 
static bool process_monster_should_stagger (struct monster *mon)
 Check if a monster should stagger or not. More...
 
static bool process_monster_can_move (struct chunk *c, struct monster *mon, const char *m_name, int nx, int ny, bool *did_something)
 Work out if a monster can move through the grid, if necessary bashing down doors in the way. More...
 
static bool process_monster_glyph (struct chunk *c, struct monster *mon, int nx, int ny)
 Try to break a glyph. More...
 
static int compare_monsters (const struct monster *mon1, const struct monster *mon2)
 Compare the "strength" of two monsters XXX XXX XXX. More...
 
static bool process_monster_try_push (struct chunk *c, struct monster *mon, const char *m_name, int nx, int ny)
 Try to push past / kill another monster. More...
 
void process_monster_grab_objects (struct chunk *c, struct monster *mon, const char *m_name, int nx, int ny)
 Grab all objects from the grid. More...
 
static void process_monster (struct chunk *c, struct monster *mon)
 Process a monster. More...
 
static void regen_monster (struct monster *mon)
 Monster regeneration of HPs. More...
 
void process_monsters (struct chunk *c, int minimum_energy)
 Process all the "live" monsters, once per game turn. More...
 
void reset_monsters (void)
 Clear 'moved' status from all monsters. More...
 

Variables

static byte side_dirs [20][8]
 Given a central direction at position [dir #][0], return a series of directions radiating out on both sides from the central direction all the way back to its rear. More...
 
static const int d_off_y_0 []
 
static const int d_off_x_0 []
 
static const int d_off_y_1 []
 
static const int d_off_x_1 []
 
static const int d_off_y_2 []
 
static const int d_off_x_2 []
 
static const int d_off_y_3 []
 
static const int d_off_x_3 []
 
static const int d_off_y_4 []
 
static const int d_off_x_4 []
 
static const int d_off_y_5 []
 
static const int d_off_x_5 []
 
static const int d_off_y_6 []
 
static const int d_off_x_6 []
 
static const int d_off_y_7 []
 
static const int d_off_x_7 []
 
static const int d_off_y_8 []
 
static const int d_off_x_8 []
 
static const int d_off_y_9 []
 
static const int d_off_x_9 []
 
static const intdist_offsets_y [10]
 
static const intdist_offsets_x [10]
 

Detailed Description

Monster movement.

Monster AI affecting movement and spells, process a monster (with spells and actions of all kinds, reproduction, effects of any terrain on monster movement, picking up and destroying objects), process all monsters.

Copyright (c) 1997 Ben Harrison, David Reeve Sward, Keldon Jones.

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.

Function Documentation

static int choose_direction ( int  dy,
int  dx 
)
static

Choose the basic direction of movement, and whether to bias left or right if the main direction is blocked.

Note that this direction is intended as an index into the side_dirs array.

References ABS, and turn.

Referenced by get_moves().

static int compare_monsters ( const struct monster mon1,
const struct monster mon2 
)
static

Compare the "strength" of two monsters XXX XXX XXX.

References monster_race::mexp, and monster::race.

Referenced by process_monster_try_push().

static bool find_hiding ( struct chunk c,
struct monster mon 
)
static

Choose a good hiding place near a monster for it to run toward.

Pack monsters will use this to "ambush" the player and lure him out of corridors into open space so they can swarm him.

Return true if a good location is available.

References dist_offsets_x, dist_offsets_y, distance(), monster::fx, monster::fy, i, PROJECT_STOP, projectable(), player::px, player::py, square_in_bounds_fully(), square_isempty(), square_isview(), monster::tx, and monster::ty.

Referenced by get_moves().

static void find_range ( struct monster mon)
static
static bool find_safety ( struct chunk c,
struct monster mon 
)
static

Choose a "safe" location near a monster for it to run toward.

A location is "safe" if it can be reached quickly and the player is not able to fire into it (it isn't a "clean shot"). So, this will cause monsters to "duck" behind walls. Hopefully, monsters will also try to run towards corridor openings if they are in a room.

This function may take lots of CPU time if lots of monsters are fleeing.

Return true if a safe location is available.

References dist_offsets_x, dist_offsets_y, distance(), monster_race::flags, monster::fx, monster::fy, i, square::noise, player::px, player::py, monster::race, rf_has, square::scent, square_in_bounds_fully(), square_isfiery(), square_ispassable(), square_isview(), chunk::squares, monster::tx, and monster::ty.

Referenced by get_moves().

static bool get_moves ( struct chunk c,
struct monster mon,
int dir 
)
static
static bool get_moves_fear ( struct chunk c,
struct monster mon 
)
static

Provide a location to flee to, but give the player a wide berth.

A monster may wish to flee to a location that is behind the player, but instead of heading directly for it, the monster should "swerve" around the player so that it has a smaller chance of getting hit.

References monster_race::aaf, ddx_ddd, ddy_ddd, distance(), monster::fx, monster::fy, i, angband_constants::max_flow_depth, square::noise, player::px, player::py, monster::race, square::scent, square_in_bounds(), chunk::squares, monster::tx, monster::ty, and z_info.

Referenced by get_moves().

static bool get_moves_flow ( struct chunk c,
struct monster mon 
)
static

Choose the best direction for "flowing".

Note that ghosts and rock-eaters generally don't flow because they can move through obstacles.

Monsters first try to use up-to-date distance information ('sound') as saved in cave->squares[y][x].noise. Failing that, they'll try using scent ('scent') which is just old noise information.

Tracking by 'scent' means that monsters end up near enough the player to switch to 'sound' (noise), or they end up somewhere the player left via teleport. Teleporting away from a location will cause the monsters who were chasing the player to converge on that location as long as the player is still near enough to "annoy" them without being close enough to chase directly.

References monster_race::aaf, ddx_ddd, ddy_ddd, FLAG_END, monster_race::flags, flags_test(), monster::fx, monster::fy, i, angband_constants::max_flow_depth, near_permwall(), square::noise, player::px, player::py, monster::race, rf_has, RF_SIZE, square::scent, square_in_bounds(), square_isfiery(), square_isview(), chunk::squares, monster::tx, monster::ty, and z_info.

Referenced by get_moves().

static bool monster_can_flow ( struct chunk c,
struct monster mon 
)
static
static bool monster_check_active ( struct chunk c,
struct monster mon 
)
static
bool multiply_monster ( const struct monster mon)

Lets the given monster attempt to reproduce.

Note that "reproduction" REQUIRES empty space.

Returns true if the monster successfully reproduced.

References cave, monster::fx, monster::fy, i, place_new_monster(), monster::race, scatter(), and square_isempty().

Referenced by process_monster_multiply(), and project_monster_handler_MON_CLONE().

static bool near_permwall ( const struct monster mon,
struct chunk c 
)
static
static void process_monster ( struct chunk c,
struct monster mon 
)
static

Process a monster.

In several cases, we directly update the monster lore

Note that a monster is only allowed to "reproduce" if there are a limited number of "reproducing" monsters on the current level. This should prevent the level from being "swamped" by reproducing monsters. It also allows a large mass of mice to prevent a louse from multiplying, but this is a small price to pay for a simple multiplication method.

XXX Monster fear is slightly odd, in particular, monsters will fixate on opening a door even if they cannot open it. Actually, the same thing happens to normal monsters when they hit a door

In addition, monsters which cannot open or bash down a door will still stand there trying to open it... XXX XXX XXX

Technically, need to check for monster in the way combined with that monster being in a wall (or door?) XXX

References become_aware(), ddd, ddx, ddy, disturb(), monster_lore::flags, monster_race::flags, monster::fx, monster::fy, get_lore(), get_moves(), i, monster::m_timed, make_attack_normal(), make_attack_spell(), MDESC_CAPITAL, MDESC_IND_HID, monster::mflag, mflag_has, mon_clear_timed(), MON_TMD_FLG_NOTIFY, monster_desc(), monster_swap(), OPT, ox, oy, process_monster_can_move(), process_monster_glyph(), process_monster_grab_objects(), process_monster_multiply(), process_monster_should_stagger(), process_monster_try_push(), monster::race, randint0, rf_has, rf_on, side_dirs, square_isplayer(), square_iswarded(), and square_monster().

Referenced by process_monsters().

static bool process_monster_can_move ( struct chunk c,
struct monster mon,
const char *  m_name,
int  nx,
int  ny,
bool *  did_something 
)
static
static bool process_monster_glyph ( struct chunk c,
struct monster mon,
int  nx,
int  ny 
)
static
void process_monster_grab_objects ( struct chunk c,
struct monster mon,
const char *  m_name,
int  nx,
int  ny 
)
static bool process_monster_multiply ( struct chunk c,
struct monster mon 
)
static
static bool process_monster_should_stagger ( struct monster mon)
static

Check if a monster should stagger or not.

Always stagger when confused, but also deal with random movement for RAND_25 and _50 monsters.

References CONF_ERRATIC_CHANCE, monster_lore::flags, monster_race::flags, get_lore(), monster::m_timed, monster::mflag, mflag_has, monster::race, randint0, rf_has, and rf_on.

Referenced by process_monster().

static bool process_monster_timed ( struct chunk c,
struct monster mon 
)
static
static bool process_monster_try_push ( struct chunk c,
struct monster mon,
const char *  m_name,
int  nx,
int  ny 
)
static
void process_monsters ( struct chunk c,
int  minimum_energy 
)

Process all the "live" monsters, once per game turn.

During each game turn, we scan through the list of all the "live" monsters, (backwards, so we can excise any "freshly dead" monsters), energizing each monster, and allowing fully energized monsters to move, attack, pass, etc.

This function and its children are responsible for a considerable fraction of the processor time in normal situations, greater if the character is resting.

References cave_monster(), cave_monster_max(), monster::energy, player_upkeep::generate_level, i, player::is_dead, is_mimicking(), monster::m_timed, monster::mflag, mflag_has, mflag_on, chunk::mon_current, monster_check_active(), angband_constants::move_energy, monster::mspeed, process_monster(), process_monster_timed(), PU_MONSTERS, monster::race, regen_monster(), turn, turn_energy(), player_upkeep::update, player::upkeep, and z_info.

Referenced by run_game_loop().

static void regen_monster ( struct monster mon)
static
void reset_monsters ( void  )

Clear 'moved' status from all monsters.

Clear noise if appropriate.

References cave, cave_monster(), cave_monster_max(), i, monster::mflag, and mflag_off.

Referenced by run_game_loop().

Variable Documentation

const int d_off_x_0[]
static
Initial value:
=
{ 0 }
const int d_off_x_1[]
static
Initial value:
=
{ -1, 0, 1, -1, 1, -1, 0, 1, 0 }
const int d_off_x_2[]
static
Initial value:
=
{ -2, 2, -1, 0, 1, -2, 2, -2, 2, -1, 0, 1, 0 }
const int d_off_x_3[]
static
Initial value:
=
{ -3, 3, -2, 2, -1, 0, 1, -3, 3, -3, 3, -2, 2,
-1, 0, 1, 0 }
const int d_off_x_4[]
static
Initial value:
=
{ -4, 4, -3, 3, -2, -3, 2, 3, -1, 0, 1, -4, 4,
-4, 4, -3, 3, -2, -3, 2, 3, -1, 0, 1, 0 }
const int d_off_x_5[]
static
Initial value:
=
{ -5, 5, -4, 4, -4, 4, -2, -3, 2, 3, -1, 0, 1,
-5, 5, -5, 5, -4, 4, -4, 4, -2, -3, 2, 3, -1,
0, 1, 0 }
const int d_off_x_6[]
static
Initial value:
=
{ -6, 6, -5, 5, -5, 5, -4, 4, -2, -3, 2, 3, -1,
0, 1, -6, 6, -6, 6, -5, 5, -5, 5, -4, 4, -2,
-3, 2, 3, -1, 0, 1, 0 }
const int d_off_x_7[]
static
Initial value:
=
{ -7, 7, -6, 6, -6, 6, -5, 5, -4, -5, 4, 5, -2,
-3, 2, 3, -1, 0, 1, -7, 7, -7, 7, -6, 6, -6,
6, -5, 5, -4, -5, 4, 5, -2, -3, 2, 3, -1, 0,
1, 0 }
const int d_off_x_8[]
static
Initial value:
=
{ -8, 8, -7, 7, -7, 7, -6, 6, -6, 6, -4, -5, 4,
5, -2, -3, 2, 3, -1, 0, 1, -8, 8, -8, 8, -7,
7, -7, 7, -6, 6, -6, 6, -4, -5, 4, 5, -2, -3,
2, 3, -1, 0, 1, 0 }
const int d_off_x_9[]
static
Initial value:
=
{ -9, 9, -8, 8, -8, 8, -7, 7, -7, 7, -6, 6, -4,
-5, 4, 5, -2, -3, 2, 3, -1, 0, 1, -9, 9, -9,
9, -8, 8, -8, 8, -7, 7, -7, 7, -6, 6, -4, -5,
4, 5, -2, -3, 2, 3, -1, 0, 1, 0 }
const int d_off_y_0[]
static
Initial value:
=
{ 0 }
const int d_off_y_1[]
static
Initial value:
=
{ -1, -1, -1, 0, 0, 1, 1, 1, 0 }
const int d_off_y_2[]
static
Initial value:
=
{ -1, -1, -2, -2, -2, 0, 0, 1, 1, 2, 2, 2, 0 }
const int d_off_y_3[]
static
Initial value:
=
{ -1, -1, -2, -2, -3, -3, -3, 0, 0, 1, 1, 2, 2,
3, 3, 3, 0 }
const int d_off_y_4[]
static
Initial value:
=
{ -1, -1, -2, -2, -3, -3, -3, -3, -4, -4, -4, 0,
0, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 0 }
const int d_off_y_5[]
static
Initial value:
=
{ -1, -1, -2, -2, -3, -3, -4, -4, -4, -4, -5, -5,
-5, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5,
5, 0 }
const int d_off_y_6[]
static
Initial value:
=
{ -1, -1, -2, -2, -3, -3, -4, -4, -5, -5, -5, -5,
-6, -6, -6, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5,
5, 5, 6, 6, 6, 0 }
const int d_off_y_7[]
static
Initial value:
=
{ -1, -1, -2, -2, -3, -3, -4, -4, -5, -5, -5, -5,
-6, -6, -6, -6, -7, -7, -7, 0, 0, 1, 1, 2, 2, 3,
3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 0 }
const int d_off_y_8[]
static
Initial value:
=
{ -1, -1, -2, -2, -3, -3, -4, -4, -5, -5, -6, -6,
-6, -6, -7, -7, -7, -7, -8, -8, -8, 0, 0, 1, 1,
2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
8, 8, 8, 0 }
const int d_off_y_9[]
static
Initial value:
=
{ -1, -1, -2, -2, -3, -3, -4, -4, -5, -5, -6, -6,
-7, -7, -7, -7, -8, -8, -8, -8, -9, -9, -9, 0,
0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 7,
7, 8, 8, 8, 8, 9, 9, 9, 0 }
const int* dist_offsets_x[10]
static
Initial value:
=
{
}
static const int d_off_x_2[]
Definition: mon-move.c:455
static const int d_off_x_0[]
Definition: mon-move.c:441
static const int d_off_x_7[]
Definition: mon-move.c:504
static const int d_off_x_9[]
Definition: mon-move.c:530
static const int d_off_x_5[]
Definition: mon-move.c:482
static const int d_off_x_6[]
Definition: mon-move.c:493
static const int d_off_x_4[]
Definition: mon-move.c:472
static const int d_off_x_3[]
Definition: mon-move.c:463
static const int d_off_x_1[]
Definition: mon-move.c:448
static const int d_off_x_8[]
Definition: mon-move.c:517

Referenced by find_hiding(), and find_safety().

const int* dist_offsets_y[10]
static
Initial value:
=
{
}
static const int d_off_y_7[]
Definition: mon-move.c:499
static const int d_off_y_0[]
Definition: mon-move.c:438
static const int d_off_y_2[]
Definition: mon-move.c:452
static const int d_off_y_1[]
Definition: mon-move.c:445
static const int d_off_y_9[]
Definition: mon-move.c:524
static const int d_off_y_8[]
Definition: mon-move.c:511
static const int d_off_y_4[]
Definition: mon-move.c:468
static const int d_off_y_6[]
Definition: mon-move.c:488
static const int d_off_y_5[]
Definition: mon-move.c:477
static const int d_off_y_3[]
Definition: mon-move.c:459

Referenced by find_hiding(), and find_safety().

byte side_dirs[20][8]
static
Initial value:
= {
{0, 0, 0, 0, 0, 0, 0, 0},
{1, 4, 2, 7, 3, 8, 6, 9},
{2, 1, 3, 4, 6, 7, 9, 8},
{3, 2, 6, 1, 9, 4, 8, 7},
{4, 7, 1, 8, 2, 9, 3, 6},
{5, 5, 5, 5, 5, 5, 5, 5},
{6, 3, 9, 2, 8, 1, 7, 4},
{7, 8, 4, 9, 1, 6, 2, 3},
{8, 9, 7, 6, 4, 3, 1, 2},
{9, 6, 8, 3, 7, 2, 4, 1},
{0, 0, 0, 0, 0, 0, 0, 0},
{1, 2, 4, 3, 7, 6, 8, 9},
{2, 3, 1, 6, 4, 9, 7, 8},
{3, 6, 2, 9, 1, 8, 4, 7},
{4, 1, 7, 2, 8, 3, 9, 6},
{5, 5, 5, 5, 5, 5, 5, 5},
{6, 9, 3, 8, 2, 7, 1, 4},
{7, 4, 8, 1, 9, 2, 6, 3},
{8, 7, 9, 4, 6, 1, 3, 2},
{9, 8, 6, 7, 3, 4, 2, 1}
}

Given a central direction at position [dir #][0], return a series of directions radiating out on both sides from the central direction all the way back to its rear.

Side directions come in pairs; for example, directions '1' and '3' flank direction '2'. The code should know which side to consider first. If the left, it must add 10 to the central direction to access the second part of the table.

Referenced by process_monster().