summaryrefslogtreecommitdiffstats
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
parentce5c888daccae3cf40be8e28176f415e54b26650 (diff)
downloadcrawl-ref-64c38d95bfd6b24e34bc86f7d4ce7ba345c5a963.tar.gz
crawl-ref-64c38d95bfd6b24e34bc86f7d4ce7ba345c5a963.zip
Split up view.cc.
-rw-r--r--crawl-ref/source/acr.cc3
-rw-r--r--crawl-ref/source/arena.cc1
-rw-r--r--crawl-ref/source/beam.cc3
-rw-r--r--crawl-ref/source/chardump.cc1
-rw-r--r--crawl-ref/source/cio.cc1
-rw-r--r--crawl-ref/source/cloud.cc1
-rw-r--r--crawl-ref/source/colour.cc129
-rw-r--r--crawl-ref/source/colour.h8
-rw-r--r--crawl-ref/source/command.cc1
-rw-r--r--crawl-ref/source/coord.cc2
-rw-r--r--crawl-ref/source/debug.cc1
-rw-r--r--crawl-ref/source/delay.cc1
-rw-r--r--crawl-ref/source/directn.cc3
-rw-r--r--crawl-ref/source/directn.h138
-rw-r--r--crawl-ref/source/dungeon.cc1
-rw-r--r--crawl-ref/source/effects.cc2
-rw-r--r--crawl-ref/source/env.h1
-rw-r--r--crawl-ref/source/envmap.cc348
-rw-r--r--crawl-ref/source/envmap.h83
-rw-r--r--crawl-ref/source/exclude.cc1
-rw-r--r--crawl-ref/source/fight.cc2
-rw-r--r--crawl-ref/source/files.cc1
-rw-r--r--crawl-ref/source/format.cc1
-rw-r--r--crawl-ref/source/initfile.cc1
-rw-r--r--crawl-ref/source/item_use.cc5
-rw-r--r--crawl-ref/source/items.cc1
-rw-r--r--crawl-ref/source/libgui.cc1
-rw-r--r--crawl-ref/source/libunix.cc1
-rw-r--r--crawl-ref/source/libutil.cc3
-rw-r--r--crawl-ref/source/los.cc2
-rw-r--r--crawl-ref/source/makefile.obj4
-rw-r--r--crawl-ref/source/mapcell.h22
-rw-r--r--crawl-ref/source/message.cc2
-rw-r--r--crawl-ref/source/misc.cc2
-rw-r--r--crawl-ref/source/mon-abil.cc2
-rw-r--r--crawl-ref/source/mon-act.cc2
-rw-r--r--crawl-ref/source/mon-behv.cc1
-rw-r--r--crawl-ref/source/mon-cast.cc2
-rw-r--r--crawl-ref/source/mon-util.cc1
-rw-r--r--crawl-ref/source/monplace.cc1
-rw-r--r--crawl-ref/source/monstuff.cc2
-rw-r--r--crawl-ref/source/output.cc2
-rw-r--r--crawl-ref/source/overmap.cc1
-rw-r--r--crawl-ref/source/player.cc2
-rw-r--r--crawl-ref/source/religion.cc1
-rw-r--r--crawl-ref/source/show.cc2
-rw-r--r--crawl-ref/source/show.h16
-rw-r--r--crawl-ref/source/spells1.cc1
-rw-r--r--crawl-ref/source/spells2.cc1
-rw-r--r--crawl-ref/source/spells3.cc2
-rw-r--r--crawl-ref/source/spells4.cc1
-rw-r--r--crawl-ref/source/spl-cast.cc1
-rw-r--r--crawl-ref/source/spl-mis.cc1
-rw-r--r--crawl-ref/source/stash.cc1
-rw-r--r--crawl-ref/source/stuff.cc2
-rw-r--r--crawl-ref/source/tags.cc1
-rw-r--r--crawl-ref/source/teleport.cc1
-rw-r--r--crawl-ref/source/terrain.cc1
-rw-r--r--crawl-ref/source/tilepick.cc2
-rw-r--r--crawl-ref/source/tilereg.cc2
-rw-r--r--crawl-ref/source/tilesdl.cc2
-rw-r--r--crawl-ref/source/traps.cc1
-rw-r--r--crawl-ref/source/travel.cc1
-rw-r--r--crawl-ref/source/tutorial.cc2
-rw-r--r--crawl-ref/source/view.cc2143
-rw-r--r--crawl-ref/source/view.h86
-rw-r--r--crawl-ref/source/viewchar.cc103
-rw-r--r--crawl-ref/source/viewchar.h13
-rw-r--r--crawl-ref/source/viewgeom.cc382
-rw-r--r--crawl-ref/source/viewgeom.h145
-rw-r--r--crawl-ref/source/viewmap.cc1188
-rw-r--r--crawl-ref/source/viewmap.h10
-rw-r--r--crawl-ref/source/xom.cc2
73 files changed, 2555 insertions, 2352 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index 7ced21d0a1..4af8c5263f 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -62,6 +62,7 @@
#include "directn.h"
#include "dungeon.h"
#include "effects.h"
+#include "envmap.h"
#include "fight.h"
#include "files.h"
#include "food.h"
@@ -118,6 +119,8 @@
#include "travel.h"
#include "tutorial.h"
#include "view.h"
+#include "viewchar.h"
+#include "viewgeom.h"
#include "stash.h"
#include "xom.h"
diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc
index 0c18e8d33d..3dbcfa9c28 100644
--- a/crawl-ref/source/arena.cc
+++ b/crawl-ref/source/arena.cc
@@ -30,6 +30,7 @@
#include "spl-util.h"
#include "state.h"
#include "view.h"
+#include "viewgeom.h"
#define DEBUG_DIAGNOSTICS 1
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index a566852a21..af3c262bf8 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -32,6 +32,7 @@
#include "dgnevent.h"
#include "effects.h"
#include "enum.h"
+#include "envmap.h"
#include "fight.h"
#include "item_use.h"
#include "it_use2.h"
@@ -59,6 +60,8 @@
#include "transfor.h"
#include "traps.h"
#include "view.h"
+#include "viewchar.h"
+#include "viewgeom.h"
#include "xom.h"
#include "tiles.h"
diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc
index 0787629f40..86f8a2df61 100644
--- a/crawl-ref/source/chardump.cc
+++ b/crawl-ref/source/chardump.cc
@@ -54,6 +54,7 @@
#include "stuff.h"
#include "transfor.h"
#include "view.h"
+#include "viewchar.h"
#include "xom.h"
struct dump_params;
diff --git a/crawl-ref/source/cio.cc b/crawl-ref/source/cio.cc
index 59f460b0ec..6f95297d84 100644
--- a/crawl-ref/source/cio.cc
+++ b/crawl-ref/source/cio.cc
@@ -12,6 +12,7 @@
#include "macro.h"
#include "message.h"
#include "state.h"
+#include "viewgeom.h"
#include <queue>
diff --git a/crawl-ref/source/cloud.cc b/crawl-ref/source/cloud.cc
index 04736fc968..52df81690c 100644
--- a/crawl-ref/source/cloud.cc
+++ b/crawl-ref/source/cloud.cc
@@ -16,6 +16,7 @@
#include "cloud.h"
#include "colour.h"
#include "coord.h"
+#include "envmap.h"
#include "mapmark.h"
#include "ouch.h"
#include "player.h"
diff --git a/crawl-ref/source/colour.cc b/crawl-ref/source/colour.cc
index 896075b8d4..9bca86e7de 100644
--- a/crawl-ref/source/colour.cc
+++ b/crawl-ref/source/colour.cc
@@ -4,6 +4,7 @@
#include "env.h"
#include "mon-util.h"
+#include "options.h"
#include "player.h"
#include "random.h"
@@ -392,3 +393,131 @@ int str_to_colour( const std::string &str, int default_colour,
return ((ret == 16) ? default_colour : ret);
}
+
+#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
+
+#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);
+}
diff --git a/crawl-ref/source/colour.h b/crawl-ref/source/colour.h
index 8c896d9148..c13aa973df 100644
--- a/crawl-ref/source/colour.h
+++ b/crawl-ref/source/colour.h
@@ -62,4 +62,12 @@ unsigned char make_high_colour(unsigned char colour);
bool is_element_colour(int col);
int element_colour(int element, bool no_random = false);
+#if defined(TARGET_OS_WINDOWS) || defined(TARGET_OS_DOS) || defined(USE_TILE)
+unsigned short dos_brand( unsigned short colour,
+ unsigned brand = CHATTR_REVERSE);
+#endif
+
+// Applies ETC_ colour substitutions and brands.
+unsigned real_colour(unsigned raw_colour);
+
#endif
diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc
index 0b117625df..ed7a181af5 100644
--- a/crawl-ref/source/command.cc
+++ b/crawl-ref/source/command.cc
@@ -51,6 +51,7 @@
#include "terrain.h"
#include "transfor.h"
#include "view.h"
+#include "viewchar.h"
static void _adjust_item(void);
static void _adjust_spells(void);
diff --git a/crawl-ref/source/coord.cc b/crawl-ref/source/coord.cc
index 59a75cf888..576c71bd27 100644
--- a/crawl-ref/source/coord.cc
+++ b/crawl-ref/source/coord.cc
@@ -2,9 +2,9 @@
#include "coord.h"
-#include "directn.h"
#include "random.h"
#include "state.h"
+#include "viewgeom.h"
//////////////////////////////////////////////////////////////////////////
// coord_def
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index 0f2fb2f966..d2c57506a9 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -39,6 +39,7 @@
#include "directn.h"
#include "dungeon.h"
#include "effects.h"
+#include "envmap.h"
#include "fight.h"
#include "files.h"
#include "food.h"
diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc
index 9ca25fabf5..5914aa4e5d 100644
--- a/crawl-ref/source/delay.cc
+++ b/crawl-ref/source/delay.cc
@@ -21,6 +21,7 @@
#include "describe.h"
#include "directn.h"
#include "enum.h"
+#include "envmap.h"
#include "exclude.h"
#include "food.h"
#include "invent.h"
diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc
index 9a981ded71..033924fc89 100644
--- a/crawl-ref/source/directn.cc
+++ b/crawl-ref/source/directn.cc
@@ -31,6 +31,7 @@
#include "debug.h"
#include "describe.h"
#include "dungeon.h"
+#include "envmap.h"
#include "initfile.h"
#include "invent.h"
#include "itemname.h"
@@ -59,6 +60,8 @@
#include "travel.h"
#include "tutorial.h"
#include "view.h"
+#include "viewchar.h"
+#include "viewgeom.h"
#include "output.h"
#include "macro.h"
diff --git a/crawl-ref/source/directn.h b/crawl-ref/source/directn.h
index d7bbd68656..08d5fd60ca 100644
--- a/crawl-ref/source/directn.h
+++ b/crawl-ref/source/directn.h
@@ -25,94 +25,6 @@ private:
bool do_anything;
};
-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;
-};
-
-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);
- // Set new location, but preserve scrolling as if the player didn't move.
- void shift_player_to(const coord_def &c);
-
- coord_def view_centre() const
- {
- return viewp + viewhalfsz;
- }
-
- coord_def glosc() const
- {
- return (glos1 + glos2) / 2;
- }
-
- 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 targetting_behaviour
{
@@ -206,56 +118,6 @@ std::vector<dungeon_feature_type> features_by_desc(const base_pattern &pattern);
void full_describe_view(void);
-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);
-}
-
-inline coord_def show2view(const coord_def &pos)
-{
- return (pos + crawl_view.vlos1);
-}
-
-inline coord_def grid2show(const coord_def &pos)
-{
- return (view2show(grid2view(pos)));
-}
-
-inline coord_def show2grid(const coord_def &pos)
-{
- return (view2grid(show2view(pos)));
-}
-
extern const struct coord_def Compass[8];
#endif
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index 9c0bf853a3..4d16c46348 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -22,6 +22,7 @@
#include "defines.h"
#include "effects.h"
#include "enum.h"
+#include "envmap.h"
#include "externs.h"
#include "options.h"
#include "directn.h"
diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc
index 1630dab32a..26289f2616 100644
--- a/crawl-ref/source/effects.cc
+++ b/crawl-ref/source/effects.cc
@@ -27,6 +27,7 @@
#include "delay.h"
#include "directn.h"
#include "dgnevent.h"
+#include "envmap.h"
#include "food.h"
#include "hiscores.h"
#include "invent.h"
@@ -62,6 +63,7 @@
#include "traps.h"
#include "tutorial.h"
#include "view.h"
+#include "viewchar.h"
#include "xom.h"
int holy_word_player(int pow, int caster, actor *attacker)
diff --git a/crawl-ref/source/env.h b/crawl-ref/source/env.h
index 32ce82e92a..fd9abf7720 100644
--- a/crawl-ref/source/env.h
+++ b/crawl-ref/source/env.h
@@ -1,6 +1,7 @@
#ifndef ENV_H
#define ENV_H
+#include "mapcell.h"
#include "monster.h"
#include "show.h"
diff --git a/crawl-ref/source/envmap.cc b/crawl-ref/source/envmap.cc
new file mode 100644
index 0000000000..fb0f948183
--- /dev/null
+++ b/crawl-ref/source/envmap.cc
@@ -0,0 +1,348 @@
+/*
+ * File: envmap.cc
+ * Summary: Functions dealing with env.map.
+ */
+
+#include "AppHdr.h"
+
+#include "envmap.h"
+
+#include "coord.h"
+#include "coordit.h"
+#include "dgnevent.h"
+#include "directn.h"
+#include "env.h"
+#include "notes.h"
+#include "overmap.h"
+#include "stuff.h"
+#include "terrain.h"
+#include "view.h"
+
+// 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
+
+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));
+}
+
+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);
+}
+
+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
+}
+
+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
+ }
+}
+
+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();
+}
diff --git a/crawl-ref/source/envmap.h b/crawl-ref/source/envmap.h
new file mode 100644
index 0000000000..f7352eab8d
--- /dev/null
+++ b/crawl-ref/source/envmap.h
@@ -0,0 +1,83 @@
+#ifndef ENVMAP_H
+#define ENVMAP_H
+
+#include "show.h"
+
+struct coord_def;
+
+void set_envmap_obj(const coord_def& where, show_type object);
+unsigned get_envmap_char(int x, int y);
+inline unsigned get_envmap_char(const coord_def& c) {
+ return get_envmap_char(c.x, c.y);
+}
+show_type get_envmap_obj(int x, int y);
+inline show_type get_envmap_obj(const coord_def& c) {
+ return get_envmap_obj(c.x, c.y);
+}
+void set_envmap_detected_item(int x, int y, bool detected = true);
+inline void set_envmap_detected_item(const coord_def& c, bool detected = true) {
+ set_envmap_detected_item(c.x, c.y, detected);
+}
+
+void set_envmap_detected_mons(int x, int y, bool detected = true);
+inline void set_envmap_detected_mons(const coord_def& c, bool detected = true) {
+ set_envmap_detected_mons(c.x, c.y, detected);
+}
+void set_envmap_col( int x, int y, int colour, int flags );
+void set_envmap_col( int x, int y, int colour );
+bool is_sanctuary( const coord_def& p );
+bool is_bloodcovered( const coord_def& p );
+
+bool is_envmap_detected_item(int x, int y);
+inline bool is_envmap_detected_item(const coord_def& c) {
+ return is_envmap_detected_item(c.x, c.y);
+}
+
+bool is_envmap_detected_mons(int x, int y);
+inline bool is_envmap_detected_mons(const coord_def& c) {
+ return is_envmap_detected_mons(c.x, c.y);
+}
+bool is_envmap_item(int x, int y);
+inline bool is_envmap_item(const coord_def& c) {
+ return is_envmap_item(c.x, c.y);
+}
+void set_terrain_mapped( int x, int y );
+inline void set_terrain_mapped( const coord_def& c ) {
+ set_terrain_mapped(c.x,c.y);
+}
+void set_terrain_seen( int x, int y );
+inline void set_terrain_seen( const coord_def& c ) {
+ set_terrain_seen(c.x, c.y);
+}
+void set_terrain_changed( int x, int y );
+bool is_terrain_known( int x, int y );
+bool is_terrain_seen( int x, int y );
+bool is_terrain_changed( int x, int y );
+inline bool is_terrain_changed( const coord_def& c ) {
+ return is_terrain_changed(c.x,c.y);
+}
+bool is_terrain_known(const coord_def &p);
+bool is_terrain_mapped(const coord_def &p);
+bool is_notable_terrain(dungeon_feature_type ftype);
+
+inline bool is_terrain_seen(const coord_def &c)
+{
+ return (is_terrain_seen(c.x, c.y));
+}
+
+inline void set_terrain_changed(const coord_def &c)
+{
+ set_terrain_changed(c.x, c.y);
+}
+
+int count_detected_mons(void);
+void clear_map(bool clear_items = true, bool clear_mons = true);
+
+int get_envmap_col(const coord_def& p);
+
+void set_envmap_glyph(const coord_def& c, show_type object, int col);
+
+void clear_envmap_grid(const coord_def& p);
+
+#endif
+
diff --git a/crawl-ref/source/exclude.cc b/crawl-ref/source/exclude.cc
index f9deb58f8b..1c91a673d4 100644
--- a/crawl-ref/source/exclude.cc
+++ b/crawl-ref/source/exclude.cc
@@ -8,6 +8,7 @@
#include "exclude.h"
#include "coord.h"
+#include "envmap.h"
#include "mon-util.h"
#include "options.h"
#include "overmap.h"
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index e15100a12e..94c765a305 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -27,6 +27,7 @@
#include "debug.h"
#include "delay.h"
#include "effects.h"
+#include "envmap.h"
#include "food.h"
#include "goditem.h"
#include "invent.h"
@@ -60,6 +61,7 @@
#include "traps.h"
#include "tutorial.h"
#include "view.h"
+#include "viewgeom.h"
#include "xom.h"
#ifdef NOTE_DEBUG_CHAOS_BRAND
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index e989cac4a2..a1bfab56dc 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -79,6 +79,7 @@
#include "travel.h"
#include "tutorial.h"
#include "view.h"
+#include "viewgeom.h"
#ifdef TARGET_COMPILER_VC
#include <direct.h>
diff --git a/crawl-ref/source/format.cc b/crawl-ref/source/format.cc
index c982501178..265100bd26 100644
--- a/crawl-ref/source/format.cc
+++ b/crawl-ref/source/format.cc
@@ -8,6 +8,7 @@
#include "colour.h"
#include "format.h"
#include "view.h"
+#include "viewchar.h"
formatted_string::formatted_string(int init_colour)
: ops()
diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc
index dc9c95b21a..85b3105c38 100644
--- a/crawl-ref/source/initfile.cc
+++ b/crawl-ref/source/initfile.cc
@@ -44,6 +44,7 @@
#include "travel.h"
#include "items.h"
#include "view.h"
+#include "viewchar.h"
// For finding the executable's path
#ifdef TARGET_OS_WINDOWS
diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc
index 52ef8bbba3..50119d4f55 100644
--- a/crawl-ref/source/item_use.cc
+++ b/crawl-ref/source/item_use.cc
@@ -14,7 +14,6 @@
#include <stdio.h>
#include "externs.h"
-#include "options.h"
#include "abl-show.h"
#include "artefact.h"
@@ -29,6 +28,7 @@
#include "describe.h"
#include "directn.h"
#include "effects.h"
+#include "envmap.h"
#include "fight.h"
#include "food.h"
#include "godabil.h"
@@ -48,6 +48,7 @@
#include "monplace.h"
#include "monstuff.h"
#include "notes.h"
+#include "options.h"
#include "ouch.h"
#include "player.h"
#include "quiver.h"
@@ -70,6 +71,8 @@
#include "traps.h"
#include "tutorial.h"
#include "view.h"
+#include "viewchar.h"
+#include "viewgeom.h"
#include "xom.h"
static bool _drink_fountain();
diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc
index 34245418e8..1a63f10c87 100644
--- a/crawl-ref/source/items.cc
+++ b/crawl-ref/source/items.cc
@@ -60,6 +60,7 @@
#include "terrain.h"
#include "tutorial.h"
#include "view.h"
+#include "viewgeom.h"
#include "xom.h"
#define PORTAL_VAULT_ORIGIN_KEY "portal_vault_origin"
diff --git a/crawl-ref/source/libgui.cc b/crawl-ref/source/libgui.cc
index e00eb851e1..93102cb775 100644
--- a/crawl-ref/source/libgui.cc
+++ b/crawl-ref/source/libgui.cc
@@ -28,6 +28,7 @@
#include "tilesdl.h"
#include "travel.h"
#include "view.h"
+#include "viewgeom.h"
#include <SDL.h>
#include "tilesdl.h"
diff --git a/crawl-ref/source/libunix.cc b/crawl-ref/source/libunix.cc
index 84597617fb..1479396951 100644
--- a/crawl-ref/source/libunix.cc
+++ b/crawl-ref/source/libunix.cc
@@ -35,6 +35,7 @@
#include "state.h"
#include "stuff.h"
#include "view.h"
+#include "viewgeom.h"
#ifdef DGL_ENABLE_CORE_DUMP
#include <sys/time.h>
diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc
index 898e1a8b83..7a0726b134 100644
--- a/crawl-ref/source/libutil.cc
+++ b/crawl-ref/source/libutil.cc
@@ -6,12 +6,13 @@
#include "AppHdr.h"
#include "defines.h"
-#include "directn.h"
#include "itemname.h" // is_vowel()
#include "libutil.h"
#include "externs.h"
#include "macro.h"
#include "stuff.h"
+#include "viewgeom.h"
+
#include <sstream>
#include <stdio.h>
#include <ctype.h>
diff --git a/crawl-ref/source/los.cc b/crawl-ref/source/los.cc
index 6c0eb0936a..5d93a9ef90 100644
--- a/crawl-ref/source/los.cc
+++ b/crawl-ref/source/los.cc
@@ -51,7 +51,6 @@
#include "coord.h"
#include "coordit.h"
#include "debug.h"
-#include "directn.h"
#include "externs.h"
#include "geom2d.h"
#include "losparam.h"
@@ -60,6 +59,7 @@
#include "state.h"
#include "stuff.h"
#include "terrain.h"
+#include "viewgeom.h"
// This determines which cells are considered out of range during
// precalculations (only positive quadrant used).
diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj
index fff4ef0229..9ebecb6531 100644
--- a/crawl-ref/source/makefile.obj
+++ b/crawl-ref/source/makefile.obj
@@ -28,6 +28,7 @@ directn.o \
dlua.o \
dungeon.o \
effects.o \
+envmap.o \
exclude.o \
feature.o \
fight.o \
@@ -141,4 +142,7 @@ traps.o \
travel.o \
tutorial.o \
view.o \
+viewchar.o \
+viewgeom.o \
+viewmap.o \
xom.o
diff --git a/crawl-ref/source/mapcell.h b/crawl-ref/source/mapcell.h
new file mode 100644
index 0000000000..45ef60f62e
--- /dev/null
+++ b/crawl-ref/source/mapcell.h
@@ -0,0 +1,22 @@
+#ifndef MAPCELL_H
+#define MAPCELL_H
+
+#include "show.h"
+
+struct map_cell
+{
+ show_type object; // The object: monster, item, feature, or cloud.
+ unsigned short flags; // Flags describing the mappedness of this square.
+ unsigned short colour;
+ unsigned long property; // Flags for blood, sanctuary, ...
+
+ map_cell() : object(), flags(0), colour(0), property(0) { }
+ void clear() { flags = colour = 0; object = show_type(); }
+
+ unsigned glyph() const;
+ bool known() const;
+ bool seen() const;
+};
+
+#endif
+
diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc
index 5ee5792081..fc1c802f17 100644
--- a/crawl-ref/source/message.cc
+++ b/crawl-ref/source/message.cc
@@ -38,6 +38,8 @@
#include "travel.h"
#include "tutorial.h"
#include "view.h"
+#include "viewchar.h"
+#include "viewgeom.h"
#include "menu.h"
class message_item {
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index cf6f450c24..4e4e1cc76f 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -43,6 +43,7 @@
#include "dgnevent.h"
#include "directn.h"
#include "dungeon.h"
+#include "envmap.h"
#include "fight.h"
#include "files.h"
#include "food.h"
@@ -80,6 +81,7 @@
#include "travel.h"
#include "tutorial.h"
#include "view.h"
+#include "viewchar.h"
#include "xom.h"
static void _create_monster_hide(const item_def corpse)
diff --git a/crawl-ref/source/mon-abil.cc b/crawl-ref/source/mon-abil.cc
index 3defd6aed2..b6e430ca40 100644
--- a/crawl-ref/source/mon-abil.cc
+++ b/crawl-ref/source/mon-abil.cc
@@ -18,6 +18,7 @@
#include "beam.h"
#include "colour.h"
#include "directn.h"
+#include "envmap.h"
#include "ghost.h"
#include "misc.h"
#include "mon-act.h"
@@ -32,6 +33,7 @@
#include "state.h"
#include "stuff.h"
#include "view.h"
+#include "viewchar.h"
bool ugly_thing_mutate(monsters *ugly, bool proximity)
{
diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc
index daa4a50577..2ad17e09a2 100644
--- a/crawl-ref/source/mon-act.cc
+++ b/crawl-ref/source/mon-act.cc
@@ -16,6 +16,7 @@
#include "cloud.h"
#include "delay.h"
#include "directn.h"
+#include "envmap.h"
#include "fight.h"
#include "itemname.h"
#include "itemprop.h"
@@ -41,6 +42,7 @@
#include "traps.h"
#include "tutorial.h"
#include "view.h"
+#include "viewchar.h"
static bool _handle_pickup(monsters *monster);
static void _mons_in_cloud(monsters *monster);
diff --git a/crawl-ref/source/mon-behv.cc b/crawl-ref/source/mon-behv.cc
index 4335854400..d3eff47330 100644
--- a/crawl-ref/source/mon-behv.cc
+++ b/crawl-ref/source/mon-behv.cc
@@ -12,6 +12,7 @@
#include "coord.h"
#include "coordit.h"
+#include "envmap.h"
#include "exclude.h"
#include "los.h"
#include "monplace.h"
diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc
index e16d901f69..95c911cc93 100644
--- a/crawl-ref/source/mon-cast.cc
+++ b/crawl-ref/source/mon-cast.cc
@@ -15,6 +15,7 @@
#include "colour.h"
#include "database.h"
#include "effects.h"
+#include "envmap.h"
#include "fight.h"
#include "ghost.h"
#include "los.h"
@@ -32,6 +33,7 @@
#include "spells3.h"
#include "stuff.h"
#include "view.h"
+#include "viewchar.h"
static void _scale_draconian_breath(bolt& beam, int drac_type)
{
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index fdf8bac529..4c44cc83b1 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -15,6 +15,7 @@
#include "colour.h"
#include "database.h"
#include "directn.h"
+#include "envmap.h"
#include "fight.h"
#include "ghost.h"
#include "goditem.h"
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index 33850d50c5..c461144c9a 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -13,6 +13,7 @@
#include "arena.h"
#include "branch.h"
#include "directn.h" // for the Compass
+#include "envmap.h"
#include "externs.h"
#include "options.h"
#include "ghost.h"
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 00181a28ba..ff2eddd821 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -22,6 +22,7 @@
#include "delay.h"
#include "dgnevent.h"
#include "directn.h"
+#include "envmap.h"
#include "files.h"
#include "food.h"
#include "godabil.h"
@@ -46,6 +47,7 @@
#include "traps.h"
#include "tutorial.h"
#include "view.h"
+#include "viewchar.h"
#include "stash.h"
#include "xom.h"
diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc
index 276e14edd6..6447463859 100644
--- a/crawl-ref/source/output.cc
+++ b/crawl-ref/source/output.cc
@@ -51,6 +51,8 @@
#include "transfor.h"
#include "travel.h"
#include "view.h"
+#include "viewchar.h"
+#include "viewgeom.h"
// Color for captions like 'Health:', 'Str:', etc.
#define HUD_CAPTION_COLOUR Options.status_caption_colour
diff --git a/crawl-ref/source/overmap.cc b/crawl-ref/source/overmap.cc
index 55cbbd2f05..cd928e8505 100644
--- a/crawl-ref/source/overmap.cc
+++ b/crawl-ref/source/overmap.cc
@@ -25,6 +25,7 @@
#include "dgnevent.h"
#include "directn.h"
#include "dungeon.h"
+#include "envmap.h"
#include "feature.h"
#include "files.h"
#include "initfile.h"
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index d3dd1d6829..34ca28d9f9 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -29,6 +29,7 @@
#include "delay.h"
#include "dgnevent.h"
#include "effects.h"
+#include "envmap.h"
#include "fight.h"
#include "food.h"
#include "godabil.h"
@@ -68,6 +69,7 @@
#include "travel.h"
#include "tutorial.h"
#include "view.h"
+#include "viewgeom.h"
#include "tiles.h"
#include "xom.h"
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index 7ac3e27811..4247dbbae3 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -33,6 +33,7 @@
#include "describe.h"
#include "effects.h"
#include "enum.h"
+#include "envmap.h"
#include "fight.h"
#include "files.h"
#include "food.h"
diff --git a/crawl-ref/source/show.cc b/crawl-ref/source/show.cc
index 35f2fb1a0f..b75a90a13c 100644
--- a/crawl-ref/source/show.cc
+++ b/crawl-ref/source/show.cc
@@ -3,6 +3,7 @@
#include "show.h"
#include "cloud.h"
+#include "colour.h"
#include "coordit.h"
#include "directn.h"
#include "feature.h"
@@ -12,6 +13,7 @@
#include "state.h"
#include "terrain.h"
#include "view.h"
+#include "viewgeom.h"
void get_show_symbol(show_type object, unsigned *ch,
unsigned short *colour)
diff --git a/crawl-ref/source/show.h b/crawl-ref/source/show.h
index a6162e23fa..7ee086b520 100644
--- a/crawl-ref/source/show.h
+++ b/crawl-ref/source/show.h
@@ -57,19 +57,11 @@ struct show_type
bool operator < (const show_type &other) const;
};
-struct map_cell
+struct show_info
{
- show_type object; // The object: monster, item, feature, or cloud.
- unsigned short flags; // Flags describing the mappedness of this square.
- unsigned short colour;
- unsigned long property; // Flags for blood, sanctuary, ...
-
- map_cell() : object(), flags(0), colour(0), property(0) { }
- void clear() { flags = colour = 0; object = show_type(); }
-
- unsigned glyph() const;
- bool known() const;
- bool seen() const;
+ dungeon_feature_type feat;
+ show_item_type item;
+ monster_type mons;
};
// Replaces get_item_symbol.
diff --git a/crawl-ref/source/spells1.cc b/crawl-ref/source/spells1.cc
index e56b9c763a..fa95cae514 100644
--- a/crawl-ref/source/spells1.cc
+++ b/crawl-ref/source/spells1.cc
@@ -49,6 +49,7 @@
#include "transfor.h"
#include "traps.h"
#include "view.h"
+#include "viewchar.h"
static bool _abyss_blocks_teleport(bool cblink)
{
diff --git a/crawl-ref/source/spells2.cc b/crawl-ref/source/spells2.cc
index 8d857c3f10..02a3cd72c3 100644
--- a/crawl-ref/source/spells2.cc
+++ b/crawl-ref/source/spells2.cc
@@ -24,6 +24,7 @@
#include "directn.h"
#include "dungeon.h"
#include "effects.h"
+#include "envmap.h"
#include "goditem.h"
#include "invent.h"
#include "itemname.h"
diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc
index 36d60ea032..8451322adb 100644
--- a/crawl-ref/source/spells3.cc
+++ b/crawl-ref/source/spells3.cc
@@ -25,6 +25,7 @@
#include "debug.h"
#include "delay.h"
#include "effects.h"
+#include "envmap.h"
#include "food.h"
#include "goditem.h"
#include "itemname.h"
@@ -49,6 +50,7 @@
#include "traps.h"
#include "travel.h"
#include "view.h"
+#include "viewgeom.h"
#include "xom.h"
bool cast_selective_amnesia(bool force)
diff --git a/crawl-ref/source/spells4.cc b/crawl-ref/source/spells4.cc
index 39f1be7c52..863acda3d5 100644
--- a/crawl-ref/source/spells4.cc
+++ b/crawl-ref/source/spells4.cc
@@ -51,6 +51,7 @@
#include "transfor.h"
#include "traps.h"
#include "view.h"
+#include "viewchar.h"
enum DEBRIS // jmf: add for shatter, dig, and Giants to throw
{
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index 468ac4cfb1..c2cbaa6971 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -19,6 +19,7 @@
#include "coordit.h"
#include "describe.h"
#include "effects.h"
+#include "envmap.h"
#include "food.h"
#include "format.h"
#include "godabil.h"
diff --git a/crawl-ref/source/spl-mis.cc b/crawl-ref/source/spl-mis.cc
index 4b349054c6..8dd1bc14b1 100644
--- a/crawl-ref/source/spl-mis.cc
+++ b/crawl-ref/source/spl-mis.cc
@@ -30,6 +30,7 @@
#include "terrain.h"
#include "transfor.h"
#include "view.h"
+#include "viewchar.h"
#include "xom.h"
// This determines how likely it is that more powerful wild magic
diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc
index 22a021e0fc..0bc84dbb6f 100644
--- a/crawl-ref/source/stash.cc
+++ b/crawl-ref/source/stash.cc
@@ -40,6 +40,7 @@
#include "traps.h"
#include "travel.h"
#include "tutorial.h"
+#include "viewgeom.h"
#include <cctype>
#include <cstdio>
diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc
index 3fefb11e7b..fa7c276f68 100644
--- a/crawl-ref/source/stuff.cc
+++ b/crawl-ref/source/stuff.cc
@@ -18,6 +18,8 @@
#include "state.h"
#include "stuff.h"
#include "view.h"
+#include "viewchar.h"
+#include "viewgeom.h"
#include <cstdarg>
#include <sstream>
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index a05a0bd18a..8fa8ceaef9 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -64,6 +64,7 @@
#include "describe.h"
#include "dungeon.h"
#include "enum.h"
+#include "envmap.h"
#include "externs.h"
#include "files.h"
#include "ghost.h"
diff --git a/crawl-ref/source/teleport.cc b/crawl-ref/source/teleport.cc
index 5db62261b2..c2c1829d4a 100644
--- a/crawl-ref/source/teleport.cc
+++ b/crawl-ref/source/teleport.cc
@@ -9,6 +9,7 @@
#include "cloud.h"
#include "coord.h"
+#include "envmap.h"
#include "los.h"
#include "player.h"
#include "random.h"
diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc
index 47b66af04a..92d4c750f7 100644
--- a/crawl-ref/source/terrain.cc
+++ b/crawl-ref/source/terrain.cc
@@ -15,6 +15,7 @@
#include "cloud.h"
#include "dgnevent.h"
#include "directn.h"
+#include "envmap.h"
#include "godabil.h"
#include "itemprop.h"
#include "items.h"
diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc
index 8b696a0ae5..d356481fa7 100644
--- a/crawl-ref/source/tilepick.cc
+++ b/crawl-ref/source/tilepick.cc
@@ -13,6 +13,7 @@
#include "coord.h"
#include "coordit.h"
#include "directn.h"
+#include "envmap.h"
#include "externs.h"
#include "options.h"
#include "food.h"
@@ -39,6 +40,7 @@
#include "traps.h"
#include "travel.h"
#include "view.h"
+#include "viewgeom.h"
void TileNewLevel(bool first_time)
{
diff --git a/crawl-ref/source/tilereg.cc b/crawl-ref/source/tilereg.cc
index 4d988e4dc5..903187da19 100644
--- a/crawl-ref/source/tilereg.cc
+++ b/crawl-ref/source/tilereg.cc
@@ -11,6 +11,7 @@
#include "cio.h"
#include "coord.h"
+#include "envmap.h"
#include "debug.h"
#include "describe.h"
#include "files.h"
@@ -40,6 +41,7 @@
#include "transfor.h"
#include "travel.h"
#include "view.h"
+#include "viewgeom.h"
#include "tilereg.h"
#include "tiles.h"
diff --git a/crawl-ref/source/tilesdl.cc b/crawl-ref/source/tilesdl.cc
index 59dae41a82..ce00292b20 100644
--- a/crawl-ref/source/tilesdl.cc
+++ b/crawl-ref/source/tilesdl.cc
@@ -5,6 +5,7 @@
#include "artefact.h"
#include "cio.h"
#include "coord.h"
+#include "envmap.h"
#include "itemname.h"
#include "items.h"
#include "itemprop.h"
@@ -22,6 +23,7 @@
#include "tilesdl.h"
#include "travel.h"
#include "view.h"
+#include "viewgeom.h"
#include "tiledef-dngn.h"
#include "tilefont.h"
diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc
index 362859a06b..40ad762116 100644
--- a/crawl-ref/source/traps.cc
+++ b/crawl-ref/source/traps.cc
@@ -18,6 +18,7 @@
#include "delay.h"
#include "describe.h"
#include "directn.h"
+#include "envmap.h"
#include "itemname.h"
#include "itemprop.h"
#include "items.h"
diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc
index f7fd190d05..62f9b9ba46 100644
--- a/crawl-ref/source/travel.cc
+++ b/crawl-ref/source/travel.cc
@@ -22,6 +22,7 @@
#include "describe.h"
#include "dgnevent.h"
#include "directn.h"
+#include "envmap.h"
#include "exclude.h"
#include "itemname.h"
#include "itemprop.h"
diff --git a/crawl-ref/source/tutorial.cc b/crawl-ref/source/tutorial.cc
index 2965d15190..d011841572 100644
--- a/crawl-ref/source/tutorial.cc
+++ b/crawl-ref/source/tutorial.cc
@@ -56,6 +56,8 @@
#include "tiles.h"
#endif
#include "view.h"
+#include "viewchar.h"
+#include "viewgeom.h"
static species_type _get_tutorial_species(unsigned int type);
static job_type _get_tutorial_job(unsigned int type);
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).
diff --git a/crawl-ref/source/view.h b/crawl-ref/source/view.h
index 978fcad050..148cd35fc6 100644
--- a/crawl-ref/source/view.h
+++ b/crawl-ref/source/view.h
@@ -11,7 +11,6 @@
#include "externs.h"
#include "show.h"
-void init_char_table(char_set_type set);
void init_monsters_seens();
void beogh_follower_convert(monsters *monster, bool orc_hit = false);
@@ -38,8 +37,6 @@ void handle_monster_shouts(monsters* monster, bool force = false);
class level_pos;
void show_map( level_pos &spec_place, bool travel_mode, bool allow_esc = false );
bool check_awaken(monsters* monster);
-int count_detected_mons(void);
-void clear_map(bool clear_items = true, bool clear_mons = true);
bool is_feature(int feature, const coord_def& where);
void get_item_glyph(const item_def *item, unsigned *glych,
unsigned short *glycol);
@@ -47,94 +44,20 @@ void get_mons_glyph(const monsters *mons, unsigned *glych,
unsigned short *glycol);
unsigned get_screen_glyph( int x, int y );
unsigned get_screen_glyph( const coord_def &p );
-std::string stringize_glyph(unsigned glyph);
-int multibyte_strlen(const std::string &s);
-// Applies ETC_ colour substitutions and brands.
-unsigned real_colour(unsigned raw_colour);
int get_mons_colour(const monsters *mons);
-void set_envmap_obj(const coord_def& where, show_type object);
-unsigned get_envmap_char(int x, int y);
-inline unsigned get_envmap_char(const coord_def& c) {
- return get_envmap_char(c.x, c.y);
-}
bool inside_level_bounds(int x, int y);
bool inside_level_bounds(const coord_def &p);
-show_type get_envmap_obj(int x, int y);
-inline show_type get_envmap_obj(const coord_def& c) {
- return get_envmap_obj(c.x, c.y);
-}
-void set_envmap_detected_item(int x, int y, bool detected = true);
-inline void set_envmap_detected_item(const coord_def& c, bool detected = true) {
- set_envmap_detected_item(c.x, c.y, detected);
-}
-
-void set_envmap_detected_mons(int x, int y, bool detected = true);
-inline void set_envmap_detected_mons(const coord_def& c, bool detected = true) {
- set_envmap_detected_mons(c.x, c.y, detected);
-}
-void set_envmap_col( int x, int y, int colour, int flags );
-void set_envmap_col( int x, int y, int colour );
-bool is_sanctuary( const coord_def& p );
-bool is_bloodcovered( const coord_def& p );
-
-bool is_envmap_detected_item(int x, int y);
-inline bool is_envmap_detected_item(const coord_def& c) {
- return is_envmap_detected_item(c.x, c.y);
-}
-
-bool is_envmap_detected_mons(int x, int y);
-inline bool is_envmap_detected_mons(const coord_def& c) {
- return is_envmap_detected_mons(c.x, c.y);
-}
-bool is_envmap_item(int x, int y);
-inline bool is_envmap_item(const coord_def& c) {
- return is_envmap_item(c.x, c.y);
-}
-void set_terrain_mapped( int x, int y );
-inline void set_terrain_mapped( const coord_def& c ) {
- set_terrain_mapped(c.x,c.y);
-}
-void set_terrain_seen( int x, int y );
-inline void set_terrain_seen( const coord_def& c ) {
- set_terrain_seen(c.x, c.y);
-}
-void set_terrain_changed( int x, int y );
-bool is_terrain_known( int x, int y );
-bool is_terrain_seen( int x, int y );
-bool is_terrain_changed( int x, int y );
-inline bool is_terrain_changed( const coord_def& c ) {
- return is_terrain_changed(c.x,c.y);
-}
-bool is_terrain_known(const coord_def &p);
-bool is_terrain_mapped(const coord_def &p);
-bool is_notable_terrain(dungeon_feature_type ftype);
-
-inline bool is_terrain_seen(const coord_def &c)
-{
- return (is_terrain_seen(c.x, c.y));
-}
-
-inline void set_terrain_changed(const coord_def &c)
-{
- set_terrain_changed(c.x, c.y);
-}
-
void clear_feature_overrides();
void add_feature_override(const std::string &text);
-void clear_cset_overrides();
-void add_cset_override(char_set_type set, const std::string &overrides);
unsigned grid_character_at(const coord_def &c);
+unsigned get_symbol(show_type object, unsigned short *colour = NULL,
+ bool magic_mapped = false);
std::string screenshot(bool fullscreen = false);
-dungeon_char_type get_feature_dchar( dungeon_feature_type feat );
-unsigned dchar_glyph(dungeon_char_type dchar);
-unsigned get_sightmap_char(int feature);
-unsigned get_magicmap_char(int feature);
-
bool view_update();
void view_update_at(const coord_def &pos);
#ifndef USE_TILE
@@ -150,9 +73,4 @@ dungeon_char_type dchar_by_name(const std::string &name);
void handle_terminal_resize(bool redraw = true);
-#if defined(TARGET_OS_WINDOWS) || defined(TARGET_OS_DOS) || defined(USE_TILE)
-unsigned short dos_brand( unsigned short colour,
- unsigned brand = CHATTR_REVERSE);
-#endif
-
#endif
diff --git a/crawl-ref/source/viewchar.cc b/crawl-ref/source/viewchar.cc
new file mode 100644
index 0000000000..a0cef43408
--- /dev/null
+++ b/crawl-ref/source/viewchar.cc
@@ -0,0 +1,103 @@
+#include "AppHdr.h"
+
+#include "viewchar.h"
+
+#include "options.h"
+#include "state.h"
+
+// 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]);
+}
+
+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());
+}
+
diff --git a/crawl-ref/source/viewchar.h b/crawl-ref/source/viewchar.h
new file mode 100644
index 0000000000..96412480ec
--- /dev/null
+++ b/crawl-ref/source/viewchar.h
@@ -0,0 +1,13 @@
+#ifndef VIEWCHAR_H
+#define VIEWCHAR_H
+
+void init_char_table(char_set_type set);
+
+dungeon_char_type get_feature_dchar( dungeon_feature_type feat );
+unsigned dchar_glyph(dungeon_char_type dchar);
+
+std::string stringize_glyph(unsigned glyph);
+int multibyte_strlen(const std::string &s);
+
+#endif
+
diff --git a/crawl-ref/source/viewgeom.cc b/crawl-ref/source/viewgeom.cc
new file mode 100644
index 0000000000..e013819a09
--- /dev/null
+++ b/crawl-ref/source/viewgeom.cc
@@ -0,0 +1,382 @@
+#include "AppHdr.h"
+
+#include "viewgeom.h"
+
+#include "options.h"
+#include "player.h"
+#include "state.h"
+#include "stuff.h"
+
+// ----------------------------------------------------------------------
+// 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_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 ];
+}
+
+// ----------------------------------------------------------------------
+// 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;
+}
+
+
diff --git a/crawl-ref/source/viewgeom.h b/crawl-ref/source/viewgeom.h
new file mode 100644
index 0000000000..6913849679
--- /dev/null
+++ b/crawl-ref/source/viewgeom.h
@@ -0,0 +1,145 @@
+#ifndef VIEWGEOM_H
+#define VIEWGEOM_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;
+};
+
+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);
+ // Set new location, but preserve scrolling as if the player didn't move.
+ void shift_player_to(const coord_def &c);
+
+ coord_def view_centre() const
+ {
+ return viewp + viewhalfsz;
+ }
+
+ coord_def glosc() const
+ {
+ return (glos1 + glos2) / 2;
+ }
+
+ 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;
+
+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);
+}
+
+inline coord_def show2view(const coord_def &pos)
+{
+ return (pos + crawl_view.vlos1);
+}
+
+inline coord_def grid2show(const coord_def &pos)
+{
+ return (view2show(grid2view(pos)));
+}
+
+inline coord_def show2grid(const coord_def &pos)
+{
+ return (view2grid(show2view(pos)));
+}
+
+#endif
+
+
+
diff --git a/crawl-ref/source/viewmap.cc b/crawl-ref/source/viewmap.cc
new file mode 100644
index 0000000000..b7d2f066e1
--- /dev/null
+++ b/crawl-ref/source/viewmap.cc
@@ -0,0 +1,1188 @@
+/*
+ * File: viewmap.cc
+ * Summary: Showing the level map (X and background).
+ */
+
+#include "AppHdr.h"
+
+#include "viewmap.h"
+
+#include "branch.h"
+#include "cio.h"
+#include "colour.h"
+#include "command.h"
+#include "coord.h"
+#include "env.h"
+#include "envmap.h"
+#include "exclude.h"
+#include "feature.h"
+#include "files.h"
+#include "format.h"
+#include "macro.h"
+#include "mon-util.h"
+#include "options.h"
+#include "place.h"
+#include "player.h"
+#include "stash.h"
+#include "stuff.h"
+#include "terrain.h"
+#include "travel.h"
+#include "viewgeom.h"
+
+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);
+}
+
+// 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();
+}
+
+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;
+}
+
+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);
+}
+
+screen_buffer_t colour_code_map(const coord_def& p, bool item_colour,
+ bool travel_colour, bool on_level)
+{
+ if (!is_terrain_known(p))
+ 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 (is_envmap_detected_item(p))
+ return real_colour(Options.detected_item_colour);
+
+ if (is_envmap_detected_mons(p))
+ {
+ 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);
+}
+
+
diff --git a/crawl-ref/source/viewmap.h b/crawl-ref/source/viewmap.h
new file mode 100644
index 0000000000..c5ab21e394
--- /dev/null
+++ b/crawl-ref/source/viewmap.h
@@ -0,0 +1,10 @@
+#ifndef VIEWMAP_H
+#define VIEWMAP_H
+
+screen_buffer_t colour_code_map(const coord_def& p, bool item_colour = false,
+ bool travel_colour = false, bool on_level = true);
+
+bool emphasise(const coord_def& where, dungeon_feature_type feat);
+
+#endif
+
diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc
index e20073681f..a1f0b98fcc 100644
--- a/crawl-ref/source/xom.cc
+++ b/crawl-ref/source/xom.cc
@@ -15,6 +15,7 @@
#include "delay.h"
#include "directn.h"
#include "effects.h"
+#include "envmap.h"
#include "feature.h"
#include "goditem.h"
#include "it_use2.h"
@@ -51,6 +52,7 @@
#include "transfor.h"
#include "traps.h"
#include "view.h"
+#include "viewchar.h"
#include "xom.h"
#ifdef DEBUG_XOM