summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/view.cc
diff options
context:
space:
mode:
authorRobert Vollmert <rvollmert@gmx.net>2009-11-04 22:45:50 +0100
committerRobert Vollmert <rvollmert@gmx.net>2009-11-04 22:45:50 +0100
commit64c38d95bfd6b24e34bc86f7d4ce7ba345c5a963 (patch)
tree9aaba99b80cd44b032cdd30e40f8b6625508ee89 /crawl-ref/source/view.cc
parentce5c888daccae3cf40be8e28176f415e54b26650 (diff)
downloadcrawl-ref-64c38d95bfd6b24e34bc86f7d4ce7ba345c5a963.tar.gz
crawl-ref-64c38d95bfd6b24e34bc86f7d4ce7ba345c5a963.zip
Split up view.cc.
Diffstat (limited to 'crawl-ref/source/view.cc')
-rw-r--r--crawl-ref/source/view.cc2143
1 files changed, 29 insertions, 2114 deletions
diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc
index 2a64183fda..1ac2a47d78 100644
--- a/crawl-ref/source/view.cc
+++ b/crawl-ref/source/view.cc
@@ -20,7 +20,11 @@
#endif
#include "externs.h"
-#include "options.h"
+
+#include "envmap.h"
+#include "viewchar.h"
+#include "viewgeom.h"
+#include "viewmap.h"
#include "branch.h"
#include "command.h"
@@ -51,6 +55,7 @@
#include "monstuff.h"
#include "mon-util.h"
#include "newgame.h"
+#include "options.h"
#include "jobs.h"
#include "notes.h"
#include "output.h"
@@ -75,50 +80,14 @@
#define DEBUG_PANE_BOUNDS 0
-// These are hidden from the rest of the world... use the functions
-// below to get information about the map grid.
-#define MAP_MAGIC_MAPPED_FLAG 0x01
-#define MAP_SEEN_FLAG 0x02
-#define MAP_CHANGED_FLAG 0x04
-#define MAP_DETECTED_MONSTER 0x08
-#define MAP_DETECTED_ITEM 0x10
-#define MAP_GRID_KNOWN 0xFF
-
-#define MC_ITEM 0x01
-#define MC_MONS 0x02
-
crawl_view_geometry crawl_view;
extern int stealth; // defined in acr.cc
-screen_buffer_t colour_code_map( const coord_def& p, bool item_colour = false,
- bool travel_colour = false, bool on_level = true );
-
static void _get_symbol( const coord_def& where,
show_type object, unsigned *ch,
unsigned short *colour,
bool magic_mapped = false );
-static unsigned _get_symbol(show_type object, unsigned short *colour = NULL,
- bool magic_mapped = false);
-
-static int _get_viewobj_flags(show_type viewobj);
-
-unsigned map_cell::glyph() const
-{
- if (!object)
- return (' ');
- return _get_symbol(object, NULL, !(flags & MAP_SEEN_FLAG));
-}
-
-bool map_cell::known() const
-{
- return (object && (flags & MAP_GRID_KNOWN));
-}
-
-bool map_cell::seen() const
-{
- return (object && (flags & MAP_SEEN_FLAG));
-}
bool inside_level_bounds(int x, int y)
{
@@ -130,298 +99,19 @@ bool inside_level_bounds(const coord_def &p)
return (inside_level_bounds(p.x, p.y));
}
-unsigned get_envmap_char(int x, int y)
-{
- return env.map[x][y].glyph();
-}
-
-show_type get_envmap_obj(int x, int y)
-{
- return (env.map[x][y].object);
-}
-
-void set_envmap_detected_item(int x, int y, bool detected)
-{
- if (detected)
- env.map[x][y].flags |= MAP_DETECTED_ITEM;
- else
- env.map[x][y].flags &= ~MAP_DETECTED_ITEM;
-}
-
-bool is_envmap_detected_item(int x, int y)
-{
- return (env.map[x][y].flags & MAP_DETECTED_ITEM);
-}
-
-void set_envmap_detected_mons(int x, int y, bool detected)
-{
- if (detected)
- env.map[x][y].flags |= MAP_DETECTED_MONSTER;
- else
- env.map[x][y].flags &= ~MAP_DETECTED_MONSTER;
-}
-
-bool is_envmap_detected_mons(int x, int y)
-{
- return (env.map[x][y].flags & MAP_DETECTED_MONSTER);
-}
-
-void set_envmap_glyph(int x, int y, show_type object, int col)
-{
- map_cell &c = env.map[x][y];
- c.object = object;
- c.colour = col;
-#ifdef USE_TILE
- tiles.update_minimap(x, y);
-#endif
-}
-
-void set_envmap_glyph(const coord_def& c, show_type object, int col)
-{
- set_envmap_glyph(c.x, c.y, object, col);
-}
-
-void set_envmap_obj(const coord_def& where, show_type obj)
-{
- env.map(where).object = obj;
-#ifdef USE_TILE
- tiles.update_minimap(where.x, where.y);
-#endif
-}
-
-void set_envmap_col( int x, int y, int colour )
-{
- env.map[x][y].colour = colour;
-}
-
-bool is_sanctuary(const coord_def& p)
-{
- if (!map_bounds(p))
- return (false);
- return (testbits(env.map(p).property, FPROP_SANCTUARY_1)
- || testbits(env.map(p).property, FPROP_SANCTUARY_2));
-}
-
-bool is_bloodcovered(const coord_def& p)
-{
- return (testbits(env.map(p).property, FPROP_BLOODY));
-}
-
-bool is_envmap_item(int x, int y)
-{
- return (_get_viewobj_flags(env.map[x][y].object) & MC_ITEM);
-}
-
-bool is_envmap_mons(int x, int y)
-{
- return (_get_viewobj_flags(env.map[x][y].object) & MC_MONS);
-}
-
-int get_envmap_col(const coord_def& p)
-{
- return (env.map[p.x][p.y].colour);
-}
-
-bool is_terrain_known( int x, int y )
-{
- return (env.map[x][y].known());
-}
-
-bool is_terrain_known(const coord_def &p)
-{
- return (env.map(p).known());
-}
-
-bool is_terrain_seen( int x, int y )
-{
- return (env.map[x][y].flags & MAP_SEEN_FLAG);
-}
-
-bool is_terrain_changed( int x, int y )
-{
- return (env.map[x][y].flags & MAP_CHANGED_FLAG);
-}
-
-bool is_terrain_mapped(const coord_def &p)
-{
- return (env.map(p).flags & MAP_MAGIC_MAPPED_FLAG);
-}
-
-// Used to mark dug out areas, unset when terrain is seen or mapped again.
-void set_terrain_changed( int x, int y )
-{
- env.map[x][y].flags |= MAP_CHANGED_FLAG;
-
- dungeon_events.fire_position_event(DET_FEAT_CHANGE, coord_def(x, y));
-}
-
-void set_terrain_mapped( int x, int y )
-{
- env.map[x][y].flags &= (~MAP_CHANGED_FLAG);
- env.map[x][y].flags |= MAP_MAGIC_MAPPED_FLAG;
-#ifdef USE_TILE
- tiles.update_minimap(x, y);
-#endif
-}
-
-static void _automap_from( int x, int y, int mutated )
-{
- if (mutated)
- magic_mapping(8 * mutated, 25, true, false,
- true, true, coord_def(x,y));
-}
-
-void reautomap_level( )
-{
- int passive = player_mutation_level(MUT_PASSIVE_MAPPING);
-
- for (int x = X_BOUND_1; x <= X_BOUND_2; ++x)
- for (int y = Y_BOUND_1; y <= Y_BOUND_2; ++y)
- if (env.map[x][y].flags & MAP_SEEN_FLAG)
- _automap_from(x, y, passive);
-}
-
-void set_terrain_seen( int x, int y )
-{
- const dungeon_feature_type feat = grd[x][y];
-
- // First time we've seen a notable feature.
- if (!(env.map[x][y].flags & MAP_SEEN_FLAG))
- {
- _automap_from(x, y, player_mutation_level(MUT_PASSIVE_MAPPING));
-
- const bool boring = !is_notable_terrain(feat)
- // A portal deeper into the Zigguart is boring.
- || (feat == DNGN_ENTER_PORTAL_VAULT
- && you.level_type == LEVEL_PORTAL_VAULT)
- // Altars in the temple are boring.
- || (feat_is_altar(feat)
- && player_in_branch(BRANCH_ECUMENICAL_TEMPLE))
- // Only note the first entrance to the Abyss/Pan/Hell
- // which is found.
- || ((feat == DNGN_ENTER_ABYSS || feat == DNGN_ENTER_PANDEMONIUM
- || feat == DNGN_ENTER_HELL)
- && overmap_knows_num_portals(feat) > 1)
- // There are at least three Zot entrances, and they're always
- // on D:27, so ignore them.
- || feat == DNGN_ENTER_ZOT;
-
- if (!boring)
- {
- coord_def pos(x, y);
- std::string desc =
- feature_description(pos, false, DESC_NOCAP_A);
-
- take_note(Note(NOTE_SEEN_FEAT, 0, 0, desc.c_str()));
- }
- }
-
-#ifdef USE_TILE
- env.map[x][y].flags &= ~(MAP_DETECTED_ITEM);
- env.map[x][y].flags &= ~(MAP_DETECTED_MONSTER);
-#endif
-
- env.map[x][y].flags &= (~MAP_CHANGED_FLAG);
- env.map[x][y].flags |= MAP_SEEN_FLAG;
-}
-
-void clear_envmap_grid( const coord_def& p )
-{
- env.map(p).clear();
-}
-
-void clear_envmap_grid( int x, int y )
-{
- env.map[x][y].clear();
-}
-
bool is_notable_terrain(dungeon_feature_type ftype)
{
return (get_feature_def(ftype).is_notable());
}
-#if defined(TARGET_OS_WINDOWS) || defined(TARGET_OS_DOS) || defined(USE_TILE)
-static unsigned _colflag2brand(int colflag)
-{
- switch (colflag)
- {
- case COLFLAG_ITEM_HEAP:
- return (Options.heap_brand);
- case COLFLAG_FRIENDLY_MONSTER:
- return (Options.friend_brand);
- case COLFLAG_NEUTRAL_MONSTER:
- return (Options.neutral_brand);
- case COLFLAG_WILLSTAB:
- return (Options.stab_brand);
- case COLFLAG_MAYSTAB:
- return (Options.may_stab_brand);
- case COLFLAG_FEATURE_ITEM:
- return (Options.feature_item_brand);
- case COLFLAG_TRAP_ITEM:
- return (Options.trap_item_brand);
- default:
- return (CHATTR_NORMAL);
- }
-}
-#endif
-
-unsigned real_colour(unsigned raw_colour)
-{
- // This order is important - is_element_colour() doesn't want to see the
- // munged colours returned by dos_brand, so it should always be done
- // before applying DOS brands.
- const int colflags = raw_colour & 0xFF00;
-
- // Evaluate any elemental colours to guarantee vanilla colour is returned
- if (is_element_colour( raw_colour ))
- raw_colour = colflags | element_colour( raw_colour );
-
-#if defined(TARGET_OS_WINDOWS) || defined(TARGET_OS_DOS) || defined(USE_TILE)
- if (colflags)
- {
- unsigned brand = _colflag2brand(colflags);
- raw_colour = dos_brand(raw_colour & 0xFF, brand);
- }
-#endif
-
-#ifndef USE_COLOUR_OPTS
- // Strip COLFLAGs for systems that can't do anything meaningful with them.
- raw_colour &= 0xFF;
-#endif
-
- return (raw_colour);
-}
-
-static int _get_viewobj_flags(show_type object)
-{
- // Check for monster glyphs.
- if (object.cls == SH_MONSTER)
- return (MC_MONS);
-
- // Check for item glyphs.
- if (object.cls == SH_ITEM)
- return (MC_ITEM);
-
- // We don't care to look further; we could check for
- // clouds here as well.
- return (0);
-}
-
-static unsigned _get_symbol(show_type object, unsigned short *colour,
- bool magic_mapped)
+unsigned get_symbol(show_type object, unsigned short *colour,
+ bool magic_mapped)
{
unsigned ch;
_get_symbol(coord_def(0,0), object, &ch, NULL, magic_mapped);
return (ch);
}
-static bool _emphasise(const coord_def& where, dungeon_feature_type feat)
-{
- return (is_unknown_stair(where, feat)
- && (you.your_level || feat_stair_direction(feat) == CMD_GO_DOWNSTAIRS)
- && you.where_are_you != BRANCH_VESTIBULE_OF_HELL);
-}
-
static bool _show_bloodcovered(const coord_def& where)
{
if (!is_bloodcovered(where))
@@ -521,7 +211,7 @@ static void _get_symbol( const coord_def& where,
*colour = _tree_colour(where) | colmask;
if (fdef.em_colour && fdef.em_colour != fdef.colour &&
- _emphasise(where, feat))
+ emphasise(where, feat))
{
*colour = (fdef.em_colour | colmask);
}
@@ -574,282 +264,6 @@ dungeon_char_type get_feature_dchar(dungeon_feature_type feat)
return (get_feature_def(feat).dchar);
}
-unsigned get_sightmap_char(dungeon_feature_type feat)
-{
- return (get_feature_def(feat).symbol);
-}
-
-unsigned get_magicmap_char(dungeon_feature_type feat)
-{
- return (get_feature_def(feat).magic_symbol);
-}
-
-static char _get_travel_colour( const coord_def& p )
-{
- if (is_waypoint(p))
- return LIGHTGREEN;
-
- short dist = travel_point_distance[p.x][p.y];
- return dist > 0? Options.tc_reachable :
- dist == PD_EXCLUDED? Options.tc_excluded :
- dist == PD_EXCLUDED_RADIUS? Options.tc_exclude_circle :
- dist < 0? Options.tc_dangerous :
- Options.tc_disconnected;
-}
-
-#if defined(TARGET_OS_WINDOWS) || defined(TARGET_OS_DOS) || defined(USE_TILE)
-static unsigned short _dos_reverse_brand(unsigned short colour)
-{
- if (Options.dos_use_background_intensity)
- {
- // If the console treats the intensity bit on background colours
- // correctly, we can do a very simple colour invert.
-
- // Special casery for shadows.
- if (colour == BLACK)
- colour = (DARKGREY << 4);
- else
- colour = (colour & 0xF) << 4;
- }
- else
- {
- // If we're on a console that takes its DOSness very seriously the
- // background high-intensity bit is actually a blink bit. Blinking is
- // evil, so we strip the background high-intensity bit. This, sadly,
- // limits us to 7 background colours.
-
- // Strip off high-intensity bit. Special case DARKGREY, since it's the
- // high-intensity counterpart of black, and we don't want black on
- // black.
- //
- // We *could* set the foreground colour to WHITE if the background
- // intensity bit is set, but I think we've carried the
- // angry-fruit-salad theme far enough already.
-
- if (colour == DARKGREY)
- colour |= (LIGHTGREY << 4);
- else if (colour == BLACK)
- colour = LIGHTGREY << 4;
- else
- {
- // Zap out any existing background colour, and the high
- // intensity bit.
- colour &= 7;
-
- // And swap the foreground colour over to the background
- // colour, leaving the foreground black.
- colour <<= 4;
- }
- }
-
- return (colour);
-}
-
-static unsigned short _dos_hilite_brand(unsigned short colour,
- unsigned short hilite)
-{
- if (!hilite)
- return (colour);
-
- if (colour == hilite)
- colour = 0;
-
- colour |= (hilite << 4);
- return (colour);
-}
-
-unsigned short dos_brand( unsigned short colour,
- unsigned brand)
-{
- if ((brand & CHATTR_ATTRMASK) == CHATTR_NORMAL)
- return (colour);
-
- colour &= 0xFF;
-
- if ((brand & CHATTR_ATTRMASK) == CHATTR_HILITE)
- return _dos_hilite_brand(colour, (brand & CHATTR_COLMASK) >> 8);
- else
- return _dos_reverse_brand(colour);
-}
-#endif
-
-// FIXME: Rework this function to use the new terrain known/seen checks
-// These are still env.map coordinates, NOT grid coordinates!
-screen_buffer_t colour_code_map(const coord_def& p, bool item_colour,
- bool travel_colour, bool on_level)
-{
- const unsigned short map_flags = env.map(p).flags;
- if (!(map_flags & MAP_GRID_KNOWN))
- return (BLACK);
-
-#ifdef WIZARD
- if (travel_colour && you.wizard
- && testbits(env.map(p).property, FPROP_HIGHLIGHT))
- {
- return (LIGHTGREEN);
- }
-#endif
-
- dungeon_feature_type feat_value = grd(p);
- if (!see_cell(p))
- {
- const show_type remembered = get_envmap_obj(p);
- if (remembered.cls == SH_FEATURE)
- feat_value = remembered.feat;
- }
-
- unsigned tc = travel_colour ? _get_travel_colour(p) : DARKGREY;
-
- if (map_flags & MAP_DETECTED_ITEM)
- return real_colour(Options.detected_item_colour);
-
- if (map_flags & MAP_DETECTED_MONSTER)
- {
- tc = Options.detected_monster_colour;
- return real_colour(tc);
- }
-
- // If this is an important travel square, don't allow the colour
- // to be overridden.
- if (is_waypoint(p) || travel_point_distance[p.x][p.y] == PD_EXCLUDED)
- return real_colour(tc);
-
- if (item_colour && is_envmap_item(p))
- return get_envmap_col(p);
-
- int feature_colour = DARKGREY;
- const bool terrain_seen = is_terrain_seen(p);
- const feature_def &fdef = get_feature_def(feat_value);
- feature_colour = terrain_seen ? fdef.seen_colour : fdef.map_colour;
-
- if (terrain_seen && fdef.seen_em_colour && _emphasise(p, feat_value))
- feature_colour = fdef.seen_em_colour;
-
- if (feature_colour != DARKGREY)
- tc = feature_colour;
- else if (you.duration[DUR_MESMERISED] && on_level)
- {
- // If mesmerised, colour the few grids that can be reached anyway
- // lightgrey.
- const monsters *blocker = monster_at(p);
- const bool seen_blocker = blocker && you.can_see(blocker);
- if (grd(p) >= DNGN_MINMOVE && !seen_blocker)
- {
- bool blocked_movement = false;
- for (unsigned int i = 0; i < you.mesmerised_by.size(); i++)
- {
- const monsters& mon = menv[you.mesmerised_by[i]];
- const int olddist = grid_distance(you.pos(), mon.pos());
- const int newdist = grid_distance(p, mon.pos());
-
- if (olddist < newdist || !see_cell(env.show_los, p, mon.pos()))
- {
- blocked_movement = true;
- break;
- }
- }
- if (!blocked_movement)
- tc = LIGHTGREY;
- }
- }
-
- if (Options.feature_item_brand
- && is_critical_feature(feat_value)
- && igrd(p) != NON_ITEM)
- {
- tc |= COLFLAG_FEATURE_ITEM;
- }
- else if (Options.trap_item_brand
- && feat_is_trap(feat_value) && igrd(p) != NON_ITEM)
- {
- // FIXME: this uses the real igrd, which the player shouldn't
- // be aware of.
- tc |= COLFLAG_TRAP_ITEM;
- }
-
- return real_colour(tc);
-}
-
-int count_detected_mons()
-{
- int count = 0;
- for (rectangle_iterator ri(BOUNDARY_BORDER - 1); ri; ++ri)
- {
- // Don't expose new dug out areas:
- // Note: assumptions are being made here about how
- // terrain can change (eg it used to be solid, and
- // thus monster/item free).
- if (is_terrain_changed(*ri))
- continue;
-
- if (is_envmap_detected_mons(*ri))
- count++;
- }
-
- return (count);
-}
-
-void clear_map(bool clear_detected_items, bool clear_detected_monsters)
-{
- for (rectangle_iterator ri(BOUNDARY_BORDER - 1); ri; ++ri)
- {
- const coord_def p = *ri;
- // Don't expose new dug out areas:
- // Note: assumptions are being made here about how
- // terrain can change (eg it used to be solid, and
- // thus monster/item free).
-
- // This reasoning doesn't make sense when it comes to *clearing*
- // the map! (jpeg)
-
- if (get_envmap_char(p) == 0)
- continue;
-
- if (is_envmap_item(p))
- continue;
-
- if (!clear_detected_items && is_envmap_detected_item(p))
- continue;
-
- if (!clear_detected_monsters && is_envmap_detected_mons(p))
- continue;
-
-#ifdef USE_TILE
- if (is_terrain_mapped(p) && !is_envmap_detected_mons(p))
- continue;
-#endif
-
- set_envmap_obj(p, show_type(is_terrain_seen(p) || is_terrain_mapped(p)
- ? grd(p) : DNGN_UNSEEN));
- set_envmap_detected_mons(p, false);
- set_envmap_detected_item(p, false);
-
-#ifdef USE_TILE
- if (is_terrain_mapped(p))
- {
- dungeon_feature_type feature = grd(p);
-
- unsigned int feat_symbol;
- unsigned short feat_colour;
- get_show_symbol(show_type(feature), &feat_symbol, &feat_colour);
-
- unsigned int fg;
- unsigned int bg;
- tileidx_unseen(fg, bg, feat_symbol, p);
- env.tile_bk_bg(p) = bg;
- env.tile_bk_fg(p) = fg;
- }
- else
- {
- env.tile_bk_bg(p) = is_terrain_seen(p) ?
- tile_idx_unseen_terrain(p.x, p.y, grd(p)) :
- tileidx_feature(DNGN_UNSEEN, p.x, p.y);
- env.tile_bk_fg(p) = 0;
- }
-#endif
- }
-}
-
int get_mons_colour(const monsters *mons)
{
int col = mons->colour;
@@ -1492,6 +906,26 @@ void get_mons_glyph(const monsters *mons, unsigned *glych,
_get_symbol(coord_def(0,0), show_type(mons), glych, glycol);
}
+unsigned get_screen_glyph( int x, int y )
+{
+ return get_screen_glyph(coord_def(x,y));
+}
+
+unsigned get_screen_glyph(const coord_def& p)
+{
+ const coord_def ep = view2show(grid2view(p));
+
+ show_type object = env.show(ep);
+ unsigned short colour = object.colour;
+ unsigned ch;
+
+ if (!object)
+ return get_envmap_char(p.x, p.y);
+
+ _get_symbol(p, object, &ch, &colour);
+ return (ch);
+}
+
// Noisy now has a messenging service for giving messages to the
// player is appropriate.
//
@@ -1701,1037 +1135,6 @@ void blood_smell( int strength, const coord_def& where )
}
-// Determines if the given feature is present at (x, y) in _feat_ coordinates.
-// If you have map coords, add (1, 1) to get grid coords.
-// Use one of
-// 1. '<' and '>' to look for stairs
-// 2. '\t' or '\\' for shops, portals.
-// 3. '^' for traps
-// 4. '_' for altars
-// 5. Anything else will look for the exact same character in the level map.
-bool is_feature(int feature, const coord_def& where)
-{
- if (!env.map(where).object && !see_cell(where))
- return (false);
-
- dungeon_feature_type grid = grd(where);
-
- switch (feature)
- {
- case 'E':
- return (travel_point_distance[where.x][where.y] == PD_EXCLUDED);
- case 'F':
- case 'W':
- return is_waypoint(where);
- case 'I':
- return is_stash(where.x, where.y);
- case '_':
- switch (grid)
- {
- case DNGN_ALTAR_ZIN:
- case DNGN_ALTAR_SHINING_ONE:
- case DNGN_ALTAR_KIKUBAAQUDGHA:
- case DNGN_ALTAR_YREDELEMNUL:
- case DNGN_ALTAR_XOM:
- case DNGN_ALTAR_VEHUMET:
- case DNGN_ALTAR_OKAWARU:
- case DNGN_ALTAR_MAKHLEB:
- case DNGN_ALTAR_SIF_MUNA:
- case DNGN_ALTAR_TROG:
- case DNGN_ALTAR_NEMELEX_XOBEH:
- case DNGN_ALTAR_ELYVILON:
- case DNGN_ALTAR_LUGONU:
- case DNGN_ALTAR_BEOGH:
- case DNGN_ALTAR_JIYVA:
- case DNGN_ALTAR_FEAWN:
- case DNGN_ALTAR_CHEIBRIADOS:
- return (true);
- default:
- return (false);
- }
- case '\t':
- case '\\':
- switch (grid)
- {
- case DNGN_ENTER_HELL:
- case DNGN_EXIT_HELL:
- case DNGN_ENTER_LABYRINTH:
- case DNGN_ENTER_PORTAL_VAULT:
- case DNGN_EXIT_PORTAL_VAULT:
- case DNGN_ENTER_SHOP:
- case DNGN_ENTER_DIS:
- case DNGN_ENTER_GEHENNA:
- case DNGN_ENTER_COCYTUS:
- case DNGN_ENTER_TARTARUS:
- case DNGN_ENTER_ABYSS:
- case DNGN_EXIT_ABYSS:
- case DNGN_ENTER_PANDEMONIUM:
- case DNGN_EXIT_PANDEMONIUM:
- case DNGN_TRANSIT_PANDEMONIUM:
- case DNGN_ENTER_ZOT:
- case DNGN_RETURN_FROM_ZOT:
- return (true);
- default:
- return (false);
- }
- case '<':
- switch (grid)
- {
- case DNGN_ESCAPE_HATCH_UP:
- case DNGN_STONE_STAIRS_UP_I:
- case DNGN_STONE_STAIRS_UP_II:
- case DNGN_STONE_STAIRS_UP_III:
- case DNGN_RETURN_FROM_ORCISH_MINES:
- case DNGN_RETURN_FROM_HIVE:
- case DNGN_RETURN_FROM_LAIR:
- case DNGN_RETURN_FROM_SLIME_PITS:
- case DNGN_RETURN_FROM_VAULTS:
- case DNGN_RETURN_FROM_CRYPT:
- case DNGN_RETURN_FROM_HALL_OF_BLADES:
- case DNGN_RETURN_FROM_TEMPLE:
- case DNGN_RETURN_FROM_SNAKE_PIT:
- case DNGN_RETURN_FROM_ELVEN_HALLS:
- case DNGN_RETURN_FROM_TOMB:
- case DNGN_RETURN_FROM_SWAMP:
- case DNGN_RETURN_FROM_SHOALS:
- case DNGN_EXIT_PORTAL_VAULT:
- return (true);
- default:
- return (false);
- }
- case '>':
- switch (grid)
- {
- case DNGN_ESCAPE_HATCH_DOWN:
- case DNGN_STONE_STAIRS_DOWN_I:
- case DNGN_STONE_STAIRS_DOWN_II:
- case DNGN_STONE_STAIRS_DOWN_III:
- case DNGN_ENTER_ORCISH_MINES:
- case DNGN_ENTER_HIVE:
- case DNGN_ENTER_LAIR:
- case DNGN_ENTER_SLIME_PITS:
- case DNGN_ENTER_VAULTS:
- case DNGN_ENTER_CRYPT:
- case DNGN_ENTER_HALL_OF_BLADES:
- case DNGN_ENTER_TEMPLE:
- case DNGN_ENTER_SNAKE_PIT:
- case DNGN_ENTER_ELVEN_HALLS:
- case DNGN_ENTER_TOMB:
- case DNGN_ENTER_SWAMP:
- case DNGN_ENTER_SHOALS:
- return (true);
- default:
- return (false);
- }
- case '^':
- switch (grid)
- {
- case DNGN_TRAP_MECHANICAL:
- case DNGN_TRAP_MAGICAL:
- case DNGN_TRAP_NATURAL:
- return (true);
- default:
- return (false);
- }
- default:
- return get_envmap_char(where.x, where.y) == (unsigned) feature;
- }
-}
-
-static bool _is_feature_fudged(int feature, const coord_def& where)
-{
- if (!env.map(where).object)
- return (false);
-
- if (is_feature(feature, where))
- return (true);
-
- // 'grid' can fit in an unsigned char, but making this a short shuts up
- // warnings about out-of-range case values.
- short grid = grd(where);
-
- if (feature == '<')
- {
- switch (grid)
- {
- case DNGN_EXIT_HELL:
- case DNGN_EXIT_PORTAL_VAULT:
- case DNGN_EXIT_ABYSS:
- case DNGN_EXIT_PANDEMONIUM:
- case DNGN_RETURN_FROM_ZOT:
- return (true);
- default:
- return (false);
- }
- }
- else if (feature == '>')
- {
- switch (grid)
- {
- case DNGN_ENTER_DIS:
- case DNGN_ENTER_GEHENNA:
- case DNGN_ENTER_COCYTUS:
- case DNGN_ENTER_TARTARUS:
- case DNGN_TRANSIT_PANDEMONIUM:
- case DNGN_ENTER_ZOT:
- return (true);
- default:
- return (false);
- }
- }
-
- return (false);
-}
-
-static int _find_feature(int feature, int curs_x, int curs_y,
- int start_x, int start_y, int anchor_x, int anchor_y,
- int ignore_count, int *move_x, int *move_y)
-{
- int cx = anchor_x,
- cy = anchor_y;
-
- int firstx = -1, firsty = -1;
- int matchcount = 0;
-
- // Find the first occurrence of feature 'feature', spiralling around (x,y)
- int maxradius = GXM > GYM ? GXM : GYM;
- for (int radius = 1; radius < maxradius; ++radius)
- for (int axis = -2; axis < 2; ++axis)
- {
- int rad = radius - (axis < 0);
- for (int var = -rad; var <= rad; ++var)
- {
- int dx = radius, dy = var;
- if (axis % 2)
- dx = -dx;
- if (axis < 0)
- {
- int temp = dx;
- dx = dy;
- dy = temp;
- }
-
- int x = cx + dx, y = cy + dy;
- if (!in_bounds(x, y))
- continue;
- if (_is_feature_fudged(feature, coord_def(x, y)))
- {
- ++matchcount;
- if (!ignore_count--)
- {
- // We want to cursor to (x,y)
- *move_x = x - (start_x + curs_x - 1);
- *move_y = y - (start_y + curs_y - 1);
- return matchcount;
- }
- else if (firstx == -1)
- {
- firstx = x;
- firsty = y;
- }
- }
- }
- }
-
- // We found something, but ignored it because of an ignorecount
- if (firstx != -1)
- {
- *move_x = firstx - (start_x + curs_x - 1);
- *move_y = firsty - (start_y + curs_y - 1);
- return 1;
- }
- return 0;
-}
-
-void find_features(const std::vector<coord_def>& features,
- unsigned char feature, std::vector<coord_def> *found)
-{
- for (unsigned feat = 0; feat < features.size(); ++feat)
- {
- const coord_def& coord = features[feat];
- if (is_feature(feature, coord))
- found->push_back(coord);
- }
-}
-
-static int _find_feature( const std::vector<coord_def>& features,
- int feature, int curs_x, int curs_y,
- int start_x, int start_y,
- int ignore_count,
- int *move_x, int *move_y,
- bool forward)
-{
- int firstx = -1, firsty = -1, firstmatch = -1;
- int matchcount = 0;
-
- for (unsigned feat = 0; feat < features.size(); ++feat)
- {
- const coord_def& coord = features[feat];
-
- if (_is_feature_fudged(feature, coord))
- {
- ++matchcount;
- if (forward? !ignore_count-- : --ignore_count == 1)
- {
- // We want to cursor to (x,y)
- *move_x = coord.x - (start_x + curs_x - 1);
- *move_y = coord.y - (start_y + curs_y - 1);
- return matchcount;
- }
- else if (!forward || firstx == -1)
- {
- firstx = coord.x;
- firsty = coord.y;
- firstmatch = matchcount;
- }
- }
- }
-
- // We found something, but ignored it because of an ignorecount
- if (firstx != -1)
- {
- *move_x = firstx - (start_x + curs_x - 1);
- *move_y = firsty - (start_y + curs_y - 1);
- return firstmatch;
- }
- return 0;
-}
-
-static int _get_number_of_lines_levelmap()
-{
- return get_number_of_lines() - (Options.level_map_title ? 1 : 0);
-}
-
-#ifndef USE_TILE
-static std::string _level_description_string()
-{
- if (you.level_type == LEVEL_PANDEMONIUM)
- return "- Pandemonium";
-
- if (you.level_type == LEVEL_ABYSS)
- return "- The Abyss";
-
- if (you.level_type == LEVEL_LABYRINTH)
- return "- a Labyrinth";
-
- if (you.level_type == LEVEL_PORTAL_VAULT)
- {
- if (!you.level_type_name.empty())
- return "- " + article_a(upcase_first(you.level_type_name));
- return "- a Portal Chamber";
- }
-
- // level_type == LEVEL_DUNGEON
- char buf[200];
- const int youbranch = you.where_are_you;
- if ( branches[youbranch].depth == 1 )
- snprintf(buf, sizeof buf, "- %s", branches[youbranch].longname);
- else
- {
- const int curr_subdungeon_level = player_branch_depth();
- snprintf(buf, sizeof buf, "%d of %s", curr_subdungeon_level,
- branches[youbranch].longname);
- }
- return buf;
-}
-
-static void _draw_level_map(int start_x, int start_y, bool travel_mode,
- bool on_level)
-{
- int bufcount2 = 0;
- screen_buffer_t buffer2[GYM * GXM * 2];
-
- const int num_lines = std::min(_get_number_of_lines_levelmap(), GYM);
- const int num_cols = std::min(get_number_of_cols(), GXM);
-
- cursor_control cs(false);
-
- int top = 1 + Options.level_map_title;
- if (Options.level_map_title)
- {
- const formatted_string help =
- formatted_string::parse_string("(Press <w>?</w> for help)");
- const int helplen = std::string(help).length();
-
- cgotoxy(1, 1);
- textcolor(WHITE);
- cprintf("%-*s",
- get_number_of_cols() - helplen,
- ("Level " + _level_description_string()).c_str());
-
- textcolor(LIGHTGREY);
- cgotoxy(get_number_of_cols() - helplen + 1, 1);
- help.display();
- }
-
- cgotoxy(1, top);
-
- for (int screen_y = 0; screen_y < num_lines; screen_y++)
- for (int screen_x = 0; screen_x < num_cols; screen_x++)
- {
- screen_buffer_t colour = DARKGREY;
-
- coord_def c(start_x + screen_x, start_y + screen_y);
-
- if (!map_bounds(c))
- {
- buffer2[bufcount2 + 1] = DARKGREY;
- buffer2[bufcount2] = 0;
- }
- else
- {
- colour = colour_code_map(c,
- Options.item_colour,
- travel_mode,
- on_level);
-
- buffer2[bufcount2 + 1] = colour;
- buffer2[bufcount2] = env.map(c).glyph();
-
- if (c == you.pos() && !crawl_state.arena_suspended && on_level)
- {
- // [dshaligram] Draw the @ symbol on the level-map. It's no
- // longer saved into the env.map, so we need to draw it
- // directly.
- buffer2[bufcount2 + 1] = WHITE;
- buffer2[bufcount2] = you.symbol;
- }
-
- // If we've a waypoint on the current square, *and* the
- // square is a normal floor square with nothing on it,
- // show the waypoint number.
- if (Options.show_waypoints)
- {
- // XXX: This is a horrible hack.
- screen_buffer_t &bc = buffer2[bufcount2];
- unsigned char ch = is_waypoint(c);
- if (ch && (bc == get_sightmap_char(DNGN_FLOOR)
- || bc == get_magicmap_char(DNGN_FLOOR)))
- {
- bc = ch;
- }
- }
- }
-
- bufcount2 += 2;
- }
-
- puttext(1, top, num_cols, top + num_lines - 1, buffer2);
-}
-#endif // USE_TILE
-
-static void _reset_travel_colours(std::vector<coord_def> &features,
- bool on_level)
-{
- // We now need to redo travel colours.
- features.clear();
-
- if (on_level)
- {
- find_travel_pos((on_level ? you.pos() : coord_def()),
- NULL, NULL, &features);
- }
- else
- {
- travel_pathfind tp;
- tp.set_feature_vector(&features);
- tp.get_features();
- }
-
- // Sort features into the order the player is likely to prefer.
- arrange_features(features);
-}
-
-class levelview_excursion : public level_excursion
-{
-public:
- void go_to(const level_id& next)
- {
-#ifdef USE_TILE
- tiles.clear_minimap();
- level_excursion::go_to(next);
- TileNewLevel(false);
-#else
- level_excursion::go_to(next);
-#endif
- }
-};
-
-// show_map() now centers the known map along x or y. This prevents
-// the player from getting "artificial" location clues by using the
-// map to see how close to the end they are. They'll need to explore
-// to get that. This function is still a mess, though. -- bwr
-void show_map( level_pos &spec_place, bool travel_mode, bool allow_esc )
-{
- levelview_excursion le;
- level_id original(level_id::current());
-
- cursor_control ccon(!Options.use_fake_cursor);
- int i, j;
-
- int move_x = 0, move_y = 0, scroll_y = 0;
-
- bool new_level = true;
-
- // Vector to track all features we can travel to, in order of distance.
- std::vector<coord_def> features;
-
- int min_x = INT_MAX, max_x = INT_MIN, min_y = INT_MAX, max_y = INT_MIN;
- const int num_lines = _get_number_of_lines_levelmap();
- const int half_screen = (num_lines - 1) / 2;
-
- const int top = 1 + Options.level_map_title;
-
- int map_lines = 0;
-
- int start_x = -1; // no x scrolling
- const int block_step = Options.level_map_cursor_step;
- int start_y; // y does scroll
-
- int screen_y = -1;
-
- int curs_x = -1, curs_y = -1;
- int search_found = 0, anchor_x = -1, anchor_y = -1;
-
- bool map_alive = true;
- bool redraw_map = true;
-
-#ifndef USE_TILE
- clrscr();
-#endif
- textcolor(DARKGREY);
-
- bool on_level = false;
-
- while (map_alive)
- {
- if (new_level)
- {
- on_level = (level_id::current() == original);
-
- move_x = 0, move_y = 0, scroll_y = 0;
-
- // Vector to track all features we can travel to, in order of distance.
- if (travel_mode)
- {
- travel_init_new_level();
- travel_cache.update();
-
- _reset_travel_colours(features, on_level);
- }
-
- min_x = GXM, max_x = 0, min_y = 0, max_y = 0;
- bool found_y = false;
-
- for (j = 0; j < GYM; j++)
- for (i = 0; i < GXM; i++)
- {
- if (env.map[i][j].known())
- {
- if (!found_y)
- {
- found_y = true;
- min_y = j;
- }
-
- max_y = j;
-
- if (i < min_x)
- min_x = i;
-
- if (i > max_x)
- max_x = i;
- }
- }
-
- map_lines = max_y - min_y + 1;
-
- start_x = min_x + (max_x - min_x + 1) / 2 - 40; // no x scrolling
- start_y = 0; // y does scroll
-
- coord_def reg;
-
- if (on_level)
- {
- reg = you.pos();
- }
- else
- {
- reg.y = min_y + (max_y - min_y + 1) / 2;
- reg.x = min_x + (max_x - min_x + 1) / 2;
- }
-
- screen_y = reg.y;
-
- // If close to top of known map, put min_y on top
- // else if close to bottom of known map, put max_y on bottom.
- //
- // The num_lines comparisons are done to keep things neat, by
- // keeping things at the top of the screen. By shifting an
- // additional one in the num_lines > map_lines case, we can
- // keep the top line clear... which makes things look a whole
- // lot better for small maps.
- if (num_lines > map_lines)
- screen_y = min_y + half_screen - 1;
- else if (num_lines == map_lines || screen_y - half_screen < min_y)
- screen_y = min_y + half_screen;
- else if (screen_y + half_screen > max_y)
- screen_y = max_y - half_screen;
-
- curs_x = reg.x - start_x + 1;
- curs_y = reg.y - screen_y + half_screen + 1;
- search_found = 0, anchor_x = -1, anchor_y = -1;
-
- redraw_map = true;
- new_level = false;
- }
-
-#if defined(USE_UNIX_SIGNALS) && defined(SIGHUP_SAVE) && defined(USE_CURSES)
- // If we've received a HUP signal then the user can't choose a
- // location, so indicate this by returning an invalid position.
- if (crawl_state.seen_hups)
- {
- spec_place = level_pos();
- break;
- }
-#endif
-
- start_y = screen_y - half_screen;
-
- move_x = move_y = 0;
-
- if (redraw_map)
- {
-#ifdef USE_TILE
- // Note: Tile versions just center on the current cursor
- // location. It silently ignores everything else going
- // on in this function. --Enne
- coord_def cen(start_x + curs_x - 1, start_y + curs_y - 1);
- tiles.load_dungeon(cen);
-#else
- _draw_level_map(start_x, start_y, travel_mode, on_level);
-
-#ifdef WIZARD
- if (you.wizard)
- {
- cgotoxy(get_number_of_cols() / 2, 1);
- textcolor(WHITE);
- cprintf("(%d, %d)", start_x + curs_x - 1,
- start_y + curs_y - 1);
-
- textcolor(LIGHTGREY);
- cgotoxy(curs_x, curs_y + top - 1);
- }
-#endif // WIZARD
-
-#endif // USE_TILE
- }
-#ifndef USE_TILE
- cursorxy(curs_x, curs_y + top - 1);
-#endif
- redraw_map = true;
-
- c_input_reset(true);
- int key = unmangle_direction_keys(getchm(KMC_LEVELMAP), KMC_LEVELMAP,
- false, false);
- command_type cmd = key_to_command(key, KMC_LEVELMAP);
- if (cmd < CMD_MIN_OVERMAP || cmd > CMD_MAX_OVERMAP)
- cmd = CMD_NO_CMD;
-
- if (key == CK_MOUSE_CLICK)
- {
- const c_mouse_event cme = get_mouse_event();
- const coord_def curp(start_x + curs_x - 1, start_y + curs_y - 1);
- const coord_def grdp =
- cme.pos + coord_def(start_x - 1, start_y - top);
-
- if (cme.left_clicked() && in_bounds(grdp))
- {
- spec_place = level_pos(level_id::current(), grdp);
- map_alive = false;
- }
- else if (cme.scroll_up())
- scroll_y = -block_step;
- else if (cme.scroll_down())
- scroll_y = block_step;
- else if (cme.right_clicked())
- {
- const coord_def delta = grdp - curp;
- move_y = delta.y;
- move_x = delta.x;
- }
- }
-
- c_input_reset(false);
-
- switch (cmd)
- {
- case CMD_MAP_HELP:
- show_levelmap_help();
- break;
-
- case CMD_MAP_CLEAR_MAP:
- clear_map();
- break;
-
- case CMD_MAP_FORGET:
- forget_map(100, true);
- break;
-
- case CMD_MAP_ADD_WAYPOINT:
- travel_cache.add_waypoint(start_x + curs_x - 1,
- start_y + curs_y - 1);
- // We need to do this all over again so that the user can jump
- // to the waypoint he just created.
- _reset_travel_colours(features, on_level);
- break;
-
- // Cycle the radius of an exclude.
- case CMD_MAP_EXCLUDE_AREA:
- {
- const coord_def p(start_x + curs_x - 1, start_y + curs_y - 1);
- cycle_exclude_radius(p);
-
- _reset_travel_colours(features, on_level);
- break;
- }
-
- case CMD_MAP_CLEAR_EXCLUDES:
- clear_excludes();
- _reset_travel_colours(features, on_level);
- break;
-
- case CMD_MAP_MOVE_DOWN_LEFT:
- move_x = -1;
- move_y = 1;
- break;
-
- case CMD_MAP_MOVE_DOWN:
- move_y = 1;
- move_x = 0;
- break;
-
- case CMD_MAP_MOVE_UP_RIGHT:
- move_x = 1;
- move_y = -1;
- break;
-
- case CMD_MAP_MOVE_UP:
- move_y = -1;
- move_x = 0;
- break;
-
- case CMD_MAP_MOVE_UP_LEFT:
- move_y = -1;
- move_x = -1;
- break;
-
- case CMD_MAP_MOVE_LEFT:
- move_x = -1;
- move_y = 0;
- break;
-
- case CMD_MAP_MOVE_DOWN_RIGHT:
- move_y = 1;
- move_x = 1;
- break;
-
- case CMD_MAP_MOVE_RIGHT:
- move_x = 1;
- move_y = 0;
- break;
-
- case CMD_MAP_PREV_LEVEL:
- case CMD_MAP_NEXT_LEVEL: {
- level_id next;
-
- next = (cmd == CMD_MAP_PREV_LEVEL)
- ? find_up_level(level_id::current())
- : find_down_level(level_id::current());
-
- if (next.is_valid() && next != level_id::current()
- && is_existing_level(next))
- {
- le.go_to(next);
- new_level = true;
- }
- break;
- }
-
- case CMD_MAP_GOTO_LEVEL: {
- std::string name;
- const level_pos pos =
- prompt_translevel_target(TPF_DEFAULT_OPTIONS, name).p;
-
- if (pos.id.depth < 1 || pos.id.depth > branches[pos.id.branch].depth
- || !is_existing_level(pos.id))
- {
- canned_msg(MSG_OK);
- redraw_map = true;
- break;
- }
-
- le.go_to(pos.id);
- new_level = true;
- break;
- }
-
- case CMD_MAP_JUMP_DOWN_LEFT:
- move_x = -block_step;
- move_y = block_step;
- break;
-
- case CMD_MAP_JUMP_DOWN:
- move_y = block_step;
- move_x = 0;
- break;
-
- case CMD_MAP_JUMP_UP_RIGHT:
- move_x = block_step;
- move_y = -block_step;
- break;
-
- case CMD_MAP_JUMP_UP:
- move_y = -block_step;
- move_x = 0;
- break;
-
- case CMD_MAP_JUMP_UP_LEFT:
- move_y = -block_step;
- move_x = -block_step;
- break;
-
- case CMD_MAP_JUMP_LEFT:
- move_x = -block_step;
- move_y = 0;
- break;
-
- case CMD_MAP_JUMP_DOWN_RIGHT:
- move_y = block_step;
- move_x = block_step;
- break;
-
- case CMD_MAP_JUMP_RIGHT:
- move_x = block_step;
- move_y = 0;
- break;
-
- case CMD_MAP_SCROLL_DOWN:
- move_y = 20;
- move_x = 0;
- scroll_y = 20;
- break;
-
- case CMD_MAP_SCROLL_UP:
- move_y = -20;
- move_x = 0;
- scroll_y = -20;
- break;
-
- case CMD_MAP_FIND_YOU:
- if (on_level)
- {
- move_x = you.pos().x - (start_x + curs_x - 1);
- move_y = you.pos().y - (start_y + curs_y - 1);
- }
- break;
-
- case CMD_MAP_FIND_UPSTAIR:
- case CMD_MAP_FIND_DOWNSTAIR:
- case CMD_MAP_FIND_PORTAL:
- case CMD_MAP_FIND_TRAP:
- case CMD_MAP_FIND_ALTAR:
- case CMD_MAP_FIND_EXCLUDED:
- case CMD_MAP_FIND_F:
- case CMD_MAP_FIND_WAYPOINT:
- case CMD_MAP_FIND_STASH:
- case CMD_MAP_FIND_STASH_REVERSE:
- {
- bool forward = (cmd != CMD_MAP_FIND_STASH_REVERSE);
-
- int getty;
- switch (cmd)
- {
- case CMD_MAP_FIND_UPSTAIR:
- getty = '<';
- break;
- case CMD_MAP_FIND_DOWNSTAIR:
- getty = '>';
- break;
- case CMD_MAP_FIND_PORTAL:
- getty = '\t';
- break;
- case CMD_MAP_FIND_TRAP:
- getty = '^';
- break;
- case CMD_MAP_FIND_ALTAR:
- getty = '_';
- break;
- case CMD_MAP_FIND_EXCLUDED:
- getty = 'E';
- break;
- case CMD_MAP_FIND_F:
- getty = 'F';
- break;
- case CMD_MAP_FIND_WAYPOINT:
- getty = 'W';
- break;
- default:
- case CMD_MAP_FIND_STASH:
- case CMD_MAP_FIND_STASH_REVERSE:
- getty = 'I';
- break;
- }
-
- if (anchor_x == -1)
- {
- anchor_x = start_x + curs_x - 1;
- anchor_y = start_y + curs_y - 1;
- }
- if (travel_mode)
- {
- search_found = _find_feature(features, getty, curs_x, curs_y,
- start_x, start_y,
- search_found,
- &move_x, &move_y,
- forward);
- }
- else
- {
- search_found = _find_feature(getty, curs_x, curs_y,
- start_x, start_y,
- anchor_x, anchor_y,
- search_found, &move_x, &move_y);
- }
- break;
- }
-
- case CMD_MAP_GOTO_TARGET:
- {
- int x = start_x + curs_x - 1, y = start_y + curs_y - 1;
- if (travel_mode && on_level && x == you.pos().x && y == you.pos().y)
- {
- if (you.travel_x > 0 && you.travel_y > 0)
- {
- move_x = you.travel_x - x;
- move_y = you.travel_y - y;
- }
- break;
- }
- else
- {
- spec_place = level_pos(level_id::current(), coord_def(x, y));
- map_alive = false;
- break;
- }
- }
-
-#ifdef WIZARD
- case CMD_MAP_WIZARD_TELEPORT:
- {
- if (!you.wizard)
- break;
- if (!on_level)
- break;
- const coord_def pos(start_x + curs_x - 1, start_y + curs_y - 1);
- if (!in_bounds(pos))
- break;
- you.moveto(pos);
- map_alive = false;
- break;
- }
-#endif
-
- case CMD_MAP_EXIT_MAP:
- if (allow_esc)
- {
- spec_place = level_pos();
- map_alive = false;
- break;
- }
- default:
- if (travel_mode)
- {
- map_alive = false;
- break;
- }
- redraw_map = false;
- continue;
- }
-
- if (!map_alive)
- break;
-
-#ifdef USE_TILE
- {
- int new_x = start_x + curs_x + move_x - 1;
- int new_y = start_y + curs_y + move_y - 1;
-
- curs_x += (new_x < 1 || new_x > GXM) ? 0 : move_x;
- curs_y += (new_y < 1 || new_y > GYM) ? 0 : move_y;
- }
-#else
- if (curs_x + move_x < 1 || curs_x + move_x > crawl_view.termsz.x)
- move_x = 0;
-
- curs_x += move_x;
-
- if (num_lines < map_lines)
- {
- // Scrolling only happens when we don't have a large enough
- // display to show the known map.
- if (scroll_y != 0)
- {
- const int old_screen_y = screen_y;
- screen_y += scroll_y;
- if (scroll_y < 0)
- screen_y = std::max(screen_y, min_y + half_screen);
- else
- screen_y = std::min(screen_y, max_y - half_screen);
- curs_y -= (screen_y - old_screen_y);
- scroll_y = 0;
- }
-
- if (curs_y + move_y < 1)
- {
- screen_y += move_y;
-
- if (screen_y < min_y + half_screen)
- {
- move_y = screen_y - (min_y + half_screen);
- screen_y = min_y + half_screen;
- }
- else
- move_y = 0;
- }
-
- if (curs_y + move_y > num_lines)
- {
- screen_y += move_y;
-
- if (screen_y > max_y - half_screen)
- {
- move_y = screen_y - (max_y - half_screen);
- screen_y = max_y - half_screen;
- }
- else
- move_y = 0;
- }
- }
-
- if (curs_y + move_y < 1 || curs_y + move_y > num_lines)
- move_y = 0;
-
- curs_y += move_y;
-#endif
- }
-
- le.go_to(original);
-
- travel_init_new_level();
- travel_cache.update();
-}
-
// We logically associate a difficulty parameter with each tile on each level,
// to make deterministic magic mapping work. This function returns the
// difficulty parameters for each tile on the current level, whose difficulty
@@ -2994,122 +1397,6 @@ bool mon_enemies_around(const monsters *monster)
}
}
-// For order and meaning of symbols, see dungeon_char_type in enum.h.
-static const unsigned dchar_table[ NUM_CSET ][ NUM_DCHAR_TYPES ] =
-{
- // CSET_ASCII
- {
- '#', '*', '.', ',', '\'', '+', '^', '>', '<', // wall .. stairs up
- '_', '\\', '}', '{', '8', '~', '~', // altar .. item detect
- '0', ')', '[', '/', '%', '?', '=', '!', '(', // orb .. missile
- ':', '|', '}', '%', '$', '"', '#', '7', // book .. trees
- ' ', '!', '#', '%', ':', ')', '*', '+', // space .. fired_burst
- '/', '=', '?', 'X', '[', '`', '#' // fi_stick .. explosion
- },
-
- // CSET_IBM - this is ANSI 437
- {
- 177, 176, 249, 250, '\'', 254, '^', '>', '<', // wall .. stairs up
- 220, 239, 244, 247, '8', '~', '~', // altar .. item detect
- '0', ')', '[', '/', '%', '?', '=', '!', '(', // orb .. missile
- '+', '\\', '}', '%', '$', '"', '#', 234, // book .. trees
- ' ', '!', '#', '%', '+', ')', '*', '+', // space .. fired_burst
- '/', '=', '?', 'X', '[', '`', '#' // fi_stick .. explosion
- },
-
- // CSET_DEC - remember: 224-255 are mapped to shifted 96-127
- {
- 225, 224, 254, ':', '\'', 238, '^', '>', '<', // wall .. stairs up
- 251, 182, 167, 187, '8', 171, 168, // altar .. item detect
- '0', ')', '[', '/', '%', '?', '=', '!', '(', // orb .. missile
- '+', '\\', '}', '%', '$', '"', '#', '7', // book .. trees
- ' ', '!', '#', '%', '+', ')', '*', '+', // space .. fired_burst
- '/', '=', '?', 'X', '[', '`', '#' // fi_stick .. explosion
- },
-
- // CSET_UNICODE
- {
- 0x2592, 0x2591, 0xB7, 0x25E6, '\'', 0x25FC, '^', '>', '<',
- '_', 0x2229, 0x2320, 0x2248, '8', '~', '~',
- '0', ')', '[', '/', '%', '?', '=', '!', '(',
- '+', '|', '}', '%', '$', '"', '#', 0x2663,
- ' ', '!', '#', '%', '+', ')', '*', '+', // space .. fired_burst
- '/', '=', '?', 'X', '[', '`', '#' // fi_stick .. explosion
- },
-};
-
-dungeon_char_type dchar_by_name(const std::string &name)
-{
- const char *dchar_names[] =
- {
- "wall", "wall_magic", "floor", "floor_magic", "door_open",
- "door_closed", "trap", "stairs_down", "stairs_up", "altar", "arch",
- "fountain", "wavy", "statue", "invis_exposed", "item_detected",
- "item_orb", "item_weapon", "item_armour", "item_wand", "item_food",
- "item_scroll", "item_ring", "item_potion", "item_missile", "item_book",
- "item_stave", "item_miscellany", "item_corpse", "item_gold",
- "item_amulet", "cloud", "trees",
- };
-
- for (unsigned i = 0; i < sizeof(dchar_names) / sizeof(*dchar_names); ++i)
- if (dchar_names[i] == name)
- return dungeon_char_type(i);
-
- return (NUM_DCHAR_TYPES);
-}
-
-void init_char_table( char_set_type set )
-{
- for (int i = 0; i < NUM_DCHAR_TYPES; i++)
- {
- if (Options.cset_override[set][i])
- Options.char_table[i] = Options.cset_override[set][i];
- else
- Options.char_table[i] = dchar_table[set][i];
- }
-}
-
-unsigned dchar_glyph(dungeon_char_type dchar)
-{
- return (Options.char_table[dchar]);
-}
-
-unsigned get_screen_glyph( int x, int y )
-{
- return get_screen_glyph(coord_def(x,y));
-}
-
-unsigned get_screen_glyph(const coord_def& p)
-{
- const coord_def ep = view2show(grid2view(p));
-
- show_type object = env.show(ep);
- unsigned short colour = object.colour;
- unsigned ch;
-
- if (!object)
- return get_envmap_char(p.x, p.y);
-
- _get_symbol(p, object, &ch, &colour);
- return (ch);
-}
-
-std::string stringize_glyph(unsigned glyph)
-{
- if (crawl_state.glyph2strfn && Options.char_set == CSET_UNICODE)
- return (*crawl_state.glyph2strfn)(glyph);
-
- return (std::string(1, glyph));
-}
-
-int multibyte_strlen(const std::string &s)
-{
- if (crawl_state.multibyte_strlen)
- return (*crawl_state.multibyte_strlen)(s);
-
- return (s.length());
-}
-
// Returns a string containing an ASCII representation of the map. If fullscreen
// is set to false, only the viewable area is returned. Leading and trailing
// spaces are trimmed from each line. Leading and trailing empty lines are also
@@ -3631,378 +1918,6 @@ void viewwindow(bool draw_it, bool do_updates)
_debug_pane_bounds();
}
-//////////////////////////////////////////////////////////////////////////////
-// crawl_view_buffer
-
-crawl_view_buffer::crawl_view_buffer()
- : buffer(NULL)
-{
-}
-
-crawl_view_buffer::~crawl_view_buffer()
-{
- delete [] buffer;
-}
-
-void crawl_view_buffer::size(const coord_def &sz)
-{
- delete [] buffer;
- buffer = new screen_buffer_t [ sz.x * sz.y * 2 ];
-}
-
-// ----------------------------------------------------------------------
-// Layout helper classes
-// ----------------------------------------------------------------------
-
-// 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
-// define VIEW_MAX_WIDTH use Options.view_max_width
-#define HUD_WIDTH 42
-#define HUD_HEIGHT 12
-// #define MSG_MIN_HEIGHT defined elsewhere
-#define MSG_MAX_HEIGHT Options.msg_max_height
-#define MLIST_MIN_HEIGHT Options.mlist_min_height
-#define MLIST_MIN_WIDTH 25 // non-inline layout only
-#define MLIST_MAX_WIDTH 42
-#define MLIST_GUTTER 1
-#define HUD_MIN_GUTTER 2
-#define HUD_MAX_GUTTER 4
-
-// Helper for layouts. Tries to increment lvalue without overflowing it.
-static void _increment(int& lvalue, int delta, int max_value)
-{
- lvalue = std::min(lvalue+delta, max_value);
-}
-
-class _layout
-{
- public:
- _layout(coord_def termsz_, coord_def hudsz_) :
- termp(1,1), termsz(termsz_),
- viewp(-1,-1), viewsz(VIEW_MIN_WIDTH, VIEW_MIN_HEIGHT),
- hudp(-1,-1), hudsz(hudsz_),
- msgp(-1,-1), msgsz(0, MSG_MIN_HEIGHT),
- mlistp(-1,-1), mlistsz(MLIST_MIN_WIDTH, 0),
- hud_gutter(HUD_MIN_GUTTER),
- valid(false) {}
-
- protected:
- void _assert_validity() const
- {
-#ifndef USE_TILE
- // Check that all the panes fit in the view.
- ASSERT( (viewp+viewsz - termp).x <= termsz.x );
- ASSERT( (viewp+viewsz - termp).y <= termsz.y );
-
- ASSERT( (hudp+hudsz - termp).x <= termsz.x );
- ASSERT( (hudp+hudsz - termp).y <= termsz.y );
-
- ASSERT( (msgp+msgsz - termp).x <= termsz.x );
- ASSERT( (msgp+msgsz - termp).y <= termsz.y );
- // Don't stretch message all the way to the bottom-right
- // character; it causes scrolling and badness.
- ASSERT( (msgp+msgsz - termp) != termsz );
-
- ASSERT( (mlistp+mlistsz-termp).x <= termsz.x );
- ASSERT( (mlistp+mlistsz-termp).y <= termsz.y );
-#endif
- }
- public:
- const coord_def termp, termsz;
- coord_def viewp, viewsz;
- coord_def hudp;
- const coord_def hudsz;
- coord_def msgp, msgsz;
- coord_def mlistp, mlistsz;
- int hud_gutter;
- bool valid;
-};
-
-// vvvvvvghhh v=view, g=hud gutter, h=hud, l=list, m=msg
-// vvvvvvghhh
-// vvvvvv lll
-// lll
-// mmmmmmmmmm
-class _inline_layout : public _layout
-{
- public:
- _inline_layout(coord_def termsz_, coord_def hudsz_) :
- _layout(termsz_, hudsz_)
- {
- valid = _init();
- }
-
- bool _init()
- {
- // x: View gets leftover; then mlist; then hud gutter
- if (leftover_x() < 0)
- return (false);
-
- _increment(viewsz.x, leftover_x(), Options.view_max_width);
-
- if ((viewsz.x % 2) != 1)
- --viewsz.x;
-
- mlistsz.x = hudsz.x;
- _increment(mlistsz.x, leftover_x(), MLIST_MAX_WIDTH);
- _increment(hud_gutter, leftover_x(), HUD_MAX_GUTTER);
- _increment(mlistsz.x, leftover_x(), INT_MAX);
- msgsz.x = termsz.x-1; // Can't use last character.
-
- // y: View gets as much as it wants.
- // mlist tries to get at least its minimum.
- // msg expands as much as it wants.
- // mlist gets any leftovers.
- if (leftover_y() < 0)
- return (false);
-
- _increment(viewsz.y, leftover_leftcol_y(), Options.view_max_height);
- if ((viewsz.y % 2) != 1)
- --viewsz.y;
-
- if (Options.classic_hud)
- {
- mlistsz.y = 0;
- _increment(msgsz.y, leftover_y(), MSG_MAX_HEIGHT);
- }
- else
- {
- if (mlistsz.y < MLIST_MIN_HEIGHT)
- _increment(mlistsz.y, leftover_rightcol_y(), MLIST_MIN_HEIGHT);
- _increment(msgsz.y, leftover_y(), MSG_MAX_HEIGHT);
- _increment(mlistsz.y, leftover_rightcol_y(), INT_MAX);
- }
-
- // Finish off by doing the positions.
- viewp = termp;
- msgp = termp + coord_def(0, std::max(viewsz.y, hudsz.y+mlistsz.y));
- hudp = viewp + coord_def(viewsz.x+hud_gutter, 0);
- mlistp = hudp + coord_def(0, hudsz.y);
-
- _assert_validity();
- return (true);
- }
-
- int leftover_x() const
- {
- int width = (viewsz.x + hud_gutter + std::max(hudsz.x, mlistsz.x));
- return (termsz.x - width);
- }
- int leftover_rightcol_y() const { return termsz.y-hudsz.y-mlistsz.y-msgsz.y; }
- int leftover_leftcol_y() const { return termsz.y-viewsz.y-msgsz.y; }
- int leftover_y() const
- {
- return std::min(leftover_rightcol_y(), leftover_leftcol_y());
- }
-};
-
-// ll vvvvvvghhh v=view, g=hud gutter, h=hud, l=list, m=msg
-// ll vvvvvvghhh
-// ll vvvvvv
-// mmmmmmmmmmmmm
-class _mlist_col_layout : public _layout
-{
- public:
- _mlist_col_layout(coord_def termsz_, coord_def hudsz_)
- : _layout(termsz_, hudsz_)
- { valid = _init(); }
- bool _init()
- {
- // Don't let the mlist column steal all the width. Up front,
- // take some for the view. If it makes the layout fail, that's fine.
- _increment(viewsz.x, MLIST_MIN_WIDTH/2, Options.view_max_width);
-
- // x: View and mlist share leftover; then hud gutter.
- if (leftover_x() < 0)
- return (false);
-
- _increment(mlistsz.x, leftover_x()/2, MLIST_MAX_WIDTH);
- _increment(viewsz.x, leftover_x(), Options.view_max_width);
-
- if ((viewsz.x % 2) != 1)
- --viewsz.x;
-
- _increment(mlistsz.x, leftover_x(), MLIST_MAX_WIDTH);
- _increment(hud_gutter, leftover_x(), HUD_MAX_GUTTER);
- msgsz.x = termsz.x-1; // Can't use last character.
-
- // y: View gets leftover; then message.
- if (leftover_y() < 0)
- return (false);
-
- _increment(viewsz.y, leftover_y(), Options.view_max_height);
-
- if ((viewsz.y % 2) != 1)
- --viewsz.y;
-
- _increment(msgsz.y, leftover_y(), INT_MAX);
- mlistsz.y = viewsz.y;
-
- // Finish off by doing the positions.
- mlistp = termp;
- viewp = mlistp+ coord_def(mlistsz.x+MLIST_GUTTER, 0);
- msgp = termp + coord_def(0, viewsz.y);
- hudp = viewp + coord_def(viewsz.x+hud_gutter, 0);
-
- _assert_validity();
- return (true);
- }
- private:
- int leftover_x() const
- {
- int width = (mlistsz.x + MLIST_GUTTER + viewsz.x + hud_gutter + hudsz.x);
- return (termsz.x - width);
- }
- int leftover_y() const
- {
- const int top_y = std::max(std::max(viewsz.y, hudsz.y), mlistsz.y);
- const int height = top_y + msgsz.y;
- return (termsz.y - height);
- }
-};
-
-// ----------------------------------------------------------------------
-// crawl_view_geometry
-// ----------------------------------------------------------------------
-
-crawl_view_geometry::crawl_view_geometry()
- : termp(1, 1), termsz(80, 24),
- viewp(1, 1), viewsz(33, 17),
- hudp(40, 1), hudsz(-1, -1),
- msgp(1, viewp.y + viewsz.y), msgsz(80, 7),
- mlistp(hudp.x, hudp.y + hudsz.y),
- mlistsz(hudsz.x, msgp.y - mlistp.y),
- vbuf(), vgrdc(), viewhalfsz(), glos1(), glos2(),
- vlos1(), vlos2(), mousep(), last_player_pos()
-{
-}
-
-void crawl_view_geometry::init_view()
-{
- viewhalfsz = viewsz / 2;
- vbuf.size(viewsz);
- set_player_at(you.pos(), true);
-}
-
-void crawl_view_geometry::shift_player_to(const coord_def &c)
-{
- // Preserve vgrdc offset after moving.
- const coord_def offset = crawl_view.vgrdc - you.pos();
- crawl_view.vgrdc = offset + c;
- last_player_pos = c;
-
- set_player_at(c);
-
- ASSERT(crawl_view.vgrdc == offset + c);
- ASSERT(last_player_pos == c);
-}
-
-void crawl_view_geometry::set_player_at(const coord_def &c, bool centre)
-{
- if (centre)
- {
- vgrdc = c;
- }
- else
- {
- const coord_def oldc = vgrdc;
- const int xmarg = Options.scroll_margin_x + LOS_RADIUS <= viewhalfsz.x
- ? Options.scroll_margin_x
- : viewhalfsz.x - LOS_RADIUS;
- const int ymarg = Options.scroll_margin_y + LOS_RADIUS <= viewhalfsz.y
- ? Options.scroll_margin_y
- : viewhalfsz.y - LOS_RADIUS;
-
- if (Options.view_lock_x)
- vgrdc.x = c.x;
- else if (c.x - LOS_RADIUS < vgrdc.x - viewhalfsz.x + xmarg)
- vgrdc.x = c.x - LOS_RADIUS + viewhalfsz.x - xmarg;
- else if (c.x + LOS_RADIUS > vgrdc.x + viewhalfsz.x - xmarg)
- vgrdc.x = c.x + LOS_RADIUS - viewhalfsz.x + xmarg;
-
- if (Options.view_lock_y)
- vgrdc.y = c.y;
- else if (c.y - LOS_RADIUS < vgrdc.y - viewhalfsz.y + ymarg)
- vgrdc.y = c.y - LOS_RADIUS + viewhalfsz.y - ymarg;
- else if (c.y + LOS_RADIUS > vgrdc.y + viewhalfsz.y - ymarg)
- vgrdc.y = c.y + LOS_RADIUS - viewhalfsz.y + ymarg;
-
- if (vgrdc != oldc && Options.center_on_scroll)
- vgrdc = c;
-
- if (!Options.center_on_scroll && Options.symmetric_scroll
- && !Options.view_lock_x
- && !Options.view_lock_y
- && (c - last_player_pos).abs() == 2
- && (vgrdc - oldc).abs() == 1)
- {
- const coord_def dp = c - last_player_pos;
- const coord_def dc = vgrdc - oldc;
- if ((dc.x == dp.x) != (dc.y == dp.y))
- vgrdc = oldc + dp;
- }
- }
-
- glos1 = c - coord_def(LOS_RADIUS, LOS_RADIUS);
- glos2 = c + coord_def(LOS_RADIUS, LOS_RADIUS);
-
- vlos1 = glos1 - vgrdc + view_centre();
- vlos2 = glos2 - vgrdc + view_centre();
-
- last_player_pos = c;
-}
-
-void crawl_view_geometry::init_geometry()
-{
- termsz = coord_def( get_number_of_cols(), get_number_of_lines() );
- hudsz = coord_def(HUD_WIDTH,
- HUD_HEIGHT + (Options.show_gold_turns ? 1 : 0));
-
- const _inline_layout lay_inline(termsz, hudsz);
- const _mlist_col_layout lay_mlist(termsz, hudsz);
-
- if (! lay_inline.valid)
- {
-#ifndef USE_TILE
- // Terminal too small; exit with an error.
- if (!crawl_state.need_save)
- {
- end(1, false, "Terminal too small (%d,%d); need at least (%d,%d)",
- termsz.x, termsz.y,
- termsz.x + std::max(0, -lay_inline.leftover_x()),
- termsz.y + std::max(0, -lay_inline.leftover_y()));
- }
-#endif
- }
-
- const _layout* winner = &lay_inline;
- if (Options.mlist_allow_alternate_layout
- && !Options.classic_hud
- && lay_mlist.valid)
- {
- winner = &lay_mlist;
- }
-
- msgp = winner->msgp;
- msgsz = winner->msgsz;
- viewp = winner->viewp;
- viewsz = winner->viewsz;
- hudp = winner->hudp;
- hudsz = winner->hudsz;
- mlistp = winner->mlistp;
- mlistsz = winner->mlistsz;
-
-#ifdef USE_TILE
- // libgui may redefine these based on its own settings.
- gui_init_view_params(*this);
-#endif
-
- init_view();
- return;
-}
-
////////////////////////////////////////////////////////////////////////////
// Term resize handling (generic).