summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-01-25 10:43:02 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-01-25 10:43:02 +0000
commita0d48b01861f3745455c731078bc2b15187b1050 (patch)
tree2f94da2a304d427bd2859f740ee170c1f1945c00 /crawl-ref
parentbe875338f295eb1a2c97e33e6444907f3b492e7d (diff)
downloadcrawl-ref-a0d48b01861f3745455c731078bc2b15187b1050.tar.gz
crawl-ref-a0d48b01861f3745455c731078bc2b15187b1050.zip
Removed USE_NEW_RANDOM, USE_MACROS.
Removed DOS_TERM, PLAIN_TERM special casery - all platforms get PLAIN_TERM. Better end-of-greedy-explore reporting for items on traps (Erik). Cleaned up find_travel_pos - moved guts of travel pathfinding to travel_pathfind class. Miscellaneous other stuff. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@882 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/AppHdr.h9
-rw-r--r--crawl-ref/source/abl-show.cc24
-rw-r--r--crawl-ref/source/acr.cc4
-rw-r--r--crawl-ref/source/chardump.cc18
-rw-r--r--crawl-ref/source/command.cc15
-rw-r--r--crawl-ref/source/describe.cc52
-rw-r--r--crawl-ref/source/direct.cc2
-rw-r--r--crawl-ref/source/dungeon.h2
-rw-r--r--crawl-ref/source/externs.h10
-rw-r--r--crawl-ref/source/files.cc15
-rw-r--r--crawl-ref/source/files.h3
-rw-r--r--crawl-ref/source/libunix.cc2
-rw-r--r--crawl-ref/source/libutil.h10
-rw-r--r--crawl-ref/source/macro.cc3
-rw-r--r--crawl-ref/source/macro.h14
-rw-r--r--crawl-ref/source/makefile.unix28
-rw-r--r--crawl-ref/source/menu.cc11
-rw-r--r--crawl-ref/source/message.cc23
-rw-r--r--crawl-ref/source/mutation.cc11
-rw-r--r--crawl-ref/source/newgame.cc24
-rw-r--r--crawl-ref/source/ouch.cc5
-rw-r--r--crawl-ref/source/player.cc3
-rw-r--r--crawl-ref/source/player.h2
-rw-r--r--crawl-ref/source/shopping.cc18
-rw-r--r--crawl-ref/source/skills2.cc10
-rw-r--r--crawl-ref/source/spl-book.cc10
-rw-r--r--crawl-ref/source/spl-cast.cc26
-rw-r--r--crawl-ref/source/stuff.cc205
-rw-r--r--crawl-ref/source/travel.cc820
-rw-r--r--crawl-ref/source/travel.h145
-rw-r--r--crawl-ref/source/view.cc136
-rw-r--r--crawl-ref/source/view.h5
32 files changed, 751 insertions, 914 deletions
diff --git a/crawl-ref/source/AppHdr.h b/crawl-ref/source/AppHdr.h
index 892679d029..f68fdd97c7 100644
--- a/crawl-ref/source/AppHdr.h
+++ b/crawl-ref/source/AppHdr.h
@@ -98,7 +98,6 @@
//
#define DGL_CLEAR_SCREEN "\033[2J"
- #define PLAIN_TERM
#define MULTIUSER
#define USE_UNIX_SIGNALS
@@ -164,7 +163,6 @@
#include "libunix.h"
#elif defined(DOS)
- #define DOS_TERM
#define SHORT_FILE_NAMES
#define EOL "\r\n"
#define CHARACTER_SET A_ALTCHARSET
@@ -184,7 +182,6 @@
#elif defined(WIN32CONSOLE)
#include "libw32c.h"
- #define PLAIN_TERM
#define EOL "\n"
#define CHARACTER_SET A_ALTCHARSET
#define getstr(X,Y) getConsoleString(X,Y)
@@ -246,16 +243,10 @@
// number of back messages saved during play (currently none saved into files)
#define NUM_STORED_MESSAGES 1000
-// if this works out okay, eventually we can change this to USE_OLD_RANDOM
-#define USE_NEW_RANDOM
-
// Uncomment this if you find the labyrinth to be buggy and want to
// remove it from the game.
// #define SHUT_LABYRINTH
-// Define USE_MACRO if you want to use the macro patch in macro.cc.
-#define USE_MACROS
-
// Set this to the number of runes that will be required to enter Zot's
// domain. You shouldn't set this really high unless you want to
// make players spend far too much time in Pandemonium/The Abyss.
diff --git a/crawl-ref/source/abl-show.cc b/crawl-ref/source/abl-show.cc
index 95821ef64d..52647aee30 100644
--- a/crawl-ref/source/abl-show.cc
+++ b/crawl-ref/source/abl-show.cc
@@ -1352,13 +1352,6 @@ char show_abilities( void )
}
-#ifdef DOS_TERM
- char buffer[4800];
-
- gettext(1, 1, 80, 25, buffer);
- window(1, 1, 80, 25);
-#endif
-
clrscr();
cprintf(" Ability Cost Success");
lines++;
@@ -1385,17 +1378,11 @@ char show_abilities( void )
if (ki == ESCAPE)
{
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
return (ESCAPE);
}
if (ki >= 'A' && ki <= 'z')
{
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
return (ki);
}
@@ -1447,26 +1434,15 @@ char show_abilities( void )
if (ki >= 'A' && ki <= 'z')
{
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
return (ki);
}
if (ki == 0)
ki = getch();
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
-
return (ki);
}
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
-
ki = getch();
return (ki);
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index 92a71f22a1..a2624a8884 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -1327,11 +1327,9 @@ void process_command( command_type cmd ) {
mpr("Char dump unsuccessful! Sorry about that.");
break;
-#ifdef USE_MACROS
case CMD_MACRO_ADD:
macro_add_query();
break;
-#endif
case CMD_LIST_WEAPONS:
list_weapons();
@@ -2671,10 +2669,8 @@ static bool initialise(void)
cio_init();
-#ifdef USE_MACROS
// Load macros
macro_init();
-#endif
// system initialisation stuff:
textbackground(0);
diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc
index 3c2a087b72..180df83a9c 100644
--- a/crawl-ref/source/chardump.cc
+++ b/crawl-ref/source/chardump.cc
@@ -1011,11 +1011,6 @@ static bool write_dump(
void display_notes()
{
-#ifdef DOS_TERM
- char dosbuffer[4000];
- gettext( 1, 1, 80, 25, dosbuffer );
- window( 1, 1, 80, 25 );
-#endif
Menu scr;
scr.set_title( new MenuEntry("| Turn |Location | Note"));
for ( unsigned int i = 0; i < note_list.size(); ++i )
@@ -1036,20 +1031,11 @@ void display_notes()
}
scr.show();
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, dosbuffer);
- window(1, 1, 80, 25);
-#endif
redraw_screen();
}
void resists_screen()
{
-#ifdef DOS_TERM
- char dosbuffer[4000];
- gettext( 1, 1, 80, 25, dosbuffer );
- window( 1, 1, 80, 25 );
-#endif
std::vector<formatted_string> vfs = get_full_detail(false);
clrscr();
gotoxy(1,1);
@@ -1060,9 +1046,5 @@ void resists_screen()
scr.add_item_formatted_string(vfs[i]);
scr.show();
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, dosbuffer);
- window(1, 1, 80, 25);
-#endif
redraw_screen();
}
diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc
index b9e9b73589..14263ce8e2 100644
--- a/crawl-ref/source/command.cc
+++ b/crawl-ref/source/command.cc
@@ -716,7 +716,9 @@ static void show_keyhelp_menu(const std::vector<formatted_string> &lines,
{
for ( int i = 0; help_files[i].name != NULL; ++i )
{
- FILE* fp=fopen(datafile_path(std::string(help_files[i].name)).c_str(),"r");
+ FILE* fp =
+ fopen(
+ datafile_path(help_files[i].name, false).c_str(), "r");
if ( !fp )
continue;
@@ -993,13 +995,6 @@ static void list_wizard_commands()
const char *line;
int j = 0;
-#ifdef DOS_TERM
- char buffer[4800];
-
- window(1, 1, 80, 25);
- gettext(1, 1, 80, 25, buffer);
-#endif
-
clrscr();
// BCR - Set to screen length - 1 to display the "more" string
@@ -1030,10 +1025,6 @@ static void list_wizard_commands()
getch();
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
-
return;
} // end list_commands()
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index eaabafcb77..17cb25705d 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -98,14 +98,7 @@ static void print_description( const std::string &d )
while(currentPos < d.length())
{
if (currentPos != 0)
- {
-#ifdef PLAIN_TERM
gotoxy(1, wherey() + 1);
-#endif
-#ifdef DOS_TERM
- cprintf(EOL);
-#endif
- }
// see if $ sign is within one lineWidth
if (nlSearch)
@@ -3348,12 +3341,6 @@ std::string get_item_description( const item_def &item, bool verbose, bool dump
//---------------------------------------------------------------
void describe_item( const item_def &item )
{
-#ifdef DOS_TERM
- char buffer[4000];
- gettext(1, 1, 80, 25, buffer);
- // window(25, 1, 80, 25);
-#endif
-
clrscr();
std::string description = get_item_description( item, 1 );
@@ -3377,10 +3364,6 @@ void describe_item( const item_def &item )
if (getch() == 0)
getch();
-
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
} // end describe_item()
@@ -3397,12 +3380,6 @@ void describe_spell(int spelled)
description.reserve(500);
-#ifdef DOS_TERM
- char buffer[4000];
- gettext(1, 1, 80, 25, buffer);
- // window(25, 1, 80, 25);
-#endif
-
clrscr();
description += spell_title( spelled );
description += "$$This spell "; // NB: the leading space is here {dlb}
@@ -4495,11 +4472,6 @@ void describe_spell(int spelled)
if (getch() == 0)
getch();
-
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
- window(1, 1, 80, 25);
-#endif
} // end describe_spell()
static std::string describe_draconian_role(const monsters *mon)
@@ -4599,12 +4571,6 @@ void describe_monsters(int class_described, unsigned char which_mons)
description.reserve(200);
-#ifdef DOS_TERM
- char buffer[4000];
- gettext(1, 1, 80, 25, buffer);
- // window(25, 1, 80, 25);
-#endif
-
clrscr();
description = ptr_monam( &(menv[ which_mons ]), DESC_CAP_A );
@@ -6306,11 +6272,6 @@ void describe_monsters(int class_described, unsigned char which_mons)
if (getch() == 0)
getch();
-
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
- window(1, 1, 80, 25);
-#endif
} // end describe_monsters
//---------------------------------------------------------------
@@ -6431,12 +6392,6 @@ void describe_god( int which_god, bool give_title )
const char *description; // mv: tmp string used for printing description
int colour; // mv: colour used for some messages
-#ifdef DOS_TERM
- char buffer[4000];
- gettext( 1, 1, 80, 25, buffer );
- window( 1, 1, 80, 25 );
-#endif
-
clrscr();
if (give_title)
@@ -6737,11 +6692,4 @@ void describe_god( int which_god, bool give_title )
end_god_info: //end of everything (life, world, universe etc.)
getch(); // wait until keypressed
-
-#ifdef DOS_TERM //mv: if DOS_TERM is defined than buffer is returned to screen
- //if not redraw_screen() is called everytime when this function is
- //called
- puttext(1, 1, 80, 25, buffer);
- window(1, 1, 80, 25);
-#endif
} //mv: That's all folks.
diff --git a/crawl-ref/source/direct.cc b/crawl-ref/source/direct.cc
index fb42388bcc..7d7b474000 100644
--- a/crawl-ref/source/direct.cc
+++ b/crawl-ref/source/direct.cc
@@ -43,9 +43,7 @@
#include "travel.h"
#include "view.h"
-#ifdef USE_MACROS
#include "macro.h"
-#endif
enum LOSSelect
{
diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h
index 79a4d4809b..c2122f8c37 100644
--- a/crawl-ref/source/dungeon.h
+++ b/crawl-ref/source/dungeon.h
@@ -17,7 +17,7 @@
#include "FixVec.h"
#include "externs.h"
-#define MAKE_GOOD_ITEM 351
+const int MAKE_GOOD_ITEM = 351;
// Should be the larger of GXM/GYM
#define MAP_SIDE GXM
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 688152562b..5817437c33 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -109,21 +109,25 @@ struct coord_def
int x;
int y;
- coord_def( int x_in, int y_in ) : x(x_in), y(y_in) { }
- coord_def() : x(0), y(0) { }
+ explicit coord_def( int x_in = 0, int y_in = 0 ) : x(x_in), y(y_in) { }
void set(int xi, int yi)
{
x = xi;
y = yi;
}
+
+ void reset()
+ {
+ set(0, 0);
+ }
bool operator == (const coord_def &other) const {
return x == other.x && y == other.y;
}
bool operator != (const coord_def &other) const {
- return x != other.x || y != other.y;
+ return !operator == (other);
}
bool operator < (const coord_def &other) const {
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index 5c79274aae..21ce1e7122 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -351,7 +351,7 @@ static bool create_dirs(const std::string &dir)
return (true);
}
-std::string datafile_path(const std::string &basename)
+std::string datafile_path(const std::string &basename, bool croak_on_fail)
{
std::string cdir = SysEnv.crawl_dir? SysEnv.crawl_dir : "";
@@ -400,8 +400,9 @@ std::string datafile_path(const std::string &basename)
}
// Die horribly.
- end(1, false, "Cannot find data file '%s' anywhere, aborting\n",
- basename.c_str());
+ if (croak_on_fail)
+ end(1, false, "Cannot find data file '%s' anywhere, aborting\n",
+ basename.c_str());
return ("");
}
@@ -629,10 +630,6 @@ void load( unsigned char stair_taken, int load_mode, bool was_a_labyrinth,
bool just_created_level = false;
-#ifdef DOS_TERM
- window(1, 1, 80, 25);
-#endif
-
std::string cha_fil = make_filename( you.your_name, you.your_level,
you.where_are_you,
you.level_type != LEVEL_DUNGEON,
@@ -1222,10 +1219,6 @@ void save_game(bool leave_game)
save_level(you.your_level, (you.level_type != LEVEL_DUNGEON),
you.where_are_you);
-#ifdef DOS_TERM
- window(1, 1, 80, 25);
-#endif
-
clrscr();
#ifdef SAVE_PACKAGE_CMD
diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h
index b87e4f9bea..577e443333 100644
--- a/crawl-ref/source/files.h
+++ b/crawl-ref/source/files.h
@@ -26,7 +26,8 @@
// referenced in files - newgame - ouch:
extern FixedArray<bool, MAX_LEVELS, NUM_BRANCHES> tmp_file_pairs;
-std::string datafile_path(const std::string &basename);
+std::string datafile_path(const std::string &basename,
+ bool croak_on_fail = true);
bool check_dir(const std::string &what, std::string &dir);
diff --git a/crawl-ref/source/libunix.cc b/crawl-ref/source/libunix.cc
index e58c4f5bf2..14c6044517 100644
--- a/crawl-ref/source/libunix.cc
+++ b/crawl-ref/source/libunix.cc
@@ -494,7 +494,7 @@ int clrscr()
#ifndef DGAMELAUNCH
refresh();
#else
- printf(DGL_CLEAR_SCREEN);
+ printf("%s", DGL_CLEAR_SCREEN);
fflush(stdout);
#endif
return (retval);
diff --git a/crawl-ref/source/libutil.h b/crawl-ref/source/libutil.h
index be30ec5ebd..5ad02e504e 100644
--- a/crawl-ref/source/libutil.h
+++ b/crawl-ref/source/libutil.h
@@ -80,8 +80,10 @@ inline std::string lowercase_first(std::string s)
return (s);
}
-template <class Z>
-std::string comma_separated_line(Z start, Z end)
+template <typename Z>
+std::string comma_separated_line(Z start, Z end,
+ const std::string &andc = " and ",
+ const std::string &comma = ", ")
{
std::string text;
for (Z i = start; i != end; ++i)
@@ -89,9 +91,9 @@ std::string comma_separated_line(Z start, Z end)
if (i != start)
{
if (i + 1 != end)
- text += ", ";
+ text += comma;
else
- text += " and ";
+ text += andc;
}
text += *i;
diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc
index 2e322e4143..6a4783519f 100644
--- a/crawl-ref/source/macro.cc
+++ b/crawl-ref/source/macro.cc
@@ -30,7 +30,6 @@
#include "AppHdr.h"
-#ifdef USE_MACROS
#define MACRO_CC
#include "macro.h"
@@ -739,5 +738,3 @@ void macro_userfn(const char *keys, const char *regname)
// to happen in a hurry.
}
#endif
-
-#endif
diff --git a/crawl-ref/source/macro.h b/crawl-ref/source/macro.h
index c3ea7516a8..9d8fa4f126 100644
--- a/crawl-ref/source/macro.h
+++ b/crawl-ref/source/macro.h
@@ -11,8 +11,6 @@
* <1> -/--/-- JS Created
*/
-#ifdef USE_MACROS
-
#ifndef MACRO_H
#define MACRO_H
@@ -51,15 +49,3 @@ bool is_userfunction(int key);
const char *get_userfunction(int key);
#endif
-
-#else
-
-#define getch_with_command_macros() getch()
-#define getchm(x) getch()
-#define flush_input_buffer(XXX) ;
-#define macro_buf_add(x)
-#define is_userfunction(x) false
-#define get_userfunction(x) NULL
-#define call_userfunction(x)
-
-#endif
diff --git a/crawl-ref/source/makefile.unix b/crawl-ref/source/makefile.unix
index 2e1f2a88ff..b8f3784aae 100644
--- a/crawl-ref/source/makefile.unix
+++ b/crawl-ref/source/makefile.unix
@@ -1,4 +1,4 @@
-# -*- Makefile -*- for Dungeon Crawl (linux)
+# -*- Makefile -*- for Dungeon Crawl (unix)
#
# Modified for Crawl Reference by $Author$ on $Date$
@@ -20,8 +20,19 @@ OS_TYPE = UNIX
# Include path for curses or ncurses.
INCLUDES = -I/usr/include/ncurses
-MCHMOD = 2755
-INSTALLDIR := /usr/games
+# If you have lex and yacc, set DOYACC to y (lowercase y).
+DOYACC := y
+
+# Permissions to set on the game executable.
+MCHMOD := 2755
+
+# Permissions to set on the save directory.
+MCHMOD_SAVEDIR := 775
+
+# The user:group to install the game as.
+INSTALL_UGRP := games:games
+
+INSTALLDIR := /usr/games
# If you're installing Crawl for multiple users, you *must* set this to a
# valid path before building Crawl. This is not necessary if you are building
@@ -50,10 +61,6 @@ endif
CFLAGS := $(INCLUDES) $(CFWARN) $(CFOTHERS)
YCFLAGS := $(INCLUDES) $(CFOTHERS)
-
-# If you have lex and yacc, set DOYACC to y (lowercase y).
-DOYACC := y
-
UTIL = util/
LEX := lex
@@ -143,6 +150,7 @@ endif
install: $(GAME)
[ -d $(INSTALLDIR) ] || mkdir -p $(INSTALLDIR)
$(COPY) $(GAME) ${INSTALLDIR}
+ chown $(INSTALL_UGRP) $(INSTALLDIR)/$(GAME)
chmod ${MCHMOD} ${INSTALLDIR}/$(GAME)
ifeq ($(DATADIR),)
$(error DATADIR not set! Set DATADIR and run make clean install again)
@@ -151,8 +159,11 @@ endif
cp dat/*.des $(DATADIR)/data
mkdir -p $(DATADIR)/docs
cp ../docs/*.txt $(DATADIR)/docs
+ chown -R $(INSTALL_UGRP) $(DATADIR)
ifneq ($(SAVEDIR),)
mkdir -p $(SAVEDIR)
+ chown $(INSTALL_UGRP) $(SAVEDIR)
+ chmod $(MCHMOD_SAVEDIR) $(SAVEDIR)
endif
clean:
@@ -192,9 +203,6 @@ profile: $(GAME_DEPENDS)
$(UTIL)%.o: $(UTIL)%.cc
$(CXX) $(YCFLAGS) -o $@ -c $<
-.h.cc:
- touch $@
-
#############################################################################
# Packaging a source tarball for release
#
diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc
index bd68b3b188..dfdefa778f 100644
--- a/crawl-ref/source/menu.cc
+++ b/crawl-ref/source/menu.cc
@@ -109,19 +109,8 @@ std::vector<MenuEntry *> Menu::show(bool reuse_selections)
if (max_pagesize > 0 && pagesize > max_pagesize)
pagesize = max_pagesize;
-#ifdef DOS_TERM
- char buffer[4600];
-
- gettext(1, 1, 80, 25, buffer);
- window(1, 1, 80, 25);
-#endif
-
do_menu();
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
-
return (sel);
}
diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc
index ece8b189c6..7f78039a17 100644
--- a/crawl-ref/source/message.cc
+++ b/crawl-ref/source/message.cc
@@ -355,10 +355,6 @@ static void base_mpr(const char *inf, int channel, int param)
flush_input_buffer( FLUSH_ON_MESSAGE );
-#ifdef DOS_TERM
- window(1, 1, 80, 25);
-#endif
-
const int num_lines = get_message_window_height();
if (New_Message_Count == num_lines - 1)
@@ -373,7 +369,12 @@ static void base_mpr(const char *inf, int channel, int param)
message_out( Message_Line, colour, inf,
Options.delay_message_clear? 2 : 1 );
- New_Message_Count++;
+ // Prompt lines are presumably shown to / seen by the player accompanied
+ // by a request for input, which should do the equivalent of a more(); to
+ // save annoyance, don't bump New_Message_Count for prompts.
+ if (channel != MSGCH_PROMPT)
+ New_Message_Count++;
+
if (Message_Line < num_lines - 1)
Message_Line++;
@@ -491,13 +492,6 @@ void replay_messages(void)
if (last_message < 0)
last_message += NUM_STORED_MESSAGES;
-#ifdef DOS_TERM
- char buffer[4800];
-
- window(1, 1, 80, 25);
- gettext(1, 1, 80, 25, buffer);
-#endif
-
// track back a screen's worth of messages from the end
win_start_line = Next_Message - (num_lines - 2);
if (win_start_line < 0)
@@ -636,10 +630,5 @@ void replay_messages(void)
}
}
-
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
-
return;
} // end replay_messages()
diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc
index 90c973c685..c69a4c7413 100644
--- a/crawl-ref/source/mutation.cc
+++ b/crawl-ref/source/mutation.cc
@@ -1129,23 +1129,12 @@ formatted_string describe_mutations()
void display_mutations()
{
-#ifdef DOS_TERM
- char buffer[4800];
-
- window(1, 1, 80, 25);
- gettext(1, 1, 80, 25, buffer);
-#endif
-
clrscr();
gotoxy(1,1);
describe_mutations().display();
if (getch() == 0)
getch();
-
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
}
bool mutate(int which_mutation, bool failMsg)
diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc
index 0f1c9d9e56..9b207ca2c6 100644
--- a/crawl-ref/source/newgame.cc
+++ b/crawl-ref/source/newgame.cc
@@ -348,18 +348,18 @@ static unsigned char random_potion_description()
// Determine starting depths of branches
static void initialise_branch_depths()
{
- branches[BRANCH_ECUMENICAL_TEMPLE].startdepth = 3 + random2(4);
- branches[BRANCH_ORCISH_MINES].startdepth = 5 + random2(6);
- branches[BRANCH_ELVEN_HALLS].startdepth = coinflip() ? 4 : 3;
- branches[BRANCH_LAIR].startdepth = 7 + random2(6);
- branches[BRANCH_HIVE].startdepth = 10 + random2(6);
- branches[BRANCH_SLIME_PITS].startdepth = 3 + random2(4);
- branches[BRANCH_SWAMP].startdepth = 2 + random2(6);
- branches[BRANCH_SNAKE_PIT].startdepth = coinflip() ? 7 : 6;
- branches[BRANCH_VAULTS].startdepth = 13 + random2(6);
- branches[BRANCH_CRYPT].startdepth = 2 + random2(3);
- branches[BRANCH_HALL_OF_BLADES].startdepth = 4;
- branches[BRANCH_TOMB].startdepth = coinflip() ? 3 : 2;
+ branches[BRANCH_ECUMENICAL_TEMPLE].startdepth = random_range(4, 7);
+ branches[BRANCH_ORCISH_MINES].startdepth = random_range(6, 11);
+ branches[BRANCH_ELVEN_HALLS].startdepth = random_range(3, 4);
+ branches[BRANCH_LAIR].startdepth = random_range(8, 13);
+ branches[BRANCH_HIVE].startdepth = random_range(11, 16);
+ branches[BRANCH_SLIME_PITS].startdepth = random_range(3, 9);
+ branches[BRANCH_SWAMP].startdepth = random_range(2, 7);
+ branches[BRANCH_SNAKE_PIT].startdepth = random_range(3, 8);
+ branches[BRANCH_VAULTS].startdepth = random_range(14, 19);
+ branches[BRANCH_CRYPT].startdepth = random_range(2, 4);
+ branches[BRANCH_HALL_OF_BLADES].startdepth = random_range(4, 6);
+ branches[BRANCH_TOMB].startdepth = random_range(2, 3);
}
bool new_game(void)
diff --git a/crawl-ref/source/ouch.cc b/crawl-ref/source/ouch.cc
index eee99451cf..85cfe0ad83 100644
--- a/crawl-ref/source/ouch.cc
+++ b/crawl-ref/source/ouch.cc
@@ -914,15 +914,10 @@ void end_game( struct scorefile_entry &se )
clrscr();
}
-#ifdef DOS_TERM
- window(1, 1, 80, 25);
-#endif
-
clrscr();
cprintf( "Goodbye, %s.", you.your_name );
cprintf( EOL EOL " " ); // Space padding where # would go in list format
-
std::string hiscore = hiscores_format_single_long( se, true );
const int lines = count_occurrences(hiscore, EOL) + 1;
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index 5915d6877a..962334975b 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -3183,9 +3183,6 @@ void redraw_skill(const char your_name[kNameLen], const char class_name[80])
print_it[40] = 0;
-#ifdef DOS_TERM
- window(1, 1, 80, 25);
-#endif
gotoxy(40, 1);
textcolor( LIGHTGREY );
diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h
index a9db520587..ed08ec44dd 100644
--- a/crawl-ref/source/player.h
+++ b/crawl-ref/source/player.h
@@ -158,7 +158,7 @@ bool player_item_conserve(bool calc_unid = true);
int player_mental_clarity(bool calc_unid = true);
bool player_can_smell();
-
+bool player_can_swim();
/* ***********************************************************************
* called from: fight - files - ouch
diff --git a/crawl-ref/source/shopping.cc b/crawl-ref/source/shopping.cc
index 755a2610cf..d4a16c5c33 100644
--- a/crawl-ref/source/shopping.cc
+++ b/crawl-ref/source/shopping.cc
@@ -125,15 +125,6 @@ char in_a_shop( char shoppy, id_arr id )
unsigned char ft;
std::string purchasable;
-#ifdef DOS_TERM
- char buffer[4800];
- gettext(1, 1, 80, 25, buffer);
-#endif
-
-#ifdef DOS_TERM
- window(1, 1, 80, 25);
-#endif
-
clrscr();
int itty = 0;
@@ -292,9 +283,6 @@ char in_a_shop( char shoppy, id_arr id )
shop_uninit_id(shoppy, shop_id);
invent(-1, false);
shop_init_id(shoppy, shop_id);
-#ifdef DOS_TERM
- window(1, 1, 80, 25);
-#endif
goto print_stock;
}
@@ -343,12 +331,6 @@ char in_a_shop( char shoppy, id_arr id )
shop_print("Goodbye!", 20);
more3();
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
- gotoxy(1, 1);
- cprintf(" ");
-#endif
-
shop_uninit_id( shoppy, shop_id );
activate_notes(true);
return 0;
diff --git a/crawl-ref/source/skills2.cc b/crawl-ref/source/skills2.cc
index 20347ca01d..810f8e6df7 100644
--- a/crawl-ref/source/skills2.cc
+++ b/crawl-ref/source/skills2.cc
@@ -1824,13 +1824,6 @@ void show_skills(void)
const int num_lines = get_number_of_lines();
-#ifdef DOS_TERM
- window(1, 1, 80, 25);
- char buffer[4600];
-
- gettext(1, 1, 80, 25, buffer);
-#endif
-
clrscr();
reprint_stuff:
@@ -1989,9 +1982,6 @@ void show_skills(void)
}
}
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
return;
}
diff --git a/crawl-ref/source/spl-book.cc b/crawl-ref/source/spl-book.cc
index ea39448bc3..b07cf9beb2 100644
--- a/crawl-ref/source/spl-book.cc
+++ b/crawl-ref/source/spl-book.cc
@@ -913,11 +913,6 @@ unsigned char spellbook_contents( item_def &book, int action,
if (update_screen)
{
cursor_control coff(false);
-#ifdef DOS_TERM
- char buffer[4800];
- gettext(1, 1, 80, 25, buffer);
- window(1, 1, 80, 25);
-#endif
clrscr();
out.display();
@@ -925,11 +920,6 @@ unsigned char spellbook_contents( item_def &book, int action,
keyn = getch();
if (keyn == 0)
getch();
-
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
- window(1, 18, 80, 25);
-#endif
}
return (keyn); // try to figure out that for which this is used {dlb}
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index 9391b81ab2..0b1ff598c1 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -92,16 +92,6 @@ char list_spells(void)
const int num_lines = get_number_of_lines();
cursor_control coff(false);
-#ifdef DOS_TERM
- char buffer[4800];
-
- gettext(1, 1, 80, 25, buffer);
-#endif
-
-#ifdef DOS_TERM
- window(1, 1, 80, 25);
-#endif
-
clrscr();
cprintf( " Your Spells Type Power Success Level" );
@@ -118,17 +108,11 @@ char list_spells(void)
if (ki == ESCAPE)
{
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
return (ESCAPE);
}
if (isalpha( ki ))
{
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
return (ki);
}
@@ -195,25 +179,15 @@ char list_spells(void)
if (ki >= 'A' && ki <= 'z')
{
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
return (ki);
}
if (ki == 0)
ki = getch();
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
-
return (anything);
}
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
// was 35
ki = getch();
diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc
index 75364a312d..0c492f03ee 100644
--- a/crawl-ref/source/stuff.cc
+++ b/crawl-ref/source/stuff.cc
@@ -62,13 +62,6 @@
#include "skills2.h"
#include "view.h"
-
-// required for stuff::coinflip() and cf_setseed()
-unsigned long cfseed;
-
-// unfortunately required for near_stairs(ugh!):
-extern unsigned char (*mapch) (unsigned char);
-
// Crude, but functional.
char *const make_time_string( time_t abs_time, char *const buff, int buff_size,
bool terse )
@@ -171,12 +164,8 @@ unsigned char get_ch(void)
void seed_rng(long seed)
{
-#ifdef USE_SYSTEM_RAND
- srand(seed);
-#else
// MT19937 -- see mt19937ar.cc for details/licence
init_genrand(seed);
-#endif
}
void seed_rng()
@@ -188,133 +177,8 @@ void seed_rng()
#endif
seed_rng(seed);
-#ifdef USE_SYSTEM_RAND
- cf_setseed();
-#endif
-}
-
-#ifdef USE_SYSTEM_RAND
-int random2(int max)
-{
-#ifdef USE_NEW_RANDOM
- //return (int) ((((float) max) * rand()) / RAND_MAX); - this is bad!
- // Uses FP, so is horribly slow on computers without coprocessors.
- // Taken from comp.lang.c FAQ. May have problems as max approaches
- // RAND_MAX, but this is rather unlikely.
- // We've used rand() rather than random() for the portability, I think.
-
- if (max < 1 || max >= RAND_MAX)
- return 0;
- else
- return (int) rand() / (RAND_MAX / max + 1);
-#else
-
- if (max < 1)
- return 0;
-
- return rand() % max;
-#endif
-}
-
-// required for stuff::coinflip()
-#define IB1 1
-#define IB2 2
-#define IB5 16
-#define IB18 131072
-#define MASK (IB1 + IB2 + IB5)
-// required for stuff::coinflip()
-
-// I got to thinking a bit more about how much people talk
-// about RNGs and RLs and also about the issue of performance
-// when it comes to Crawl's RNG ... turning to *Numerical
-// Recipies in C* (Chapter 7-4, page 298), I hit upon what
-// struck me as a fine solution.
-
-// You can read all the details about this function (pretty
-// much stolen shamelessly from NRinC) elsewhere, but having
-// tested it out myself I think it satisfies Crawl's incessant
-// need to decide things on a 50-50 flip of the coin. No call
-// to random2() required -- along with all that wonderful math
-// and type casting -- and only a single variable its pointer,
-// and some bitwise operations to randomly generate 1s and 0s!
-// No parameter passing, nothing. Too good to be true, but it
-// works as long as cfseed is not set to absolute zero when it
-// is initialized ... good for 2**n-1 random bits before the
-// pattern repeats (n = long's bitlength on your platform).
-// It also avoids problems with poor implementations of rand()
-// on some platforms in regards to low-order bits ... a big
-// problem if one is only looking for a 1 or a 0 with random2()!
-
-// Talk about a hard sell! Anyway, it returns bool, so please
-// use appropriately -- I set it to bool to prevent such
-// tomfoolery, as I think that pure RNG and quickly grabbing
-// either a value of 1 or 0 should be separated where possible
-// to lower overhead in Crawl ... at least until it assembles
-// itself into something a bit more orderly :P 16jan2000 {dlb}
-
-// NB(1): cfseed is defined atop stuff.cc
-// NB(2): IB(foo) and MASK are defined somewhere in defines.h
-// NB(3): the function assumes that cf_setseed() has been called
-// beforehand - the call is presently made in acr::initialise()
-// right after srandom() and srand() are called (note also
-// that cf_setseed() requires rand() - random2 returns int
-// but a long can't hurt there).
-bool coinflip(void)
-{
- extern unsigned long cfseed; // defined atop stuff.cc
- unsigned long *ptr_cfseed = &cfseed;
-
- if (*ptr_cfseed & IB18)
- {
- *ptr_cfseed = ((*ptr_cfseed ^ MASK) << 1) | IB1;
- return true;
- }
- else
- {
- *ptr_cfseed <<= 1;
- return false;
- }
-} // end coinflip()
-
-// cf_setseed should only be called but once in all of Crawl!!! {dlb}
-void cf_setseed(void)
-{
- extern unsigned long cfseed; // defined atop stuff.cc
- unsigned long *ptr_cfseed = &cfseed;
-
- do
- {
- // using rand() here makes these predictable -- bwr
- *ptr_cfseed = rand();
- }
- while (*ptr_cfseed == 0);
-}
-
-static std::stack<long> rng_states;
-void push_rng_state()
-{
- // XXX: Does this even work? randart.cc uses it, but I can't find anything
- // that says this will restore the RNG to its original state. Anyway, we're
- // now using MT with a deterministic push/pop.
- rng_states.push(rand());
}
-void pop_rng_state()
-{
- if (!rng_states.empty())
- {
- seed_rng(rng_states.top());
- rng_states.pop();
- }
-}
-
-unsigned long random_int( void )
-{
- return rand();
-}
-
-#else // USE_SYSTEM_RAND
-
// MT19937 -- see mt19937ar.cc for details
unsigned long random_int( void )
{
@@ -350,8 +214,6 @@ void pop_rng_state()
pop_mt_state();
}
-#endif // USE_SYSTEM_RAND
-
// Attempts to make missile weapons nicer to the player by
// reducing the extreme variance in damage done.
void scale_dice( dice_def &dice, int threshold )
@@ -508,7 +370,7 @@ void end(int exit_code, bool print_error, const char *format, ...)
error = std::string(buffer) + ": " + error;
}
- if (error.length())
+ if (!error.empty())
{
if (error[error.length() - 1] != '\n')
error += "\n";
@@ -520,9 +382,6 @@ void end(int exit_code, bool print_error, const char *format, ...)
void redraw_screen(void)
{
-#ifdef PLAIN_TERM
-// this function is used for systems without gettext/puttext to redraw the
-// playing screen after a call to for example inventory.
draw_border();
you.redraw_hit_points = 1;
@@ -536,7 +395,8 @@ void redraw_screen(void)
you.redraw_experience = 1;
you.wield_change = true;
- set_redraw_status( REDRAW_LINE_1_MASK | REDRAW_LINE_2_MASK | REDRAW_LINE_3_MASK );
+ set_redraw_status(
+ REDRAW_LINE_1_MASK | REDRAW_LINE_2_MASK | REDRAW_LINE_3_MASK );
print_stats();
@@ -550,7 +410,6 @@ void redraw_screen(void)
activate_notes(note_status);
viewwindow(1, false);
-#endif
} // end redraw_screen()
// STEPDOWN FUNCTION to replace conditional chains in spells2.cc 12jan2000 {dlb}
@@ -902,59 +761,6 @@ void random_in_bounds( int &x_pos, int &y_pos, int terr, bool empty, bool excl )
while (!done);
}
-// takes rectangle (x1,y1)-(x2,y2) and shifts it somewhere randomly in bounds
-void random_place_rectangle( int &x1, int &y1, int &x2, int &y2, bool excl )
-{
- const unsigned int dx = abs( x2 - x1 );
- const unsigned int dy = abs( y2 - y1 );
-
- x1 = X_BOUND_1 + random2( X_WIDTH - dx - 2 * excl ) + excl;
- y1 = Y_BOUND_1 + random2( Y_WIDTH - dy - 2 * excl ) + excl;
-
- x2 = x1 + dx;
- y2 = y1 + dy;
-}
-
-// returns true if point (px,py) is in rectangle (rx1, ry1) - (rx2, ry2)
-bool in_rectangle( int px, int py, int rx1, int ry1, int rx2, int ry2,
- bool excl )
-{
- ASSERT( rx1 < rx2 - 1 && ry1 < ry2 - 1 );
-
- if (excl)
- {
- rx1++;
- rx2--;
- ry1++;
- ry2--;
- }
-
- return (px >= rx1 && px <= rx2 && py >= ry1 && py <= ry2);
-}
-
-// XXX: this can be done better
-// returns true if rectables a and b overlap
-bool rectangles_overlap( int ax1, int ay1, int ax2, int ay2,
- int bx1, int by1, int bx2, int by2,
- bool excl )
-{
- ASSERT( ax1 < ax2 - 1 && ay1 < ay2 - 1 );
- ASSERT( bx1 < bx2 - 1 && by1 < by2 - 1 );
-
- if (excl)
- {
- ax1++;
- ax2--;
- ay1++;
- ay2--;
- }
-
- return (in_rectangle( ax1, ay1, bx1, by1, bx2, by2, excl )
- || in_rectangle( ax1, ay2, bx1, by1, bx2, by2, excl )
- || in_rectangle( ax2, ay1, bx1, by1, bx2, by2, excl )
- || in_rectangle( ax2, ay2, bx1, by1, bx2, by2, excl ));
-}
-
unsigned char random_colour(void)
{
return (1 + random2(15));
@@ -1256,9 +1062,8 @@ void zap_los_monsters()
continue;
#ifdef DEBUG_DIAGNOSTICS
- char mname[ITEMNAME_SIZE];
- moname(mon->type, true, DESC_PLAIN, mname);
- mprf(MSGCH_DIAGNOSTICS, "Dismissing %s", mname);
+ mprf(MSGCH_DIAGNOSTICS, "Dismissing %s",
+ ptr_monam(mon, DESC_PLAIN) );
#endif
monster_die(mon, KILL_DISMISSED, 0);
}
diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc
index 1807dca9d6..6e5de5d843 100644
--- a/crawl-ref/source/travel.cc
+++ b/crawl-ref/source/travel.cc
@@ -87,17 +87,16 @@ inline int sgn(int x)
// would have to travel to get there. Negative distances imply that the point
// is a) a trap or hostile terrain or b) only reachable by crossing a trap or
// hostile terrain.
-short point_distance[GXM][GYM];
+travel_distance_grid_t travel_point_distance;
-unsigned char curr_waypoints[GXM][GYM];
-
-signed char curr_traps[GXM][GYM];
+static unsigned char curr_waypoints[GXM][GYM];
+static signed char curr_traps[GXM][GYM];
static FixedArray< unsigned short, GXM, GYM > mapshadow;
-#define TRAVERSABLE 1
-#define IMPASSABLE 0
-#define FORBIDDEN -1
+const signed char TRAVERSABLE = 1;
+const signed char IMPASSABLE = 0;
+const signed char FORBIDDEN = -1;
// Map of terrain types that are traversable.
static signed char traversable_terrain[256];
@@ -165,8 +164,8 @@ bool is_altar(const coord_def &c)
inline bool is_player_altar(unsigned char grid)
{
// An ugly hack, but that's what religion.cc does.
- return you.religion
- && grid == DNGN_ALTAR_ZIN - 1 + you.religion;
+ return you.religion != GOD_NO_GOD
+ && grid_altar_god(grid) == you.religion;
}
inline bool is_player_altar(const coord_def &c)
@@ -255,25 +254,6 @@ static bool is_exclude_root(int x, int y)
return false;
}
-// Determines if the level is fully explored. Clobbers you.run_x/y.
-static bool fully_explored()
-{
- const int oldrun = you.running;
-
- if (!you.running.is_explore())
- you.running = RMODE_EXPLORE;
-
- // Do a second floodfill to check if the level is fully explored.
- // Note we're passing in a features vector to force find_travel_pos to
- // reseed past traps/deep water/lava. Icky.
-
- std::vector<coord_def> features_dummy;
- find_travel_pos(you.x_pos, you.y_pos, NULL, NULL, &features_dummy);
- you.running = oldrun;
-
- return !(you.running.x > 0 && you.running.y > 0);
-}
-
const char *run_mode_name(int runmode)
{
return runmode == RMODE_TRAVEL? "travel" :
@@ -372,7 +352,7 @@ void forget_square(int x, int y)
static bool is_reseedable(int x, int y)
{
if (is_excluded(x, y))
- return true;
+ return (true);
unsigned char grid = grd[x][y];
return (grid == DNGN_DEEP_WATER || grid == DNGN_SHALLOW_WATER ||
grid == DNGN_LAVA || is_trap(x, y));
@@ -385,11 +365,11 @@ static bool is_reseedable(int x, int y)
*/
static bool is_travel_ok(int x, int y, bool ignore_hostile)
{
- const int grid = grd[x][y];
-
if (!is_terrain_known(x, y))
return (false);
+ const int grid = grd[x][y];
+
// Special-case secret doors so that we don't run into awkwardness when
// a monster opens a secret door without the hero seeing it, but the travel
// code paths through the secret door because it looks at the actual grid,
@@ -413,14 +393,7 @@ static bool is_travel_ok(int x, int y, bool ignore_hostile)
if (player_monster_visible(&menv[mon])
&& mons_class_flag( menv[mon].type, M_NO_EXP_GAIN ))
{
- extern short point_distance[GXM][GYM];
-
- // We have to set the point_distance array if the level map is
- // to be properly coloured. The caller isn't going to do it because
- // we say this square is inaccessible, so in a horrible hack, we
- // do it ourselves. Ecch.
- point_distance[x][y] = ignore_hostile? -42 : 42;
- return false;
+ return (false);
}
}
@@ -486,16 +459,17 @@ static void set_pass_feature(unsigned char grid, signed char pass)
*/
static void init_terrain_check()
{
- // Merfolk get deep water.
- signed char water = you.species == SP_MERFOLK? TRAVERSABLE : IMPASSABLE;
+ // Swimmers get deep water.
+ signed char water = player_can_swim()? TRAVERSABLE : IMPASSABLE;
+
// If the player has overridden deep water already, we'll respect that.
set_pass_feature(DNGN_DEEP_WATER, water);
// Permanently levitating players can cross most hostile terrain.
signed char trav = player_is_permalevitating()?
TRAVERSABLE : IMPASSABLE;
- if (you.species != SP_MERFOLK)
- set_pass_feature(DNGN_DEEP_WATER, trav);
+
+ set_pass_feature(DNGN_DEEP_WATER, trav);
set_pass_feature(DNGN_LAVA, trav);
set_pass_feature(DNGN_TRAP_MECHANICAL, trav);
}
@@ -706,7 +680,7 @@ bool is_travelable_stair(unsigned gridc)
bool prompt_stop_explore(int es_why)
{
return (!(Options.explore_stop_prompt & es_why)
- || yesno("Stop exploring?", true, 'n', true, false));
+ || yesno("Stop exploring?", true, 'y', true, false));
}
#define ES_item (Options.explore_stop & ES_ITEM)
@@ -794,6 +768,79 @@ static bool is_valid_explore_target(int x, int y)
return (false);
}
+enum explore_status_type
+{
+ EST_FULLY_EXPLORED = 0,
+
+ // Could not explore because of hostile terrain
+ EST_PARTLY_EXPLORED = 1,
+
+ // Could not pick up interesting items because of hostile terrain. Note
+ // that this and EST_PARTLY_EXPLORED are not mutually exclusive.
+ EST_GREED_UNFULFILLED = 2
+};
+
+// Determines if the level is fully explored.
+static int find_explore_status(const travel_pathfind &tp)
+{
+ int explore_status = 0;
+
+ const coord_def greed = tp.greedy_square();
+ if (greed.x || greed.y)
+ explore_status |= EST_GREED_UNFULFILLED;
+
+ const coord_def unexplored = tp.unexplored_square();
+ if (unexplored.x || unexplored.y)
+ explore_status |= EST_PARTLY_EXPLORED;
+
+ return (explore_status);
+}
+
+static void explore_find_target_square()
+{
+ travel_pathfind tp;
+ tp.set_floodseed(coord_def(you.x_pos, you.y_pos), true);
+
+ coord_def whereto =
+ tp.pathfind( static_cast<run_mode_type>(you.running.runmode) );
+
+ if (whereto.x || whereto.y)
+ {
+ // Make sure this is a square that is reachable, since we asked
+ // travel_pathfind to give us even unreachable squares.
+ if (travel_point_distance[whereto.x][whereto.y] <= 0)
+ whereto.reset();
+ }
+
+ if (whereto.x || whereto.y)
+ {
+ you.running.x = whereto.x;
+ you.running.y = whereto.y;
+ }
+ else
+ {
+ // No place to go? Report to the player.
+ const int estatus = find_explore_status(tp);
+
+ if (!estatus)
+ mpr("Done exploring.");
+ else
+ {
+ std::vector<std::string> inacc;
+ if (estatus & EST_GREED_UNFULFILLED)
+ inacc.push_back("items");
+ if (estatus & EST_PARTLY_EXPLORED)
+ inacc.push_back("places");
+
+ mprf("Partly explored, can't reach some %s.",
+ comma_separated_line(
+ inacc.begin(),
+ inacc.end()).c_str());
+ }
+ stop_running();
+ }
+}
+
/*
* Top-level travel control (called from input() in acr.cc).
*
@@ -865,18 +912,7 @@ command_type travel()
|| (you.running.x == you.x_pos && you.running.y == you.y_pos)
|| !is_valid_explore_target(you.running.x, you.running.y))
{
- you.running.x = 0;
- find_travel_pos(you.x_pos, you.y_pos, NULL, NULL);
- // No place to go?
- if (!you.running.x)
- {
- // Do fully_explored() *before* stop_running!
- if (fully_explored())
- mpr("Done exploring.");
- else
- mpr("Partly explored, some areas are inaccessible.");
- stop_running();
- }
+ explore_find_target_square();
}
}
@@ -1028,335 +1064,460 @@ static void fill_exclude_radius(const coord_def &c)
for (int x = c.x - radius; x <= c.x + radius; ++x)
{
if (!map_bounds(x, y) || !is_terrain_known(x, y)
- || point_distance[x][y])
+ || travel_point_distance[x][y])
continue;
if (is_exclude_root(x, y))
- point_distance[x][y] = PD_EXCLUDED;
+ travel_point_distance[x][y] = PD_EXCLUDED;
else if (is_excluded(x, y))
- point_distance[x][y] = PD_EXCLUDED_RADIUS;
+ travel_point_distance[x][y] = PD_EXCLUDED_RADIUS;
}
}
}
-static bool is_greed_inducing_square(const LevelStashes *ls, int x, int y)
+/////////////////////////////////////////////////////////////////////////////
+// travel_pathfind
+
+FixedVector<coord_def, GXM * GYM> travel_pathfind::circumference[2];
+
+const int travel_pathfind::UNFOUND_DIST;
+const int travel_pathfind::INFINITE_DIST;
+
+travel_pathfind::travel_pathfind()
+ : runmode(RMODE_NOT_RUNNING), start(), dest(), next_travel_move(),
+ floodout(false), double_flood(false), ignore_hostile(false),
+ annotate_map(false), ls(NULL), need_for_greed(false),
+ unexplored_place(), greedy_place(), unexplored_dist(0),
+ greedy_dist(0), refdist(NULL), reseed_points(),
+ features(NULL), point_distance(travel_point_distance),
+ points(0), next_iter_points(0), traveled_distance(0),
+ circ_index(0)
{
- return (ls && ls->needs_visit(x, y));
}
-/*
- * The travel algorithm is based on the NetHack travel code written by Warwick
- * Allison - used with his permission.
- */
-void find_travel_pos(int youx, int youy,
- char *move_x, char *move_y,
- std::vector<coord_def>* features)
+bool travel_pathfind::is_greed_inducing_square(const coord_def &c) const
{
- init_terrain_check();
+ return (ls && ls->needs_visit(c.x, c.y));
+}
- int start_x = you.running.x, start_y = you.running.y;
- int dest_x = youx, dest_y = youy;
- bool floodout = false;
- unsigned char feature;
- const LevelStashes *lev = stashes.find_current_level();
- const bool need_for_greed =
- you.running == RMODE_EXPLORE_GREEDY && can_autopickup();
+void travel_pathfind::set_src_dst(const coord_def &src, const coord_def &dst)
+{
+ // Yes, this is backwards - for travel, we always start from the destination
+ // and search outwards for the starting position.
+ start = dst;
+ dest = src;
- // For greedy explore, keep track of the closest unexplored
- // territory and the closest greedy square.
- int e_x = 0, e_y = 0; // Unexplored
- int i_x = 0, i_y = 0; // Square with interesting item.
- // Use these weird defaults to handle negative item greeds.
- int ex_dist = -10000, ix_dist = -10000;
+ floodout = double_flood = false;
+}
- // Normally we start from the destination and floodfill outwards, looking
- // for the character's current position. If we're merely trying to populate
- // the point_distance array (or exploring), we'll want to start from the
- // character's current position and fill outwards
- if (!move_x || !move_y)
- {
- start_x = youx;
- start_y = youy;
+void travel_pathfind::set_floodseed(const coord_def &seed, bool dblflood)
+{
+ start = seed;
+ dest.reset();
- dest_x = dest_y = -1;
+ floodout = true;
+ double_flood = dblflood;
+}
- floodout = true;
- }
+void travel_pathfind::set_annotate_map(bool annotate)
+{
+ annotate_map = annotate;
+}
+
+void travel_pathfind::set_distance_grid(travel_distance_grid_t grid)
+{
+ point_distance = grid;
+}
+
+void travel_pathfind::set_feature_vector(std::vector<coord_def> *feats)
+{
+ features = feats;
- // Abort run if we're trying to go someplace evil
- if (dest_x != -1 && !is_travel_ok(start_x, start_y, false) &&
- !is_trap(start_x, start_y))
+ if (features)
{
- you.running = RMODE_NOT_RUNNING;
- return ;
+ double_flood = true;
+ annotate_map = true;
}
+}
+
+const coord_def travel_pathfind::travel_move() const
+{
+ return (next_travel_move);
+}
+
+const coord_def travel_pathfind::explore_target() const
+{
+ if (unexplored_dist != UNFOUND_DIST && greedy_dist != UNFOUND_DIST)
+ return (unexplored_dist < greedy_dist? unexplored_place : greedy_place);
+ else if (unexplored_dist != UNFOUND_DIST)
+ return (unexplored_place);
+ else if (greedy_dist != UNFOUND_DIST)
+ return (greedy_place);
+
+ return coord_def(0, 0);
+}
+
+const coord_def travel_pathfind::greedy_square() const
+{
+ return (greedy_place);
+}
+
+const coord_def travel_pathfind::unexplored_square() const
+{
+ return (unexplored_place);
+}
+
+/*
+ * The travel algorithm is based on the NetHack travel code written by Warwick
+ * Allison - used with his permission.
+ */
+const coord_def travel_pathfind::pathfind(run_mode_type rmode)
+{
+ if (rmode == RMODE_INTERLEVEL)
+ rmode = RMODE_TRAVEL;
+
+ runmode = rmode;
+
+ // Check whether species or levitation permits travel through terrain such
+ // as deep water.
+ init_terrain_check();
- // Abort run if we're going nowhere.
- if (start_x == dest_x && start_y == dest_y)
+ need_for_greed =
+ (rmode == RMODE_EXPLORE_GREEDY && can_autopickup());
+
+ if (!ls && (annotate_map || need_for_greed))
+ ls = stashes.find_current_level();
+
+ next_travel_move.reset();
+
+ // For greedy explore, keep track of the closest unexplored territory and
+ // the closest greedy square. Exploring to the nearest (unexplored / greedy)
+ // square is easier, but it produces unintuitive explore behaviour where
+ // grabbing items is not favoured over simple exploring.
+ //
+ // Greedy explore instead uses the explore_item_greed option to weight
+ // greedy explore towards grabbing items over exploring. An
+ // explore_item_greed set to 10, for instance, forces explore to prefer
+ // items that are less than 10 squares farther away from the player than the
+ // nearest unmapped square. Negative explore_item_greed values force greedy
+ // explore to favour unexplored territory over picking up items. For the
+ // most natural greedy explore behaviour, explore_item_greed should be set
+ // to 10 or more.
+ //
+ unexplored_place = greedy_place = coord_def(0, 0);
+ unexplored_dist = greedy_dist = UNFOUND_DIST;
+
+ refdist = Options.explore_item_greed > 0? &unexplored_dist: &greedy_dist;
+
+ // Abort run if we're trying to go someplace evil. Travel to traps is
+ // specifically allowed here if the player insists on it.
+ if (!floodout
+ && !is_travel_ok(start.x, start.y, false)
+ && !is_trap(start.x, start.y)) // The player likes pain
{
- you.running = RMODE_NOT_RUNNING;
- return ;
+ return coord_def(0, 0);
}
+ // Nothing to do?
+ if (!floodout && start == dest)
+ return (start);
+
// How many points are we currently considering? We start off with just one
// point, and spread outwards like a flood-filler.
- int points = 1;
+ points = 1;
// How many points we'll consider next iteration.
- int next_iter_points = 0;
+ next_iter_points = 0;
// How far we've traveled from (start_x, start_y), in moves (a diagonal move
// is no longer than an orthogonal move).
- int traveled_distance = 1;
+ traveled_distance = 1;
// Which index of the circumference array are we currently looking at?
- int circ_index = 0;
-
- // The circumference points of the floodfilled area, for this iteration
- // and the next (this iteration's points being circ_index amd the next one's
- // being !circ_index).
- static FixedVector<coord_def, GXM * GYM> circumference[2];
-
- // Coordinates of all discovered traps. If we're exploring instead of
- // travelling, we'll reseed from these points after we've explored the map
- std::vector<coord_def> trap_seeds;
-
- // When set to true, the travel code ignores features, traps and hostile
- // terrain, and simply tries to map contiguous floorspace. Will only be set
- // to true if we're exploring, instead of travelling.
- bool ignore_hostile = false;
+ circ_index = 0;
+
+ ignore_hostile = false;
// Set the seed point
- circumference[circ_index][0].x = start_x;
- circumference[circ_index][0].y = start_y;
+ circumference[circ_index][0] = start;
// Zap out previous distances array
- memset(point_distance, 0, sizeof point_distance);
+ memset(point_distance, 0, sizeof(travel_distance_grid_t));
for ( ; points > 0; ++traveled_distance, circ_index = !circ_index,
points = next_iter_points, next_iter_points = 0)
{
for (int i = 0; i < points; ++i)
{
- int x = circumference[circ_index][i].x,
- y = circumference[circ_index][i].y;
-
- // (x,y) is a known (explored) location - we never put unknown
- // points in the circumference vector, so we don't need to examine
- // the map array, just the grid array.
- feature = grd[x][y];
-
- // If this is a feature that'll take time to travel past, we
- // simulate that extra turn by taking this feature next turn,
- // thereby artificially increasing traveled_distance.
- //
- // Note: I don't know how slow walking through shallow water and
- // opening closed doors is - right now it's considered to have
- // the cost of two normal moves.
- int feat_cost = feature_traverse_cost(feature);
- if (feat_cost > 1
- && point_distance[x][y] > traveled_distance - feat_cost)
+ if (path_examine_point(circumference[circ_index][i]))
{
- circumference[!circ_index][next_iter_points].x = x;
- circumference[!circ_index][next_iter_points].y = y;
- next_iter_points++;
- continue;
+ return (runmode == RMODE_TRAVEL? travel_move()
+ : explore_target());
}
+ }
- // For each point, we look at all surrounding points. Take them
- // orthogonals first so that the travel path doesn't zigzag all over
- // the map. Note the (dir = 1) is intentional assignment.
- for (int dir = 0; dir < 8; (dir += 2) == 8 && (dir = 1))
+ if (next_iter_points == 0)
+ {
+ // Don't reseed unless we've found no target for explore, OR
+ // we're doing map annotation or feature tracking.
+ if ((runmode == RMODE_EXPLORE || runmode == RMODE_EXPLORE_GREEDY)
+ && double_flood
+ && !ignore_hostile
+ && !features
+ && !annotate_map
+ && (unexplored_dist != UNFOUND_DIST
+ || greedy_dist != UNFOUND_DIST))
{
- int dx = x + Compass[dir].x, dy = y + Compass[dir].y;
+ break;
+ }
- if (!in_bounds(dx, dy))
- continue;
+ if (double_flood
+ && !ignore_hostile
+ && !reseed_points.empty())
+ {
+ // Reseed here
+ for (unsigned i = 0, size = reseed_points.size(); i < size; ++i)
+ circumference[!circ_index][i] = reseed_points[i];
+ next_iter_points = reseed_points.size();
+ ignore_hostile = true;
+ }
+ }
+ } // for ( ; points > 0 ...
- unsigned char envf = env.map[dx - 1][dy - 1];
+ if (features && floodout)
+ {
+ for (int i = 0, size = curr_excludes.size(); i < size; ++i)
+ {
+ const coord_def &exc = curr_excludes[i];
+ // An exclude - wherever it is - is always a feature.
+ if (std::find(features->begin(), features->end(), exc)
+ == features->end())
+ features->push_back(exc);
- if (floodout && you.running.is_explore())
- {
- if (!is_player_mapped(envf))
- {
- if (!need_for_greed)
- {
- you.running.x = x;
- you.running.y = y;
- return;
- }
-
- if (ex_dist == -10000)
- {
- e_x = x;
- e_y = y;
- ex_dist =
- traveled_distance + Options.explore_item_greed;
- }
- }
- else if (need_for_greed
- && ix_dist == -10000
- && is_greed_inducing_square(lev, dx, dy)
- && is_travel_ok(dx, dy, ignore_hostile))
- {
- i_x = dx;
- i_y = dy;
- ix_dist = traveled_distance + 1;
- }
+ fill_exclude_radius(exc);
+ }
+ }
- // Short-circuit if we can.
- if (need_for_greed)
- {
- const int refdist =
- Options.explore_item_greed > 0? ex_dist: ix_dist;
-
- if (refdist != -10000
- && traveled_distance > refdist)
- {
- if (Options.explore_item_greed > 0)
- ix_dist = 10000;
- else
- ex_dist = 10000;
- }
- }
-
- // ex_dist/ix_dist are only ever set in
- // greedy-explore so this check implies
- // greedy-explore.
- if (ex_dist != -10000 && ix_dist != -10000)
- {
- if (ex_dist < ix_dist)
- {
- you.running.x = e_x;
- you.running.y = e_y;
- }
- else
- {
- you.running.x = i_x;
- you.running.y = i_y;
- }
- return;
- }
-
- }
+ return (rmode == RMODE_TRAVEL? travel_move()
+ : explore_target());
+}
- if ((dx != dest_x || dy != dest_y)
- && !is_travel_ok(dx, dy, ignore_hostile))
- {
- // This point is not okay to travel on, but if this is a
- // trap, we'll want to put it on the feature vector anyway.
- if (is_reseedable(dx, dy)
- && !point_distance[dx][dy]
- && (dx != start_x || dy != start_y))
- {
- if (features)
- {
- const coord_def c(dx, dy);
- if (is_trap(dx, dy) || is_exclude_root(dx, dy))
- features->push_back(c);
- trap_seeds.push_back(c);
- }
-
- // Appropriate mystic number. Nobody else should check
- // this number, since this square is unsafe for travel.
- point_distance[dx][dy] =
- is_exclude_root(dx, dy)? PD_EXCLUDED :
- is_excluded(dx, dy) ? PD_EXCLUDED_RADIUS :
- PD_TRAP;
- }
- continue;
- }
+bool travel_pathfind::square_slows_movement(const coord_def &c)
+{
+ // c is a known (explored) location - we never put unknown points in the
+ // circumference vector, so we don't need to examine the map array, just the
+ // grid array.
+ const int feature = grd(c);
- if (dx == dest_x && dy == dest_y)
- {
- // Hallelujah, we're home!
- if (is_safe_move(x, y) && move_x && move_y)
- {
- *move_x = sgn(x - dest_x);
- *move_y = sgn(y - dest_y);
- }
- return ;
- }
- else if (!point_distance[dx][dy])
- {
- // This point is going to be on the agenda for the next
- // iteration
- circumference[!circ_index][next_iter_points].x = dx;
- circumference[!circ_index][next_iter_points].y = dy;
- next_iter_points++;
+ // If this is a feature that'll take time to travel past, we simulate that
+ // extra turn by taking this feature next turn, thereby artificially
+ // increasing traveled_distance.
+ //
+ // Walking through shallow water and opening closed doors is considered to
+ // have the cost of two normal moves for travel purposes.
+ const int feat_cost = feature_traverse_cost(feature);
+ if (feat_cost > 1
+ && point_distance[c.x][c.y] > traveled_distance - feat_cost)
+ {
+ circumference[!circ_index][next_iter_points++] = c;
+ return (true);
+ }
- point_distance[dx][dy] = traveled_distance;
+ return (false);
+}
- // Negative distances here so that show_map can colour
- // the map differently for these squares.
- if (ignore_hostile)
- {
- point_distance[dx][dy] = -point_distance[dx][dy];
- if (is_exclude_root(dx, dy))
- point_distance[dx][dy] = PD_EXCLUDED;
- else if (is_excluded(dx, dy))
- point_distance[dx][dy] = PD_EXCLUDED_RADIUS;
- }
+void travel_pathfind::check_square_greed(const coord_def &c)
+{
+ if (greedy_dist == UNFOUND_DIST
+ && is_greed_inducing_square(c)
+ && is_travel_ok(c.x, c.y, ignore_hostile))
+ {
+ greedy_place = c;
+ greedy_dist = traveled_distance;
+ }
+}
- feature = grd[dx][dy];
- if (features && !ignore_hostile
- && ((feature != DNGN_FLOOR
- && feature != DNGN_SHALLOW_WATER
- && feature != DNGN_DEEP_WATER
- && feature != DNGN_LAVA)
- || is_waypoint(dx, dy)
- || is_stash(lev, dx, dy))
- && (dx != start_x || dy != start_y))
- {
- const coord_def c(dx, dy);
- features->push_back(c);
- }
+bool travel_pathfind::path_flood(const coord_def &c, const coord_def &dc)
+{
+ if (!in_bounds(dc))
+ return (false);
- if (features && is_exclude_root(dx, dy) && dx != start_x
- && dy != start_y)
- {
- const coord_def c(dx, dy);
- features->push_back(c);
- }
- }
- } // for (dir = 0; dir < 8 ...
- } // for (i = 0; i < points ...
+ if (floodout
+ && (runmode == RMODE_EXPLORE || runmode == RMODE_EXPLORE_GREEDY))
+ {
+ if (!is_terrain_seen(dc))
+ {
+ if (!need_for_greed)
+ {
+ // Found explore target!
+ unexplored_place = c;
+ unexplored_dist = traveled_distance;
+ return (true);
+ }
+
+ if (unexplored_dist == UNFOUND_DIST)
+ {
+ unexplored_place = c;
+ unexplored_dist =
+ traveled_distance + Options.explore_item_greed;
+ }
+ }
- if (!next_iter_points && features && !move_x && !ignore_hostile
- && trap_seeds.size())
+ // Short-circuit if we can. If traveled_distance (the current
+ // distance from the center of the floodfill) is greater
+ // than the adjusted distance to the nearest greedy explore
+ // target, we have a target. Note the adjusted distance is
+ // the distance with explore_item_greed applied (if
+ // explore_item_greed > 0, it is added to the distance to
+ // unexplored terrain, if explore_item_greed < 0, it is
+ // added to the distance to interesting items.
+ //
+ // We never short-circuit if ignore_hostile is true. This is
+ // important so we don't need to do multiple floods to work out
+ // whether explore is complete.
+ if (need_for_greed
+ && !ignore_hostile
+ && *refdist != UNFOUND_DIST
+ && traveled_distance > *refdist)
{
- // Reseed here
- for (unsigned i = 0; i < trap_seeds.size(); ++i)
- circumference[!circ_index][i] = trap_seeds[i];
- next_iter_points = trap_seeds.size();
- ignore_hostile = true;
+ if (Options.explore_item_greed > 0)
+ greedy_dist = INFINITE_DIST;
+ else
+ unexplored_dist = INFINITE_DIST;
}
- } // for ( ; points > 0 ...
+
+ // greedy_dist is only ever set in greedy-explore so this check
+ // implies greedy-explore.
+ if (unexplored_dist != UNFOUND_DIST && greedy_dist != UNFOUND_DIST)
+ return (true);
+ }
- if (features && floodout)
+ if (dc != dest && !is_travel_ok(dc.x, dc.y, ignore_hostile))
{
- for (int i = 0, size = curr_excludes.size(); i < size; ++i)
+ // This point is not okay to travel on, but if this is a
+ // trap, we'll want to put it on the feature vector anyway.
+ if (is_reseedable(dc.x, dc.y)
+ && !point_distance[dc.x][dc.y]
+ && dc != start)
{
- const coord_def &exc = curr_excludes[i];
- // An exclude - wherever it is - is always a feature.
- if (std::find(features->begin(), features->end(), exc)
- == features->end())
- features->push_back(exc);
+ if (features &&
+ (is_trap(dc.x, dc.y) || is_exclude_root(dc.x, dc.y)))
+ {
+ features->push_back(dc);
+ }
- fill_exclude_radius(exc);
+ if (double_flood)
+ reseed_points.push_back(dc);
+
+ // Appropriate mystic number. Nobody else should check
+ // this number, since this square is unsafe for travel.
+ point_distance[dc.x][dc.y] =
+ is_exclude_root(dc.x, dc.y)? PD_EXCLUDED :
+ is_excluded(dc.x, dc.y) ? PD_EXCLUDED_RADIUS :
+ PD_TRAP;
}
+ return (false);
}
- if (need_for_greed && (ex_dist != -10000 || ix_dist != -10000))
+ if (dc == dest)
+ {
+ // Hallelujah, we're home!
+ if (is_safe_move(c.x, c.y))
+ next_travel_move = c;
+ return (true);
+ }
+ else if (!point_distance[dc.x][dc.y])
{
- if (ix_dist != -10000)
+ // This point is going to be on the agenda for the next
+ // iteration
+ circumference[!circ_index][next_iter_points++] = dc;
+ point_distance[dc.x][dc.y] = traveled_distance;
+
+ // Negative distances here so that show_map can colour
+ // the map differently for these squares.
+ if (ignore_hostile)
{
- e_x = i_x;
- e_y = i_y;
+ point_distance[dc.x][dc.y] = -point_distance[dc.x][dc.y];
+ if (is_exclude_root(dc.x, dc.y))
+ point_distance[dc.x][dc.y] = PD_EXCLUDED;
+ else if (is_excluded(dc.x, dc.y))
+ point_distance[dc.x][dc.y] = PD_EXCLUDED_RADIUS;
}
- you.running.x = e_x;
- you.running.y = e_y;
+ if (features && !ignore_hostile)
+ {
+ const int feature = grd(dc);
+
+ if (((feature != DNGN_FLOOR
+ && feature != DNGN_SHALLOW_WATER
+ && feature != DNGN_DEEP_WATER
+ && feature != DNGN_LAVA)
+ || is_waypoint(dc.x, dc.y)
+ || is_stash(ls, dc.x, dc.y))
+ && dc != start)
+ {
+ features->push_back(dc);
+ }
+ }
+
+ if (features && dc != start && is_exclude_root(dc.x, dc.y))
+ features->push_back(dc);
+ }
+
+ return (false);
+}
+
+bool travel_pathfind::path_examine_point(const coord_def &c)
+{
+ if (square_slows_movement(c))
+ return (false);
+
+ // Greedy explore check should happen on (x,y), not (dx,dy) as for
+ // regular explore.
+ if (need_for_greed)
+ check_square_greed(c);
+
+ // For each point, we look at all surrounding points. Take them orthogonals
+ // first so that the travel path doesn't zigzag all over the map. Note the
+ // (dir = 1) is intentional assignment.
+ for (int dir = 0; dir < 8; (dir += 2) == 8 && (dir = 1))
+ {
+ if (path_flood(c, c + Compass[dir]))
+ return (true);
+ }
+
+ return (false);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void find_travel_pos(int youx, int youy,
+ char *move_x, char *move_y,
+ std::vector<coord_def>* features)
+{
+ travel_pathfind tp;
+
+ if (move_x && move_y)
+ tp.set_src_dst(coord_def(youx, youy),
+ coord_def(you.running.x, you.running.y));
+ else
+ tp.set_floodseed(coord_def(youx, youy));
+
+ tp.set_feature_vector(features);
+
+ run_mode_type rmode = move_x && move_y? RMODE_TRAVEL : RMODE_NOT_RUNNING;
+
+ const coord_def dest = tp.pathfind( rmode );
+
+ if (dest.x == 0 && dest.y == 0)
+ {
+ if (move_x && move_y)
+ you.running = RMODE_NOT_RUNNING;
+ }
+ else if (move_x && move_y)
+ {
+ *move_x = dest.x - youx;
+ *move_y = dest.y - youy;
}
}
@@ -1915,8 +2076,9 @@ static int target_distance_from(const coord_def &pos)
* travel-safe path between the player's current level and the target level OR
* the player's current level *is* the target level.
*
- * This function relies on the point_distance array being correctly populated
- * with a floodout call to find_travel_pos starting from the player's location.
+ * This function relies on the travel_point_distance array being correctly
+ * populated with a floodout call to find_travel_pos starting from the player's
+ * location.
*/
static int find_transtravel_stair( const level_id &cur,
const level_pos &target,
@@ -1958,8 +2120,8 @@ static int find_transtravel_stair( const level_id &cur,
// populate_stair_distances. Assuming we're not on stairs, that
// situation can arise only if interlevel travel has been triggered
// for a location on the same level. If that's the case, we can get
- // the distance off the point_distance matrix.
- deltadist = point_distance[target.pos.x][target.pos.y];
+ // the distance off the travel_point_distance matrix.
+ deltadist = travel_point_distance[target.pos.x][target.pos.y];
if (!deltadist &&
(stair.x != target.pos.x || stair.y != target.pos.y))
deltadist = -1;
@@ -2012,7 +2174,7 @@ static int find_transtravel_stair( const level_id &cur,
int deltadist = li.distance_between(this_stair, &si);
if (!this_stair)
{
- deltadist = point_distance[si.position.x][si.position.y];
+ deltadist = travel_point_distance[si.position.x][si.position.y];
if (!deltadist &&
(you.x_pos != si.position.x || you.y_pos != si.position.y))
deltadist = -1;
@@ -2128,7 +2290,7 @@ static bool loadlev_populate_stair_distances(const level_pos &target)
static void populate_stair_distances(const level_pos &target)
{
- // Populate point_distance.
+ // Populate travel_point_distance.
find_travel_pos(target.pos.x, target.pos.y, NULL, NULL, NULL);
LevelInfo &li = travel_cache.get_level_info(target.id);
@@ -2138,7 +2300,7 @@ static void populate_stair_distances(const level_pos &target)
for (int i = 0, count = stairs.size(); i < count; ++i)
{
stair_info si = stairs[i];
- si.distance = point_distance[si.position.x][si.position.y];
+ si.distance = travel_point_distance[si.position.x][si.position.y];
if (!si.distance && target.pos != si.position)
si.distance = -1;
if (si.distance < -1)
@@ -2200,8 +2362,8 @@ void start_travel(int x, int y)
// Start running
you.running = RMODE_TRAVEL;
- you.running.x = x;
- you.running.y = y;
+ you.running.x = x;
+ you.running.y = y;
// Remember where we're going so we can easily go back if interrupted.
you.travel_x = x;
@@ -2210,7 +2372,7 @@ void start_travel(int x, int y)
// Check whether we can get to the square.
find_travel_pos(you.x_pos, you.y_pos, NULL, NULL, NULL);
- if (point_distance[x][y] == 0
+ if (travel_point_distance[x][y] == 0
&& (x != you.x_pos || you.running.y != you.y_pos)
&& is_travel_ok(x, y, false)
&& can_travel_interlevel())
@@ -2462,7 +2624,7 @@ void LevelInfo::update_stair_distances()
{
int ox = stairs[other].position.x,
oy = stairs[other].position.y;
- int dist = point_distance[ox][oy];
+ int dist = travel_point_distance[ox][oy];
// Note dist == 0 is illegal because we can't have two stairs on
// the same square.
@@ -3225,7 +3387,9 @@ void explore_discoveries::found_feature(const coord_def &pos, int grid)
cleaned_feature_description(grid), grid ) );
es_flags |= ES_STAIR;
}
- else if (is_altar(grid) && ES_altar)
+ else if (is_altar(grid)
+ && ES_altar
+ && !player_in_branch(BRANCH_ECUMENICAL_TEMPLE))
{
altars.push_back(
named_thing<int>(
@@ -3290,9 +3454,9 @@ bool explore_discoveries::prompt_stop() const
return (false);
say_any(items, "Found %u items.");
- say_any(stairs, "Found %u stairs.");
- say_any(altars, "Found %u altars.");
say_any(shops, "Found %u shops.");
+ say_any(altars, "Found %u altars.");
+ say_any(stairs, "Found %u stairs.");
return ((Options.explore_stop_prompt & es_flags) != es_flags
|| prompt_stop_explore(es_flags));
diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h
index 010d8cd626..6493e37209 100644
--- a/crawl-ref/source/travel.h
+++ b/crawl-ref/source/travel.h
@@ -71,19 +71,26 @@ void prevent_travel_to(const std::string &dungeon_feature_name);
// Sort dungeon features as appropriate.
void arrange_features(std::vector<coord_def> &features);
+struct level_id;
+int level_distance(level_id first, level_id second);
+
+bool can_travel_to(const level_id &lid);
+bool can_travel_interlevel();
+bool prompt_stop_explore(int es_why);
+
// Magic numbers for point_distance:
// This square is a trap
-#define PD_TRAP -42
+const int PD_TRAP = -42;
// The user never wants to travel this square
-#define PD_EXCLUDED -20099
+const int PD_EXCLUDED = -20099;
// This square is within LOS radius of an excluded square
-#define PD_EXCLUDED_RADIUS -20100
+const int PD_EXCLUDED_RADIUS = -20100;
-// This square is a waypoint
-#define PD_WAYPOINT -20200
+typedef int travel_distance_col[GYM];
+typedef travel_distance_col travel_distance_grid_t[GXM];
/* ***********************************************************************
* Array of points on the map, each value being the distance the character
@@ -93,7 +100,7 @@ void arrange_features(std::vector<coord_def> &features);
* ***********************************************************************
* referenced in: travel - view
* *********************************************************************** */
-extern short point_distance[GXM][GYM];
+extern travel_distance_grid_t travel_point_distance;
enum explore_stop_type
{
@@ -345,7 +352,7 @@ private:
friend class TravelCache;
};
-#define TRAVEL_WAYPOINT_COUNT 10
+const int TRAVEL_WAYPOINT_COUNT = 10;
// Tracks all levels that the player has seen.
class TravelCache
{
@@ -408,11 +415,127 @@ private:
level_pos waypoints[TRAVEL_WAYPOINT_COUNT];
};
-int level_distance(level_id first, level_id second);
+// Handles travel and explore floodfill pathfinding. Does not do interlevel
+// travel pathfinding directly (but is used internally by interlevel travel).
+// * All coordinates are grid coords.
+// * Do not reuse one travel_pathfind for different runmodes.
+class travel_pathfind
+{
+public:
+ travel_pathfind();
-bool can_travel_to(const level_id &lid);
-bool can_travel_interlevel();
-bool prompt_stop_explore(int es_why);
+ // Finds travel direction or explore target.
+ const coord_def pathfind(run_mode_type rt);
+
+ // For flood-fills (explore), sets starting (seed) square.
+ void set_floodseed(const coord_def &seed, bool double_flood = false);
+
+ // For regular travel, set starting point (usually the character's current
+ // position) and destination.
+ void set_src_dst(const coord_def &src, const coord_def &dst);
+
+ // Request that the point distance array be annotated with magic numbers for
+ // excludes and waypoints.
+ void set_annotate_map(bool annotate);
+
+ // Sets the travel_distance_grid_t to use instead of travel_point_distance.
+ void set_distance_grid(travel_distance_grid_t distgrid);
+
+ // Set feature vector to use; if non-NULL, also sets annotate_map to true.
+ void set_feature_vector(std::vector<coord_def> *features);
+
+ // The next square to go to to move towards the travel destination. Return
+ // value is undefined if pathfind was not called with RMODE_TRAVEL.
+ const coord_def travel_move() const;
+
+ // Square to go to for (greedy) explore. Return value is undefined if
+ // pathfind was not called with RMODE_EXPLORE or RMODE_EXPLORE_GREEDY.
+ const coord_def explore_target() const;
+
+ // Nearest greed-inducing square. Return value is undefined if
+ // pathfind was not called with RMODE_EXPLORE_GREEDY.
+ const coord_def greedy_square() const;
+
+ // Nearest unexplored territory. Return value is undefined if
+ // pathfind was not called with RMODE_EXPLORE or
+ // RMODE_EXPLORE_GREEDY.
+ const coord_def unexplored_square() const;
+
+private:
+ bool is_greed_inducing_square(const coord_def &c) const;
+ bool path_examine_point(const coord_def &c);
+ bool path_flood(const coord_def &c, const coord_def &dc);
+ bool square_slows_movement(const coord_def &c);
+ void check_square_greed(const coord_def &c);
+
+private:
+ static const int UNFOUND_DIST = -10000;
+ static const int INFINITE_DIST = 10000;
+
+private:
+ run_mode_type runmode;
+
+ // Where pathfinding starts, and the destination. Note that dest is not
+ // relevant for explore!
+ coord_def start, dest;
+
+ // This is the square adjacent to the starting position to move
+ // along the shortest path to the destination. Does *not* apply
+ // for explore!
+ coord_def next_travel_move;
+
+ // True if flooding outwards from start square for explore.
+ bool floodout, double_flood;
+
+ // Set true in the second part of a double floodfill to completely ignore
+ // hostile squares.
+ bool ignore_hostile;
+
+ // If true, use magic numbers in point distance array which can be
+ // used to colour the level-map.
+ bool annotate_map;
+
+ // Stashes on this level (needed for greedy explore and to populate the
+ // feature vector with stashes on the X level-map).
+ const LevelStashes *ls;
+
+ // Are we greedy exploring?
+ bool need_for_greed;
+
+ // Targets for explore and greedy explore.
+ coord_def unexplored_place, greedy_place;
+
+ // How far from player's location unexplored_place and greedy_place are.
+ int unexplored_dist, greedy_dist;
+
+ const int *refdist;
+
+ // For double-floods, the points to restart floodfill from at the end of
+ // the first flood.
+ std::vector<coord_def> reseed_points;
+
+ std::vector<coord_def> *features;
+
+ travel_distance_col *point_distance;
+
+ // How many points are we currently considering? We start off with just one
+ // point, and spread outwards like a flood-filler.
+ int points;
+
+ // How many points we'll consider next iteration.
+ int next_iter_points;
+
+ // How far we've traveled from (start_x, start_y), in moves (a diagonal move
+ // is no longer than an orthogonal move).
+ int traveled_distance;
+
+ // Which index of the circumference array are we currently looking at?
+ int circ_index;
+
+ // Used by all instances of travel_pathfind. Happily, we do not need to be
+ // re-entrant or thread-safe.
+ static FixedVector<coord_def, GXM * GYM> circumference[2];
+};
extern TravelCache travel_cache;
diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc
index d6c4820850..9802222118 100644
--- a/crawl-ref/source/view.cc
+++ b/crawl-ref/source/view.cc
@@ -70,13 +70,7 @@
static FixedVector<feature_def, NUM_FEATURES> Feature;
-#if defined(DOS_TERM)
-// DOS functions like gettext() and puttext() can only
-// work with arrays of characters, not shorts.
-typedef unsigned char screen_buffer_t;
-#else
typedef unsigned short screen_buffer_t;
-#endif
FixedArray < unsigned int, 20, 19 > Show_Backup;
@@ -240,7 +234,7 @@ void clear_envmap( void )
}
}
-#if defined(WIN32CONSOLE) || defined(DOS) || defined(DOS_TERM)
+#if defined(WIN32CONSOLE) || defined(DOS)
static unsigned colflag2brand(int colflag)
{
switch (colflag)
@@ -264,7 +258,7 @@ static unsigned fix_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.
-#if defined(WIN32CONSOLE) || defined(DOS) || defined(DOS_TERM)
+#if defined(WIN32CONSOLE) || defined(DOS)
const int colflags = raw_colour & 0xFF00;
#endif
@@ -272,7 +266,7 @@ static unsigned fix_colour(unsigned raw_colour)
if (is_element_colour( raw_colour ))
raw_colour = element_colour( raw_colour );
-#if defined(WIN32CONSOLE) || defined(DOS) || defined(DOS_TERM)
+#if defined(WIN32CONSOLE) || defined(DOS)
if (colflags)
{
unsigned brand = colflag2brand(colflags);
@@ -352,7 +346,7 @@ static char get_travel_colour( int x, int y )
if (is_waypoint(x + 1, y + 1))
return LIGHTGREEN;
- short dist = point_distance[x + 1][y + 1];
+ short dist = travel_point_distance[x + 1][y + 1];
return dist > 0? Options.tc_reachable :
dist == PD_EXCLUDED? Options.tc_excluded :
dist == PD_EXCLUDED_RADIUS? Options.tc_exclude_circle :
@@ -1661,7 +1655,7 @@ bool is_feature(int feature, int x, int y) {
switch (feature) {
case 'X':
- return (point_distance[x][y] == PD_EXCLUDED);
+ return (travel_point_distance[x][y] == PD_EXCLUDED);
case 'F':
case 'W':
return is_waypoint(x, y);
@@ -1892,57 +1886,50 @@ static int get_number_of_lines_levelmap()
return get_number_of_lines() - (Options.level_map_title ? 1 : 0);
}
-static void draw_level_map(
- int start_x, int start_y, int screen_y, bool travel_mode)
+static void draw_level_map(int start_x, int start_y, bool travel_mode)
{
int bufcount2 = 0;
screen_buffer_t buffer2[GYM * GXM * 2];
const int num_lines = get_number_of_lines_levelmap();
+ const int num_cols = get_number_of_cols();
cursor_control cs(false);
-#ifdef PLAIN_TERM
+ int top = 1 + Options.level_map_title;
if ( Options.level_map_title )
{
- gotoxy(1,1);
+ gotoxy(1, 1);
textcolor(WHITE);
cprintf("Level %s", level_description_string().c_str());
- gotoxy(1,2);
}
- else
- gotoxy(1, 1);
-#endif
- for (int j = 0; j < num_lines; j++)
+ gotoxy(1, top);
+
+ for (int screen_y = 0; screen_y < num_lines; screen_y++)
{
- for (int i = 0; i < 80; i++)
+ for (int screen_x = 0; screen_x < num_cols - 1; screen_x++)
{
screen_buffer_t colour = DARKGREY;
- if (start_y + j >= 65 || start_y + j <= 3
- || start_x + i < 0 || start_x + i >= GXM - 1)
+
+ coord_def c(start_x + screen_x, start_y + screen_y);
+
+ if (!in_bounds(c + coord_def(1, 1)))
{
buffer2[bufcount2 + 1] = DARKGREY;
buffer2[bufcount2] = 0;
bufcount2 += 2;
-#ifdef PLAIN_TERM
goto print_it;
-#endif
-
-#ifdef DOS_TERM
- continue;
-#endif
}
- colour = colour_code_map(start_x + i, start_y + j,
+ colour = colour_code_map(c.x, c.y,
Options.item_colour,
travel_mode && Options.travel_colour);
buffer2[bufcount2 + 1] = colour;
- buffer2[bufcount2] =
- (unsigned char) env.map[start_x + i][start_y + j];
+ buffer2[bufcount2] = (unsigned char) env.map(c);
- if (start_x + i + 1 == you.x_pos && start_y + j + 1 == you.y_pos)
+ if (c.x + 1 == you.x_pos && c.y + 1 == you.y_pos)
{
// [dshaligram] Draw the @ symbol on the level-map. It's no
// longer saved into the env.map, so we need to draw it
@@ -1951,15 +1938,16 @@ static void draw_level_map(
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 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];
- int gridx = start_x + i + 1, gridy = start_y + j + 1;
- unsigned char ch = is_waypoint(gridx, gridy);
+ const coord_def gridc = c + coord_def(1, 1);
+
+ unsigned char ch = is_waypoint(gridc.x, gridc.y);
if (ch && (bc == get_sightmap_char(DNGN_FLOOR) ||
bc == get_magicmap_char(DNGN_FLOOR)))
bc = ch;
@@ -1967,16 +1955,10 @@ static void draw_level_map(
bufcount2 += 2;
-#ifdef PLAIN_TERM
-
- print_it:
- // avoid line wrap
- if (i == 79)
- continue;
-
+ print_it:
// newline
- if (i == 0 && j > 0)
- gotoxy( 1, j + 1 );
+ if (screen_x == 0 && screen_y > 0)
+ gotoxy( 1, screen_y + top );
int ch = buffer2[bufcount2 - 2];
#ifdef USE_CURSES
@@ -1984,17 +1966,12 @@ static void draw_level_map(
#endif
textcolor( buffer2[bufcount2 - 1] );
putch(ch);
-#endif
}
}
#ifdef USE_CURSES
set_altcharset(false);
#endif
-
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer2);
-#endif
}
// show_map() now centers the known map along x or y. This prevents
@@ -2010,10 +1987,6 @@ void show_map( FixedVector<int, 2> &spec_place, bool travel_mode )
char move_y = 0;
char getty = 0;
-#ifdef DOS_TERM
- char buffer[4800];
-#endif
-
// Vector to track all features we can travel to, in order of distance.
std::vector<coord_def> features;
if (travel_mode)
@@ -2029,7 +2002,9 @@ void show_map( FixedVector<int, 2> &spec_place, bool travel_mode )
bool found_y = false;
const int num_lines = get_number_of_lines_levelmap();
- const int half_screen = num_lines / 2 - 1;
+ const int half_screen = (num_lines - 1) / 2;
+
+ const int top = 1 + Options.level_map_title;
for (j = 0; j < GYM; j++)
{
@@ -2084,11 +2059,6 @@ void show_map( FixedVector<int, 2> &spec_place, bool travel_mode )
bool map_alive = true;
bool redraw_map = true;
-#ifdef DOS_TERM
- gettext(1, 1, 80, 25, buffer);
- window(1, 1, 80, 25);
-#endif
-
clrscr();
textcolor(DARKGREY);
@@ -2097,10 +2067,10 @@ void show_map( FixedVector<int, 2> &spec_place, bool travel_mode )
start_y = screen_y - half_screen;
if (redraw_map)
- draw_level_map(start_x, start_y, screen_y, travel_mode);
+ draw_level_map(start_x, start_y, travel_mode);
redraw_map = true;
- gotoxy(curs_x, curs_y);
+ gotoxy(curs_x, curs_y + top - 1);
getty = unmangle_direction_keys(getchm(KC_LEVELMAP), KC_LEVELMAP);
@@ -2350,10 +2320,10 @@ void show_map( FixedVector<int, 2> &spec_place, bool travel_mode )
if (curs_y + move_y < 1)
{
- // screen_y += (curs_y + move_y) - 1;
screen_y += move_y;
- if (screen_y < min_y + half_screen) {
+ if (screen_y < min_y + half_screen)
+ {
move_y = screen_y - (min_y + half_screen);
screen_y = min_y + half_screen;
}
@@ -2361,12 +2331,12 @@ void show_map( FixedVector<int, 2> &spec_place, bool travel_mode )
move_y = 0;
}
- if (curs_y + move_y > num_lines - 1)
+ if (curs_y + move_y > num_lines)
{
- // screen_y += (curs_y + move_y) - num_lines + 1;
screen_y += move_y;
- if (screen_y > max_y - half_screen) {
+ if (screen_y > max_y - half_screen)
+ {
move_y = screen_y - (max_y - half_screen);
screen_y = max_y - half_screen;
}
@@ -2381,10 +2351,6 @@ void show_map( FixedVector<int, 2> &spec_place, bool travel_mode )
curs_y += move_y;
}
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
-
return;
} // end show_map()
@@ -2453,17 +2419,30 @@ void magic_mapping(int map_radius, int proportion)
if (empty_count > 0)
{
if (!get_envmap_char(i, j))
+ {
set_envmap_char(i, j, get_magicmap_char(grd[i][j]));
+#ifdef WIZARD
+ if (map_radius == 1000)
+ set_envmap_char(i, j, get_sightmap_char(grd[i][j]));
+#endif
+ }
+
// Hack to give demonspawn Pandemonium mutation the ability
// to detect exits magically.
if ((you.mutation[MUT_PANDEMONIUM] > 1
&& grd[i][j] == DNGN_EXIT_PANDEMONIUM)
- // Wizmode
- || map_radius == 1000)
+#ifdef WIZARD
+ || map_radius == 1000
+#endif
+ )
+ {
set_terrain_seen( i, j );
+ }
else
+ {
set_terrain_mapped( i, j );
+ }
}
}
}
@@ -3460,11 +3439,6 @@ void viewwindow(bool draw_it, bool do_updates)
// and this simply works without requiring a stack.
you.flash_colour = BLACK;
-#ifdef DOS_TERM
- puttext( 2, 1, X_SIZE + 1, Y_SIZE, buffy.buffer() );
-#endif
-
-#ifdef PLAIN_TERM
// avoiding unneeded draws when running
if (!you.running || (you.running < 0 && Options.travel_delay > -1))
{
@@ -3490,7 +3464,5 @@ void viewwindow(bool draw_it, bool do_updates)
#ifdef USE_CURSES
set_altcharset( false );
#endif
-
-#endif
}
} // end viewwindow()
diff --git a/crawl-ref/source/view.h b/crawl-ref/source/view.h
index 9175f46e95..a4eba7d894 100644
--- a/crawl-ref/source/view.h
+++ b/crawl-ref/source/view.h
@@ -127,6 +127,11 @@ 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_seen(const coord_def &c)
+{
+ return (is_terrain_seen(c.x, c.y));
+}
+
void clear_feature_overrides();
void add_feature_override(const std::string &text);
void clear_cset_overrides();