From 9ba57ee3a6f72308ff01263dfe143cf23c1cf321 Mon Sep 17 00:00:00 2001 From: dshaligram Date: Sat, 19 Apr 2008 23:13:26 +0000 Subject: Fixes to compile with Visual C++. Moved direct.cc and direct.h to directn.* to avoid conflict with VC++ direct.h header. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4390 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/acr.cc | 2 +- crawl-ref/source/cio.h | 2 +- crawl-ref/source/command.cc | 2 +- crawl-ref/source/database.cc | 4 +- crawl-ref/source/debug.cc | 2 +- crawl-ref/source/decks.cc | 6 +- crawl-ref/source/defines.h | 4 +- crawl-ref/source/describe.cc | 6 +- crawl-ref/source/direct.cc | 2436 ----------------------------------------- crawl-ref/source/direct.h | 228 ---- crawl-ref/source/directn.cc | 2436 +++++++++++++++++++++++++++++++++++++++++ crawl-ref/source/directn.h | 228 ++++ crawl-ref/source/dungeon.cc | 2 +- crawl-ref/source/effects.cc | 2 +- crawl-ref/source/files.cc | 42 +- crawl-ref/source/initfile.cc | 11 +- crawl-ref/source/invent.cc | 2 +- crawl-ref/source/it_use3.cc | 2 +- crawl-ref/source/item_use.cc | 6 +- crawl-ref/source/itemname.cc | 4 +- crawl-ref/source/items.cc | 2 +- crawl-ref/source/libgui.cc | 2 +- crawl-ref/source/libutil.cc | 4 +- crawl-ref/source/libw32c.cc | 2 +- crawl-ref/source/luadgn.cc | 16 +- crawl-ref/source/makefile.obj | 2 +- crawl-ref/source/mapdef.cc | 6 +- crawl-ref/source/mapmark.cc | 2 +- crawl-ref/source/mgrow.cc | 2 +- crawl-ref/source/misc.cc | 4 +- crawl-ref/source/mon-util.cc | 12 +- crawl-ref/source/mutation.cc | 4 +- crawl-ref/source/newgame.cc | 32 +- crawl-ref/source/output.cc | 2 +- crawl-ref/source/overmap.cc | 2 +- crawl-ref/source/quiver.cc | 20 +- crawl-ref/source/religion.cc | 4 +- crawl-ref/source/spells1.cc | 4 +- crawl-ref/source/spells1.h | 2 +- crawl-ref/source/spells2.cc | 2 +- crawl-ref/source/spells3.cc | 4 +- crawl-ref/source/spells4.cc | 4 +- crawl-ref/source/spl-cast.cc | 2 +- crawl-ref/source/spl-util.cc | 2 +- crawl-ref/source/spl-util.h | 2 +- crawl-ref/source/stash.cc | 2 +- crawl-ref/source/state.cc | 2 +- crawl-ref/source/stuff.cc | 2 +- crawl-ref/source/terrain.cc | 4 +- crawl-ref/source/tile1.cc | 2 +- crawl-ref/source/tile2.cc | 2 +- crawl-ref/source/transfor.cc | 2 +- crawl-ref/source/traps.cc | 2 +- crawl-ref/source/travel.cc | 2 +- crawl-ref/source/view.cc | 4 +- crawl-ref/source/xom.cc | 2 +- 56 files changed, 2811 insertions(+), 2782 deletions(-) delete mode 100644 crawl-ref/source/direct.cc delete mode 100644 crawl-ref/source/direct.h create mode 100644 crawl-ref/source/directn.cc create mode 100644 crawl-ref/source/directn.h diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index 4fbcfe8081..6ef42b9a85 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -83,7 +83,7 @@ #include "debug.h" #include "delay.h" #include "describe.h" -#include "direct.h" +#include "directn.h" #include "dungeon.h" #include "effects.h" #include "fight.h" diff --git a/crawl-ref/source/cio.h b/crawl-ref/source/cio.h index 805ed2396d..26caa23be2 100644 --- a/crawl-ref/source/cio.h +++ b/crawl-ref/source/cio.h @@ -12,7 +12,7 @@ #include "AppHdr.h" #include "externs.h" #include "defines.h" -#include "direct.h" +#include "directn.h" #include #include #include diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index 025ae033e4..163f9403fe 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -97,7 +97,7 @@ void version(void) { mpr( "This is " CRAWL " " VERSION " (" VERSION_DETAIL ")." ); mprf("Features: %s", - comma_separated_line(features, features + ARRAYSIZE(features)) + comma_separated_line(features, features + ARRAYSZ(features)) .c_str()); } // end version() diff --git a/crawl-ref/source/database.cc b/crawl-ref/source/database.cc index 8417b6e689..af43a29c76 100644 --- a/crawl-ref/source/database.cc +++ b/crawl-ref/source/database.cc @@ -182,13 +182,13 @@ void TextDB::_regenerate_db() void databaseSystemInit() { - for (unsigned int i = 0; i < ARRAYSIZE(AllDBs); i++) + for (unsigned int i = 0; i < ARRAYSZ(AllDBs); i++) AllDBs[i].init(); } void databaseSystemShutdown() { - for (unsigned int i = 0; i < ARRAYSIZE(AllDBs); i++) + for (unsigned int i = 0; i < ARRAYSZ(AllDBs); i++) AllDBs[i].shutdown(); } diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc index 6b65e9bce1..ee2d8053ba 100644 --- a/crawl-ref/source/debug.cc +++ b/crawl-ref/source/debug.cc @@ -43,7 +43,7 @@ #include "decks.h" #include "delay.h" #include "describe.h" -#include "direct.h" +#include "directn.h" #include "dungeon.h" #include "effects.h" #include "fight.h" diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc index a22534197a..3d7740277e 100644 --- a/crawl-ref/source/decks.cc +++ b/crawl-ref/source/decks.cc @@ -819,7 +819,7 @@ bool deck_peek() already_seen++; // always increase if seen 2, 50% increase if seen 1 - if ( coinflip() < already_seen) + if ( already_seen && random2(2) < already_seen ) deck.props["non_brownie_draws"]++; mprf("You draw two cards from the deck. They are: %s and %s.", @@ -2004,7 +2004,7 @@ const mutation_type bad_mutations[] = { bool _has_bad_mutation() { - for ( unsigned int i = 0; i < ARRAYSIZE(bad_mutations); ++i ) + for ( unsigned int i = 0; i < ARRAYSZ(bad_mutations); ++i ) if (you.mutation[bad_mutations[i]] > you.demon_pow[bad_mutations[i]]) return true; @@ -2015,7 +2015,7 @@ static void _remove_bad_mutation() { mutation_type which_mut = NUM_MUTATIONS; int numfound = 0; - for ( unsigned int i = 0; i < ARRAYSIZE(bad_mutations); ++i ) + for ( unsigned int i = 0; i < ARRAYSZ(bad_mutations); ++i ) if (you.mutation[bad_mutations[i]] > you.demon_pow[bad_mutations[i]]) { if ( one_chance_in(++numfound) ) diff --git a/crawl-ref/source/defines.h b/crawl-ref/source/defines.h index a028036591..d899dda451 100644 --- a/crawl-ref/source/defines.h +++ b/crawl-ref/source/defines.h @@ -299,8 +299,8 @@ const int LABYRINTH_BORDER = 4; // it wants to be used in case labels. #define CONTROL( xxx ) ((xxx) - 'A' + 1) -#define ARRAYSIZE(x) (sizeof(x) / sizeof(x[0])) -#define RANDOM_ELEMENT(x) (x[random2(ARRAYSIZE(x))]) +#define ARRAYSZ(x) (sizeof(x) / sizeof(x[0])) +#define RANDOM_ELEMENT(x) (x[random2(ARRAYSZ(x))]) #define MIN(x, y) MINIMUM(x, y) #define MAX(x,y) (((x) > (y)) ? (x) : (y)) diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 7a1bde8feb..caa1e8e3cf 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -260,7 +260,7 @@ static std::vector _randart_propnames( const item_def& item ) ego = ego.substr(2, ego.length()-3); // and another one for adding a comma if needed - for ( unsigned i = 0; i < ARRAYSIZE(propanns); ++i ) + for ( unsigned i = 0; i < ARRAYSZ(propanns); ++i ) if (known_proprt(propanns[i].prop)) { ego += ","; @@ -271,7 +271,7 @@ static std::vector _randart_propnames( const item_def& item ) } } - for ( unsigned i = 0; i < ARRAYSIZE(propanns); ++i ) + for ( unsigned i = 0; i < ARRAYSZ(propanns); ++i ) { if (known_proprt(propanns[i].prop)) { @@ -401,7 +401,7 @@ static std::string _randart_descrip( const item_def &item ) { RAP_ANGRY, "It makes you angry.", false} }; - for ( unsigned i = 0; i < ARRAYSIZE(propdescs); ++i ) + for ( unsigned i = 0; i < ARRAYSZ(propdescs); ++i ) { if ( known_proprt(propdescs[i].property)) { diff --git a/crawl-ref/source/direct.cc b/crawl-ref/source/direct.cc deleted file mode 100644 index afe73c0522..0000000000 --- a/crawl-ref/source/direct.cc +++ /dev/null @@ -1,2436 +0,0 @@ -/* - * File: direct.cc - * Summary: Functions used when picking squares. - * Written by: Linley Henzell - * - * Modified for Crawl Reference by $Author$ on $Date$ - * - * Change History (most recent first): - * - * <5> 01/08/01 GDL complete rewrite of direction() - * <4> 11/23/99 LRH Looking at monsters now - * displays more info - * <3> 5/12/99 BWR changes to allow for space selection of target. - * CR, ESC, and 't' in targeting. - * <2> 5/09/99 JDJ look_around no longer prints a prompt. - * <1> -/--/-- LRH Created - */ - -#include "AppHdr.h" -#include "direct.h" -#include "format.h" - -#include -#include -#include -#include -#include -#include - -#ifdef DOS - #include -#endif - -#include "externs.h" - -#include "cio.h" -#include "command.h" -#include "debug.h" -#include "describe.h" -#include "dungeon.h" -#include "itemname.h" -#include "mapmark.h" -#include "message.h" -#include "misc.h" -#include "menu.h" -#include "monstuff.h" -#include "mon-util.h" -#include "player.h" -#include "shopping.h" -#include "state.h" -#include "stuff.h" -#include "spells4.h" -#include "stash.h" -#include "tiles.h" -#include "terrain.h" -#include "traps.h" -#include "travel.h" -#include "tutorial.h" -#include "view.h" - -#include "macro.h" - -enum LOSSelect -{ - LOS_ANY = 0x00, - - // Check only visible squares - LOS_VISIBLE = 0x01, - - // Check only hidden squares - LOS_HIDDEN = 0x02, - - LOS_VISMASK = 0x03, - - // Flip from visible to hidden when going forward, - // or hidden to visible when going backwards. - LOS_FLIPVH = 0x20, - - // Flip from hidden to visible when going forward, - // or visible to hidden when going backwards. - LOS_FLIPHV = 0x40, - - LOS_NONE = 0xFFFF -}; - -static void describe_feature(int mx, int my, bool oos); -static void describe_cell(int mx, int my); - -static bool find_object( int x, int y, int mode, int range ); -static bool find_monster( int x, int y, int mode, int range ); -static bool find_feature( int x, int y, int mode, int range ); - -static char find_square_wrapper( int tx, int ty, - FixedVector &mfp, char direction, - bool (*targ)(int, int, int, int), - int mode = TARG_ANY, int range = -1, - bool wrap = false, - int los = LOS_ANY); - -static char find_square( int xps, int yps, - FixedVector &mfp, int direction, - bool (*targ)(int, int, int, int), - int mode = TARG_ANY, int range = -1, - bool wrap = false, - int los = LOS_ANY); - -static int targeting_cmd_to_compass( command_type command ); -static void describe_oos_square(int x, int y); -static void extend_move_to_edge(dist &moves); - -void direction_choose_compass( dist& moves, targeting_behaviour *beh) -{ - moves.isValid = true; - moves.isTarget = false; - moves.isMe = false; - moves.isCancel = false; - moves.dx = moves.dy = 0; - -#ifdef USE_TILE - mouse_control mc(MOUSE_MODE_TARGET_DIR); -#endif - - beh->compass = true; - - do - { - const command_type key_command = beh->get_command(); - - if (key_command == CMD_TARGET_SELECT) - { - moves.dx = moves.dy = 0; - moves.isMe = true; - break; - } - - const int i = targeting_cmd_to_compass(key_command); - if ( i != -1 ) - { - moves.dx = Compass[i].x; - moves.dy = Compass[i].y; - } - else if ( key_command == CMD_TARGET_CANCEL ) - { - moves.isCancel = true; - moves.isValid = false; - } - } - while ( !moves.isCancel && moves.dx == 0 && moves.dy == 0 ); - - return; -} - -static int targeting_cmd_to_compass( command_type command ) -{ - switch ( command ) - { - case CMD_TARGET_UP: case CMD_TARGET_DIR_UP: - return 0; - case CMD_TARGET_UP_RIGHT: case CMD_TARGET_DIR_UP_RIGHT: - return 1; - case CMD_TARGET_RIGHT: case CMD_TARGET_DIR_RIGHT: - return 2; - case CMD_TARGET_DOWN_RIGHT: case CMD_TARGET_DIR_DOWN_RIGHT: - return 3; - case CMD_TARGET_DOWN: case CMD_TARGET_DIR_DOWN: - return 4; - case CMD_TARGET_DOWN_LEFT: case CMD_TARGET_DIR_DOWN_LEFT: - return 5; - case CMD_TARGET_LEFT: case CMD_TARGET_DIR_LEFT: - return 6; - case CMD_TARGET_UP_LEFT: case CMD_TARGET_DIR_UP_LEFT: - return 7; - default: - return -1; - } -} - -static int targeting_cmd_to_feature( command_type command ) -{ - switch ( command ) - { - case CMD_TARGET_FIND_TRAP: - return '^'; - case CMD_TARGET_FIND_PORTAL: - return '\\'; - case CMD_TARGET_FIND_ALTAR: - return '_'; - case CMD_TARGET_FIND_UPSTAIR: - return '<'; - case CMD_TARGET_FIND_DOWNSTAIR: - return '>'; - default: - return 0; - } -} - -static command_type shift_direction(command_type cmd) -{ - switch (cmd) - { - case CMD_TARGET_DOWN_LEFT: return CMD_TARGET_DIR_DOWN_LEFT; - case CMD_TARGET_LEFT: return CMD_TARGET_DIR_LEFT; - case CMD_TARGET_DOWN: return CMD_TARGET_DIR_DOWN; - case CMD_TARGET_UP: return CMD_TARGET_DIR_UP; - case CMD_TARGET_RIGHT: return CMD_TARGET_DIR_RIGHT; - case CMD_TARGET_DOWN_RIGHT: return CMD_TARGET_DIR_DOWN_RIGHT; - case CMD_TARGET_UP_RIGHT: return CMD_TARGET_DIR_UP_RIGHT; - case CMD_TARGET_UP_LEFT: return CMD_TARGET_DIR_UP_LEFT; - default: return (cmd); - } -} - -static const char *target_mode_help_text(int mode) -{ - switch (mode) - { - case DIR_NONE: - return Options.target_unshifted_dirs? "? - help" : - "? - help, Shift-Dir - shoot in a straight line"; - case DIR_TARGET: - return "? - help, Dir - move target cursor"; - default: - return "? - help"; - } -} - -static void draw_ray_glyph(const coord_def &pos, int colour, - int glych, int mcol) -{ -#ifdef USE_TILE - tile_place_ray(pos); -#else - int mid = mgrd(pos); - if (mid != NON_MONSTER) - { - const monsters *mons = &menv[mid]; - if (mons->alive() && player_monster_visible(mons)) - { - glych = get_screen_glyph(pos.x, pos.y); - colour = mcol; - } - } - const coord_def vp = grid2view(pos); - cgotoxy(vp.x, vp.y, GOTO_DNGN); - textcolor( real_colour(colour) ); - putch(glych); -#endif -} - -// Unseen monsters in shallow water show a "strange disturbance". -// (Unless flying!) -static bool _mon_submerged_in_water(const monsters *mon) -{ - if (!mon) - return false; - - return (grd[mon->x][mon->y] == DNGN_SHALLOW_WATER - && see_grid(mon->x, mon->y) - && !player_monster_visible(mon) - && !mons_flies(mon)); -} - -static bool _is_target_in_range(int x, int y, int range) -{ - // range doesn't matter - if (range == -1) - return true; - - return (grid_distance(you.x_pos, you.y_pos, x, y) <= range); -} - -// We handle targeting for repeating commands and re-doing the -// previous command differently (i.e., not just letting the keys -// stuffed into the macro buffer replay as-is) because if the player -// targeted a monster using the movement keys and the monster then -// moved between repititions, then simply replaying the keys in the -// buffer will target an empty square. -static void direction_again(dist& moves, targeting_type restricts, - targ_mode_type mode, int range, bool just_looking, - const char *prompt, targeting_behaviour *beh) -{ - moves.isValid = false; - moves.isTarget = false; - moves.isMe = false; - moves.isCancel = false; - moves.isEndpoint = false; - moves.choseRay = false; - - if (you.prev_targ == MHITNOT && you.prev_grd_targ == coord_def(0, 0)) - { - moves.isCancel = true; - crawl_state.cancel_cmd_repeat(); - return; - } - - int targ_types = 0; - if (you.prev_targ != MHITNOT && you.prev_targ != MHITYOU) - targ_types++; - if (you.prev_targ == MHITYOU) - targ_types++; - if (you.prev_grd_targ != coord_def(0, 0)) - targ_types++; - ASSERT(targ_types == 1); - - // Discard keys until we get to a set-target command - command_type key_command = CMD_NO_CMD; - - while (crawl_state.is_replaying_keys()) - { - key_command = beh->get_command(); - - if (key_command == CMD_TARGET_PREV_TARGET - || key_command == CMD_TARGET_SELECT_ENDPOINT - || key_command == CMD_TARGET_SELECT - || key_command == CMD_TARGET_MAYBE_PREV_TARGET) - { - break; - } - } - - if (!crawl_state.is_replaying_keys()) - { - moves.isCancel = true; - - mpr("Ran out of keys."); - - return; - } - - if (key_command == CMD_TARGET_SELECT_ENDPOINT) - moves.isEndpoint = true; - - if (you.prev_grd_targ != coord_def(0, 0)) - { - if (!see_grid(you.prev_grd_targ)) - { - moves.isCancel = true; - - crawl_state.cancel_cmd_repeat("You can no longer see the dungeon " - "square you previously targeted."); - return; - } - else if (you.prev_grd_targ.x == you.x_pos - && you.prev_grd_targ.y == you.y_pos) - { - moves.isCancel = true; - - crawl_state.cancel_cmd_repeat("You are now standing on your " - "previously targeted dungeon " - "square."); - return; - } - else if (!_is_target_in_range(you.prev_grd_targ.x, you.prev_grd_targ.y, - range)) - { - moves.isCancel = true; - - crawl_state.cancel_cmd_repeat("Your previous target is now out of " - "range."); - return; - } - - moves.tx = you.prev_grd_targ.x; - moves.ty = you.prev_grd_targ.y; - - ray_def ray; - find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, true, ray, - 0, true); - moves.ray = ray; - } - else if (you.prev_targ == MHITYOU) - { - moves.isMe = true; - moves.tx = you.x_pos; - moves.ty = you.y_pos; - - // Discard 'Y' player gave to yesno() - if (mode == TARG_ENEMY) - getchm(); - } - else - { - const monsters *montarget = &menv[you.prev_targ]; - - if (!mons_near(montarget) - || !player_monster_visible( montarget )) - { - moves.isCancel = true; - - crawl_state.cancel_cmd_repeat("Your target is gone."); - - return; - } - else if (!_is_target_in_range(you.prev_grd_targ.x, you.prev_grd_targ.y, - range)) - { - moves.isCancel = true; - - crawl_state.cancel_cmd_repeat("Your previous target is now out of " - "range."); - return; - } - - moves.tx = montarget->x; - moves.ty = montarget->y; - - ray_def ray; - find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, true, ray, - 0, true); - moves.ray = ray; - } - - moves.isValid = true; - moves.isTarget = true; - - return; -} - -//--------------------------------------------------------------- -// -// direction -// -// use restrict == DIR_DIR to allow only a compass direction; -// == DIR_TARGET to allow only choosing a square; -// == DIR_NONE to allow either. -// -// outputs: dist structure: -// -// isValid a valid target or direction was chosen -// isCancel player hit 'escape' -// isTarget targetting was used -// choseRay player wants a specific ray -// ray ...this one -// isEndpoint player wants the ray to stop on the dime -// tx,ty target x,y -// dx,dy direction delta for DIR_DIR -// -//--------------------------------------------------------------- -void direction(dist& moves, targeting_type restricts, - targ_mode_type mode, int range, bool just_looking, - bool needs_path, const char *prompt, - targeting_behaviour *beh) -{ - static targeting_behaviour stock_behaviour; - if (!beh) - beh = &stock_behaviour; - - beh->just_looking = just_looking; - - if (crawl_state.is_replaying_keys() && restricts != DIR_DIR) - { - direction_again(moves, restricts, mode, range, just_looking, - prompt, beh); - return; - } - - // NOTE: Even if just_looking is set, moves is still interesting, - // because we can travel there! - - if ( restricts == DIR_DIR ) - { - direction_choose_compass( moves, beh ); - return; - } - - cursor_control con(!Options.use_fake_cursor); - - int dir = 0; - bool show_beam = Options.show_beam && !just_looking && needs_path; - ray_def ray; - - FixedVector < char, 2 > objfind_pos; - FixedVector < char, 2 > monsfind_pos; - - // init - moves.dx = moves.dy = 0; - moves.tx = you.x_pos; - moves.ty = you.y_pos; - - // If we show the beam on startup, we have to initialise it. - if ( show_beam ) - find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, true, ray); - - bool skip_iter = false; - bool found_autotarget = false; - bool target_unshifted = Options.target_unshifted_dirs; - - // Find a default target - if ( Options.default_target && mode == TARG_ENEMY ) - { - skip_iter = true; // skip first iteration...XXX mega-hack - if ( you.prev_targ != MHITNOT && you.prev_targ != MHITYOU ) - { - const monsters *montarget = &menv[you.prev_targ]; - if ( mons_near(montarget) && player_monster_visible(montarget) - && !mons_friendly(montarget) // not made friendly since then - && _is_target_in_range(montarget->x, montarget->y, range) ) - { - found_autotarget = true; - moves.tx = montarget->x; - moves.ty = montarget->y; - } - } - } - - bool show_prompt = true; - while (true) - { - // Prompts might get scrolled off if you have too few lines available. - // We'll live with that. - if ( !just_looking && (show_prompt || beh->should_redraw()) ) - { - mprf(MSGCH_PROMPT, "%s (%s)", prompt? prompt : "Aim", - target_mode_help_text(restricts)); - - if ((mode == TARG_ANY || mode == TARG_FRIEND) - && moves.tx == you.x_pos && moves.ty == you.y_pos) - { - terse_describe_square(moves.target()); - } - - show_prompt = false; - } - - // Reinit...this needs to be done every loop iteration - // because moves is more persistent than loop_done. - moves.isValid = false; - moves.isTarget = false; - moves.isMe = false; - moves.isCancel = false; - moves.isEndpoint = false; - moves.choseRay = false; - - cursorxy( grid2viewX(moves.tx), grid2viewY(moves.ty) ); - - command_type key_command; - - if ( skip_iter ) - { - if ( found_autotarget ) - key_command = CMD_NO_CMD; - else - key_command = CMD_TARGET_CYCLE_FORWARD; // find closest enemy - } - else - { -#ifdef USE_TILE - mouse_control mc(MOUSE_MODE_TARGET); -#endif - key_command = beh->get_command(); - } - -#ifdef USE_TILE - // if a mouse command, update location to mouse position... - if ( key_command == CMD_TARGET_MOUSE_MOVE - || key_command == CMD_TARGET_MOUSE_SELECT ) - { - coord_def gc; - if (gui_get_mouse_grid_pos(gc)) - { - moves.tx = gc.x; - moves.ty = gc.y; - - if (key_command == CMD_TARGET_MOUSE_SELECT) - key_command = CMD_TARGET_SELECT; - } - else - { - key_command = CMD_NO_CMD; - } - } -#endif - - if (target_unshifted && moves.tx == you.x_pos && moves.ty == you.y_pos - && restricts != DIR_TARGET) - { - key_command = shift_direction(key_command); - } - - if (target_unshifted - && (key_command == CMD_TARGET_CYCLE_FORWARD - || key_command == CMD_TARGET_CYCLE_BACK - || key_command == CMD_TARGET_OBJ_CYCLE_FORWARD - || key_command == CMD_TARGET_OBJ_CYCLE_BACK)) - { - target_unshifted = false; - } - - if ( key_command == CMD_TARGET_MAYBE_PREV_TARGET ) - { - if ( moves.tx == you.x_pos && moves.ty == you.y_pos ) - key_command = CMD_TARGET_PREV_TARGET; - else - key_command = CMD_TARGET_SELECT; - } - - bool need_beam_redraw = false; - bool force_redraw = false; - bool loop_done = false; - - const int old_tx = moves.tx + (skip_iter ? 500 : 0); // hmmm...hack - const int old_ty = moves.ty; - - int i, mid; - - switch ( key_command ) - { - // standard movement - case CMD_TARGET_DOWN_LEFT: - case CMD_TARGET_DOWN: - case CMD_TARGET_DOWN_RIGHT: - case CMD_TARGET_LEFT: - case CMD_TARGET_RIGHT: - case CMD_TARGET_UP_LEFT: - case CMD_TARGET_UP: - case CMD_TARGET_UP_RIGHT: - i = targeting_cmd_to_compass(key_command); - moves.tx += Compass[i].x; - moves.ty += Compass[i].y; - break; - - case CMD_TARGET_DIR_DOWN_LEFT: - case CMD_TARGET_DIR_DOWN: - case CMD_TARGET_DIR_DOWN_RIGHT: - case CMD_TARGET_DIR_LEFT: - case CMD_TARGET_DIR_RIGHT: - case CMD_TARGET_DIR_UP_LEFT: - case CMD_TARGET_DIR_UP: - case CMD_TARGET_DIR_UP_RIGHT: - i = targeting_cmd_to_compass(key_command); - - if ( restricts != DIR_TARGET ) - { - // A direction is allowed, and we've selected it. - moves.dx = Compass[i].x; - moves.dy = Compass[i].y; - // Needed for now...eventually shouldn't be necessary - moves.tx = you.x_pos + moves.dx; - moves.ty = you.y_pos + moves.dy; - moves.isValid = true; - moves.isTarget = false; - show_beam = false; - moves.choseRay = false; - loop_done = true; - } - else - { - // Direction not allowed, so just move in that direction. - // Maybe make this a bigger jump? - if (restricts == DIR_TARGET) - { - moves.tx += Compass[i].x * 3; - moves.ty += Compass[i].y * 3; - } - else - { - moves.tx += Compass[i].x; - moves.ty += Compass[i].y; - } - } - break; - -#ifdef WIZARD - case CMD_TARGET_CYCLE_BEAM: - show_beam = find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, - true, ray, (show_beam ? 1 : 0)); - need_beam_redraw = true; - break; -#endif - - case CMD_TARGET_HIDE_BEAM: - if (show_beam) - { - show_beam = false; - need_beam_redraw = true; - } - else - { - if (!needs_path) - { - mprf(MSGCH_EXAMINE_FILTER, - "This spell doesn't need a beam path."); - break; - } - - show_beam = find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, - true, ray, 0, true); - need_beam_redraw = show_beam; - } - break; - - case CMD_TARGET_FIND_YOU: - moves.tx = you.x_pos; - moves.ty = you.y_pos; - moves.dx = 0; - moves.dy = 0; - break; - - case CMD_TARGET_FIND_TRAP: - case CMD_TARGET_FIND_PORTAL: - case CMD_TARGET_FIND_ALTAR: - case CMD_TARGET_FIND_UPSTAIR: - case CMD_TARGET_FIND_DOWNSTAIR: - { - const int thing_to_find = targeting_cmd_to_feature(key_command); - if (find_square_wrapper(moves.tx, moves.ty, objfind_pos, 1, - find_feature, thing_to_find, range, true, - Options.target_los_first ? - LOS_FLIPVH : LOS_ANY)) - { - moves.tx = objfind_pos[0]; - moves.ty = objfind_pos[1]; - } - else - { - if (!skip_iter) - flush_input_buffer(FLUSH_ON_FAILURE); - } - break; - } - - case CMD_TARGET_CYCLE_TARGET_MODE: - mode = static_cast((mode + 1) % TARG_NUM_MODES); - mprf( "Targeting mode is now: %s", - (mode == TARG_ANY) ? "any" : - (mode == TARG_ENEMY) ? "enemies" - : "friends" ); - break; - - case CMD_TARGET_PREV_TARGET: - // Do we have a previous target? - if (you.prev_targ == MHITNOT || you.prev_targ == MHITYOU) - { - mpr("You haven't got a previous target.", MSGCH_EXAMINE_FILTER); - break; - } - - // we have a valid previous target (maybe) - { - const monsters *montarget = &menv[you.prev_targ]; - - if (!mons_near(montarget) - || !player_monster_visible( montarget )) - { - mpr("You can't see that creature any more.", - MSGCH_EXAMINE_FILTER); - } - else - { - // We have all the information we need - moves.isValid = true; - moves.isTarget = true; - moves.tx = montarget->x; - moves.ty = montarget->y; - if ( !just_looking ) - { - // We have to turn off show_beam, because - // when jumping to a previous target we don't - // care about the beam; otherwise Bad Things - // will happen because the ray is invalid, - // and we don't get a chance to update it before - // breaking from the loop. - show_beam = false; - loop_done = true; - } - } - break; - } - - case CMD_TARGET_SELECT_ENDPOINT: - moves.isEndpoint = true; - // intentional fall-through - case CMD_TARGET_SELECT: // finalize current choice - if (!moves.isEndpoint - && mgrd[moves.tx][moves.ty] != NON_MONSTER - && _mon_submerged_in_water(&menv[mgrd[moves.tx][moves.ty]])) - { - moves.isEndpoint = true; - } - moves.isValid = true; - moves.isTarget = true; - loop_done = true; - - you.prev_grd_targ = coord_def(0, 0); - - // maybe we should except just_looking here? - mid = mgrd[moves.tx][moves.ty]; - - if ( mid != NON_MONSTER ) - you.prev_targ = mid; - else if (moves.tx == you.x_pos && moves.ty == you.y_pos) - you.prev_targ = MHITYOU; - else - you.prev_grd_targ = coord_def(moves.tx, moves.ty); - break; - - case CMD_TARGET_OBJ_CYCLE_BACK: - case CMD_TARGET_OBJ_CYCLE_FORWARD: - dir = (key_command == CMD_TARGET_OBJ_CYCLE_BACK) ? -1 : 1; - if (find_square_wrapper( moves.tx, moves.ty, objfind_pos, dir, - find_object, 0, range, true, - Options.target_los_first - ? (dir == 1? LOS_FLIPVH : LOS_FLIPHV) - : LOS_ANY)) - { - moves.tx = objfind_pos[0]; - moves.ty = objfind_pos[1]; - } - else if (!skip_iter) - flush_input_buffer(FLUSH_ON_FAILURE); - - break; - - case CMD_TARGET_CYCLE_FORWARD: - case CMD_TARGET_CYCLE_BACK: - dir = (key_command == CMD_TARGET_CYCLE_BACK) ? -1 : 1; - if (find_square_wrapper( moves.tx, moves.ty, monsfind_pos, dir, - find_monster, mode, range, - Options.target_wrap)) - { - moves.tx = monsfind_pos[0]; - moves.ty = monsfind_pos[1]; - } - else if (!skip_iter) - flush_input_buffer(FLUSH_ON_FAILURE); - - break; - - case CMD_TARGET_CANCEL: - loop_done = true; - moves.isCancel = true; - break; - -#ifdef WIZARD - case CMD_TARGET_WIZARD_MAKE_FRIENDLY: - // Maybe we can skip this check...but it can't hurt - if (!you.wizard || !in_bounds(moves.tx, moves.ty)) - break; - mid = mgrd[moves.tx][moves.ty]; - if (mid == NON_MONSTER) // can put in terrain description here - break; - - { - monsters &m = menv[mid]; - switch (m.attitude) - { - case ATT_FRIENDLY: - m.attitude = ATT_NEUTRAL; - m.flags &= ~MF_CREATED_FRIENDLY; - m.flags |= MF_WAS_NEUTRAL; - break; - case ATT_NEUTRAL: - m.attitude = ATT_HOSTILE; - m.flags &= ~MF_WAS_NEUTRAL; - break; - case ATT_HOSTILE: - m.attitude = ATT_FRIENDLY; - m.flags |= MF_CREATED_FRIENDLY; - break; - default: - break; - } - - // To update visual branding of friendlies. Only - // seem capabable of adding bolding, not removing it, - // though. - viewwindow(true, false); - } - break; - - case CMD_TARGET_WIZARD_MAKE_SHOUT: - // Maybe we can skip this check...but it can't hurt - if (!you.wizard || !in_bounds(moves.tx, moves.ty)) - break; - mid = mgrd[moves.tx][moves.ty]; - if (mid == NON_MONSTER) // can put in terrain description here - break; - - debug_make_monster_shout(&menv[mid]); - break; - - case CMD_TARGET_WIZARD_GIVE_ITEM: - if (!you.wizard || !in_bounds(moves.tx, moves.ty)) - break; - mid = mgrd[moves.tx][moves.ty]; - if (mid == NON_MONSTER) // can put in terrain description here - break; - - wizard_give_monster_item(&menv[mid]); - break; -#endif - - case CMD_TARGET_DESCRIBE: - full_describe_square(moves.target()); - force_redraw = true; - break; - - case CMD_TARGET_HELP: - show_targeting_help(); - force_redraw = true; - redraw_screen(); - mesclr(true); - show_prompt = true; - break; - - default: - break; - } - - if ( loop_done == true ) - { - // This is where we either finalize everything, or else - // decide that we're not really done and continue looping. - - if ( just_looking ) // easy out - break; - - // A bunch of confirmation tests; if we survive them all, - // then break out. - - // Confirm self-targeting on TARG_ENEMY. - // Conceivably we might want to confirm on TARG_ANY too. - if ( moves.isTarget - && moves.tx == you.x_pos && moves.ty == you.y_pos - && mode == TARG_ENEMY - && !yesno("Really target yourself?", false, 'n')) - { - mesclr(); - show_prompt = true; - } - else if ( moves.isTarget && !see_grid(moves.tx, moves.ty) ) - { - mpr("Sorry, you can't target what you can't see.", - MSGCH_EXAMINE_FILTER); - } - // Ask for confirmation if we're quitting for some odd reason - else if ( moves.isValid || moves.isCancel - || yesno("Are you sure you want to fizzle?", false, 'n') ) - { - // Finalize whatever is inside the loop - // (moves-internal finalizations can be done later) - moves.choseRay = show_beam; - moves.ray = ray; - break; - } - } - - // We'll go on looping. Redraw whatever is necessary. - - if ( !in_viewport_bounds(grid2viewX(moves.tx), grid2viewY(moves.ty)) ) - { - // Tried to step out of bounds - moves.tx = old_tx; - moves.ty = old_ty; - } - - bool have_moved = false; - - if ( old_tx != moves.tx || old_ty != moves.ty ) - { - have_moved = true; - show_beam = show_beam && - find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, true, ray, - 0, true); - } - - if ( force_redraw ) - have_moved = true; - - if ( have_moved ) - { - // If the target x,y has changed, the beam must have changed. - if ( show_beam ) - need_beam_redraw = true; - - if ( !skip_iter ) // don't clear before we get a chance to see - mesclr(true); // maybe not completely necessary - - terse_describe_square(moves.target()); - } - -#ifdef USE_TILE - // tiles always need a beam redraw if show_beam is true (and if valid...) - if ( need_beam_redraw - || show_beam && find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, - true, ray, 0, true) ) - { -#else - if ( need_beam_redraw ) - { - viewwindow(true, false); -#endif - if ( show_beam - && in_vlos(grid2viewX(moves.tx), grid2viewY(moves.ty)) - && moves.target() != you.pos() ) - { - // Draw the new ray with magenta '*'s, not including - // your square or the target square. - ray_def raycopy = ray; // temporary copy to work with - while ( raycopy.pos() != moves.target() ) - { - if ( raycopy.pos() != you.pos() ) - { - // Sanity: don't loop forever if the ray is problematic - if ( !in_los(raycopy.x(), raycopy.y()) ) - break; - draw_ray_glyph(raycopy.pos(), MAGENTA, '*', - MAGENTA | COLFLAG_REVERSE); - } - raycopy.advance_through(moves.target()); - } - textcolor(LIGHTGREY); -#ifdef USE_TILE - draw_ray_glyph(moves.target(), MAGENTA, '*', - MAGENTA | COLFLAG_REVERSE); - } - viewwindow(true, false); -#else - } -#endif - - } - skip_iter = false; // only skip one iteration at most - } - moves.isMe = (moves.tx == you.x_pos && moves.ty == you.y_pos); - mesclr(); - - // We need this for directional explosions, otherwise they'll explode one - // square away from the player. - extend_move_to_edge(moves); -} - -void terse_describe_square(const coord_def &c) -{ - if (!see_grid(c.x, c.y)) - describe_oos_square(c.x, c.y); - else if (in_bounds(c) ) - describe_cell(c.x, c.y); -} - -void full_describe_square(const coord_def &c) -{ - // Don't give out information for things outside LOS - if (!see_grid(c.x, c.y)) - return; - - const int mid = mgrd(c); - const int oid = igrd(c); - - if (mid != NON_MONSTER && player_monster_visible(&menv[mid])) - { - // First priority: monsters - describe_monsters(menv[mid]); - } - else if (oid != NON_ITEM) - { - // Second priority: objects - describe_item( mitm[oid] ); - } - else - { - // Third priority: features - describe_feature_wide(c.x, c.y); - } - - redraw_screen(); - mesclr(true); -} - -static void extend_move_to_edge(dist &moves) -{ - if (!moves.dx && !moves.dy) - return; - - // now the tricky bit - extend the target x,y out to map edge. - int mx = 0, my = 0; - - if (moves.dx > 0) - mx = (GXM - 1) - you.x_pos; - if (moves.dx < 0) - mx = you.x_pos; - - if (moves.dy > 0) - my = (GYM - 1) - you.y_pos; - if (moves.dy < 0) - my = you.y_pos; - - if (!(mx == 0 || my == 0)) - { - if (mx < my) - my = mx; - else - mx = my; - } - moves.tx = you.x_pos + moves.dx * mx; - moves.ty = you.y_pos + moves.dy * my; -} - -// Attempts to describe a square that's not in line-of-sight. If -// there's a stash on the square, announces the top item and number -// of items, otherwise, if there's a stair that's in the travel -// cache and noted in the Dungeon (O)verview, names the stair. -static void describe_oos_square(int x, int y) -{ - mpr("You can't see that place.", MSGCH_EXAMINE_FILTER); - - if (!in_bounds(x, y) || !is_terrain_seen(x, y)) - return; - - describe_stash(x, y); - describe_feature(x, y, true); -} - -bool in_vlos(int x, int y) -{ - return (in_los_bounds(x, y) - && (env.show(view2show(coord_def(x, y))) - || coord_def(x, y) == grid2view(you.pos()))); -} - -bool in_vlos(const coord_def &pos) -{ - return (in_vlos(pos.x, pos.y)); -} - -bool in_los(int x, int y) -{ - return (in_vlos(grid2view(coord_def(x, y)))); -} - -static bool find_monster( int x, int y, int mode, int range = -1) -{ - // target the player for friendly and general spells - if ((mode == TARG_FRIEND || mode == TARG_ANY) - && x == you.x_pos && y == you.y_pos) - { - return (true); - } - - // don't target out of range - if (!_is_target_in_range(x, y, range)) - return (false); - - const int targ_mon = mgrd[ x ][ y ]; - - // No monster or outside LOS. - if (targ_mon == NON_MONSTER || !in_los(x,y)) - return (false); - - monsters *mon = &menv[targ_mon]; - - // Unknown mimics don't count as monsters, either. - if (mons_is_mimic(mon->type) - && !(mon->flags & MF_KNOWN_MIMIC)) - { - return (false); - } - - // Don't usually target unseen monsters... - if (!player_monster_visible(mon)) - { - // ... unless it creates a "disturbance in the water". - // Since you can't see the monster, assume it's not a friend. - // Also don't target submerged monsters if there are other targets - // in sight. (This might be too restrictive.) - return (mode != TARG_FRIEND - && _mon_submerged_in_water(mon) - && i_feel_safe(false, false, true, range)); - } - - // Now compare target modes. - if (mode == TARG_ANY) - return true; - - if (mode == TARG_FRIEND) - return (mons_friendly(&menv[targ_mon] )); - - ASSERT(mode == TARG_ENEMY); - if (mons_friendly(&menv[targ_mon])) - return false; - - // Don't target zero xp monsters, unless target_zero_exp is set. - return (Options.target_zero_exp - || !mons_class_flag( menv[targ_mon].type, M_NO_EXP_GAIN )); -} - -static bool find_feature( int x, int y, int mode, int /* range */) -{ - // The stair need not be in LOS if the square is mapped. - if (!in_los(x, y) && (!Options.target_oos || !is_terrain_seen(x, y))) - return (false); - - return is_feature(mode, x, y); -} - -static bool find_object(int x, int y, int mode, int /* range */) -{ - // First, check for mimics. - bool is_mimic = false; - const int mons = mgrd[ x ][ y ]; - if (mons != NON_MONSTER - && player_monster_visible( &(menv[mons]) ) - && mons_is_mimic(menv[mons].type) - && !(menv[mons].flags & MF_KNOWN_MIMIC)) - { - is_mimic = true; - } - - const int item = igrd[x][y]; - if (item == NON_ITEM && !is_mimic) - return false; - - return (in_los(x, y) || Options.target_oos && is_terrain_seen(x, y) - && (is_stash(x, y) || is_mimic)); -} - -static int next_los(int dir, int los, bool wrap) -{ - if (los == LOS_ANY) - return (wrap? los : LOS_NONE); - - bool vis = los & LOS_VISIBLE; - bool hidden = los & LOS_HIDDEN; - bool flipvh = los & LOS_FLIPVH; - bool fliphv = los & LOS_FLIPHV; - - if (!vis && !hidden) - vis = true; - - if (wrap) - { - if (!flipvh && !fliphv) - return (los); - - // We have to invert flipvh and fliphv if we're wrapping. Here's - // why: - // - // * Say the cursor is on the last item in LOS, there are no - // items outside LOS, and wrap == true. flipvh is true. - // * We set wrap false and flip from visible to hidden, but there - // are no hidden items. So now we need to flip back to visible - // so we can go back to the first item in LOS. Unless we set - // fliphv, we can't flip from hidden to visible. - // - los = flipvh? LOS_FLIPHV : LOS_FLIPVH; - } - else - { - if (!flipvh && !fliphv) - return (LOS_NONE); - - if (flipvh && vis != (dir == 1)) - return (LOS_NONE); - - if (fliphv && vis == (dir == 1)) - return (LOS_NONE); - } - - los = (los & ~LOS_VISMASK) | (vis? LOS_HIDDEN : LOS_VISIBLE); - return (los); -} - -bool in_viewport_bounds(int x, int y) -{ - return crawl_view.in_view_viewport(coord_def(x, y)); -} - -bool in_los_bounds(int x, int y) -{ - return crawl_view.in_view_los(coord_def(x, y)); -} - -//--------------------------------------------------------------- -// -// find_square -// -// Finds the next monster/object/whatever (moving in a spiral -// outwards from the player, so closer targets are chosen first; -// starts to player's left) and puts its coordinates in mfp. -// Returns 1 if it found something, zero otherwise. If direction -// is -1, goes backwards. -// -// If the game option target_zero_exp is true, zero experience -// monsters will be targeted. -// -//--------------------------------------------------------------- -static char find_square( int xps, int yps, - FixedVector &mfp, int direction, - bool (*find_targ)( int x, int y, int mode, int range ), - int mode, int range, bool wrap, int los ) -{ - // the day will come when [unsigned] chars will be consigned to - // the fires of Gehenna. Not quite yet, though. - - int temp_xps = xps; - int temp_yps = yps; - int x_change = 0; - int y_change = 0; - - bool onlyVis = false, onlyHidden = false; - - int i, j; - - if (los == LOS_NONE) - return (0); - - if (los == LOS_FLIPVH || los == LOS_FLIPHV) - { - if (in_los_bounds(xps, yps)) - { - // We've been told to flip between visible/hidden, so we - // need to find what we're currently on. - const bool vis = (env.show(view2show(coord_def(xps, yps))) - || view2grid(coord_def(xps, yps)) == you.pos()); - - if (wrap && (vis != (los == LOS_FLIPVH)) == (direction == 1)) - { - // We've already flipped over into the other direction, - // so correct the flip direction if we're wrapping. - los = los == LOS_FLIPHV? LOS_FLIPVH : LOS_FLIPHV; - } - - los = (los & ~LOS_VISMASK) | (vis? LOS_VISIBLE : LOS_HIDDEN); - } - else - { - if (wrap) - los = LOS_HIDDEN | (direction == 1? LOS_FLIPHV : LOS_FLIPVH); - else - los |= LOS_HIDDEN; - } - } - - onlyVis = (los & LOS_VISIBLE); - onlyHidden = (los & LOS_HIDDEN); - - int radius = 0; - if (crawl_view.viewsz.x > crawl_view.viewsz.y) - radius = crawl_view.viewsz.x - LOS_RADIUS - 1; - else - radius = crawl_view.viewsz.y - LOS_RADIUS - 1; - - const coord_def vyou = grid2view(you.pos()); - - const int minx = vyou.x - radius, maxx = vyou.x + radius, - miny = vyou.y - radius, maxy = vyou.y + radius, - ctrx = vyou.x, ctry = vyou.y; - - while (temp_xps >= minx - 1 && temp_xps <= maxx - && temp_yps <= maxy && temp_yps >= miny - 1) - { - if (direction == 1 && temp_xps == minx && temp_yps == maxy) - { - if (find_targ(you.x_pos, you.y_pos, mode, range)) - { - mfp[0] = ctrx; - mfp[1] = ctry; - return (1); - } - return find_square(ctrx, ctry, mfp, direction, find_targ, mode, - range, false, next_los(direction, los, wrap)); - } - if (direction == -1 && temp_xps == ctrx && temp_yps == ctry) - { - return find_square(minx, maxy, mfp, direction, find_targ, mode, - range, false, next_los(direction, los, wrap)); - } - - if (direction == 1) - { - if (temp_xps == minx - 1) - { - x_change = 0; - y_change = -1; - } - else if (temp_xps == ctrx && temp_yps == ctry) - { - x_change = -1; - y_change = 0; - } - else if (abs(temp_xps - ctrx) <= abs(temp_yps - ctry)) - { - if (temp_xps - ctrx >= 0 && temp_yps - ctry <= 0) - { - if (abs(temp_xps - ctrx) > abs(temp_yps - ctry + 1)) - { - x_change = 0; - y_change = -1; - if (temp_xps - ctrx > 0) - y_change = 1; - goto finished_spiralling; - } - } - x_change = -1; - if (temp_yps - ctry < 0) - x_change = 1; - y_change = 0; - } - else - { - x_change = 0; - y_change = -1; - if (temp_xps - ctrx > 0) - y_change = 1; - } - } // end if (direction == 1) - else - { - /* - This part checks all eight surrounding squares to find the - one that leads on to the present square. - */ - for (i = -1; i < 2; i++) - { - for (j = -1; j < 2; j++) - { - if (i == 0 && j == 0) - continue; - - if (temp_xps + i == minx - 1) - { - x_change = 0; - y_change = -1; - } - else if (temp_xps + i - ctrx == 0 && temp_yps + j - ctry == 0) - { - x_change = -1; - y_change = 0; - } - else if (abs(temp_xps + i - ctrx) <= abs(temp_yps + j - ctry)) - { - const int xi = temp_xps + i - ctrx; - const int yj = temp_yps + j - ctry; - - if (xi >= 0 && yj <= 0 - && abs(xi) > abs(yj + 1)) - { - x_change = 0; - y_change = -1; - if (xi > 0) - y_change = 1; - goto finished_spiralling; - } - - x_change = -1; - if (yj < 0) - x_change = 1; - y_change = 0; - } - else - { - x_change = 0; - y_change = -1; - if (temp_xps + i - ctrx > 0) - y_change = 1; - } - - if (temp_xps + i + x_change == temp_xps - && temp_yps + j + y_change == temp_yps) - { - goto finished_spiralling; - } - } - } - } // end else - - - finished_spiralling: - x_change *= direction; - y_change *= direction; - - temp_xps += x_change; - if (temp_yps + y_change <= maxy) // it can wrap, unfortunately - temp_yps += y_change; - - const int targ_x = you.x_pos + temp_xps - ctrx; - const int targ_y = you.y_pos + temp_yps - ctry; - - // We don't want to be looking outside the bounds of the arrays: - //if (!in_los_bounds(temp_xps, temp_yps)) - // continue; - - if (!crawl_view.in_grid_viewport(coord_def(targ_x, targ_y))) - continue; - - if (!in_bounds(targ_x, targ_y)) - continue; - - if ((onlyVis || onlyHidden) && onlyVis != in_los(targ_x, targ_y)) - continue; - - if (find_targ(targ_x, targ_y, mode, range)) - { - mfp[0] = temp_xps; - mfp[1] = temp_yps; - return (1); - } - } - - return (direction == 1? - find_square(ctrx, ctry, mfp, direction, find_targ, mode, range, false, - next_los(direction, los, wrap)) - : find_square(minx, maxy, mfp, direction, find_targ, mode, range, false, - next_los(direction, los, wrap))); -} - -// XXX Unbelievably hacky. And to think that my goal was to clean up the code. -// Identical to find_square, except that input (tx, ty) and output -// (mfp) are in grid coordinates rather than view coordinates. -static char find_square_wrapper( int tx, int ty, - FixedVector &mfp, char direction, - bool (*find_targ)( int x, int y, int mode, - int range ), - int mode, int range, bool wrap, int los ) -{ - const char r = find_square(grid2viewX(tx), grid2viewY(ty), mfp, - direction, find_targ, mode, range, wrap, los); - mfp[0] = view2gridX(mfp[0]); - mfp[1] = view2gridY(mfp[1]); - return r; -} - -static void describe_feature(int mx, int my, bool oos) -{ - if (oos && !is_terrain_seen(mx, my)) - return; - - dungeon_feature_type grid = grd[mx][my]; - if ( grid == DNGN_SECRET_DOOR ) - grid = grid_secret_door_appearance(mx, my); - - std::string desc = feature_description(grid); - if (desc.length()) - { - if (oos) - desc = "[" + desc + "]"; - - msg_channel_type channel = MSGCH_EXAMINE; - if (oos || grid == DNGN_FLOOR) - channel = MSGCH_EXAMINE_FILTER; - - mpr(desc.c_str(), channel); - } -} - -// Returns a vector of features matching the given pattern. -std::vector features_by_desc(const base_pattern &pattern) -{ - std::vector features; - - if (pattern.valid()) - { - for (int i = 0; i < NUM_FEATURES; ++i) - { - std::string fdesc = - feature_description(static_cast(i)); - if (fdesc.empty()) - continue; - - if (pattern.matches( fdesc )) - features.push_back( dungeon_feature_type(i) ); - } - } - return (features); -} - -void describe_floor() -{ - const int grid = grd(you.pos()); - - std::string prefix = "There is "; - std::string feat; - std::string suffix = " here."; - switch (grid) - { - case DNGN_FLOOR: - case DNGN_FLOOR_SPECIAL: - return; - - case DNGN_ENTER_SHOP: - prefix = "There is an entrance to "; - break; - - default: - break; - } - - feat = feature_description(you.x_pos, you.y_pos, - is_bloodcovered(you.x_pos, you.y_pos), - DESC_NOCAP_A, false); - if (feat.empty()) - return; - - msg_channel_type channel = MSGCH_EXAMINE; - - // water is not terribly important if you don't mind it - if ((grd[you.x_pos][you.y_pos] == DNGN_DEEP_WATER - || grd[you.x_pos][you.y_pos] == DNGN_SHALLOW_WATER) - && player_likes_water()) - { - channel = MSGCH_EXAMINE_FILTER; - } - mpr((prefix + feat + suffix).c_str(), channel); - if (grid == DNGN_ENTER_LABYRINTH && you.is_undead != US_UNDEAD) - mpr("Beware, for starvation awaits!", MSGCH_EXAMINE); -} - -static std::string feature_do_grammar(description_level_type dtype, - bool add_stop, - bool force_article, - std::string desc) -{ - if (add_stop) - desc += "."; - if (dtype == DESC_PLAIN || (!force_article && isupper(desc[0]))) - { - if (isupper(desc[0])) - { - switch (dtype) - { - case DESC_PLAIN: case DESC_NOCAP_THE: case DESC_NOCAP_A: - desc[0] = tolower(desc[0]); - break; - default: - break; - } - } - return (desc); - } - - switch (dtype) - { - case DESC_CAP_THE: - return "The " + desc; - case DESC_NOCAP_THE: - return "the " + desc; - case DESC_CAP_A: - return article_a(desc, false); - case DESC_NOCAP_A: - return article_a(desc, true); - case DESC_NONE: - return (""); - default: - return (desc); - } -} - -std::string feature_description(dungeon_feature_type grid, - trap_type trap, bool bloody, - description_level_type dtype, - bool add_stop) -{ - std::string desc = raw_feature_description(grid, trap); - if (bloody) - desc += ", spattered with blood"; - - return feature_do_grammar(dtype, add_stop, grid_is_trap(grid), desc); -} - -std::string raw_feature_description(dungeon_feature_type grid, - trap_type trap) -{ - if (grid_is_trap(grid) && trap != NUM_TRAPS) - { - switch (trap) - { - case TRAP_DART: - return ("dart trap"); - case TRAP_ARROW: - return ("arrow trap"); - case TRAP_SPEAR: - return ("spear trap"); - case TRAP_AXE: - return ("axe trap"); - case TRAP_TELEPORT: - return ("teleportation trap"); - case TRAP_ALARM: - return ("alarm trap"); - case TRAP_BLADE: - return ("blade trap"); - case TRAP_BOLT: - return ("bolt trap"); - case TRAP_NET: - return ("net trap"); - case TRAP_ZOT: - return ("Zot trap"); - case TRAP_NEEDLE: - return ("needle trap"); - case TRAP_SHAFT: - return ("shaft"); - default: - error_message_to_player(); - return ("undefined trap"); - } - } - - switch (grid) - { - case DNGN_STONE_WALL: - return ("stone wall"); - case DNGN_ROCK_WALL: - case DNGN_SECRET_DOOR: - if (you.level_type == LEVEL_PANDEMONIUM) - return ("wall of the weird stuff which makes up Pandemonium"); - else - return ("rock wall"); - case DNGN_PERMAROCK_WALL: - return ("unnaturally hard rock wall"); - case DNGN_CLOSED_DOOR: - return ("closed door"); - case DNGN_METAL_WALL: - return ("metal wall"); - case DNGN_GREEN_CRYSTAL_WALL: - return ("wall of green crystal"); - case DNGN_CLEAR_ROCK_WALL: - return ("translucent rock wall"); - case DNGN_CLEAR_STONE_WALL: - return ("translucent stone wall"); - case DNGN_CLEAR_PERMAROCK_WALL: - return ("translucent unnaturally hard rock wall"); - case DNGN_ORCISH_IDOL: - if (you.species == SP_HILL_ORC) - return ("idol of Beogh"); - else - return ("orcish idol"); - case DNGN_WAX_WALL: - return ("wall of solid wax"); - case DNGN_GRANITE_STATUE: - return ("granite statue"); - case DNGN_LAVA: - return ("Some lava"); - case DNGN_DEEP_WATER: - return ("Some deep water"); - case DNGN_SHALLOW_WATER: - return ("Some shallow water"); - case DNGN_UNDISCOVERED_TRAP: - case DNGN_FLOOR: - case DNGN_FLOOR_SPECIAL: - return ("Floor"); - case DNGN_OPEN_DOOR: - return ("open door"); - case DNGN_ESCAPE_HATCH_DOWN: - return ("escape hatch in the floor"); - case DNGN_ESCAPE_HATCH_UP: - return ("escape hatch in the ceiling"); - case DNGN_STONE_STAIRS_DOWN_I: - case DNGN_STONE_STAIRS_DOWN_II: - case DNGN_STONE_STAIRS_DOWN_III: - return ("stone staircase leading down"); - case DNGN_STONE_STAIRS_UP_I: - case DNGN_STONE_STAIRS_UP_II: - case DNGN_STONE_STAIRS_UP_III: - return ("stone staircase leading up"); - case DNGN_ENTER_HELL: - return ("gateway to Hell"); - case DNGN_TRAP_MECHANICAL: - return ("mechanical trap"); - case DNGN_TRAP_MAGICAL: - return ("magical trap"); - case DNGN_TRAP_NATURAL: - return ("natural trap"); - case DNGN_ENTER_SHOP: - return ("shop"); - case DNGN_ENTER_LABYRINTH: - return ("labyrinth entrance"); - case DNGN_ENTER_DIS: - return ("gateway to the Iron City of Dis"); - case DNGN_ENTER_GEHENNA: - return ("gateway to Gehenna"); - case DNGN_ENTER_COCYTUS: - return ("gateway to the freezing wastes of Cocytus"); - case DNGN_ENTER_TARTARUS: - return ("gateway to the decaying netherworld of Tartarus"); - case DNGN_ENTER_ABYSS: - return ("one-way gate to the infinite horrors of the Abyss"); - case DNGN_EXIT_ABYSS: - return ("gateway leading out of the Abyss"); - case DNGN_STONE_ARCH: - return ("empty arch of ancient stone"); - case DNGN_ENTER_PANDEMONIUM: - return ("gate leading to the halls of Pandemonium"); - case DNGN_EXIT_PANDEMONIUM: - return ("gate leading out of Pandemonium"); - case DNGN_TRANSIT_PANDEMONIUM: - return ("gate leading to another region of Pandemonium"); - case DNGN_ENTER_ORCISH_MINES: - return ("staircase to the Orcish Mines"); - case DNGN_ENTER_HIVE: - return ("staircase to the Hive"); - case DNGN_ENTER_LAIR: - return ("staircase to the Lair"); - case DNGN_ENTER_SLIME_PITS: - return ("staircase to the Slime Pits"); - case DNGN_ENTER_VAULTS: - return ("staircase to the Vaults"); - case DNGN_ENTER_CRYPT: - return ("staircase to the Crypt"); - case DNGN_ENTER_HALL_OF_BLADES: - return ("staircase to the Hall of Blades"); - case DNGN_ENTER_ZOT: - return ("gate to the Realm of Zot"); - case DNGN_ENTER_TEMPLE: - return ("staircase to the Ecumenical Temple"); - case DNGN_ENTER_SNAKE_PIT: - return ("staircase to the Snake Pit"); - case DNGN_ENTER_ELVEN_HALLS: - return ("staircase to the Elven Halls"); - case DNGN_ENTER_TOMB: - return ("staircase to the Tomb"); - case DNGN_ENTER_SWAMP: - return ("staircase to the Swamp"); - case DNGN_ENTER_SHOALS: - return ("staircase to the Shoals"); - case DNGN_ENTER_PORTAL_VAULT: - return ("gate leading to a distant place"); - case DNGN_EXIT_PORTAL_VAULT: - return ("gate leading back to the Dungeon"); - case DNGN_RETURN_FROM_ORCISH_MINES: - case DNGN_RETURN_FROM_HIVE: - case DNGN_RETURN_FROM_LAIR: - case DNGN_RETURN_FROM_VAULTS: - case DNGN_RETURN_FROM_TEMPLE: - return ("staircase back to the Dungeon"); - case DNGN_RETURN_FROM_SLIME_PITS: - case DNGN_RETURN_FROM_SNAKE_PIT: - case DNGN_RETURN_FROM_SWAMP: - case DNGN_RETURN_FROM_SHOALS: - return ("staircase back to the Lair"); - case DNGN_RETURN_FROM_CRYPT: - case DNGN_RETURN_FROM_HALL_OF_BLADES: - return ("staircase back to the Vaults"); - case DNGN_RETURN_FROM_ELVEN_HALLS: - return ("staircase back to the Mines"); - case DNGN_RETURN_FROM_TOMB: - return ("staircase back to the Crypt"); - case DNGN_RETURN_FROM_ZOT: - return ("gate leading back out of this place"); - case DNGN_ALTAR_ZIN: - return ("glowing white marble altar of Zin"); - case DNGN_ALTAR_SHINING_ONE: - return ("glowing golden altar of the Shining One"); - case DNGN_ALTAR_KIKUBAAQUDGHA: - return ("ancient bone altar of Kikubaaqudgha"); - case DNGN_ALTAR_YREDELEMNUL: - return ("basalt altar of Yredelemnul"); - case DNGN_ALTAR_XOM: - return ("shimmering altar of Xom"); - case DNGN_ALTAR_VEHUMET: - return ("shining altar of Vehumet"); - case DNGN_ALTAR_OKAWARU: - return ("iron altar of Okawaru"); - case DNGN_ALTAR_MAKHLEB: - return ("burning altar of Makhleb"); - case DNGN_ALTAR_SIF_MUNA: - return ("deep blue altar of Sif Muna"); - case DNGN_ALTAR_TROG: - return ("bloodstained altar of Trog"); - case DNGN_ALTAR_NEMELEX_XOBEH: - return ("sparkling altar of Nemelex Xobeh"); - case DNGN_ALTAR_ELYVILON: - return ("silver altar of Elyvilon"); - case DNGN_ALTAR_LUGONU: - return ("corrupted altar of Lugonu"); - case DNGN_ALTAR_BEOGH: - return ("roughly hewn altar of Beogh"); - case DNGN_FOUNTAIN_BLUE: - return ("fountain of clear blue water"); - case DNGN_FOUNTAIN_SPARKLING: - return ("fountain of sparkling water"); - case DNGN_FOUNTAIN_BLOOD: - return ("fountain of blood"); - case DNGN_DRY_FOUNTAIN_BLUE: - case DNGN_DRY_FOUNTAIN_SPARKLING: - case DNGN_DRY_FOUNTAIN_BLOOD: - case DNGN_PERMADRY_FOUNTAIN: - return ("dry fountain"); - default: - return (""); - } -} - -static std::string marker_feature_description(const coord_def &p) -{ - std::vector markers = env.markers.get_markers_at(p); - for (int i = 0, size = markers.size(); i < size; ++i) - { - const std::string desc = markers[i]->feature_description(); - if (!desc.empty()) - return (desc); - } - return (""); -} - -#ifndef DEBUG_DIAGNOSTICS -// Is a feature interesting enough to 'v'iew it, even if a player normally -// doesn't care about descriptions, i.e. does the description hold important -// information? (Yes, this is entirely subjective. JPEG) - -static bool interesting_feature(dungeon_feature_type feat) -{ - return (get_feature_def(feat).flags & FFT_EXAMINE_HINT); -} -#endif - -std::string feature_description(int mx, int my, bool bloody, - description_level_type dtype, bool add_stop) -{ - dungeon_feature_type grid = grd[mx][my]; - if ( grid == DNGN_SECRET_DOOR ) - grid = grid_secret_door_appearance(mx, my); - - if ( grid == DNGN_OPEN_DOOR || grid == DNGN_CLOSED_DOOR ) - { - std::set all_door; - find_connected_identical(coord_def(mx, my), grd[mx][my], all_door); - const char *adj, *noun; - get_door_description(all_door.size(), &adj, &noun); - - std::string desc = adj; - desc += (grid == DNGN_OPEN_DOOR) ? "open " : "closed "; - desc += noun; - - if (bloody) - desc += ", spattered with blood"; - - return feature_do_grammar(dtype, add_stop, false, desc); - } - - switch (grid) - { - case DNGN_TRAP_MECHANICAL: - case DNGN_TRAP_MAGICAL: - case DNGN_TRAP_NATURAL: - return (feature_description(grid, trap_type_at_xy(mx, my), bloody, - dtype, add_stop)); - case DNGN_ENTER_SHOP: - return (shop_name(mx, my, add_stop)); - - case DNGN_ENTER_PORTAL_VAULT: - return (feature_do_grammar( - dtype, add_stop, false, - marker_feature_description(coord_def(mx, my)))); - default: - return (feature_description(grid, NUM_TRAPS, bloody, dtype, add_stop)); - } -} - -static std::string describe_mons_enchantment(const monsters &mons, - const mon_enchant &ench, - bool paralysed) -{ - // Suppress silly-looking combinations, even if they're - // internally valid. - if (paralysed && (ench.ench == ENCH_SLOW || ench.ench == ENCH_HASTE)) - return ""; - - if ((ench.ench == ENCH_HASTE || ench.ench == ENCH_BATTLE_FRENZY) - && mons.has_ench(ENCH_BERSERK)) - { - return ""; - } - - switch (ench.ench) - { - case ENCH_POISON: - return "poisoned"; - case ENCH_SICK: - return "sick"; - case ENCH_ROT: - return "rotting away"; //jmf: "covered in sores"? - case ENCH_BACKLIGHT: - return "softly glowing"; - case ENCH_SLOW: - return "moving slowly"; - case ENCH_BERSERK: - return "berserk"; - case ENCH_BATTLE_FRENZY: - return "consumed by blood-lust"; - case ENCH_HASTE: - return "moving very quickly"; - case ENCH_CONFUSION: - return "bewildered and confused"; - case ENCH_INVIS: - return "slightly transparent"; - case ENCH_CHARM: - return "in your thrall"; - case ENCH_STICKY_FLAME: - return "covered in liquid flames"; - case ENCH_HELD: - return "entangled in a net"; - default: - return ""; - } // end switch -} - -static std::string describe_monster_weapon(const monsters *mons) -{ - std::string desc = ""; - std::string name1, name2; - const item_def *weap = mons->mslot_item(MSLOT_WEAPON); - const item_def *alt = mons->mslot_item(MSLOT_ALT_WEAPON); - - if (weap) - name1 = weap->name(DESC_NOCAP_A, false, false, true, - false, ISFLAG_KNOW_CURSE); - if (alt && (!weap || mons_wields_two_weapons(mons))) - name2 = alt->name(DESC_NOCAP_A, false, false, true, - false, ISFLAG_KNOW_CURSE); - - if (name1.empty() && !name2.empty()) - name1.swap(name2); - - if (name1 == name2 && weap) - { - item_def dup = *weap; - ++dup.quantity; - name1 = dup.name(DESC_NOCAP_A, false, false, true, true, - ISFLAG_KNOW_CURSE); - name2.clear(); - } - - if (name1.empty()) - return (desc); - - desc += " wielding "; - desc += name1; - - if (!name2.empty()) - { - desc += " and "; - desc += name2; - } - - return (desc); -} - -#ifdef DEBUG_DIAGNOSTICS -static std::string stair_destination_description(const coord_def &pos) -{ - if (LevelInfo *linf = travel_cache.find_level_info(level_id::current())) - { - const stair_info *si = linf->get_stair(pos); - if (si) - return (" " + si->describe()); - else if (is_stair(grd(pos))) - return (" (unknown stair)"); - } - return (""); -} -#endif - -static void describe_monster(const monsters *mon) -{ - - // first print type and equipment - std::string text = get_monster_desc(mon); - text += "."; - print_formatted_paragraph(text, get_number_of_cols()); - - if (player_beheld_by(mon)) - mpr("You are beheld by her song.", MSGCH_EXAMINE); - - if (mon->type == MONS_HYDRA) - { - mprf(MSGCH_EXAMINE, "It has %d head%s.", mon->number, - (mon->number > 1? "s" : "")); - } - - print_wounds(mon); - - if (!mons_is_mimic(mon->type) && mons_behaviour_perceptible(mon)) - { - if (mon->behaviour == BEH_SLEEP) - { - mprf(MSGCH_EXAMINE, "%s appears to be resting.", - mon->pronoun(PRONOUN_CAP).c_str()); - } - // Applies to both friendlies and hostiles - else if (mon->behaviour == BEH_FLEE) - { - mprf(MSGCH_EXAMINE, "%s is retreating.", - mon->pronoun(PRONOUN_CAP).c_str()); - } - // hostile with target != you - else if (!mons_friendly(mon) && !mons_neutral(mon) && mon->foe != MHITYOU) - { - // special case: batty monsters get set to BEH_WANDER as - // part of their special behaviour. - if (!testbits(mon->flags, MF_BATTY)) - { - mprf(MSGCH_EXAMINE, "%s doesn't appear to have noticed you.", - mon->pronoun(PRONOUN_CAP).c_str()); - } - } - } - - if (mon->attitude == ATT_FRIENDLY) - { - mprf(MSGCH_EXAMINE, "%s is friendly.", - mon->pronoun(PRONOUN_CAP).c_str()); - } - else if (mons_neutral(mon)) // don't differentiate between permanent or not - { - mprf(MSGCH_EXAMINE, "%s is indifferent to you.", - mon->pronoun(PRONOUN_CAP).c_str()); - } - - if (mon->haloed()) - { - mprf(MSGCH_EXAMINE, "%s is illuminated by a halo.", - mon->pronoun(PRONOUN_CAP).c_str()); - } - - std::string desc = ""; - std::string last_desc = ""; - std::string tmp = ""; - - const bool paralysed = mons_is_paralysed(mon); - if (paralysed) - last_desc += "paralysed"; - - for (mon_enchant_list::const_iterator e = mon->enchantments.begin(); - e != mon->enchantments.end(); ++e) - { - tmp = describe_mons_enchantment(*mon, e->second, paralysed); - if (!tmp.empty()) - { - if (!desc.empty()) - desc += ", "; - desc += last_desc; - last_desc = tmp; - } - } - - if (!last_desc.empty()) - { - if (!desc.empty()) - desc += ", and "; - desc += last_desc; - } - - if (!desc.empty()) - { - text = mon->pronoun(PRONOUN_CAP); - text += " is "; - text += desc; - text += "."; - print_formatted_paragraph(text, get_number_of_cols()); - } -} - -std::string get_monster_desc(const monsters *mon, bool full_desc, - description_level_type mondtype) -{ - std::string desc = mon->name(mondtype); - - const int mon_arm = mon->inv[MSLOT_ARMOUR]; - std::string weap = ""; - - if (mon->type != MONS_DANCING_WEAPON) - weap = describe_monster_weapon(mon); - - if (!weap.empty()) - { - if (full_desc) - desc += ","; - desc += weap; - } - - if (full_desc && mon_arm != NON_ITEM) - { - desc += ", "; - if (!weap.empty()) - desc += "and "; - desc += "wearing "; - desc += mitm[mon_arm].name(DESC_NOCAP_A); - } - - return desc; -} - -static void describe_cell(int mx, int my) -{ - bool mimic_item = false; - bool monster_described = false; - bool cloud_described = false; - bool item_described = false; - - if (mx == you.x_pos && my == you.y_pos) - mpr("You.", MSGCH_EXAMINE_FILTER); - - if (mgrd[mx][my] != NON_MONSTER) - { - int i = mgrd[mx][my]; - - if (_mon_submerged_in_water(&menv[i])) - { - mpr("There is a strange disturbance in the water here.", - MSGCH_EXAMINE_FILTER); - } - -#if DEBUG_DIAGNOSTICS - if (!player_monster_visible( &menv[i] )) - mpr( "There is a non-visible monster here.", MSGCH_DIAGNOSTICS ); -#else - if (!player_monster_visible( &menv[i] )) - goto look_clouds; -#endif - - describe_monster(&menv[i]); - - if (mons_is_mimic( menv[i].type )) - { - mimic_item = true; - item_described = true; - } - else - monster_described = true; - -#if DEBUG_DIAGNOSTICS - stethoscope(i); -#endif - if (Options.tutorial_left && tutorial_monster_interesting(&menv[i])) - { - std::string msg = "(Press v for more information.)"; - print_formatted_paragraph(msg, get_number_of_cols()); - } - } - -#if (!DEBUG_DIAGNOSTICS) - // removing warning - look_clouds: -#endif - - if (is_sanctuary(mx, my)) - mpr("This square lies inside a sanctuary."); - - if (env.cgrid[mx][my] != EMPTY_CLOUD) - { - const int cloud_inspected = env.cgrid[mx][my]; - const cloud_type ctype = (cloud_type) env.cloud[cloud_inspected].type; - - mprf(MSGCH_EXAMINE, "There is a cloud of %s here.", - cloud_name(ctype).c_str()); - - cloud_described = true; - } - - int targ_item = igrd[ mx ][ my ]; - - if (targ_item != NON_ITEM) - { - // If a mimic is on this square, we pretend it's the first item -- bwr - if (mimic_item) - mpr("There is something else lying underneath.", MSGCH_FLOOR_ITEMS); - else - { - if (mitm[ targ_item ].base_type == OBJ_GOLD) - mprf( MSGCH_FLOOR_ITEMS, "A pile of gold coins." ); - else - { - mprf( MSGCH_FLOOR_ITEMS, "You see %s here.", - mitm[targ_item].name(DESC_NOCAP_A).c_str()); - } - - if (mitm[ targ_item ].link != NON_ITEM) - { - mprf( MSGCH_FLOOR_ITEMS, - "There is something else lying underneath."); - } - } - item_described = true; - } - - bool bloody = false; - if (is_bloodcovered(mx, my)) - bloody = true; - - std::string feature_desc = feature_description(mx, my, bloody); -#ifdef DEBUG_DIAGNOSTICS - std::string marker; - if (map_marker *mark = env.markers.find(coord_def(mx, my), MAT_ANY)) - { - std::string desc = mark->debug_describe(); - if (desc.empty()) - desc = "?"; - marker = " (" + desc + ")"; - } - const std::string traveldest = - stair_destination_description(coord_def(mx, my)); - const dungeon_feature_type feat = grd[mx][my]; - mprf(MSGCH_DIAGNOSTICS, "(%d,%d): %s - %s (%d/%s)%s%s", mx, my, - stringize_glyph(get_screen_glyph(mx, my)).c_str(), - feature_desc.c_str(), - feat, - dungeon_feature_name(feat), - marker.c_str(), - traveldest.c_str()); -#else - if (Options.tutorial_left && tutorial_feat_interesting(grd[mx][my])) - { - feature_desc += " (Press v for more information.)"; - - print_formatted_paragraph(feature_desc, get_number_of_cols()); - } - else - { - const dungeon_feature_type feat = grd[mx][my]; - - if (interesting_feature(feat)) - feature_desc += " (Press 'v' for more information.)"; - - // Suppress "Floor." if there's something on that square that we've - // already described. - if ((feat == DNGN_FLOOR || feat == DNGN_FLOOR_SPECIAL) && !bloody - && (monster_described || item_described || cloud_described)) - { - return; - } - - msg_channel_type channel = MSGCH_EXAMINE; - if (feat == DNGN_FLOOR - || feat == DNGN_FLOOR_SPECIAL - || feat == DNGN_SHALLOW_WATER - || feat == DNGN_DEEP_WATER) - { - channel = MSGCH_EXAMINE_FILTER; - } - mpr(feature_desc.c_str(), channel); - } -#endif -} - -/////////////////////////////////////////////////////////////////////////// -// targeting_behaviour - -targeting_behaviour::targeting_behaviour(bool look_around) - : just_looking(look_around), compass(false) -{ -} - -targeting_behaviour::~targeting_behaviour() -{ -} - -int targeting_behaviour::get_key() -{ -#ifdef USE_TILE - mouse_control mc(MOUSE_MODE_TARGET_DIR); -#endif - - if (!crawl_state.is_replaying_keys()) - flush_input_buffer(FLUSH_BEFORE_COMMAND); - - return unmangle_direction_keys( getchm(KC_TARGETING), KC_TARGETING, - false, false); -} - -command_type targeting_behaviour::get_command(int key) -{ - if (key == -1) - key = get_key(); - - switch ( key ) - { - case ESCAPE: - case 'x': return CMD_TARGET_CANCEL; - -#ifdef USE_TILE - case CK_MOUSE_MOVE: return CMD_TARGET_MOUSE_MOVE; - case CK_MOUSE_CLICK: return CMD_TARGET_MOUSE_SELECT; -#endif - -#ifdef WIZARD - case 'F': return CMD_TARGET_WIZARD_MAKE_FRIENDLY; - case 's': return CMD_TARGET_WIZARD_MAKE_SHOUT; - case 'g': return CMD_TARGET_WIZARD_GIVE_ITEM; -#endif - case 'v': return CMD_TARGET_DESCRIBE; - case '?': return CMD_TARGET_HELP; - case ' ': return just_looking? CMD_TARGET_CANCEL : CMD_TARGET_SELECT; -#ifdef WIZARD - case CONTROL('C'): return CMD_TARGET_CYCLE_BEAM; -#endif - case ':': return CMD_TARGET_HIDE_BEAM; - case '\r': return CMD_TARGET_SELECT; - case '.': return CMD_TARGET_SELECT; - case '5': return CMD_TARGET_SELECT; - case '!': return CMD_TARGET_SELECT_ENDPOINT; - - case '\\': - case '\t': return CMD_TARGET_FIND_PORTAL; - case '^': return CMD_TARGET_FIND_TRAP; - case '_': return CMD_TARGET_FIND_ALTAR; - case '<': return CMD_TARGET_FIND_UPSTAIR; - case '>': return CMD_TARGET_FIND_DOWNSTAIR; - - case CONTROL('F'): return CMD_TARGET_CYCLE_TARGET_MODE; - case 'p': return CMD_TARGET_PREV_TARGET; - case 'f': return CMD_TARGET_MAYBE_PREV_TARGET; - case 't': return CMD_TARGET_MAYBE_PREV_TARGET; // for the 0.3.4 keys - - case '-': return CMD_TARGET_CYCLE_BACK; - case '+': - case '=': return CMD_TARGET_CYCLE_FORWARD; - case ';': - case '/': return CMD_TARGET_OBJ_CYCLE_BACK; - case '*': - case '\'': return CMD_TARGET_OBJ_CYCLE_FORWARD; - - case 'b': return CMD_TARGET_DOWN_LEFT; - case 'h': return CMD_TARGET_LEFT; - case 'j': return CMD_TARGET_DOWN; - case 'k': return CMD_TARGET_UP; - case 'l': return CMD_TARGET_RIGHT; - case 'n': return CMD_TARGET_DOWN_RIGHT; - case 'u': return CMD_TARGET_UP_RIGHT; - case 'y': return CMD_TARGET_UP_LEFT; - - case 'B': return CMD_TARGET_DIR_DOWN_LEFT; - case 'H': return CMD_TARGET_DIR_LEFT; - case 'J': return CMD_TARGET_DIR_DOWN; - case 'K': return CMD_TARGET_DIR_UP; - case 'L': return CMD_TARGET_DIR_RIGHT; - case 'N': return CMD_TARGET_DIR_DOWN_RIGHT; - case 'U': return CMD_TARGET_DIR_UP_RIGHT; - case 'Y': return CMD_TARGET_DIR_UP_LEFT; - - default: return CMD_NO_CMD; - } -} - -bool targeting_behaviour::should_redraw() -{ - return (false); -} diff --git a/crawl-ref/source/direct.h b/crawl-ref/source/direct.h deleted file mode 100644 index bf060d1d61..0000000000 --- a/crawl-ref/source/direct.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - * File: direct.h - * Summary: Functions used when picking squares. - * Written by: Linley Henzell - * - * Modified for Crawl Reference by $Author$ on $Date$ - * - * Change History (most recent first): - * - * <1> -/--/-- LRH Created - */ - - -#ifndef DIRECT_H -#define DIRECT_H - -#include "externs.h" -#include "enum.h" -#include "libgui.h" -#include "ray.h" - -class crawl_view_buffer -{ -public: - crawl_view_buffer(); - ~crawl_view_buffer(); - void size(const coord_def &size); - operator screen_buffer_t * () { return (buffer); } - - void draw(); -private: - screen_buffer_t *buffer; -}; - -// last updated 12may2000 {dlb} -/* *********************************************************************** - * called from: acr - debug - effects - it_use3 - item_use - spells1 - - * spells2 - spells3 - spells4 - * *********************************************************************** */ -struct crawl_view_geometry -{ -public: - coord_def termp; // Left-top pos of terminal. - coord_def termsz; // Size of the terminal. - coord_def viewp; // Left-top pos of viewport. - coord_def viewsz; // Size of the viewport (play area). - coord_def hudp; // Left-top pos of status area. - coord_def hudsz; // Size of the status area. - coord_def msgp; // Left-top pos of the message pane. - coord_def msgsz; // Size of the message pane. - coord_def mlistp; // Left-top pos of the monster list. - coord_def mlistsz; // Size of the monster list. - - crawl_view_buffer vbuf; // Buffer for drawing the main game map. - - coord_def vgrdc; // What grid pos is at the centre of the view - // usually you.pos(). - - coord_def viewhalfsz; - - coord_def glos1, glos2; // LOS limit grid coords (inclusive) - coord_def vlos1, vlos2; // LOS limit viewport coords (inclusive) - - coord_def mousep; // Where the mouse is. - -private: - coord_def last_player_pos; - -public: - crawl_view_geometry(); - void init_geometry(); - - void init_view(); - void set_player_at(const coord_def &c, bool force_centre = false); - - coord_def view_centre() const - { - return viewp + viewhalfsz; - } - - bool in_grid_los(const coord_def &c) const - { - return (c.x >= glos1.x && c.x <= glos2.x - && c.y >= glos1.y && c.y <= glos2.y); - } - - bool in_view_los(const coord_def &c) const - { - return (c.x >= vlos1.x && c.x <= vlos2.x - && c.y >= vlos1.y && c.y <= vlos2.y); - } - - bool in_view_viewport(const coord_def &c) const - { - return (c.x >= viewp.x && c.y >= viewp.y - && c.x < viewp.x + viewsz.x - && c.y < viewp.y + viewsz.y); - } - - bool in_grid_viewport(const coord_def &c) const - { - return in_view_viewport(c - vgrdc + view_centre()); - } -}; - -extern crawl_view_geometry crawl_view; - -// An object that modifies the behaviour of the direction prompt. -class targeting_behaviour -{ -public: - targeting_behaviour(bool just_looking = false); - virtual ~targeting_behaviour(); - - // Returns a keystroke for the prompt. - virtual int get_key(); - virtual command_type get_command(int key = -1); - virtual bool should_redraw(); - -public: - bool just_looking; - bool compass; -}; - -// output from direction() function: -struct dist -{ - bool isValid; // valid target chosen? - bool isTarget; // target (true), or direction (false)? - bool isMe; // selected self (convenience: tx == you.x_pos, - // ty == you.y_pos) - bool isEndpoint; // Does the player want the attack to stop at (tx,ty)? - bool isCancel; // user cancelled (usually key) - bool choseRay; // user wants a specific beam - int tx,ty; // target x,y or logical extension of beam to map edge - int dx,dy; // delta x and y if direction - always -1,0,1 - ray_def ray; // ray chosen if necessary - - // internal use - ignore - int prev_target; // previous target - - // target - source (source == you.pos()) - coord_def target() const - { - return coord_def(tx, ty); - } -}; - -void direction( dist &moves, targeting_type restricts = DIR_NONE, - targ_mode_type mode = TARG_ANY, int range = -1, - bool just_looking = false, bool needs_path = true, - const char *prompt = NULL, targeting_behaviour *mod = NULL ); - -bool in_los_bounds(int x, int y); -bool in_viewport_bounds(int x, int y); -bool in_los(int x, int y); -bool in_vlos(int x, int y); -bool in_vlos(const coord_def &pos); - -void terse_describe_square(const coord_def &c); -void full_describe_square(const coord_def &c); -void describe_floor(); -std::string get_monster_desc(const monsters *mon, - bool full_desc = true, - description_level_type mondtype = DESC_CAP_A); - -int dos_direction_unmunge(int doskey); - -std::string feature_description(int mx, int my, bool bloody = false, - description_level_type dtype = DESC_CAP_A, - bool add_stop = true); -std::string raw_feature_description(dungeon_feature_type grid, - trap_type tr = NUM_TRAPS); -std::string feature_description(dungeon_feature_type grid, - trap_type trap = NUM_TRAPS, bool bloody = false, - description_level_type dtype = DESC_CAP_A, - bool add_stop = true); - -std::vector features_by_desc(const base_pattern &pattern); - -inline int view2gridX(int vx) -{ - return (crawl_view.vgrdc.x + vx - crawl_view.view_centre().x); -} - -inline int view2gridY(int vy) -{ - return (crawl_view.vgrdc.y + vy - crawl_view.view_centre().y); -} - -inline coord_def view2grid(const coord_def &pos) -{ - return pos - crawl_view.view_centre() + crawl_view.vgrdc; -} - -inline int grid2viewX(int gx) -{ - return (gx - crawl_view.vgrdc.x + crawl_view.view_centre().x); -} - -inline int grid2viewY(int gy) -{ - return (gy - crawl_view.vgrdc.y + crawl_view.view_centre().y); -} - -inline coord_def grid2view(const coord_def &pos) -{ - return (pos - crawl_view.vgrdc + crawl_view.view_centre()); -} - -inline coord_def view2show(const coord_def &pos) -{ - return (pos - crawl_view.vlos1 + coord_def(1, 1)); -} - -inline coord_def show2view(const coord_def &pos) -{ - return (pos + crawl_view.vlos1 - coord_def(1, 1)); -} - -inline coord_def grid2show(const coord_def &pos) -{ - return (view2show(grid2view(pos))); -} - -extern const struct coord_def Compass[8]; - -#endif diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc new file mode 100644 index 0000000000..f18e22e0f5 --- /dev/null +++ b/crawl-ref/source/directn.cc @@ -0,0 +1,2436 @@ +/* + * File: direct.cc + * Summary: Functions used when picking squares. + * Written by: Linley Henzell + * + * Modified for Crawl Reference by $Author$ on $Date$ + * + * Change History (most recent first): + * + * <5> 01/08/01 GDL complete rewrite of direction() + * <4> 11/23/99 LRH Looking at monsters now + * displays more info + * <3> 5/12/99 BWR changes to allow for space selection of target. + * CR, ESC, and 't' in targeting. + * <2> 5/09/99 JDJ look_around no longer prints a prompt. + * <1> -/--/-- LRH Created + */ + +#include "AppHdr.h" +#include "directn.h" +#include "format.h" + +#include +#include +#include +#include +#include +#include + +#ifdef DOS + #include +#endif + +#include "externs.h" + +#include "cio.h" +#include "command.h" +#include "debug.h" +#include "describe.h" +#include "dungeon.h" +#include "itemname.h" +#include "mapmark.h" +#include "message.h" +#include "misc.h" +#include "menu.h" +#include "monstuff.h" +#include "mon-util.h" +#include "player.h" +#include "shopping.h" +#include "state.h" +#include "stuff.h" +#include "spells4.h" +#include "stash.h" +#include "tiles.h" +#include "terrain.h" +#include "traps.h" +#include "travel.h" +#include "tutorial.h" +#include "view.h" + +#include "macro.h" + +enum LOSSelect +{ + LOS_ANY = 0x00, + + // Check only visible squares + LOS_VISIBLE = 0x01, + + // Check only hidden squares + LOS_HIDDEN = 0x02, + + LOS_VISMASK = 0x03, + + // Flip from visible to hidden when going forward, + // or hidden to visible when going backwards. + LOS_FLIPVH = 0x20, + + // Flip from hidden to visible when going forward, + // or visible to hidden when going backwards. + LOS_FLIPHV = 0x40, + + LOS_NONE = 0xFFFF +}; + +static void describe_feature(int mx, int my, bool oos); +static void describe_cell(int mx, int my); + +static bool find_object( int x, int y, int mode, int range ); +static bool find_monster( int x, int y, int mode, int range ); +static bool find_feature( int x, int y, int mode, int range ); + +static char find_square_wrapper( int tx, int ty, + FixedVector &mfp, char direction, + bool (*targ)(int, int, int, int), + int mode = TARG_ANY, int range = -1, + bool wrap = false, + int los = LOS_ANY); + +static char find_square( int xps, int yps, + FixedVector &mfp, int direction, + bool (*targ)(int, int, int, int), + int mode = TARG_ANY, int range = -1, + bool wrap = false, + int los = LOS_ANY); + +static int targeting_cmd_to_compass( command_type command ); +static void describe_oos_square(int x, int y); +static void extend_move_to_edge(dist &moves); + +void direction_choose_compass( dist& moves, targeting_behaviour *beh) +{ + moves.isValid = true; + moves.isTarget = false; + moves.isMe = false; + moves.isCancel = false; + moves.dx = moves.dy = 0; + +#ifdef USE_TILE + mouse_control mc(MOUSE_MODE_TARGET_DIR); +#endif + + beh->compass = true; + + do + { + const command_type key_command = beh->get_command(); + + if (key_command == CMD_TARGET_SELECT) + { + moves.dx = moves.dy = 0; + moves.isMe = true; + break; + } + + const int i = targeting_cmd_to_compass(key_command); + if ( i != -1 ) + { + moves.dx = Compass[i].x; + moves.dy = Compass[i].y; + } + else if ( key_command == CMD_TARGET_CANCEL ) + { + moves.isCancel = true; + moves.isValid = false; + } + } + while ( !moves.isCancel && moves.dx == 0 && moves.dy == 0 ); + + return; +} + +static int targeting_cmd_to_compass( command_type command ) +{ + switch ( command ) + { + case CMD_TARGET_UP: case CMD_TARGET_DIR_UP: + return 0; + case CMD_TARGET_UP_RIGHT: case CMD_TARGET_DIR_UP_RIGHT: + return 1; + case CMD_TARGET_RIGHT: case CMD_TARGET_DIR_RIGHT: + return 2; + case CMD_TARGET_DOWN_RIGHT: case CMD_TARGET_DIR_DOWN_RIGHT: + return 3; + case CMD_TARGET_DOWN: case CMD_TARGET_DIR_DOWN: + return 4; + case CMD_TARGET_DOWN_LEFT: case CMD_TARGET_DIR_DOWN_LEFT: + return 5; + case CMD_TARGET_LEFT: case CMD_TARGET_DIR_LEFT: + return 6; + case CMD_TARGET_UP_LEFT: case CMD_TARGET_DIR_UP_LEFT: + return 7; + default: + return -1; + } +} + +static int targeting_cmd_to_feature( command_type command ) +{ + switch ( command ) + { + case CMD_TARGET_FIND_TRAP: + return '^'; + case CMD_TARGET_FIND_PORTAL: + return '\\'; + case CMD_TARGET_FIND_ALTAR: + return '_'; + case CMD_TARGET_FIND_UPSTAIR: + return '<'; + case CMD_TARGET_FIND_DOWNSTAIR: + return '>'; + default: + return 0; + } +} + +static command_type shift_direction(command_type cmd) +{ + switch (cmd) + { + case CMD_TARGET_DOWN_LEFT: return CMD_TARGET_DIR_DOWN_LEFT; + case CMD_TARGET_LEFT: return CMD_TARGET_DIR_LEFT; + case CMD_TARGET_DOWN: return CMD_TARGET_DIR_DOWN; + case CMD_TARGET_UP: return CMD_TARGET_DIR_UP; + case CMD_TARGET_RIGHT: return CMD_TARGET_DIR_RIGHT; + case CMD_TARGET_DOWN_RIGHT: return CMD_TARGET_DIR_DOWN_RIGHT; + case CMD_TARGET_UP_RIGHT: return CMD_TARGET_DIR_UP_RIGHT; + case CMD_TARGET_UP_LEFT: return CMD_TARGET_DIR_UP_LEFT; + default: return (cmd); + } +} + +static const char *target_mode_help_text(int mode) +{ + switch (mode) + { + case DIR_NONE: + return Options.target_unshifted_dirs? "? - help" : + "? - help, Shift-Dir - shoot in a straight line"; + case DIR_TARGET: + return "? - help, Dir - move target cursor"; + default: + return "? - help"; + } +} + +static void draw_ray_glyph(const coord_def &pos, int colour, + int glych, int mcol) +{ +#ifdef USE_TILE + tile_place_ray(pos); +#else + int mid = mgrd(pos); + if (mid != NON_MONSTER) + { + const monsters *mons = &menv[mid]; + if (mons->alive() && player_monster_visible(mons)) + { + glych = get_screen_glyph(pos.x, pos.y); + colour = mcol; + } + } + const coord_def vp = grid2view(pos); + cgotoxy(vp.x, vp.y, GOTO_DNGN); + textcolor( real_colour(colour) ); + putch(glych); +#endif +} + +// Unseen monsters in shallow water show a "strange disturbance". +// (Unless flying!) +static bool _mon_submerged_in_water(const monsters *mon) +{ + if (!mon) + return false; + + return (grd[mon->x][mon->y] == DNGN_SHALLOW_WATER + && see_grid(mon->x, mon->y) + && !player_monster_visible(mon) + && !mons_flies(mon)); +} + +static bool _is_target_in_range(int x, int y, int range) +{ + // range doesn't matter + if (range == -1) + return true; + + return (grid_distance(you.x_pos, you.y_pos, x, y) <= range); +} + +// We handle targeting for repeating commands and re-doing the +// previous command differently (i.e., not just letting the keys +// stuffed into the macro buffer replay as-is) because if the player +// targeted a monster using the movement keys and the monster then +// moved between repititions, then simply replaying the keys in the +// buffer will target an empty square. +static void direction_again(dist& moves, targeting_type restricts, + targ_mode_type mode, int range, bool just_looking, + const char *prompt, targeting_behaviour *beh) +{ + moves.isValid = false; + moves.isTarget = false; + moves.isMe = false; + moves.isCancel = false; + moves.isEndpoint = false; + moves.choseRay = false; + + if (you.prev_targ == MHITNOT && you.prev_grd_targ == coord_def(0, 0)) + { + moves.isCancel = true; + crawl_state.cancel_cmd_repeat(); + return; + } + + int targ_types = 0; + if (you.prev_targ != MHITNOT && you.prev_targ != MHITYOU) + targ_types++; + if (you.prev_targ == MHITYOU) + targ_types++; + if (you.prev_grd_targ != coord_def(0, 0)) + targ_types++; + ASSERT(targ_types == 1); + + // Discard keys until we get to a set-target command + command_type key_command = CMD_NO_CMD; + + while (crawl_state.is_replaying_keys()) + { + key_command = beh->get_command(); + + if (key_command == CMD_TARGET_PREV_TARGET + || key_command == CMD_TARGET_SELECT_ENDPOINT + || key_command == CMD_TARGET_SELECT + || key_command == CMD_TARGET_MAYBE_PREV_TARGET) + { + break; + } + } + + if (!crawl_state.is_replaying_keys()) + { + moves.isCancel = true; + + mpr("Ran out of keys."); + + return; + } + + if (key_command == CMD_TARGET_SELECT_ENDPOINT) + moves.isEndpoint = true; + + if (you.prev_grd_targ != coord_def(0, 0)) + { + if (!see_grid(you.prev_grd_targ)) + { + moves.isCancel = true; + + crawl_state.cancel_cmd_repeat("You can no longer see the dungeon " + "square you previously targeted."); + return; + } + else if (you.prev_grd_targ.x == you.x_pos + && you.prev_grd_targ.y == you.y_pos) + { + moves.isCancel = true; + + crawl_state.cancel_cmd_repeat("You are now standing on your " + "previously targeted dungeon " + "square."); + return; + } + else if (!_is_target_in_range(you.prev_grd_targ.x, you.prev_grd_targ.y, + range)) + { + moves.isCancel = true; + + crawl_state.cancel_cmd_repeat("Your previous target is now out of " + "range."); + return; + } + + moves.tx = you.prev_grd_targ.x; + moves.ty = you.prev_grd_targ.y; + + ray_def ray; + find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, true, ray, + 0, true); + moves.ray = ray; + } + else if (you.prev_targ == MHITYOU) + { + moves.isMe = true; + moves.tx = you.x_pos; + moves.ty = you.y_pos; + + // Discard 'Y' player gave to yesno() + if (mode == TARG_ENEMY) + getchm(); + } + else + { + const monsters *montarget = &menv[you.prev_targ]; + + if (!mons_near(montarget) + || !player_monster_visible( montarget )) + { + moves.isCancel = true; + + crawl_state.cancel_cmd_repeat("Your target is gone."); + + return; + } + else if (!_is_target_in_range(you.prev_grd_targ.x, you.prev_grd_targ.y, + range)) + { + moves.isCancel = true; + + crawl_state.cancel_cmd_repeat("Your previous target is now out of " + "range."); + return; + } + + moves.tx = montarget->x; + moves.ty = montarget->y; + + ray_def ray; + find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, true, ray, + 0, true); + moves.ray = ray; + } + + moves.isValid = true; + moves.isTarget = true; + + return; +} + +//--------------------------------------------------------------- +// +// direction +// +// use restrict == DIR_DIR to allow only a compass direction; +// == DIR_TARGET to allow only choosing a square; +// == DIR_NONE to allow either. +// +// outputs: dist structure: +// +// isValid a valid target or direction was chosen +// isCancel player hit 'escape' +// isTarget targetting was used +// choseRay player wants a specific ray +// ray ...this one +// isEndpoint player wants the ray to stop on the dime +// tx,ty target x,y +// dx,dy direction delta for DIR_DIR +// +//--------------------------------------------------------------- +void direction(dist& moves, targeting_type restricts, + targ_mode_type mode, int range, bool just_looking, + bool needs_path, const char *prompt, + targeting_behaviour *beh) +{ + static targeting_behaviour stock_behaviour; + if (!beh) + beh = &stock_behaviour; + + beh->just_looking = just_looking; + + if (crawl_state.is_replaying_keys() && restricts != DIR_DIR) + { + direction_again(moves, restricts, mode, range, just_looking, + prompt, beh); + return; + } + + // NOTE: Even if just_looking is set, moves is still interesting, + // because we can travel there! + + if ( restricts == DIR_DIR ) + { + direction_choose_compass( moves, beh ); + return; + } + + cursor_control con(!Options.use_fake_cursor); + + int dir = 0; + bool show_beam = Options.show_beam && !just_looking && needs_path; + ray_def ray; + + FixedVector < char, 2 > objfind_pos; + FixedVector < char, 2 > monsfind_pos; + + // init + moves.dx = moves.dy = 0; + moves.tx = you.x_pos; + moves.ty = you.y_pos; + + // If we show the beam on startup, we have to initialise it. + if ( show_beam ) + find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, true, ray); + + bool skip_iter = false; + bool found_autotarget = false; + bool target_unshifted = Options.target_unshifted_dirs; + + // Find a default target + if ( Options.default_target && mode == TARG_ENEMY ) + { + skip_iter = true; // skip first iteration...XXX mega-hack + if ( you.prev_targ != MHITNOT && you.prev_targ != MHITYOU ) + { + const monsters *montarget = &menv[you.prev_targ]; + if ( mons_near(montarget) && player_monster_visible(montarget) + && !mons_friendly(montarget) // not made friendly since then + && _is_target_in_range(montarget->x, montarget->y, range) ) + { + found_autotarget = true; + moves.tx = montarget->x; + moves.ty = montarget->y; + } + } + } + + bool show_prompt = true; + while (true) + { + // Prompts might get scrolled off if you have too few lines available. + // We'll live with that. + if ( !just_looking && (show_prompt || beh->should_redraw()) ) + { + mprf(MSGCH_PROMPT, "%s (%s)", prompt? prompt : "Aim", + target_mode_help_text(restricts)); + + if ((mode == TARG_ANY || mode == TARG_FRIEND) + && moves.tx == you.x_pos && moves.ty == you.y_pos) + { + terse_describe_square(moves.target()); + } + + show_prompt = false; + } + + // Reinit...this needs to be done every loop iteration + // because moves is more persistent than loop_done. + moves.isValid = false; + moves.isTarget = false; + moves.isMe = false; + moves.isCancel = false; + moves.isEndpoint = false; + moves.choseRay = false; + + cursorxy( grid2viewX(moves.tx), grid2viewY(moves.ty) ); + + command_type key_command; + + if ( skip_iter ) + { + if ( found_autotarget ) + key_command = CMD_NO_CMD; + else + key_command = CMD_TARGET_CYCLE_FORWARD; // find closest enemy + } + else + { +#ifdef USE_TILE + mouse_control mc(MOUSE_MODE_TARGET); +#endif + key_command = beh->get_command(); + } + +#ifdef USE_TILE + // if a mouse command, update location to mouse position... + if ( key_command == CMD_TARGET_MOUSE_MOVE + || key_command == CMD_TARGET_MOUSE_SELECT ) + { + coord_def gc; + if (gui_get_mouse_grid_pos(gc)) + { + moves.tx = gc.x; + moves.ty = gc.y; + + if (key_command == CMD_TARGET_MOUSE_SELECT) + key_command = CMD_TARGET_SELECT; + } + else + { + key_command = CMD_NO_CMD; + } + } +#endif + + if (target_unshifted && moves.tx == you.x_pos && moves.ty == you.y_pos + && restricts != DIR_TARGET) + { + key_command = shift_direction(key_command); + } + + if (target_unshifted + && (key_command == CMD_TARGET_CYCLE_FORWARD + || key_command == CMD_TARGET_CYCLE_BACK + || key_command == CMD_TARGET_OBJ_CYCLE_FORWARD + || key_command == CMD_TARGET_OBJ_CYCLE_BACK)) + { + target_unshifted = false; + } + + if ( key_command == CMD_TARGET_MAYBE_PREV_TARGET ) + { + if ( moves.tx == you.x_pos && moves.ty == you.y_pos ) + key_command = CMD_TARGET_PREV_TARGET; + else + key_command = CMD_TARGET_SELECT; + } + + bool need_beam_redraw = false; + bool force_redraw = false; + bool loop_done = false; + + const int old_tx = moves.tx + (skip_iter ? 500 : 0); // hmmm...hack + const int old_ty = moves.ty; + + int i, mid; + + switch ( key_command ) + { + // standard movement + case CMD_TARGET_DOWN_LEFT: + case CMD_TARGET_DOWN: + case CMD_TARGET_DOWN_RIGHT: + case CMD_TARGET_LEFT: + case CMD_TARGET_RIGHT: + case CMD_TARGET_UP_LEFT: + case CMD_TARGET_UP: + case CMD_TARGET_UP_RIGHT: + i = targeting_cmd_to_compass(key_command); + moves.tx += Compass[i].x; + moves.ty += Compass[i].y; + break; + + case CMD_TARGET_DIR_DOWN_LEFT: + case CMD_TARGET_DIR_DOWN: + case CMD_TARGET_DIR_DOWN_RIGHT: + case CMD_TARGET_DIR_LEFT: + case CMD_TARGET_DIR_RIGHT: + case CMD_TARGET_DIR_UP_LEFT: + case CMD_TARGET_DIR_UP: + case CMD_TARGET_DIR_UP_RIGHT: + i = targeting_cmd_to_compass(key_command); + + if ( restricts != DIR_TARGET ) + { + // A direction is allowed, and we've selected it. + moves.dx = Compass[i].x; + moves.dy = Compass[i].y; + // Needed for now...eventually shouldn't be necessary + moves.tx = you.x_pos + moves.dx; + moves.ty = you.y_pos + moves.dy; + moves.isValid = true; + moves.isTarget = false; + show_beam = false; + moves.choseRay = false; + loop_done = true; + } + else + { + // Direction not allowed, so just move in that direction. + // Maybe make this a bigger jump? + if (restricts == DIR_TARGET) + { + moves.tx += Compass[i].x * 3; + moves.ty += Compass[i].y * 3; + } + else + { + moves.tx += Compass[i].x; + moves.ty += Compass[i].y; + } + } + break; + +#ifdef WIZARD + case CMD_TARGET_CYCLE_BEAM: + show_beam = find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, + true, ray, (show_beam ? 1 : 0)); + need_beam_redraw = true; + break; +#endif + + case CMD_TARGET_HIDE_BEAM: + if (show_beam) + { + show_beam = false; + need_beam_redraw = true; + } + else + { + if (!needs_path) + { + mprf(MSGCH_EXAMINE_FILTER, + "This spell doesn't need a beam path."); + break; + } + + show_beam = find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, + true, ray, 0, true); + need_beam_redraw = show_beam; + } + break; + + case CMD_TARGET_FIND_YOU: + moves.tx = you.x_pos; + moves.ty = you.y_pos; + moves.dx = 0; + moves.dy = 0; + break; + + case CMD_TARGET_FIND_TRAP: + case CMD_TARGET_FIND_PORTAL: + case CMD_TARGET_FIND_ALTAR: + case CMD_TARGET_FIND_UPSTAIR: + case CMD_TARGET_FIND_DOWNSTAIR: + { + const int thing_to_find = targeting_cmd_to_feature(key_command); + if (find_square_wrapper(moves.tx, moves.ty, objfind_pos, 1, + find_feature, thing_to_find, range, true, + Options.target_los_first ? + LOS_FLIPVH : LOS_ANY)) + { + moves.tx = objfind_pos[0]; + moves.ty = objfind_pos[1]; + } + else + { + if (!skip_iter) + flush_input_buffer(FLUSH_ON_FAILURE); + } + break; + } + + case CMD_TARGET_CYCLE_TARGET_MODE: + mode = static_cast((mode + 1) % TARG_NUM_MODES); + mprf( "Targeting mode is now: %s", + (mode == TARG_ANY) ? "any" : + (mode == TARG_ENEMY) ? "enemies" + : "friends" ); + break; + + case CMD_TARGET_PREV_TARGET: + // Do we have a previous target? + if (you.prev_targ == MHITNOT || you.prev_targ == MHITYOU) + { + mpr("You haven't got a previous target.", MSGCH_EXAMINE_FILTER); + break; + } + + // we have a valid previous target (maybe) + { + const monsters *montarget = &menv[you.prev_targ]; + + if (!mons_near(montarget) + || !player_monster_visible( montarget )) + { + mpr("You can't see that creature any more.", + MSGCH_EXAMINE_FILTER); + } + else + { + // We have all the information we need + moves.isValid = true; + moves.isTarget = true; + moves.tx = montarget->x; + moves.ty = montarget->y; + if ( !just_looking ) + { + // We have to turn off show_beam, because + // when jumping to a previous target we don't + // care about the beam; otherwise Bad Things + // will happen because the ray is invalid, + // and we don't get a chance to update it before + // breaking from the loop. + show_beam = false; + loop_done = true; + } + } + break; + } + + case CMD_TARGET_SELECT_ENDPOINT: + moves.isEndpoint = true; + // intentional fall-through + case CMD_TARGET_SELECT: // finalize current choice + if (!moves.isEndpoint + && mgrd[moves.tx][moves.ty] != NON_MONSTER + && _mon_submerged_in_water(&menv[mgrd[moves.tx][moves.ty]])) + { + moves.isEndpoint = true; + } + moves.isValid = true; + moves.isTarget = true; + loop_done = true; + + you.prev_grd_targ = coord_def(0, 0); + + // maybe we should except just_looking here? + mid = mgrd[moves.tx][moves.ty]; + + if ( mid != NON_MONSTER ) + you.prev_targ = mid; + else if (moves.tx == you.x_pos && moves.ty == you.y_pos) + you.prev_targ = MHITYOU; + else + you.prev_grd_targ = coord_def(moves.tx, moves.ty); + break; + + case CMD_TARGET_OBJ_CYCLE_BACK: + case CMD_TARGET_OBJ_CYCLE_FORWARD: + dir = (key_command == CMD_TARGET_OBJ_CYCLE_BACK) ? -1 : 1; + if (find_square_wrapper( moves.tx, moves.ty, objfind_pos, dir, + find_object, 0, range, true, + Options.target_los_first + ? (dir == 1? LOS_FLIPVH : LOS_FLIPHV) + : LOS_ANY)) + { + moves.tx = objfind_pos[0]; + moves.ty = objfind_pos[1]; + } + else if (!skip_iter) + flush_input_buffer(FLUSH_ON_FAILURE); + + break; + + case CMD_TARGET_CYCLE_FORWARD: + case CMD_TARGET_CYCLE_BACK: + dir = (key_command == CMD_TARGET_CYCLE_BACK) ? -1 : 1; + if (find_square_wrapper( moves.tx, moves.ty, monsfind_pos, dir, + find_monster, mode, range, + Options.target_wrap)) + { + moves.tx = monsfind_pos[0]; + moves.ty = monsfind_pos[1]; + } + else if (!skip_iter) + flush_input_buffer(FLUSH_ON_FAILURE); + + break; + + case CMD_TARGET_CANCEL: + loop_done = true; + moves.isCancel = true; + break; + +#ifdef WIZARD + case CMD_TARGET_WIZARD_MAKE_FRIENDLY: + // Maybe we can skip this check...but it can't hurt + if (!you.wizard || !in_bounds(moves.tx, moves.ty)) + break; + mid = mgrd[moves.tx][moves.ty]; + if (mid == NON_MONSTER) // can put in terrain description here + break; + + { + monsters &m = menv[mid]; + switch (m.attitude) + { + case ATT_FRIENDLY: + m.attitude = ATT_NEUTRAL; + m.flags &= ~MF_CREATED_FRIENDLY; + m.flags |= MF_WAS_NEUTRAL; + break; + case ATT_NEUTRAL: + m.attitude = ATT_HOSTILE; + m.flags &= ~MF_WAS_NEUTRAL; + break; + case ATT_HOSTILE: + m.attitude = ATT_FRIENDLY; + m.flags |= MF_CREATED_FRIENDLY; + break; + default: + break; + } + + // To update visual branding of friendlies. Only + // seem capabable of adding bolding, not removing it, + // though. + viewwindow(true, false); + } + break; + + case CMD_TARGET_WIZARD_MAKE_SHOUT: + // Maybe we can skip this check...but it can't hurt + if (!you.wizard || !in_bounds(moves.tx, moves.ty)) + break; + mid = mgrd[moves.tx][moves.ty]; + if (mid == NON_MONSTER) // can put in terrain description here + break; + + debug_make_monster_shout(&menv[mid]); + break; + + case CMD_TARGET_WIZARD_GIVE_ITEM: + if (!you.wizard || !in_bounds(moves.tx, moves.ty)) + break; + mid = mgrd[moves.tx][moves.ty]; + if (mid == NON_MONSTER) // can put in terrain description here + break; + + wizard_give_monster_item(&menv[mid]); + break; +#endif + + case CMD_TARGET_DESCRIBE: + full_describe_square(moves.target()); + force_redraw = true; + break; + + case CMD_TARGET_HELP: + show_targeting_help(); + force_redraw = true; + redraw_screen(); + mesclr(true); + show_prompt = true; + break; + + default: + break; + } + + if ( loop_done == true ) + { + // This is where we either finalize everything, or else + // decide that we're not really done and continue looping. + + if ( just_looking ) // easy out + break; + + // A bunch of confirmation tests; if we survive them all, + // then break out. + + // Confirm self-targeting on TARG_ENEMY. + // Conceivably we might want to confirm on TARG_ANY too. + if ( moves.isTarget + && moves.tx == you.x_pos && moves.ty == you.y_pos + && mode == TARG_ENEMY + && !yesno("Really target yourself?", false, 'n')) + { + mesclr(); + show_prompt = true; + } + else if ( moves.isTarget && !see_grid(moves.tx, moves.ty) ) + { + mpr("Sorry, you can't target what you can't see.", + MSGCH_EXAMINE_FILTER); + } + // Ask for confirmation if we're quitting for some odd reason + else if ( moves.isValid || moves.isCancel + || yesno("Are you sure you want to fizzle?", false, 'n') ) + { + // Finalize whatever is inside the loop + // (moves-internal finalizations can be done later) + moves.choseRay = show_beam; + moves.ray = ray; + break; + } + } + + // We'll go on looping. Redraw whatever is necessary. + + if ( !in_viewport_bounds(grid2viewX(moves.tx), grid2viewY(moves.ty)) ) + { + // Tried to step out of bounds + moves.tx = old_tx; + moves.ty = old_ty; + } + + bool have_moved = false; + + if ( old_tx != moves.tx || old_ty != moves.ty ) + { + have_moved = true; + show_beam = show_beam && + find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, true, ray, + 0, true); + } + + if ( force_redraw ) + have_moved = true; + + if ( have_moved ) + { + // If the target x,y has changed, the beam must have changed. + if ( show_beam ) + need_beam_redraw = true; + + if ( !skip_iter ) // don't clear before we get a chance to see + mesclr(true); // maybe not completely necessary + + terse_describe_square(moves.target()); + } + +#ifdef USE_TILE + // tiles always need a beam redraw if show_beam is true (and if valid...) + if ( need_beam_redraw + || show_beam && find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, + true, ray, 0, true) ) + { +#else + if ( need_beam_redraw ) + { + viewwindow(true, false); +#endif + if ( show_beam + && in_vlos(grid2viewX(moves.tx), grid2viewY(moves.ty)) + && moves.target() != you.pos() ) + { + // Draw the new ray with magenta '*'s, not including + // your square or the target square. + ray_def raycopy = ray; // temporary copy to work with + while ( raycopy.pos() != moves.target() ) + { + if ( raycopy.pos() != you.pos() ) + { + // Sanity: don't loop forever if the ray is problematic + if ( !in_los(raycopy.x(), raycopy.y()) ) + break; + draw_ray_glyph(raycopy.pos(), MAGENTA, '*', + MAGENTA | COLFLAG_REVERSE); + } + raycopy.advance_through(moves.target()); + } + textcolor(LIGHTGREY); +#ifdef USE_TILE + draw_ray_glyph(moves.target(), MAGENTA, '*', + MAGENTA | COLFLAG_REVERSE); + } + viewwindow(true, false); +#else + } +#endif + + } + skip_iter = false; // only skip one iteration at most + } + moves.isMe = (moves.tx == you.x_pos && moves.ty == you.y_pos); + mesclr(); + + // We need this for directional explosions, otherwise they'll explode one + // square away from the player. + extend_move_to_edge(moves); +} + +void terse_describe_square(const coord_def &c) +{ + if (!see_grid(c.x, c.y)) + describe_oos_square(c.x, c.y); + else if (in_bounds(c) ) + describe_cell(c.x, c.y); +} + +void full_describe_square(const coord_def &c) +{ + // Don't give out information for things outside LOS + if (!see_grid(c.x, c.y)) + return; + + const int mid = mgrd(c); + const int oid = igrd(c); + + if (mid != NON_MONSTER && player_monster_visible(&menv[mid])) + { + // First priority: monsters + describe_monsters(menv[mid]); + } + else if (oid != NON_ITEM) + { + // Second priority: objects + describe_item( mitm[oid] ); + } + else + { + // Third priority: features + describe_feature_wide(c.x, c.y); + } + + redraw_screen(); + mesclr(true); +} + +static void extend_move_to_edge(dist &moves) +{ + if (!moves.dx && !moves.dy) + return; + + // now the tricky bit - extend the target x,y out to map edge. + int mx = 0, my = 0; + + if (moves.dx > 0) + mx = (GXM - 1) - you.x_pos; + if (moves.dx < 0) + mx = you.x_pos; + + if (moves.dy > 0) + my = (GYM - 1) - you.y_pos; + if (moves.dy < 0) + my = you.y_pos; + + if (!(mx == 0 || my == 0)) + { + if (mx < my) + my = mx; + else + mx = my; + } + moves.tx = you.x_pos + moves.dx * mx; + moves.ty = you.y_pos + moves.dy * my; +} + +// Attempts to describe a square that's not in line-of-sight. If +// there's a stash on the square, announces the top item and number +// of items, otherwise, if there's a stair that's in the travel +// cache and noted in the Dungeon (O)verview, names the stair. +static void describe_oos_square(int x, int y) +{ + mpr("You can't see that place.", MSGCH_EXAMINE_FILTER); + + if (!in_bounds(x, y) || !is_terrain_seen(x, y)) + return; + + describe_stash(x, y); + describe_feature(x, y, true); +} + +bool in_vlos(int x, int y) +{ + return (in_los_bounds(x, y) + && (env.show(view2show(coord_def(x, y))) + || coord_def(x, y) == grid2view(you.pos()))); +} + +bool in_vlos(const coord_def &pos) +{ + return (in_vlos(pos.x, pos.y)); +} + +bool in_los(int x, int y) +{ + return (in_vlos(grid2view(coord_def(x, y)))); +} + +static bool find_monster( int x, int y, int mode, int range = -1) +{ + // target the player for friendly and general spells + if ((mode == TARG_FRIEND || mode == TARG_ANY) + && x == you.x_pos && y == you.y_pos) + { + return (true); + } + + // don't target out of range + if (!_is_target_in_range(x, y, range)) + return (false); + + const int targ_mon = mgrd[ x ][ y ]; + + // No monster or outside LOS. + if (targ_mon == NON_MONSTER || !in_los(x,y)) + return (false); + + monsters *mon = &menv[targ_mon]; + + // Unknown mimics don't count as monsters, either. + if (mons_is_mimic(mon->type) + && !(mon->flags & MF_KNOWN_MIMIC)) + { + return (false); + } + + // Don't usually target unseen monsters... + if (!player_monster_visible(mon)) + { + // ... unless it creates a "disturbance in the water". + // Since you can't see the monster, assume it's not a friend. + // Also don't target submerged monsters if there are other targets + // in sight. (This might be too restrictive.) + return (mode != TARG_FRIEND + && _mon_submerged_in_water(mon) + && i_feel_safe(false, false, true, range)); + } + + // Now compare target modes. + if (mode == TARG_ANY) + return true; + + if (mode == TARG_FRIEND) + return (mons_friendly(&menv[targ_mon] )); + + ASSERT(mode == TARG_ENEMY); + if (mons_friendly(&menv[targ_mon])) + return false; + + // Don't target zero xp monsters, unless target_zero_exp is set. + return (Options.target_zero_exp + || !mons_class_flag( menv[targ_mon].type, M_NO_EXP_GAIN )); +} + +static bool find_feature( int x, int y, int mode, int /* range */) +{ + // The stair need not be in LOS if the square is mapped. + if (!in_los(x, y) && (!Options.target_oos || !is_terrain_seen(x, y))) + return (false); + + return is_feature(mode, x, y); +} + +static bool find_object(int x, int y, int mode, int /* range */) +{ + // First, check for mimics. + bool is_mimic = false; + const int mons = mgrd[ x ][ y ]; + if (mons != NON_MONSTER + && player_monster_visible( &(menv[mons]) ) + && mons_is_mimic(menv[mons].type) + && !(menv[mons].flags & MF_KNOWN_MIMIC)) + { + is_mimic = true; + } + + const int item = igrd[x][y]; + if (item == NON_ITEM && !is_mimic) + return false; + + return (in_los(x, y) || Options.target_oos && is_terrain_seen(x, y) + && (is_stash(x, y) || is_mimic)); +} + +static int next_los(int dir, int los, bool wrap) +{ + if (los == LOS_ANY) + return (wrap? los : LOS_NONE); + + bool vis = los & LOS_VISIBLE; + bool hidden = los & LOS_HIDDEN; + bool flipvh = los & LOS_FLIPVH; + bool fliphv = los & LOS_FLIPHV; + + if (!vis && !hidden) + vis = true; + + if (wrap) + { + if (!flipvh && !fliphv) + return (los); + + // We have to invert flipvh and fliphv if we're wrapping. Here's + // why: + // + // * Say the cursor is on the last item in LOS, there are no + // items outside LOS, and wrap == true. flipvh is true. + // * We set wrap false and flip from visible to hidden, but there + // are no hidden items. So now we need to flip back to visible + // so we can go back to the first item in LOS. Unless we set + // fliphv, we can't flip from hidden to visible. + // + los = flipvh? LOS_FLIPHV : LOS_FLIPVH; + } + else + { + if (!flipvh && !fliphv) + return (LOS_NONE); + + if (flipvh && vis != (dir == 1)) + return (LOS_NONE); + + if (fliphv && vis == (dir == 1)) + return (LOS_NONE); + } + + los = (los & ~LOS_VISMASK) | (vis? LOS_HIDDEN : LOS_VISIBLE); + return (los); +} + +bool in_viewport_bounds(int x, int y) +{ + return crawl_view.in_view_viewport(coord_def(x, y)); +} + +bool in_los_bounds(int x, int y) +{ + return crawl_view.in_view_los(coord_def(x, y)); +} + +//--------------------------------------------------------------- +// +// find_square +// +// Finds the next monster/object/whatever (moving in a spiral +// outwards from the player, so closer targets are chosen first; +// starts to player's left) and puts its coordinates in mfp. +// Returns 1 if it found something, zero otherwise. If direction +// is -1, goes backwards. +// +// If the game option target_zero_exp is true, zero experience +// monsters will be targeted. +// +//--------------------------------------------------------------- +static char find_square( int xps, int yps, + FixedVector &mfp, int direction, + bool (*find_targ)( int x, int y, int mode, int range ), + int mode, int range, bool wrap, int los ) +{ + // the day will come when [unsigned] chars will be consigned to + // the fires of Gehenna. Not quite yet, though. + + int temp_xps = xps; + int temp_yps = yps; + int x_change = 0; + int y_change = 0; + + bool onlyVis = false, onlyHidden = false; + + int i, j; + + if (los == LOS_NONE) + return (0); + + if (los == LOS_FLIPVH || los == LOS_FLIPHV) + { + if (in_los_bounds(xps, yps)) + { + // We've been told to flip between visible/hidden, so we + // need to find what we're currently on. + const bool vis = (env.show(view2show(coord_def(xps, yps))) + || view2grid(coord_def(xps, yps)) == you.pos()); + + if (wrap && (vis != (los == LOS_FLIPVH)) == (direction == 1)) + { + // We've already flipped over into the other direction, + // so correct the flip direction if we're wrapping. + los = los == LOS_FLIPHV? LOS_FLIPVH : LOS_FLIPHV; + } + + los = (los & ~LOS_VISMASK) | (vis? LOS_VISIBLE : LOS_HIDDEN); + } + else + { + if (wrap) + los = LOS_HIDDEN | (direction == 1? LOS_FLIPHV : LOS_FLIPVH); + else + los |= LOS_HIDDEN; + } + } + + onlyVis = (los & LOS_VISIBLE); + onlyHidden = (los & LOS_HIDDEN); + + int radius = 0; + if (crawl_view.viewsz.x > crawl_view.viewsz.y) + radius = crawl_view.viewsz.x - LOS_RADIUS - 1; + else + radius = crawl_view.viewsz.y - LOS_RADIUS - 1; + + const coord_def vyou = grid2view(you.pos()); + + const int minx = vyou.x - radius, maxx = vyou.x + radius, + miny = vyou.y - radius, maxy = vyou.y + radius, + ctrx = vyou.x, ctry = vyou.y; + + while (temp_xps >= minx - 1 && temp_xps <= maxx + && temp_yps <= maxy && temp_yps >= miny - 1) + { + if (direction == 1 && temp_xps == minx && temp_yps == maxy) + { + if (find_targ(you.x_pos, you.y_pos, mode, range)) + { + mfp[0] = ctrx; + mfp[1] = ctry; + return (1); + } + return find_square(ctrx, ctry, mfp, direction, find_targ, mode, + range, false, next_los(direction, los, wrap)); + } + if (direction == -1 && temp_xps == ctrx && temp_yps == ctry) + { + return find_square(minx, maxy, mfp, direction, find_targ, mode, + range, false, next_los(direction, los, wrap)); + } + + if (direction == 1) + { + if (temp_xps == minx - 1) + { + x_change = 0; + y_change = -1; + } + else if (temp_xps == ctrx && temp_yps == ctry) + { + x_change = -1; + y_change = 0; + } + else if (abs(temp_xps - ctrx) <= abs(temp_yps - ctry)) + { + if (temp_xps - ctrx >= 0 && temp_yps - ctry <= 0) + { + if (abs(temp_xps - ctrx) > abs(temp_yps - ctry + 1)) + { + x_change = 0; + y_change = -1; + if (temp_xps - ctrx > 0) + y_change = 1; + goto finished_spiralling; + } + } + x_change = -1; + if (temp_yps - ctry < 0) + x_change = 1; + y_change = 0; + } + else + { + x_change = 0; + y_change = -1; + if (temp_xps - ctrx > 0) + y_change = 1; + } + } // end if (direction == 1) + else + { + /* + This part checks all eight surrounding squares to find the + one that leads on to the present square. + */ + for (i = -1; i < 2; i++) + { + for (j = -1; j < 2; j++) + { + if (i == 0 && j == 0) + continue; + + if (temp_xps + i == minx - 1) + { + x_change = 0; + y_change = -1; + } + else if (temp_xps + i - ctrx == 0 && temp_yps + j - ctry == 0) + { + x_change = -1; + y_change = 0; + } + else if (abs(temp_xps + i - ctrx) <= abs(temp_yps + j - ctry)) + { + const int xi = temp_xps + i - ctrx; + const int yj = temp_yps + j - ctry; + + if (xi >= 0 && yj <= 0 + && abs(xi) > abs(yj + 1)) + { + x_change = 0; + y_change = -1; + if (xi > 0) + y_change = 1; + goto finished_spiralling; + } + + x_change = -1; + if (yj < 0) + x_change = 1; + y_change = 0; + } + else + { + x_change = 0; + y_change = -1; + if (temp_xps + i - ctrx > 0) + y_change = 1; + } + + if (temp_xps + i + x_change == temp_xps + && temp_yps + j + y_change == temp_yps) + { + goto finished_spiralling; + } + } + } + } // end else + + + finished_spiralling: + x_change *= direction; + y_change *= direction; + + temp_xps += x_change; + if (temp_yps + y_change <= maxy) // it can wrap, unfortunately + temp_yps += y_change; + + const int targ_x = you.x_pos + temp_xps - ctrx; + const int targ_y = you.y_pos + temp_yps - ctry; + + // We don't want to be looking outside the bounds of the arrays: + //if (!in_los_bounds(temp_xps, temp_yps)) + // continue; + + if (!crawl_view.in_grid_viewport(coord_def(targ_x, targ_y))) + continue; + + if (!in_bounds(targ_x, targ_y)) + continue; + + if ((onlyVis || onlyHidden) && onlyVis != in_los(targ_x, targ_y)) + continue; + + if (find_targ(targ_x, targ_y, mode, range)) + { + mfp[0] = temp_xps; + mfp[1] = temp_yps; + return (1); + } + } + + return (direction == 1? + find_square(ctrx, ctry, mfp, direction, find_targ, mode, range, false, + next_los(direction, los, wrap)) + : find_square(minx, maxy, mfp, direction, find_targ, mode, range, false, + next_los(direction, los, wrap))); +} + +// XXX Unbelievably hacky. And to think that my goal was to clean up the code. +// Identical to find_square, except that input (tx, ty) and output +// (mfp) are in grid coordinates rather than view coordinates. +static char find_square_wrapper( int tx, int ty, + FixedVector &mfp, char direction, + bool (*find_targ)( int x, int y, int mode, + int range ), + int mode, int range, bool wrap, int los ) +{ + const char r = find_square(grid2viewX(tx), grid2viewY(ty), mfp, + direction, find_targ, mode, range, wrap, los); + mfp[0] = view2gridX(mfp[0]); + mfp[1] = view2gridY(mfp[1]); + return r; +} + +static void describe_feature(int mx, int my, bool oos) +{ + if (oos && !is_terrain_seen(mx, my)) + return; + + dungeon_feature_type grid = grd[mx][my]; + if ( grid == DNGN_SECRET_DOOR ) + grid = grid_secret_door_appearance(mx, my); + + std::string desc = feature_description(grid); + if (desc.length()) + { + if (oos) + desc = "[" + desc + "]"; + + msg_channel_type channel = MSGCH_EXAMINE; + if (oos || grid == DNGN_FLOOR) + channel = MSGCH_EXAMINE_FILTER; + + mpr(desc.c_str(), channel); + } +} + +// Returns a vector of features matching the given pattern. +std::vector features_by_desc(const base_pattern &pattern) +{ + std::vector features; + + if (pattern.valid()) + { + for (int i = 0; i < NUM_FEATURES; ++i) + { + std::string fdesc = + feature_description(static_cast(i)); + if (fdesc.empty()) + continue; + + if (pattern.matches( fdesc )) + features.push_back( dungeon_feature_type(i) ); + } + } + return (features); +} + +void describe_floor() +{ + const int grid = grd(you.pos()); + + std::string prefix = "There is "; + std::string feat; + std::string suffix = " here."; + switch (grid) + { + case DNGN_FLOOR: + case DNGN_FLOOR_SPECIAL: + return; + + case DNGN_ENTER_SHOP: + prefix = "There is an entrance to "; + break; + + default: + break; + } + + feat = feature_description(you.x_pos, you.y_pos, + is_bloodcovered(you.x_pos, you.y_pos), + DESC_NOCAP_A, false); + if (feat.empty()) + return; + + msg_channel_type channel = MSGCH_EXAMINE; + + // water is not terribly important if you don't mind it + if ((grd[you.x_pos][you.y_pos] == DNGN_DEEP_WATER + || grd[you.x_pos][you.y_pos] == DNGN_SHALLOW_WATER) + && player_likes_water()) + { + channel = MSGCH_EXAMINE_FILTER; + } + mpr((prefix + feat + suffix).c_str(), channel); + if (grid == DNGN_ENTER_LABYRINTH && you.is_undead != US_UNDEAD) + mpr("Beware, for starvation awaits!", MSGCH_EXAMINE); +} + +static std::string feature_do_grammar(description_level_type dtype, + bool add_stop, + bool force_article, + std::string desc) +{ + if (add_stop) + desc += "."; + if (dtype == DESC_PLAIN || (!force_article && isupper(desc[0]))) + { + if (isupper(desc[0])) + { + switch (dtype) + { + case DESC_PLAIN: case DESC_NOCAP_THE: case DESC_NOCAP_A: + desc[0] = tolower(desc[0]); + break; + default: + break; + } + } + return (desc); + } + + switch (dtype) + { + case DESC_CAP_THE: + return "The " + desc; + case DESC_NOCAP_THE: + return "the " + desc; + case DESC_CAP_A: + return article_a(desc, false); + case DESC_NOCAP_A: + return article_a(desc, true); + case DESC_NONE: + return (""); + default: + return (desc); + } +} + +std::string feature_description(dungeon_feature_type grid, + trap_type trap, bool bloody, + description_level_type dtype, + bool add_stop) +{ + std::string desc = raw_feature_description(grid, trap); + if (bloody) + desc += ", spattered with blood"; + + return feature_do_grammar(dtype, add_stop, grid_is_trap(grid), desc); +} + +std::string raw_feature_description(dungeon_feature_type grid, + trap_type trap) +{ + if (grid_is_trap(grid) && trap != NUM_TRAPS) + { + switch (trap) + { + case TRAP_DART: + return ("dart trap"); + case TRAP_ARROW: + return ("arrow trap"); + case TRAP_SPEAR: + return ("spear trap"); + case TRAP_AXE: + return ("axe trap"); + case TRAP_TELEPORT: + return ("teleportation trap"); + case TRAP_ALARM: + return ("alarm trap"); + case TRAP_BLADE: + return ("blade trap"); + case TRAP_BOLT: + return ("bolt trap"); + case TRAP_NET: + return ("net trap"); + case TRAP_ZOT: + return ("Zot trap"); + case TRAP_NEEDLE: + return ("needle trap"); + case TRAP_SHAFT: + return ("shaft"); + default: + error_message_to_player(); + return ("undefined trap"); + } + } + + switch (grid) + { + case DNGN_STONE_WALL: + return ("stone wall"); + case DNGN_ROCK_WALL: + case DNGN_SECRET_DOOR: + if (you.level_type == LEVEL_PANDEMONIUM) + return ("wall of the weird stuff which makes up Pandemonium"); + else + return ("rock wall"); + case DNGN_PERMAROCK_WALL: + return ("unnaturally hard rock wall"); + case DNGN_CLOSED_DOOR: + return ("closed door"); + case DNGN_METAL_WALL: + return ("metal wall"); + case DNGN_GREEN_CRYSTAL_WALL: + return ("wall of green crystal"); + case DNGN_CLEAR_ROCK_WALL: + return ("translucent rock wall"); + case DNGN_CLEAR_STONE_WALL: + return ("translucent stone wall"); + case DNGN_CLEAR_PERMAROCK_WALL: + return ("translucent unnaturally hard rock wall"); + case DNGN_ORCISH_IDOL: + if (you.species == SP_HILL_ORC) + return ("idol of Beogh"); + else + return ("orcish idol"); + case DNGN_WAX_WALL: + return ("wall of solid wax"); + case DNGN_GRANITE_STATUE: + return ("granite statue"); + case DNGN_LAVA: + return ("Some lava"); + case DNGN_DEEP_WATER: + return ("Some deep water"); + case DNGN_SHALLOW_WATER: + return ("Some shallow water"); + case DNGN_UNDISCOVERED_TRAP: + case DNGN_FLOOR: + case DNGN_FLOOR_SPECIAL: + return ("Floor"); + case DNGN_OPEN_DOOR: + return ("open door"); + case DNGN_ESCAPE_HATCH_DOWN: + return ("escape hatch in the floor"); + case DNGN_ESCAPE_HATCH_UP: + return ("escape hatch in the ceiling"); + case DNGN_STONE_STAIRS_DOWN_I: + case DNGN_STONE_STAIRS_DOWN_II: + case DNGN_STONE_STAIRS_DOWN_III: + return ("stone staircase leading down"); + case DNGN_STONE_STAIRS_UP_I: + case DNGN_STONE_STAIRS_UP_II: + case DNGN_STONE_STAIRS_UP_III: + return ("stone staircase leading up"); + case DNGN_ENTER_HELL: + return ("gateway to Hell"); + case DNGN_TRAP_MECHANICAL: + return ("mechanical trap"); + case DNGN_TRAP_MAGICAL: + return ("magical trap"); + case DNGN_TRAP_NATURAL: + return ("natural trap"); + case DNGN_ENTER_SHOP: + return ("shop"); + case DNGN_ENTER_LABYRINTH: + return ("labyrinth entrance"); + case DNGN_ENTER_DIS: + return ("gateway to the Iron City of Dis"); + case DNGN_ENTER_GEHENNA: + return ("gateway to Gehenna"); + case DNGN_ENTER_COCYTUS: + return ("gateway to the freezing wastes of Cocytus"); + case DNGN_ENTER_TARTARUS: + return ("gateway to the decaying netherworld of Tartarus"); + case DNGN_ENTER_ABYSS: + return ("one-way gate to the infinite horrors of the Abyss"); + case DNGN_EXIT_ABYSS: + return ("gateway leading out of the Abyss"); + case DNGN_STONE_ARCH: + return ("empty arch of ancient stone"); + case DNGN_ENTER_PANDEMONIUM: + return ("gate leading to the halls of Pandemonium"); + case DNGN_EXIT_PANDEMONIUM: + return ("gate leading out of Pandemonium"); + case DNGN_TRANSIT_PANDEMONIUM: + return ("gate leading to another region of Pandemonium"); + case DNGN_ENTER_ORCISH_MINES: + return ("staircase to the Orcish Mines"); + case DNGN_ENTER_HIVE: + return ("staircase to the Hive"); + case DNGN_ENTER_LAIR: + return ("staircase to the Lair"); + case DNGN_ENTER_SLIME_PITS: + return ("staircase to the Slime Pits"); + case DNGN_ENTER_VAULTS: + return ("staircase to the Vaults"); + case DNGN_ENTER_CRYPT: + return ("staircase to the Crypt"); + case DNGN_ENTER_HALL_OF_BLADES: + return ("staircase to the Hall of Blades"); + case DNGN_ENTER_ZOT: + return ("gate to the Realm of Zot"); + case DNGN_ENTER_TEMPLE: + return ("staircase to the Ecumenical Temple"); + case DNGN_ENTER_SNAKE_PIT: + return ("staircase to the Snake Pit"); + case DNGN_ENTER_ELVEN_HALLS: + return ("staircase to the Elven Halls"); + case DNGN_ENTER_TOMB: + return ("staircase to the Tomb"); + case DNGN_ENTER_SWAMP: + return ("staircase to the Swamp"); + case DNGN_ENTER_SHOALS: + return ("staircase to the Shoals"); + case DNGN_ENTER_PORTAL_VAULT: + return ("gate leading to a distant place"); + case DNGN_EXIT_PORTAL_VAULT: + return ("gate leading back to the Dungeon"); + case DNGN_RETURN_FROM_ORCISH_MINES: + case DNGN_RETURN_FROM_HIVE: + case DNGN_RETURN_FROM_LAIR: + case DNGN_RETURN_FROM_VAULTS: + case DNGN_RETURN_FROM_TEMPLE: + return ("staircase back to the Dungeon"); + case DNGN_RETURN_FROM_SLIME_PITS: + case DNGN_RETURN_FROM_SNAKE_PIT: + case DNGN_RETURN_FROM_SWAMP: + case DNGN_RETURN_FROM_SHOALS: + return ("staircase back to the Lair"); + case DNGN_RETURN_FROM_CRYPT: + case DNGN_RETURN_FROM_HALL_OF_BLADES: + return ("staircase back to the Vaults"); + case DNGN_RETURN_FROM_ELVEN_HALLS: + return ("staircase back to the Mines"); + case DNGN_RETURN_FROM_TOMB: + return ("staircase back to the Crypt"); + case DNGN_RETURN_FROM_ZOT: + return ("gate leading back out of this place"); + case DNGN_ALTAR_ZIN: + return ("glowing white marble altar of Zin"); + case DNGN_ALTAR_SHINING_ONE: + return ("glowing golden altar of the Shining One"); + case DNGN_ALTAR_KIKUBAAQUDGHA: + return ("ancient bone altar of Kikubaaqudgha"); + case DNGN_ALTAR_YREDELEMNUL: + return ("basalt altar of Yredelemnul"); + case DNGN_ALTAR_XOM: + return ("shimmering altar of Xom"); + case DNGN_ALTAR_VEHUMET: + return ("shining altar of Vehumet"); + case DNGN_ALTAR_OKAWARU: + return ("iron altar of Okawaru"); + case DNGN_ALTAR_MAKHLEB: + return ("burning altar of Makhleb"); + case DNGN_ALTAR_SIF_MUNA: + return ("deep blue altar of Sif Muna"); + case DNGN_ALTAR_TROG: + return ("bloodstained altar of Trog"); + case DNGN_ALTAR_NEMELEX_XOBEH: + return ("sparkling altar of Nemelex Xobeh"); + case DNGN_ALTAR_ELYVILON: + return ("silver altar of Elyvilon"); + case DNGN_ALTAR_LUGONU: + return ("corrupted altar of Lugonu"); + case DNGN_ALTAR_BEOGH: + return ("roughly hewn altar of Beogh"); + case DNGN_FOUNTAIN_BLUE: + return ("fountain of clear blue water"); + case DNGN_FOUNTAIN_SPARKLING: + return ("fountain of sparkling water"); + case DNGN_FOUNTAIN_BLOOD: + return ("fountain of blood"); + case DNGN_DRY_FOUNTAIN_BLUE: + case DNGN_DRY_FOUNTAIN_SPARKLING: + case DNGN_DRY_FOUNTAIN_BLOOD: + case DNGN_PERMADRY_FOUNTAIN: + return ("dry fountain"); + default: + return (""); + } +} + +static std::string marker_feature_description(const coord_def &p) +{ + std::vector markers = env.markers.get_markers_at(p); + for (int i = 0, size = markers.size(); i < size; ++i) + { + const std::string desc = markers[i]->feature_description(); + if (!desc.empty()) + return (desc); + } + return (""); +} + +#ifndef DEBUG_DIAGNOSTICS +// Is a feature interesting enough to 'v'iew it, even if a player normally +// doesn't care about descriptions, i.e. does the description hold important +// information? (Yes, this is entirely subjective. JPEG) + +static bool interesting_feature(dungeon_feature_type feat) +{ + return (get_feature_def(feat).flags & FFT_EXAMINE_HINT); +} +#endif + +std::string feature_description(int mx, int my, bool bloody, + description_level_type dtype, bool add_stop) +{ + dungeon_feature_type grid = grd[mx][my]; + if ( grid == DNGN_SECRET_DOOR ) + grid = grid_secret_door_appearance(mx, my); + + if ( grid == DNGN_OPEN_DOOR || grid == DNGN_CLOSED_DOOR ) + { + std::set all_door; + find_connected_identical(coord_def(mx, my), grd[mx][my], all_door); + const char *adj, *noun; + get_door_description(all_door.size(), &adj, &noun); + + std::string desc = adj; + desc += (grid == DNGN_OPEN_DOOR) ? "open " : "closed "; + desc += noun; + + if (bloody) + desc += ", spattered with blood"; + + return feature_do_grammar(dtype, add_stop, false, desc); + } + + switch (grid) + { + case DNGN_TRAP_MECHANICAL: + case DNGN_TRAP_MAGICAL: + case DNGN_TRAP_NATURAL: + return (feature_description(grid, trap_type_at_xy(mx, my), bloody, + dtype, add_stop)); + case DNGN_ENTER_SHOP: + return (shop_name(mx, my, add_stop)); + + case DNGN_ENTER_PORTAL_VAULT: + return (feature_do_grammar( + dtype, add_stop, false, + marker_feature_description(coord_def(mx, my)))); + default: + return (feature_description(grid, NUM_TRAPS, bloody, dtype, add_stop)); + } +} + +static std::string describe_mons_enchantment(const monsters &mons, + const mon_enchant &ench, + bool paralysed) +{ + // Suppress silly-looking combinations, even if they're + // internally valid. + if (paralysed && (ench.ench == ENCH_SLOW || ench.ench == ENCH_HASTE)) + return ""; + + if ((ench.ench == ENCH_HASTE || ench.ench == ENCH_BATTLE_FRENZY) + && mons.has_ench(ENCH_BERSERK)) + { + return ""; + } + + switch (ench.ench) + { + case ENCH_POISON: + return "poisoned"; + case ENCH_SICK: + return "sick"; + case ENCH_ROT: + return "rotting away"; //jmf: "covered in sores"? + case ENCH_BACKLIGHT: + return "softly glowing"; + case ENCH_SLOW: + return "moving slowly"; + case ENCH_BERSERK: + return "berserk"; + case ENCH_BATTLE_FRENZY: + return "consumed by blood-lust"; + case ENCH_HASTE: + return "moving very quickly"; + case ENCH_CONFUSION: + return "bewildered and confused"; + case ENCH_INVIS: + return "slightly transparent"; + case ENCH_CHARM: + return "in your thrall"; + case ENCH_STICKY_FLAME: + return "covered in liquid flames"; + case ENCH_HELD: + return "entangled in a net"; + default: + return ""; + } // end switch +} + +static std::string describe_monster_weapon(const monsters *mons) +{ + std::string desc = ""; + std::string name1, name2; + const item_def *weap = mons->mslot_item(MSLOT_WEAPON); + const item_def *alt = mons->mslot_item(MSLOT_ALT_WEAPON); + + if (weap) + name1 = weap->name(DESC_NOCAP_A, false, false, true, + false, ISFLAG_KNOW_CURSE); + if (alt && (!weap || mons_wields_two_weapons(mons))) + name2 = alt->name(DESC_NOCAP_A, false, false, true, + false, ISFLAG_KNOW_CURSE); + + if (name1.empty() && !name2.empty()) + name1.swap(name2); + + if (name1 == name2 && weap) + { + item_def dup = *weap; + ++dup.quantity; + name1 = dup.name(DESC_NOCAP_A, false, false, true, true, + ISFLAG_KNOW_CURSE); + name2.clear(); + } + + if (name1.empty()) + return (desc); + + desc += " wielding "; + desc += name1; + + if (!name2.empty()) + { + desc += " and "; + desc += name2; + } + + return (desc); +} + +#ifdef DEBUG_DIAGNOSTICS +static std::string stair_destination_description(const coord_def &pos) +{ + if (LevelInfo *linf = travel_cache.find_level_info(level_id::current())) + { + const stair_info *si = linf->get_stair(pos); + if (si) + return (" " + si->describe()); + else if (is_stair(grd(pos))) + return (" (unknown stair)"); + } + return (""); +} +#endif + +static void describe_monster(const monsters *mon) +{ + + // first print type and equipment + std::string text = get_monster_desc(mon); + text += "."; + print_formatted_paragraph(text, get_number_of_cols()); + + if (player_beheld_by(mon)) + mpr("You are beheld by her song.", MSGCH_EXAMINE); + + if (mon->type == MONS_HYDRA) + { + mprf(MSGCH_EXAMINE, "It has %d head%s.", mon->number, + (mon->number > 1? "s" : "")); + } + + print_wounds(mon); + + if (!mons_is_mimic(mon->type) && mons_behaviour_perceptible(mon)) + { + if (mon->behaviour == BEH_SLEEP) + { + mprf(MSGCH_EXAMINE, "%s appears to be resting.", + mon->pronoun(PRONOUN_CAP).c_str()); + } + // Applies to both friendlies and hostiles + else if (mon->behaviour == BEH_FLEE) + { + mprf(MSGCH_EXAMINE, "%s is retreating.", + mon->pronoun(PRONOUN_CAP).c_str()); + } + // hostile with target != you + else if (!mons_friendly(mon) && !mons_neutral(mon) && mon->foe != MHITYOU) + { + // special case: batty monsters get set to BEH_WANDER as + // part of their special behaviour. + if (!testbits(mon->flags, MF_BATTY)) + { + mprf(MSGCH_EXAMINE, "%s doesn't appear to have noticed you.", + mon->pronoun(PRONOUN_CAP).c_str()); + } + } + } + + if (mon->attitude == ATT_FRIENDLY) + { + mprf(MSGCH_EXAMINE, "%s is friendly.", + mon->pronoun(PRONOUN_CAP).c_str()); + } + else if (mons_neutral(mon)) // don't differentiate between permanent or not + { + mprf(MSGCH_EXAMINE, "%s is indifferent to you.", + mon->pronoun(PRONOUN_CAP).c_str()); + } + + if (mon->haloed()) + { + mprf(MSGCH_EXAMINE, "%s is illuminated by a halo.", + mon->pronoun(PRONOUN_CAP).c_str()); + } + + std::string desc = ""; + std::string last_desc = ""; + std::string tmp = ""; + + const bool paralysed = mons_is_paralysed(mon); + if (paralysed) + last_desc += "paralysed"; + + for (mon_enchant_list::const_iterator e = mon->enchantments.begin(); + e != mon->enchantments.end(); ++e) + { + tmp = describe_mons_enchantment(*mon, e->second, paralysed); + if (!tmp.empty()) + { + if (!desc.empty()) + desc += ", "; + desc += last_desc; + last_desc = tmp; + } + } + + if (!last_desc.empty()) + { + if (!desc.empty()) + desc += ", and "; + desc += last_desc; + } + + if (!desc.empty()) + { + text = mon->pronoun(PRONOUN_CAP); + text += " is "; + text += desc; + text += "."; + print_formatted_paragraph(text, get_number_of_cols()); + } +} + +std::string get_monster_desc(const monsters *mon, bool full_desc, + description_level_type mondtype) +{ + std::string desc = mon->name(mondtype); + + const int mon_arm = mon->inv[MSLOT_ARMOUR]; + std::string weap = ""; + + if (mon->type != MONS_DANCING_WEAPON) + weap = describe_monster_weapon(mon); + + if (!weap.empty()) + { + if (full_desc) + desc += ","; + desc += weap; + } + + if (full_desc && mon_arm != NON_ITEM) + { + desc += ", "; + if (!weap.empty()) + desc += "and "; + desc += "wearing "; + desc += mitm[mon_arm].name(DESC_NOCAP_A); + } + + return desc; +} + +static void describe_cell(int mx, int my) +{ + bool mimic_item = false; + bool monster_described = false; + bool cloud_described = false; + bool item_described = false; + + if (mx == you.x_pos && my == you.y_pos) + mpr("You.", MSGCH_EXAMINE_FILTER); + + if (mgrd[mx][my] != NON_MONSTER) + { + int i = mgrd[mx][my]; + + if (_mon_submerged_in_water(&menv[i])) + { + mpr("There is a strange disturbance in the water here.", + MSGCH_EXAMINE_FILTER); + } + +#if DEBUG_DIAGNOSTICS + if (!player_monster_visible( &menv[i] )) + mpr( "There is a non-visible monster here.", MSGCH_DIAGNOSTICS ); +#else + if (!player_monster_visible( &menv[i] )) + goto look_clouds; +#endif + + describe_monster(&menv[i]); + + if (mons_is_mimic( menv[i].type )) + { + mimic_item = true; + item_described = true; + } + else + monster_described = true; + +#if DEBUG_DIAGNOSTICS + stethoscope(i); +#endif + if (Options.tutorial_left && tutorial_monster_interesting(&menv[i])) + { + std::string msg = "(Press v for more information.)"; + print_formatted_paragraph(msg, get_number_of_cols()); + } + } + +#if (!DEBUG_DIAGNOSTICS) + // removing warning + look_clouds: +#endif + + if (is_sanctuary(mx, my)) + mpr("This square lies inside a sanctuary."); + + if (env.cgrid[mx][my] != EMPTY_CLOUD) + { + const int cloud_inspected = env.cgrid[mx][my]; + const cloud_type ctype = (cloud_type) env.cloud[cloud_inspected].type; + + mprf(MSGCH_EXAMINE, "There is a cloud of %s here.", + cloud_name(ctype).c_str()); + + cloud_described = true; + } + + int targ_item = igrd[ mx ][ my ]; + + if (targ_item != NON_ITEM) + { + // If a mimic is on this square, we pretend it's the first item -- bwr + if (mimic_item) + mpr("There is something else lying underneath.", MSGCH_FLOOR_ITEMS); + else + { + if (mitm[ targ_item ].base_type == OBJ_GOLD) + mprf( MSGCH_FLOOR_ITEMS, "A pile of gold coins." ); + else + { + mprf( MSGCH_FLOOR_ITEMS, "You see %s here.", + mitm[targ_item].name(DESC_NOCAP_A).c_str()); + } + + if (mitm[ targ_item ].link != NON_ITEM) + { + mprf( MSGCH_FLOOR_ITEMS, + "There is something else lying underneath."); + } + } + item_described = true; + } + + bool bloody = false; + if (is_bloodcovered(mx, my)) + bloody = true; + + std::string feature_desc = feature_description(mx, my, bloody); +#ifdef DEBUG_DIAGNOSTICS + std::string marker; + if (map_marker *mark = env.markers.find(coord_def(mx, my), MAT_ANY)) + { + std::string desc = mark->debug_describe(); + if (desc.empty()) + desc = "?"; + marker = " (" + desc + ")"; + } + const std::string traveldest = + stair_destination_description(coord_def(mx, my)); + const dungeon_feature_type feat = grd[mx][my]; + mprf(MSGCH_DIAGNOSTICS, "(%d,%d): %s - %s (%d/%s)%s%s", mx, my, + stringize_glyph(get_screen_glyph(mx, my)).c_str(), + feature_desc.c_str(), + feat, + dungeon_feature_name(feat), + marker.c_str(), + traveldest.c_str()); +#else + if (Options.tutorial_left && tutorial_feat_interesting(grd[mx][my])) + { + feature_desc += " (Press v for more information.)"; + + print_formatted_paragraph(feature_desc, get_number_of_cols()); + } + else + { + const dungeon_feature_type feat = grd[mx][my]; + + if (interesting_feature(feat)) + feature_desc += " (Press 'v' for more information.)"; + + // Suppress "Floor." if there's something on that square that we've + // already described. + if ((feat == DNGN_FLOOR || feat == DNGN_FLOOR_SPECIAL) && !bloody + && (monster_described || item_described || cloud_described)) + { + return; + } + + msg_channel_type channel = MSGCH_EXAMINE; + if (feat == DNGN_FLOOR + || feat == DNGN_FLOOR_SPECIAL + || feat == DNGN_SHALLOW_WATER + || feat == DNGN_DEEP_WATER) + { + channel = MSGCH_EXAMINE_FILTER; + } + mpr(feature_desc.c_str(), channel); + } +#endif +} + +/////////////////////////////////////////////////////////////////////////// +// targeting_behaviour + +targeting_behaviour::targeting_behaviour(bool look_around) + : just_looking(look_around), compass(false) +{ +} + +targeting_behaviour::~targeting_behaviour() +{ +} + +int targeting_behaviour::get_key() +{ +#ifdef USE_TILE + mouse_control mc(MOUSE_MODE_TARGET_DIR); +#endif + + if (!crawl_state.is_replaying_keys()) + flush_input_buffer(FLUSH_BEFORE_COMMAND); + + return unmangle_direction_keys( getchm(KC_TARGETING), KC_TARGETING, + false, false); +} + +command_type targeting_behaviour::get_command(int key) +{ + if (key == -1) + key = get_key(); + + switch ( key ) + { + case ESCAPE: + case 'x': return CMD_TARGET_CANCEL; + +#ifdef USE_TILE + case CK_MOUSE_MOVE: return CMD_TARGET_MOUSE_MOVE; + case CK_MOUSE_CLICK: return CMD_TARGET_MOUSE_SELECT; +#endif + +#ifdef WIZARD + case 'F': return CMD_TARGET_WIZARD_MAKE_FRIENDLY; + case 's': return CMD_TARGET_WIZARD_MAKE_SHOUT; + case 'g': return CMD_TARGET_WIZARD_GIVE_ITEM; +#endif + case 'v': return CMD_TARGET_DESCRIBE; + case '?': return CMD_TARGET_HELP; + case ' ': return just_looking? CMD_TARGET_CANCEL : CMD_TARGET_SELECT; +#ifdef WIZARD + case CONTROL('C'): return CMD_TARGET_CYCLE_BEAM; +#endif + case ':': return CMD_TARGET_HIDE_BEAM; + case '\r': return CMD_TARGET_SELECT; + case '.': return CMD_TARGET_SELECT; + case '5': return CMD_TARGET_SELECT; + case '!': return CMD_TARGET_SELECT_ENDPOINT; + + case '\\': + case '\t': return CMD_TARGET_FIND_PORTAL; + case '^': return CMD_TARGET_FIND_TRAP; + case '_': return CMD_TARGET_FIND_ALTAR; + case '<': return CMD_TARGET_FIND_UPSTAIR; + case '>': return CMD_TARGET_FIND_DOWNSTAIR; + + case CONTROL('F'): return CMD_TARGET_CYCLE_TARGET_MODE; + case 'p': return CMD_TARGET_PREV_TARGET; + case 'f': return CMD_TARGET_MAYBE_PREV_TARGET; + case 't': return CMD_TARGET_MAYBE_PREV_TARGET; // for the 0.3.4 keys + + case '-': return CMD_TARGET_CYCLE_BACK; + case '+': + case '=': return CMD_TARGET_CYCLE_FORWARD; + case ';': + case '/': return CMD_TARGET_OBJ_CYCLE_BACK; + case '*': + case '\'': return CMD_TARGET_OBJ_CYCLE_FORWARD; + + case 'b': return CMD_TARGET_DOWN_LEFT; + case 'h': return CMD_TARGET_LEFT; + case 'j': return CMD_TARGET_DOWN; + case 'k': return CMD_TARGET_UP; + case 'l': return CMD_TARGET_RIGHT; + case 'n': return CMD_TARGET_DOWN_RIGHT; + case 'u': return CMD_TARGET_UP_RIGHT; + case 'y': return CMD_TARGET_UP_LEFT; + + case 'B': return CMD_TARGET_DIR_DOWN_LEFT; + case 'H': return CMD_TARGET_DIR_LEFT; + case 'J': return CMD_TARGET_DIR_DOWN; + case 'K': return CMD_TARGET_DIR_UP; + case 'L': return CMD_TARGET_DIR_RIGHT; + case 'N': return CMD_TARGET_DIR_DOWN_RIGHT; + case 'U': return CMD_TARGET_DIR_UP_RIGHT; + case 'Y': return CMD_TARGET_DIR_UP_LEFT; + + default: return CMD_NO_CMD; + } +} + +bool targeting_behaviour::should_redraw() +{ + return (false); +} diff --git a/crawl-ref/source/directn.h b/crawl-ref/source/directn.h new file mode 100644 index 0000000000..e968d82926 --- /dev/null +++ b/crawl-ref/source/directn.h @@ -0,0 +1,228 @@ +/* + * File: directn.h + * Summary: Functions used when picking squares. + * Written by: Linley Henzell + * + * Modified for Crawl Reference by $Author$ on $Date$ + * + * Change History (most recent first): + * + * <1> -/--/-- LRH Created + */ + + +#ifndef DIRECT_H +#define DIRECT_H + +#include "externs.h" +#include "enum.h" +#include "libgui.h" +#include "ray.h" + +class crawl_view_buffer +{ +public: + crawl_view_buffer(); + ~crawl_view_buffer(); + void size(const coord_def &size); + operator screen_buffer_t * () { return (buffer); } + + void draw(); +private: + screen_buffer_t *buffer; +}; + +// last updated 12may2000 {dlb} +/* *********************************************************************** + * called from: acr - debug - effects - it_use3 - item_use - spells1 - + * spells2 - spells3 - spells4 + * *********************************************************************** */ +struct crawl_view_geometry +{ +public: + coord_def termp; // Left-top pos of terminal. + coord_def termsz; // Size of the terminal. + coord_def viewp; // Left-top pos of viewport. + coord_def viewsz; // Size of the viewport (play area). + coord_def hudp; // Left-top pos of status area. + coord_def hudsz; // Size of the status area. + coord_def msgp; // Left-top pos of the message pane. + coord_def msgsz; // Size of the message pane. + coord_def mlistp; // Left-top pos of the monster list. + coord_def mlistsz; // Size of the monster list. + + crawl_view_buffer vbuf; // Buffer for drawing the main game map. + + coord_def vgrdc; // What grid pos is at the centre of the view + // usually you.pos(). + + coord_def viewhalfsz; + + coord_def glos1, glos2; // LOS limit grid coords (inclusive) + coord_def vlos1, vlos2; // LOS limit viewport coords (inclusive) + + coord_def mousep; // Where the mouse is. + +private: + coord_def last_player_pos; + +public: + crawl_view_geometry(); + void init_geometry(); + + void init_view(); + void set_player_at(const coord_def &c, bool force_centre = false); + + coord_def view_centre() const + { + return viewp + viewhalfsz; + } + + bool in_grid_los(const coord_def &c) const + { + return (c.x >= glos1.x && c.x <= glos2.x + && c.y >= glos1.y && c.y <= glos2.y); + } + + bool in_view_los(const coord_def &c) const + { + return (c.x >= vlos1.x && c.x <= vlos2.x + && c.y >= vlos1.y && c.y <= vlos2.y); + } + + bool in_view_viewport(const coord_def &c) const + { + return (c.x >= viewp.x && c.y >= viewp.y + && c.x < viewp.x + viewsz.x + && c.y < viewp.y + viewsz.y); + } + + bool in_grid_viewport(const coord_def &c) const + { + return in_view_viewport(c - vgrdc + view_centre()); + } +}; + +extern crawl_view_geometry crawl_view; + +// An object that modifies the behaviour of the direction prompt. +class targeting_behaviour +{ +public: + targeting_behaviour(bool just_looking = false); + virtual ~targeting_behaviour(); + + // Returns a keystroke for the prompt. + virtual int get_key(); + virtual command_type get_command(int key = -1); + virtual bool should_redraw(); + +public: + bool just_looking; + bool compass; +}; + +// output from direction() function: +struct dist +{ + bool isValid; // valid target chosen? + bool isTarget; // target (true), or direction (false)? + bool isMe; // selected self (convenience: tx == you.x_pos, + // ty == you.y_pos) + bool isEndpoint; // Does the player want the attack to stop at (tx,ty)? + bool isCancel; // user cancelled (usually key) + bool choseRay; // user wants a specific beam + int tx,ty; // target x,y or logical extension of beam to map edge + int dx,dy; // delta x and y if direction - always -1,0,1 + ray_def ray; // ray chosen if necessary + + // internal use - ignore + int prev_target; // previous target + + // target - source (source == you.pos()) + coord_def target() const + { + return coord_def(tx, ty); + } +}; + +void direction( dist &moves, targeting_type restricts = DIR_NONE, + targ_mode_type mode = TARG_ANY, int range = -1, + bool just_looking = false, bool needs_path = true, + const char *prompt = NULL, targeting_behaviour *mod = NULL ); + +bool in_los_bounds(int x, int y); +bool in_viewport_bounds(int x, int y); +bool in_los(int x, int y); +bool in_vlos(int x, int y); +bool in_vlos(const coord_def &pos); + +void terse_describe_square(const coord_def &c); +void full_describe_square(const coord_def &c); +void describe_floor(); +std::string get_monster_desc(const monsters *mon, + bool full_desc = true, + description_level_type mondtype = DESC_CAP_A); + +int dos_direction_unmunge(int doskey); + +std::string feature_description(int mx, int my, bool bloody = false, + description_level_type dtype = DESC_CAP_A, + bool add_stop = true); +std::string raw_feature_description(dungeon_feature_type grid, + trap_type tr = NUM_TRAPS); +std::string feature_description(dungeon_feature_type grid, + trap_type trap = NUM_TRAPS, bool bloody = false, + description_level_type dtype = DESC_CAP_A, + bool add_stop = true); + +std::vector features_by_desc(const base_pattern &pattern); + +inline int view2gridX(int vx) +{ + return (crawl_view.vgrdc.x + vx - crawl_view.view_centre().x); +} + +inline int view2gridY(int vy) +{ + return (crawl_view.vgrdc.y + vy - crawl_view.view_centre().y); +} + +inline coord_def view2grid(const coord_def &pos) +{ + return pos - crawl_view.view_centre() + crawl_view.vgrdc; +} + +inline int grid2viewX(int gx) +{ + return (gx - crawl_view.vgrdc.x + crawl_view.view_centre().x); +} + +inline int grid2viewY(int gy) +{ + return (gy - crawl_view.vgrdc.y + crawl_view.view_centre().y); +} + +inline coord_def grid2view(const coord_def &pos) +{ + return (pos - crawl_view.vgrdc + crawl_view.view_centre()); +} + +inline coord_def view2show(const coord_def &pos) +{ + return (pos - crawl_view.vlos1 + coord_def(1, 1)); +} + +inline coord_def show2view(const coord_def &pos) +{ + return (pos + crawl_view.vlos1 - coord_def(1, 1)); +} + +inline coord_def grid2show(const coord_def &pos) +{ + return (view2show(grid2view(pos))); +} + +extern const struct coord_def Compass[8]; + +#endif diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 7ba2ce11c2..1c55e88d6c 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -39,7 +39,7 @@ #include "defines.h" #include "enum.h" #include "externs.h" -#include "direct.h" +#include "directn.h" #include "dungeon.h" #include "files.h" #include "food.h" diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc index a245da13a2..7d8a0a62ca 100644 --- a/crawl-ref/source/effects.cc +++ b/crawl-ref/source/effects.cc @@ -25,7 +25,7 @@ #include "decks.h" #include "delay.h" #include "describe.h" -#include "direct.h" +#include "directn.h" #include "dgnevent.h" #include "food.h" #include "hiscores.h" diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 7b7211adce..7d04269590 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -52,20 +52,13 @@ #include #include -#if _MSC_VER -// # include conflicts with crawl's header. Yes this sucks -# include -#else -#include -#endif - #include "externs.h" #include "chardump.h" #include "cloud.h" #include "clua.h" #include "debug.h" -#include "direct.h" +#include "directn.h" #include "dungeon.h" #include "effects.h" #include "ghost.h" @@ -100,6 +93,14 @@ #include "view.h" #include "xom.h" +#if _MSC_VER +#include +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +#endif + #ifndef HAVE_STAT #if defined(UNIX) || defined(__MINGW32__) || defined(DOS) #define HAVE_STAT @@ -225,12 +226,30 @@ player_save_info read_character_info(const std::string &savefile) return fromfile; } +static bool _is_good_filename(const std::string &s) +{ + return (s != "." && s != ".."); +} + // Returns the names of all files in the given directory. Note that the // filenames returned are relative to the directory. std::vector get_dir_files(const std::string &dirname) { std::vector files; +#ifdef _MSC_VER + WIN32_FIND_DATA lData; + HANDLE hFind = FindFirstFile(dirname.c_str(), &lData); + if (hFind != INVALID_HANDLE_VALUE) + { + if (_is_good_filename(lData.cFileName)) + files.push_back(lData.cFileName); + while (FindNextFile(hFind, &lData)) + files.push_back(lData.cFileName); + FindClose(hFind); + } +#else // non-MS VC++ compilers + DIR *dir = opendir(dirname.c_str()); if (!dir) return (files); @@ -244,6 +263,7 @@ std::vector get_dir_files(const std::string &dirname) files.push_back(name); } closedir(dir); +#endif return (files); } @@ -323,12 +343,18 @@ static bool file_exists(const std::string &name) // Low-tech existence check. static bool dir_exists(const std::string &dir) { +#ifdef _MSC_VER + DWORD lAttr = GetFileAttributes(dir.c_str()); + return (lAttr != INVALID_FILE_ATTRIBUTES + && (lAttr & FILE_ATTRIBUTE_DIRECTORY)); +#else DIR *d = opendir(dir.c_str()); const bool exists = !!d; if (d) closedir(d); return (exists); +#endif } static int create_directory(const char *dir) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 8ce4243eca..f822989c55 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -25,7 +25,7 @@ #include "chardump.h" #include "clua.h" #include "delay.h" -#include "direct.h" +#include "directn.h" #include "Kills.h" #include "files.h" #include "defines.h" @@ -143,7 +143,7 @@ int str_to_colour( const std::string &str, int default_colour, "iron", "bone", "random" }; - ASSERT(ARRAYSIZE(element_cols) == (EC_RANDOM - EC_FIRE) + 1); + ASSERT(ARRAYSZ(element_cols) == (EC_RANDOM - EC_FIRE) + 1); for (ret = 0; ret < 16; ret++) { @@ -2411,8 +2411,9 @@ void game_options::read_option_line(const std::string &str, bool runscript) } else BOOL_OPTION(explore_greedy); else BOOL_OPTION(explore_improved); - else BOOL_OPTION(trap_prompt); - else if (key == "stash_tracking") + + BOOL_OPTION(trap_prompt); + else if (key == "stash_tracking") { stash_tracking = field == "dropped" ? STM_DROPPED : @@ -3102,7 +3103,7 @@ void menu_sort_condition::set_menu_type(std::string &s) { "pickup:", MT_PICKUP } }; - for (unsigned mi = 0; mi < ARRAYSIZE(menu_type_map); ++mi) + for (unsigned mi = 0; mi < ARRAYSZ(menu_type_map); ++mi) { const std::string &name = menu_type_map[mi].mname; if (s.find(name) == 0) diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index 31c4c09e11..cfe295166b 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -517,7 +517,7 @@ void init_item_sort_comparators(item_sort_comparators &list, if (s[0] == '<' || s[0] == '>') s = s.substr(1); - for (unsigned ci = 0; ci < ARRAYSIZE(cmp_map); ++ci) + for (unsigned ci = 0; ci < ARRAYSZ(cmp_map); ++ci) if (cmp_map[ci].cname == s) { list.push_back( item_comparator( cmp_map[ci].cmp, negated ) ); diff --git a/crawl-ref/source/it_use3.cc b/crawl-ref/source/it_use3.cc index fa6ee7194a..4a674f84e3 100644 --- a/crawl-ref/source/it_use3.cc +++ b/crawl-ref/source/it_use3.cc @@ -25,7 +25,7 @@ #include "cloud.h" #include "database.h" #include "decks.h" -#include "direct.h" +#include "directn.h" #include "effects.h" #include "fight.h" #include "food.h" diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc index 78f2315915..902565deed 100644 --- a/crawl-ref/source/item_use.cc +++ b/crawl-ref/source/item_use.cc @@ -42,7 +42,7 @@ #include "debug.h" #include "delay.h" #include "describe.h" -#include "direct.h" +#include "directn.h" #include "effects.h" #include "fight.h" #include "food.h" @@ -3586,10 +3586,10 @@ bool _drink_fountain() 20, 20, 4, 4, 4 }; - COMPILE_CHECK( ARRAYSIZE(weights) == ARRAYSIZE(effects), c1 ); + COMPILE_CHECK( ARRAYSZ(weights) == ARRAYSZ(effects), c1 ); fountain_effect = effects[choose_random_weighted(weights, - weights + ARRAYSIZE(weights))]; + weights + ARRAYSZ(weights))]; } if (fountain_effect != POT_WATER && fountain_effect != POT_BLOOD) diff --git a/crawl-ref/source/itemname.cc b/crawl-ref/source/itemname.cc index 63faef7768..f25bd8f34f 100644 --- a/crawl-ref/source/itemname.cc +++ b/crawl-ref/source/itemname.cc @@ -1296,14 +1296,14 @@ std::string item_def::name_aux( description_level_type desc, "smoky ", "glowing ", "sedimented ", "metallic ", "murky ", "gluggy ", "oily ", "slimy ", "emulsified " }; - COMPILE_CHECK( ARRAYSIZE(potion_qualifiers) == PDQ_NQUALS, c1 ); + COMPILE_CHECK( ARRAYSZ(potion_qualifiers) == PDQ_NQUALS, c1 ); static const char *potion_colours[] = { "clear", "blue", "black", "silvery", "cyan", "purple", "orange", "inky", "red", "yellow", "green", "brown", "pink", "white" }; - COMPILE_CHECK( ARRAYSIZE(potion_colours) == PDC_NCOLOURS, c1 ); + COMPILE_CHECK( ARRAYSZ(potion_colours) == PDC_NCOLOURS, c1 ); const char *qualifier = (pqual < 0 || pqual >= PDQ_NQUALS)? "bug-filled " diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index 541b339301..f2c89cd3e6 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -42,7 +42,7 @@ #include "debug.h" #include "delay.h" #include "dgnevent.h" -#include "direct.h" +#include "directn.h" #include "effects.h" #include "food.h" #include "hiscores.h" diff --git a/crawl-ref/source/libgui.cc b/crawl-ref/source/libgui.cc index eef00e35f5..4ade6d9bb3 100644 --- a/crawl-ref/source/libgui.cc +++ b/crawl-ref/source/libgui.cc @@ -19,7 +19,7 @@ #include "cio.h" #include "defines.h" #include "describe.h" -#include "direct.h" +#include "directn.h" #include "files.h" #include "food.h" #include "itemname.h" diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc index 5a3aa0cbb9..722091bd9a 100644 --- a/crawl-ref/source/libutil.cc +++ b/crawl-ref/source/libutil.cc @@ -13,7 +13,7 @@ #include "AppHdr.h" #include "defines.h" -#include "direct.h" +#include "directn.h" #include "initfile.h" #include "libutil.h" #include "externs.h" @@ -26,7 +26,7 @@ #include #if defined(WIN32CONSOLE) || defined(WIN32TILES) - #undef ARRAYSIZE + #undef ARRAYSZ #include #undef max diff --git a/crawl-ref/source/libw32c.cc b/crawl-ref/source/libw32c.cc index 3e9f4b9675..015e33c906 100644 --- a/crawl-ref/source/libw32c.cc +++ b/crawl-ref/source/libw32c.cc @@ -58,7 +58,7 @@ #include #include -#undef ARRAYSIZE +#undef ARRAYSZ #include #undef max diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc index 2e7657b84a..f99ea111d5 100644 --- a/crawl-ref/source/luadgn.cc +++ b/crawl-ref/source/luadgn.cc @@ -14,7 +14,7 @@ #include "branch.h" #include "clua.h" #include "cloud.h" -#include "direct.h" +#include "directn.h" #include "dungeon.h" #include "files.h" #include "initfile.h" @@ -1120,11 +1120,11 @@ const char *dngn_feature_names[] = dungeon_feature_type dungeon_feature_by_name(const std::string &name) { - COMPILE_CHECK(ARRAYSIZE(dngn_feature_names) == NUM_REAL_FEATURES, c1); + COMPILE_CHECK(ARRAYSZ(dngn_feature_names) == NUM_REAL_FEATURES, c1); if (name.empty()) return (DNGN_UNSEEN); - for (unsigned i = 0; i < ARRAYSIZE(dngn_feature_names); ++i) + for (unsigned i = 0; i < ARRAYSZ(dngn_feature_names); ++i) if (dngn_feature_names[i] == name) return static_cast(i); @@ -1135,11 +1135,11 @@ std::vector dungeon_feature_matches(const std::string &name) { std::vector matches; - COMPILE_CHECK(ARRAYSIZE(dngn_feature_names) == NUM_REAL_FEATURES, c1); + COMPILE_CHECK(ARRAYSZ(dngn_feature_names) == NUM_REAL_FEATURES, c1); if (name.empty()) return (matches); - for (unsigned i = 0; i < ARRAYSIZE(dngn_feature_names); ++i) + for (unsigned i = 0; i < ARRAYSZ(dngn_feature_names); ++i) if (strstr(dngn_feature_names[i], name.c_str())) matches.push_back(dngn_feature_names[i]); @@ -1150,7 +1150,7 @@ const char *dungeon_feature_name(dungeon_feature_type rfeat) { const unsigned feat = rfeat; - if (feat >= ARRAYSIZE(dngn_feature_names)) + if (feat >= ARRAYSZ(dngn_feature_names)) return (NULL); return dngn_feature_names[feat]; @@ -1178,7 +1178,7 @@ static const char *dgn_event_type_names[] = static dgn_event_type dgn_event_type_by_name(const std::string &name) { - for (unsigned i = 0; i < ARRAYSIZE(dgn_event_type_names); ++i) + for (unsigned i = 0; i < ARRAYSZ(dgn_event_type_names); ++i) if (dgn_event_type_names[i] == name) return static_cast(i? 1 << (i - 1) : 0); return (DET_NONE); @@ -1189,7 +1189,7 @@ static const char *dgn_event_type_name(unsigned evmask) if (evmask == 0) return (dgn_event_type_names[0]); - for (unsigned i = 1; i < ARRAYSIZE(dgn_event_type_names); ++i) + for (unsigned i = 1; i < ARRAYSZ(dgn_event_type_names); ++i) if (evmask & (1 << (i - 1))) return (dgn_event_type_names[i]); diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj index ae4db2fb9c..dc1bce8539 100644 --- a/crawl-ref/source/makefile.obj +++ b/crawl-ref/source/makefile.obj @@ -16,7 +16,7 @@ decks.o \ delay.o \ describe.o \ dgnevent.o \ -direct.o \ +directn.o \ dungeon.o \ effects.o \ fight.o \ diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index 594ce07464..26fb4f78aa 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -15,7 +15,7 @@ #include "AppHdr.h" #include "branch.h" #include "describe.h" -#include "direct.h" +#include "directn.h" #include "dungeon.h" #include "files.h" #include "initfile.h" @@ -1426,6 +1426,7 @@ std::string map_def::validate_map_def() if (!err.empty()) return (err); + fixup(); resolve(); test_lua_validate(true); @@ -1719,8 +1720,7 @@ void map_def::rotate(bool clock) void map_def::normalise() { - // Minivaults are padded out with floor tiles, normal maps are - // padded out with rock walls. + // Pad out lines that are shorter than max. map.normalise(' '); } diff --git a/crawl-ref/source/mapmark.cc b/crawl-ref/source/mapmark.cc index dfcc66ab34..5c7a008d49 100644 --- a/crawl-ref/source/mapmark.cc +++ b/crawl-ref/source/mapmark.cc @@ -14,7 +14,7 @@ #include "mapmark.h" #include "clua.h" -#include "direct.h" +#include "directn.h" #include "libutil.h" #include "luadgn.h" #include "stuff.h" diff --git a/crawl-ref/source/mgrow.cc b/crawl-ref/source/mgrow.cc index 482f33889e..74fa4c07e2 100644 --- a/crawl-ref/source/mgrow.cc +++ b/crawl-ref/source/mgrow.cc @@ -82,7 +82,7 @@ mons_experience_levels::mons_experience_levels() static const monster_level_up *monster_level_up_target( monster_type type, int hit_dice) { - for (unsigned i = 0; i < ARRAYSIZE(mon_grow); ++i) + for (unsigned i = 0; i < ARRAYSZ(mon_grow); ++i) { const monster_level_up &mlup(mon_grow[i]); if (mlup.before == type) diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc index 211682bb46..b5e2093fab 100644 --- a/crawl-ref/source/misc.cc +++ b/crawl-ref/source/misc.cc @@ -45,9 +45,9 @@ #include "clua.h" #include "cloud.h" #include "delay.h" -#include "direct.h" +#include "directn.h" #include "dgnevent.h" -#include "direct.h" +#include "directn.h" #include "dungeon.h" #include "files.h" #include "food.h" diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 1902d96dbe..c1262ee618 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -80,7 +80,7 @@ static monsterentry mondata[] = { #include "mon-data.h" }; -#define MONDATASIZE ARRAYSIZE(mondata) +#define MONDATASIZE ARRAYSZ(mondata) static mon_spellbook mspell_list[] = { #include "mon-spll.h" @@ -1509,7 +1509,7 @@ static const char *drac_colour_names[] = { std::string draconian_colour_name(monster_type mtype) { - COMPILE_CHECK(ARRAYSIZE(drac_colour_names) == + COMPILE_CHECK(ARRAYSZ(drac_colour_names) == MONS_PALE_DRACONIAN - MONS_DRACONIAN, c1); if (mtype < MONS_BLACK_DRACONIAN || mtype > MONS_PALE_DRACONIAN) @@ -1519,10 +1519,10 @@ std::string draconian_colour_name(monster_type mtype) monster_type draconian_colour_by_name(const std::string &name) { - COMPILE_CHECK(ARRAYSIZE(drac_colour_names) + COMPILE_CHECK(ARRAYSZ(drac_colour_names) == (MONS_PALE_DRACONIAN - MONS_DRACONIAN), c1); - for (unsigned i = 0; i < ARRAYSIZE(drac_colour_names); ++i) + for (unsigned i = 0; i < ARRAYSZ(drac_colour_names); ++i) if (name == drac_colour_names[i]) return static_cast(i + MONS_BLACK_DRACONIAN); @@ -4149,7 +4149,7 @@ void monsters::load_spells(mon_spellbook_type book) spells = ghost->spells; else { - for (unsigned int i = 0; i < ARRAYSIZE(mspell_list); ++i) + for (unsigned int i = 0; i < ARRAYSZ(mspell_list); ++i) { if (mspell_list[i].type == book) { @@ -5451,7 +5451,7 @@ static const char *enchant_names[] = const char *mons_enchantment_name(enchant_type ench) { - COMPILE_CHECK(ARRAYSIZE(enchant_names) == NUM_ENCHANTMENTS+1, c1); + COMPILE_CHECK(ARRAYSZ(enchant_names) == NUM_ENCHANTMENTS+1, c1); if (ench > NUM_ENCHANTMENTS) ench = NUM_ENCHANTMENTS; diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 7cd4b1c931..47ff11bdc7 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -994,13 +994,13 @@ static mutation_def mutation_defs[] = { { MUT_PATTERNED_SCALES, 1, 3, false, true } }; -COMPILE_CHECK(ARRAYSIZE(mutation_defs) == NUM_MUTATIONS, c1); +COMPILE_CHECK(ARRAYSZ(mutation_defs) == NUM_MUTATIONS, c1); #ifdef DEBUG_DIAGNOSTICS void sanity_check_mutation_defs() { - for (unsigned i = 0; i < ARRAYSIZE(mutation_defs); ++i) + for (unsigned i = 0; i < ARRAYSZ(mutation_defs); ++i) { const mutation_def &mdef(mutation_defs[i]); ASSERT(mdef.mutation == static_cast(i) diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 75338d3386..ff017dfefd 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -192,7 +192,7 @@ static species_type _random_draconian_species() static species_type _get_species(const int index) { - if (index < 0 || (unsigned int) index >= ARRAYSIZE(old_species_order)) + if (index < 0 || (unsigned int) index >= ARRAYSZ(old_species_order)) { return (SP_UNKNOWN); } @@ -246,7 +246,7 @@ static job_type new_jobs_order[] = { static job_type _get_class(const int index) { - if (index < 0 || (unsigned int) index >= ARRAYSIZE(old_jobs_order)) + if (index < 0 || (unsigned int) index >= ARRAYSZ(old_jobs_order)) return JOB_UNKNOWN; return (Options.use_old_selection_order? old_jobs_order[index] @@ -264,9 +264,9 @@ static const char * Species_Abbrev_List[ NUM_SPECIES ] = int get_species_index_by_abbrev( const char *abbrev ) { - COMPILE_CHECK(ARRAYSIZE(Species_Abbrev_List) == NUM_SPECIES, c1); + COMPILE_CHECK(ARRAYSZ(Species_Abbrev_List) == NUM_SPECIES, c1); - for (unsigned i = 0; i < ARRAYSIZE(old_species_order); i++) + for (unsigned i = 0; i < ARRAYSZ(old_species_order); i++) { const int sp = (Options.use_old_selection_order ? old_species_order[i] : new_species_order[i]); @@ -292,7 +292,7 @@ int get_species_index_by_name( const char *name ) strncpy( lowered_buff, name, sizeof( lowered_buff ) ); strlwr( lowered_buff ); - for (i = 0; i < ARRAYSIZE(old_species_order); i++) + for (i = 0; i < ARRAYSZ(old_species_order); i++) { const species_type real_sp = (Options.use_old_selection_order ? old_species_order[i] @@ -323,7 +323,7 @@ const char *get_species_abbrev( int which_species ) int get_species_by_abbrev( const char *abbrev ) { int i; - COMPILE_CHECK(ARRAYSIZE(Species_Abbrev_List) == NUM_SPECIES, c1); + COMPILE_CHECK(ARRAYSZ(Species_Abbrev_List) == NUM_SPECIES, c1); for (i = SP_HUMAN; i < NUM_SPECIES; i++) { if (tolower( abbrev[0] ) == tolower( Species_Abbrev_List[i][0] ) @@ -351,10 +351,10 @@ static const char * Class_Name_List[ NUM_JOBS ] = int get_class_index_by_abbrev( const char *abbrev ) { - COMPILE_CHECK(ARRAYSIZE(Class_Abbrev_List) == NUM_JOBS, c1); + COMPILE_CHECK(ARRAYSZ(Class_Abbrev_List) == NUM_JOBS, c1); unsigned int job; - for (unsigned int i = 0; i < ARRAYSIZE(old_jobs_order); i++) + for (unsigned int i = 0; i < ARRAYSZ(old_jobs_order); i++) { job = (Options.use_old_selection_order ? old_jobs_order[i] : new_jobs_order[i]); @@ -394,7 +394,7 @@ int get_class_by_abbrev( const char *abbrev ) int get_class_index_by_name( const char *name ) { - COMPILE_CHECK(ARRAYSIZE(Class_Name_List) == NUM_JOBS, c1); + COMPILE_CHECK(ARRAYSZ(Class_Name_List) == NUM_JOBS, c1); char *ptr; char lowered_buff[80]; @@ -405,7 +405,7 @@ int get_class_index_by_name( const char *name ) int cl = -1; unsigned int job; - for (unsigned int i = 0; i < ARRAYSIZE(old_jobs_order); i++) + for (unsigned int i = 0; i < ARRAYSZ(old_jobs_order); i++) { job = (Options.use_old_selection_order ? old_jobs_order[i] : new_jobs_order[i]); @@ -3137,12 +3137,12 @@ bool choose_race() printed = true; // the list musn't be longer than the number of actual species - COMPILE_CHECK(ARRAYSIZE(old_species_order) <= NUM_SPECIES, c1); + COMPILE_CHECK(ARRAYSZ(old_species_order) <= NUM_SPECIES, c1); // check whether the two lists have the same size - COMPILE_CHECK(ARRAYSIZE(old_species_order) == ARRAYSIZE(new_species_order), c2); + COMPILE_CHECK(ARRAYSZ(old_species_order) == ARRAYSZ(new_species_order), c2); - const int num_species = ARRAYSIZE(old_species_order); + const int num_species = ARRAYSZ(old_species_order); spec_query: bool prevraceok = (Options.prev_race == '*'); @@ -3386,12 +3386,12 @@ bool choose_class(void) ng_cls = 0; // the list musn't be longer than the number of actual classes - COMPILE_CHECK(ARRAYSIZE(old_jobs_order) <= NUM_JOBS, c1); + COMPILE_CHECK(ARRAYSZ(old_jobs_order) <= NUM_JOBS, c1); // check whether the two lists have the same size - COMPILE_CHECK(ARRAYSIZE(old_jobs_order) == ARRAYSIZE(new_jobs_order), c2); + COMPILE_CHECK(ARRAYSZ(old_jobs_order) == ARRAYSZ(new_jobs_order), c2); - const int num_classes = ARRAYSIZE(old_jobs_order); + const int num_classes = ARRAYSZ(old_jobs_order); job_query: bool prevclassok = (Options.prev_cls == '*'); diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index 3ffea35dd0..ffb09dde4b 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -26,7 +26,7 @@ #include "abl-show.h" #include "branch.h" #include "describe.h" -#include "direct.h" +#include "directn.h" #include "format.h" #include "fight.h" #include "initfile.h" diff --git a/crawl-ref/source/overmap.cc b/crawl-ref/source/overmap.cc index cf02458678..b7968ea31f 100644 --- a/crawl-ref/source/overmap.cc +++ b/crawl-ref/source/overmap.cc @@ -29,7 +29,7 @@ #include "branch.h" #include "cio.h" #include "dgnevent.h" -#include "direct.h" +#include "directn.h" #include "dungeon.h" #include "files.h" #include "menu.h" diff --git a/crawl-ref/source/quiver.cc b/crawl-ref/source/quiver.cc index d737bcb0d7..5e4744d7c3 100644 --- a/crawl-ref/source/quiver.cc +++ b/crawl-ref/source/quiver.cc @@ -18,6 +18,8 @@ #include "stuff.h" #include "tags.h" +#include + // checks base_type for OBJ_UNASSIGNED, and quantity // bool is_valid_item( const item_def &item ) @@ -32,7 +34,7 @@ static bool _items_similar(const item_def& a, const item_def& b); player_quiver::player_quiver() : m_last_used_type(AMMO_THROW) { - COMPILE_CHECK(ARRAYSIZE(m_last_used_of_type) == NUM_AMMO, a); + COMPILE_CHECK(ARRAYSZ(m_last_used_of_type) == NUM_AMMO, a); } // Return: @@ -292,16 +294,16 @@ void player_quiver::_get_fire_order( // Save/load // ---------------------------------------------------------------------- -static const short QUIVER_COOKIE = static_cast(0xb015); +static const short QUIVER_COOKIE = short(0xb015); void player_quiver::save(writer& outf) const { marshallShort(outf, QUIVER_COOKIE); marshallItem(outf, m_last_weapon); marshallLong(outf, m_last_used_type); - marshallLong(outf, ARRAYSIZE(m_last_used_of_type)); + marshallLong(outf, ARRAYSZ(m_last_used_of_type)); - for (unsigned int i = 0; i < ARRAYSIZE(m_last_used_of_type); i++) + for (unsigned int i = 0; i < ARRAYSZ(m_last_used_of_type); i++) marshallItem(outf, m_last_used_of_type[i]); } @@ -315,7 +317,7 @@ void player_quiver::load(reader& inf) ASSERT(m_last_used_type >= AMMO_THROW && m_last_used_type < NUM_AMMO); const unsigned long count = unmarshallLong(inf); - ASSERT(count <= ARRAYSIZE(m_last_used_of_type)); + ASSERT(count <= ARRAYSZ(m_last_used_of_type)); for (unsigned int i = 0; i < count; i++) unmarshallItem(inf, m_last_used_of_type[i]); @@ -328,9 +330,9 @@ void player_quiver::load(reader& inf) preserve_quiver_slots::preserve_quiver_slots() { if (!you.m_quiver) return; - COMPILE_CHECK(ARRAYSIZE(m_last_used_of_type) == - ARRAYSIZE(you.m_quiver->m_last_used_of_type), a); - for (unsigned int i = 0; i < ARRAYSIZE(m_last_used_of_type); i++) + COMPILE_CHECK(ARRAYSZ(m_last_used_of_type) == + ARRAYSZ(you.m_quiver->m_last_used_of_type), a); + for (unsigned int i = 0; i < ARRAYSZ(m_last_used_of_type); i++) { m_last_used_of_type[i] = _get_pack_slot(you.m_quiver->m_last_used_of_type[i]); @@ -340,7 +342,7 @@ preserve_quiver_slots::preserve_quiver_slots() preserve_quiver_slots::~preserve_quiver_slots() { if (! you.m_quiver) return; - for (unsigned int i = 0; i < ARRAYSIZE(m_last_used_of_type); i++) + for (unsigned int i = 0; i < ARRAYSZ(m_last_used_of_type); i++) { const int slot = m_last_used_of_type[i]; if (slot != -1) diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 6b803b434c..1ff77bcc29 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -966,7 +966,7 @@ static bool _beogh_blessing_reinforcement() for (int i = 0; i < how_many; ++i) { monster_type follower_type = - followers[random2(ARRAYSIZE(followers))]; + followers[random2(ARRAYSZ(followers))]; int monster = create_monster(follower_type, 0, BEH_GOD_GIFT, you.x_pos, you.y_pos, you.pet_target, @@ -2209,7 +2209,7 @@ bool did_god_conduct( conduct_type thing_done, int level, bool known, "Create Life" }; - COMPILE_CHECK(ARRAYSIZE(conducts) == NUM_CONDUCTS, c1); + COMPILE_CHECK(ARRAYSZ(conducts) == NUM_CONDUCTS, c1); mprf( MSGCH_DIAGNOSTICS, "conduct: %s; piety: %d (%+d); penance: %d (%+d)", conducts[thing_done], diff --git a/crawl-ref/source/spells1.cc b/crawl-ref/source/spells1.cc index 8e4702584d..1e9d1bb5f0 100644 --- a/crawl-ref/source/spells1.cc +++ b/crawl-ref/source/spells1.cc @@ -29,7 +29,7 @@ #include "abyss.h" #include "beam.h" #include "cloud.h" -#include "direct.h" +#include "directn.h" #include "effects.h" #include "invent.h" #include "it_use2.h" @@ -905,7 +905,7 @@ void antimagic() if (!you.permanent_flight() && you.duration[DUR_CONTROLLED_FLIGHT] > 1) you.duration[DUR_CONTROLLED_FLIGHT] = 1; - for ( unsigned int i = 0; i < ARRAYSIZE(dur_list); ++i ) + for ( unsigned int i = 0; i < ARRAYSZ(dur_list); ++i ) if ( you.duration[dur_list[i]] > 1 ) you.duration[dur_list[i]] = 1; diff --git a/crawl-ref/source/spells1.h b/crawl-ref/source/spells1.h index 66b66c0187..816ce24386 100644 --- a/crawl-ref/source/spells1.h +++ b/crawl-ref/source/spells1.h @@ -16,7 +16,7 @@ #include "externs.h" -#include "direct.h" +#include "directn.h" struct bolt; diff --git a/crawl-ref/source/spells2.cc b/crawl-ref/source/spells2.cc index 3b52fc9428..17bc885061 100644 --- a/crawl-ref/source/spells2.cc +++ b/crawl-ref/source/spells2.cc @@ -32,7 +32,7 @@ #include "beam.h" #include "cloud.h" #include "delay.h" -#include "direct.h" +#include "directn.h" #include "dungeon.h" #include "effects.h" #include "itemname.h" diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc index 29126e8206..32ceaa126a 100644 --- a/crawl-ref/source/spells3.cc +++ b/crawl-ref/source/spells3.cc @@ -27,7 +27,7 @@ #include "beam.h" #include "branch.h" #include "cloud.h" -#include "direct.h" +#include "directn.h" #include "debug.h" #include "delay.h" #include "effects.h" // holy word @@ -755,7 +755,7 @@ bool entomb(int powc) continue; bool proceed = false; - for (unsigned int i = 0; i < ARRAYSIZE(safe_to_overwrite); ++i) + for (unsigned int i = 0; i < ARRAYSZ(safe_to_overwrite); ++i) { if (grd[srx][sry] == safe_to_overwrite[i]) { diff --git a/crawl-ref/source/spells4.cc b/crawl-ref/source/spells4.cc index 18a23fe6d9..6347edfcf4 100644 --- a/crawl-ref/source/spells4.cc +++ b/crawl-ref/source/spells4.cc @@ -27,7 +27,7 @@ #include "debug.h" #include "delay.h" #include "describe.h" -#include "direct.h" +#include "directn.h" #include "dungeon.h" #include "effects.h" #include "it_use2.h" @@ -750,7 +750,7 @@ static bool is_domesticated_animal(int type) MONS_SPINY_FROG, MONS_BLINK_FROG, MONS_WOLF, MONS_WARG, MONS_BEAR, MONS_GRIZZLY_BEAR, MONS_POLAR_BEAR, MONS_BLACK_BEAR }; - for ( unsigned int i = 0; i < ARRAYSIZE(types); ++i ) + for ( unsigned int i = 0; i < ARRAYSZ(types); ++i ) if ( types[i] == type ) return true; return false; diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index 1b7d2dfdd7..b100a966cb 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -3676,7 +3676,7 @@ static int _power_to_barcount( int power ) const int breakpoints[] = { 5, 10, 15, 25, 35, 50, 75, 100, 150 }; int result = 0; - for ( unsigned int i = 0; i < ARRAYSIZE(breakpoints); ++i ) + for ( unsigned int i = 0; i < ARRAYSZ(breakpoints); ++i ) if ( power > breakpoints[i] ) ++result; diff --git a/crawl-ref/source/spl-util.cc b/crawl-ref/source/spl-util.cc index abf3ebabc6..d6993925e7 100644 --- a/crawl-ref/source/spl-util.cc +++ b/crawl-ref/source/spl-util.cc @@ -24,7 +24,7 @@ #include "externs.h" #include "beam.h" -#include "direct.h" +#include "directn.h" #include "debug.h" #include "stuff.h" #include "itemname.h" diff --git a/crawl-ref/source/spl-util.h b/crawl-ref/source/spl-util.h index 98ff8faac8..c7d60e80ae 100644 --- a/crawl-ref/source/spl-util.h +++ b/crawl-ref/source/spl-util.h @@ -16,7 +16,7 @@ #define SPL_UTIL_H #include "enum.h" // just for NUM_SPELL_TYPES and TARG_ENEMY -#include "direct.h" // just for DIR_NONE +#include "directn.h" // just for DIR_NONE enum spschool_flag_type { diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc index 69b52bdd73..314dd4fe19 100644 --- a/crawl-ref/source/stash.cc +++ b/crawl-ref/source/stash.cc @@ -13,7 +13,7 @@ #include "clua.h" #include "command.h" #include "describe.h" -#include "direct.h" +#include "directn.h" #include "food.h" #include "itemname.h" #include "itemprop.h" diff --git a/crawl-ref/source/state.cc b/crawl-ref/source/state.cc index 992380132e..8cb1300b5b 100644 --- a/crawl-ref/source/state.cc +++ b/crawl-ref/source/state.cc @@ -14,7 +14,7 @@ #include "externs.h" #include "delay.h" -#include "direct.h" +#include "directn.h" #include "macro.h" #include "menu.h" // For print_formatted_paragraph() #include "message.h" diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc index 359ff03da3..9bbec1f7c7 100644 --- a/crawl-ref/source/stuff.cc +++ b/crawl-ref/source/stuff.cc @@ -16,7 +16,7 @@ #include "AppHdr.h" #include "cio.h" #include "database.h" -#include "direct.h" +#include "directn.h" #include "message.h" #include "misc.h" #include "monplace.h" diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc index 7ed006e988..a96c3647b3 100644 --- a/crawl-ref/source/terrain.cc +++ b/crawl-ref/source/terrain.cc @@ -17,7 +17,7 @@ #include #include "dgnevent.h" -#include "direct.h" +#include "directn.h" #include "itemprop.h" #include "items.h" #include "message.h" @@ -254,7 +254,7 @@ void get_door_description(int door_size, const char** adjective, const char** no "huge " , "gate", }; - const unsigned int idx = MIN((unsigned int)door_size*2, ARRAYSIZE(descriptions)-2); + const unsigned int idx = MIN((unsigned int)door_size*2, ARRAYSZ(descriptions)-2); *adjective = descriptions[idx]; *noun = descriptions[idx+1]; } diff --git a/crawl-ref/source/tile1.cc b/crawl-ref/source/tile1.cc index 6828ca631f..e3f0d6e52c 100644 --- a/crawl-ref/source/tile1.cc +++ b/crawl-ref/source/tile1.cc @@ -9,7 +9,7 @@ #ifdef USE_TILE #include #include "decks.h" -#include "direct.h" +#include "directn.h" #include "externs.h" #include "food.h" #include "itemname.h" diff --git a/crawl-ref/source/tile2.cc b/crawl-ref/source/tile2.cc index 16b75861d5..09d309d02c 100644 --- a/crawl-ref/source/tile2.cc +++ b/crawl-ref/source/tile2.cc @@ -14,7 +14,7 @@ #include "branch.h" #include "describe.h" -#include "direct.h" +#include "directn.h" #include "dungeon.h" #include "files.h" #include "ghost.h" diff --git a/crawl-ref/source/transfor.cc b/crawl-ref/source/transfor.cc index 0bcc023131..ce766cbe40 100644 --- a/crawl-ref/source/transfor.cc +++ b/crawl-ref/source/transfor.cc @@ -173,7 +173,7 @@ bool transform(int pow, transformation_type which_trans) }; std::set rem_stuff(default_rem, - default_rem + ARRAYSIZE(default_rem)); + default_rem + ARRAYSZ(default_rem)); you.redraw_evasion = true; you.redraw_armour_class = true; diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index 0301a3082e..b5f9fe7c99 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -20,7 +20,7 @@ #include "beam.h" #include "branch.h" #include "delay.h" -#include "direct.h" +#include "directn.h" #include "it_use2.h" #include "items.h" #include "itemprop.h" diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index 54e4fe8194..2822672f93 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -19,7 +19,7 @@ #include "delay.h" #include "describe.h" #include "dgnevent.h" -#include "direct.h" +#include "directn.h" #include "itemname.h" #include "itemprop.h" #include "items.h" diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index b43475b8a8..a642aea2b0 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -46,7 +46,7 @@ #include "debug.h" #include "delay.h" #include "dgnevent.h" -#include "direct.h" +#include "directn.h" #include "dungeon.h" #include "format.h" #include "ghost.h" @@ -4945,7 +4945,7 @@ void crawl_view_buffer::size(const coord_def &sz) // Layout helper classes // ---------------------------------------------------------------------- -// Moved from direct.h, where they didn't need to be. +// Moved from directn.h, where they didn't need to be. // define VIEW_MIN_HEIGHT defined elsewhere // define VIEW_MAX_HEIGHT use Options.view_max_height // define VIEW_MIN_WIDTH defined elsewhere diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc index e00f3b8e43..2427a2b680 100644 --- a/crawl-ref/source/xom.cc +++ b/crawl-ref/source/xom.cc @@ -186,7 +186,7 @@ void xom_makes_you_cast_random_spell(int sever) god_acting gdact(GOD_XOM); - const int nxomspells = ARRAYSIZE(xom_spells); + const int nxomspells = ARRAYSZ(xom_spells); if (spellenum > nxomspells) spellenum = nxomspells; -- cgit v1.2.3-54-g00ecf