summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2006-11-22 08:41:20 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2006-11-22 08:41:20 +0000
commit1d0f57cbceb778139ca215cc4fcfd1584951f6dd (patch)
treecafd60c944c51fcce778aa5d6912bc548c518339 /crawl-ref
parent6f5e187a9e5cd348296dba2fd89d2e206e775a01 (diff)
downloadcrawl-ref-1d0f57cbceb778139ca215cc4fcfd1584951f6dd.tar.gz
crawl-ref-1d0f57cbceb778139ca215cc4fcfd1584951f6dd.zip
Merged stone_soup r15:451 into trunk.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@452 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/AppHdr.h100
-rw-r--r--crawl-ref/source/Crawl.xcodeproj/project.pbxproj401
-rw-r--r--crawl-ref/source/FixAry.h2
-rw-r--r--crawl-ref/source/FixVec.h96
-rw-r--r--crawl-ref/source/Kills.cc147
-rw-r--r--crawl-ref/source/Kills.h9
-rw-r--r--crawl-ref/source/MacString.cc199
-rw-r--r--crawl-ref/source/MacString.h71
-rw-r--r--crawl-ref/source/abl-show.cc111
-rw-r--r--crawl-ref/source/abyss.cc2
-rw-r--r--crawl-ref/source/acr.cc1751
-rw-r--r--crawl-ref/source/beam.cc1698
-rw-r--r--crawl-ref/source/beam.h5
-rw-r--r--crawl-ref/source/chardump.cc860
-rw-r--r--crawl-ref/source/chardump.h12
-rw-r--r--crawl-ref/source/cloud.cc2
-rw-r--r--crawl-ref/source/clua.cc87
-rw-r--r--crawl-ref/source/command.cc510
-rw-r--r--crawl-ref/source/command.h8
-rw-r--r--crawl-ref/source/dat/levdes.vim75
-rw-r--r--crawl-ref/source/dat/splev.des1563
-rw-r--r--crawl-ref/source/dat/vaults.des1689
-rw-r--r--crawl-ref/source/debug.cc679
-rw-r--r--crawl-ref/source/debug.h6
-rw-r--r--crawl-ref/source/decks.cc40
-rw-r--r--crawl-ref/source/decks.h2
-rw-r--r--crawl-ref/source/defines.h143
-rw-r--r--crawl-ref/source/delay.cc1129
-rw-r--r--crawl-ref/source/delay.h16
-rw-r--r--crawl-ref/source/describe.cc377
-rw-r--r--crawl-ref/source/describe.h9
-rw-r--r--crawl-ref/source/direct.cc361
-rw-r--r--crawl-ref/source/direct.h29
-rw-r--r--crawl-ref/source/dungeon.cc1177
-rw-r--r--crawl-ref/source/dungeon.h19
-rw-r--r--crawl-ref/source/effects.cc448
-rw-r--r--crawl-ref/source/effects.h5
-rw-r--r--crawl-ref/source/enum.h1332
-rw-r--r--crawl-ref/source/externs.h382
-rw-r--r--crawl-ref/source/fight.cc761
-rw-r--r--crawl-ref/source/fight.h8
-rw-r--r--crawl-ref/source/files.cc1057
-rw-r--r--crawl-ref/source/files.h27
-rw-r--r--crawl-ref/source/food.cc550
-rw-r--r--crawl-ref/source/food.h4
-rw-r--r--crawl-ref/source/hiscores.cc2152
-rw-r--r--crawl-ref/source/hiscores.h6
-rw-r--r--crawl-ref/source/initfile.cc1248
-rw-r--r--crawl-ref/source/initfile.h8
-rw-r--r--crawl-ref/source/insult.cc2
-rw-r--r--crawl-ref/source/invent.cc995
-rw-r--r--crawl-ref/source/invent.h134
-rw-r--r--crawl-ref/source/it_use2.cc65
-rw-r--r--crawl-ref/source/it_use2.h3
-rw-r--r--crawl-ref/source/it_use3.cc82
-rw-r--r--crawl-ref/source/item_use.cc1626
-rw-r--r--crawl-ref/source/item_use.h27
-rw-r--r--crawl-ref/source/itemname.cc1792
-rw-r--r--crawl-ref/source/itemname.h62
-rw-r--r--crawl-ref/source/itemprop.cc2085
-rw-r--r--crawl-ref/source/itemprop.h148
-rw-r--r--crawl-ref/source/items.cc520
-rw-r--r--crawl-ref/source/items.h10
-rw-r--r--crawl-ref/source/lev-pand.cc2
-rw-r--r--crawl-ref/source/libdos.cc21
-rw-r--r--crawl-ref/source/libdos.h6
-rw-r--r--crawl-ref/source/libemx.cc233
-rw-r--r--crawl-ref/source/libemx.h38
-rw-r--r--crawl-ref/source/libmac.cc2116
-rw-r--r--crawl-ref/source/libmac.h86
-rw-r--r--crawl-ref/source/libunix.cc221
-rw-r--r--crawl-ref/source/libunix.h7
-rw-r--r--crawl-ref/source/libutil.cc681
-rw-r--r--crawl-ref/source/libutil.h93
-rw-r--r--crawl-ref/source/libw32c.cc53
-rw-r--r--crawl-ref/source/libw32c.h5
-rw-r--r--crawl-ref/source/lua/runrest.lua3
-rw-r--r--crawl-ref/source/lua/safechnk.lua (renamed from crawl-ref/source/lua/safechunk.lua)2
-rw-r--r--crawl-ref/source/lua/stash.lua2
-rw-r--r--crawl-ref/source/lua/trapwalk.lua46
-rw-r--r--crawl-ref/source/machdr.h185
-rw-r--r--crawl-ref/source/macro.cc19
-rw-r--r--crawl-ref/source/macro.h2
-rw-r--r--crawl-ref/source/makefile23
-rw-r--r--crawl-ref/source/makefile.bor53
-rw-r--r--crawl-ref/source/makefile.bsd64
-rw-r--r--crawl-ref/source/makefile.dos115
-rw-r--r--crawl-ref/source/makefile.emx53
-rw-r--r--crawl-ref/source/makefile.lnx68
-rw-r--r--crawl-ref/source/makefile.mgw151
-rw-r--r--crawl-ref/source/makefile.obj6
-rw-r--r--crawl-ref/source/makefile.osx83
-rw-r--r--crawl-ref/source/makefile.sgi54
-rw-r--r--crawl-ref/source/makefile.sol68
-rw-r--r--crawl-ref/source/makefile.unix198
-rw-r--r--crawl-ref/source/mapdef.cc412
-rw-r--r--crawl-ref/source/mapdef.h167
-rw-r--r--crawl-ref/source/maps.cc3744
-rw-r--r--crawl-ref/source/maps.h30
-rw-r--r--crawl-ref/source/menu.cc880
-rw-r--r--crawl-ref/source/menu.h251
-rw-r--r--crawl-ref/source/message.cc122
-rw-r--r--crawl-ref/source/message.h14
-rw-r--r--crawl-ref/source/misc.cc484
-rw-r--r--crawl-ref/source/misc.h46
-rw-r--r--crawl-ref/source/misc/header2
-rw-r--r--crawl-ref/source/misc/src-pkg-excludes.lst3
-rw-r--r--crawl-ref/source/mon-data.h1807
-rw-r--r--crawl-ref/source/mon-pick.cc149
-rw-r--r--crawl-ref/source/mon-pick.h10
-rw-r--r--crawl-ref/source/mon-spll.h61
-rw-r--r--crawl-ref/source/mon-util.cc1000
-rw-r--r--crawl-ref/source/mon-util.h154
-rw-r--r--crawl-ref/source/monplace.cc406
-rw-r--r--crawl-ref/source/monplace.h24
-rw-r--r--crawl-ref/source/monspeak.cc12
-rw-r--r--crawl-ref/source/monstuff.cc1561
-rw-r--r--crawl-ref/source/monstuff.h14
-rw-r--r--crawl-ref/source/mstuff2.cc562
-rw-r--r--crawl-ref/source/mstuff2.h25
-rw-r--r--crawl-ref/source/mutation.cc99
-rw-r--r--crawl-ref/source/newgame.cc746
-rw-r--r--crawl-ref/source/notes.cc405
-rw-r--r--crawl-ref/source/notes.h67
-rw-r--r--crawl-ref/source/ouch.cc552
-rw-r--r--crawl-ref/source/ouch.h2
-rw-r--r--crawl-ref/source/output.cc46
-rw-r--r--crawl-ref/source/output.h2
-rw-r--r--crawl-ref/source/overmap.cc55
-rw-r--r--crawl-ref/source/overmap.h2
-rw-r--r--crawl-ref/source/player.cc963
-rw-r--r--crawl-ref/source/player.h46
-rw-r--r--crawl-ref/source/prebuilt/levcomp.lex.cc2522
-rw-r--r--crawl-ref/source/prebuilt/levcomp.tab.cc1907
-rw-r--r--crawl-ref/source/prebuilt/levcomp.tab.h125
-rw-r--r--crawl-ref/source/randart.cc59
-rw-r--r--crawl-ref/source/religion.cc1090
-rw-r--r--crawl-ref/source/religion.h89
-rw-r--r--crawl-ref/source/shopping.cc280
-rw-r--r--crawl-ref/source/shopping.h2
-rw-r--r--crawl-ref/source/skills.cc82
-rw-r--r--crawl-ref/source/skills.h4
-rw-r--r--crawl-ref/source/skills2.cc214
-rw-r--r--crawl-ref/source/skills2.h4
-rw-r--r--crawl-ref/source/spells1.cc286
-rw-r--r--crawl-ref/source/spells1.h14
-rw-r--r--crawl-ref/source/spells2.cc142
-rw-r--r--crawl-ref/source/spells2.h4
-rw-r--r--crawl-ref/source/spells3.cc106
-rw-r--r--crawl-ref/source/spells3.h10
-rw-r--r--crawl-ref/source/spells4.cc206
-rw-r--r--crawl-ref/source/spells4.h7
-rw-r--r--crawl-ref/source/spl-book.cc282
-rw-r--r--crawl-ref/source/spl-book.h4
-rw-r--r--crawl-ref/source/spl-cast.cc622
-rw-r--r--crawl-ref/source/spl-cast.h6
-rw-r--r--crawl-ref/source/spl-data.h224
-rw-r--r--crawl-ref/source/spl-util.cc62
-rw-r--r--crawl-ref/source/spl-util.h9
-rw-r--r--crawl-ref/source/stash.cc175
-rw-r--r--crawl-ref/source/stash.h4
-rw-r--r--crawl-ref/source/stuff.cc477
-rw-r--r--crawl-ref/source/stuff.h150
-rw-r--r--crawl-ref/source/tags.cc172
-rw-r--r--crawl-ref/source/tags.h4
-rw-r--r--crawl-ref/source/transfor.cc100
-rw-r--r--crawl-ref/source/transfor.h8
-rw-r--r--crawl-ref/source/travel.cc485
-rw-r--r--crawl-ref/source/travel.h39
-rw-r--r--crawl-ref/source/unrand.h2
-rw-r--r--crawl-ref/source/util/levcomp.cc18
-rw-r--r--crawl-ref/source/util/levcomp.h12
-rw-r--r--crawl-ref/source/util/levcomp.lpp155
-rw-r--r--crawl-ref/source/util/levcomp.ypp226
-rw-r--r--crawl-ref/source/version.h7
-rw-r--r--crawl-ref/source/view.cc4399
-rw-r--r--crawl-ref/source/view.h43
-rw-r--r--crawl-ref/source/wpn-misc.cc268
-rw-r--r--crawl-ref/source/wpn-misc.h67
179 files changed, 38483 insertions, 25296 deletions
diff --git a/crawl-ref/source/AppHdr.h b/crawl-ref/source/AppHdr.h
index 44c115b80a..602d351444 100644
--- a/crawl-ref/source/AppHdr.h
+++ b/crawl-ref/source/AppHdr.h
@@ -14,6 +14,8 @@
*
* Copyright © 1999 Jesse Jones.
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <9> 9 Aug 2001 MV Added USE_RIVERS,USE_NEW_UNRANDS
@@ -58,35 +60,26 @@
//
// #define CLUA_BINDINGS
-// =========================================================================
-// System Defines
-// =========================================================================
-// Define plain_term for Unix and dos_term for DOS and EMX.
-
-#if defined(LINUX)
- #define UNIX
- #define USE_UNIX_SIGNALS
-#elif defined(SOLARIS)
- #define UNIX
- #define USE_UNIX_SIGNALS
-#elif defined(BSD)
- #define UNIX
-#elif defined(OSX)
+// OS X's Terminal.app has color handling problems; dark grey is
+// especially bad, so we'll want to remap that. OS X is otherwise
+// Unix-ish, so we shouldn't need other special handling.
+#if defined(OSX)
#define UNIX
- // Darkgrey is a particular problem in Terminal.app.
#define USE_8_COLOUR_TERM_MAP
#define COL_TO_REPLACE_DARKGREY BLUE
-#elif defined(HPUX)
- #define UNIX
- #define USE_UNIX_SIGNALS
- // Under HP-UX it's typically easier to use ncurses than try and
- // get the colour curses library to work. -- bwr
- #define CURSES_INCLUDE_FILE <ncurses.h>
#endif
+// =========================================================================
+// System Defines
+// =========================================================================
+// Define plain_term for Unix and dos_term for DOS.
+
#ifdef UNIX
#define PLAIN_TERM
#define MULTIUSER
+ #define USE_UNIX_SIGNALS
+
+ #define FILE_SEPARATOR '/'
#define CHARACTER_SET 0
#define USE_ASCII_CHARACTERS
@@ -143,30 +136,13 @@
#include "libunix.h"
-// To compile with EMX for OS/2 define USE_EMX macro with compiler command line
-// (already defined in supplied makefile.emx)
-#elif defined(USE_EMX)
- #define DOS_TERM
- #define EOL "\n"
- #define CHARACTER_SET A_ALTCHARSET
-
- #include <string>
- #include "libemx.h"
-
#elif _MSC_VER >= 1100
#include <string>
#include "WinHdr.h"
#error MSVC is not supported yet
#define CHARACTER_SET A_ALTCHARSET
-// macintosh is predefined on all the common Mac compilers
-#elif defined(macintosh)
- #define PLAIN_TERM
- #define HAS_NAMESPACES 1
- #define EOL "\r"
- #define CHARACTER_SET A_ALTCHARSET
- #include <string>
- #include "libmac.h"
+ #define FILE_SEPARATOR '/'
#elif defined(DOS)
#define DOS_TERM
@@ -174,13 +150,20 @@
#define EOL "\r\n"
#define CHARACTER_SET A_ALTCHARSET
+ #define FILE_SEPARATOR '\\'
+
#include <string>
+ #include "libdos.h"
#ifdef __DJGPP__
#define NEED_SNPRINTF
+
+ // [dshaligram] This is distressing, but djgpp lacks (v)snprintf, and
+ // we have to support DOS. Ow. FIXME
+ #define vsnprintf(buf, size, format, args) vsprintf(buf, format, args)
#endif
-#elif defined(WIN32CONSOLE) && (defined(__IBMCPP__) || defined(__BCPLUSPLUS__) || defined(__MINGW32__))
+#elif defined(WIN32CONSOLE) && (defined(__IBMCPP__) || defined(__MINGW32__))
#include "libw32c.h"
#define PLAIN_TERM
#define SHORT_FILE_NAMES
@@ -188,6 +171,9 @@
#define CHARACTER_SET A_ALTCHARSET
#define getstr(X,Y) getConsoleString(X,Y)
+ // NT and better are happy with /; I'm not sure how 9x reacts.
+ #define FILE_SEPARATOR '/'
+
// Uncomment to play sounds. winmm must be linked in if this is uncommented.
// #define WINMM_PLAY_SOUNDS
@@ -271,9 +257,6 @@
//jmf: New defines for a bunch of optional features.
// ================================================= --------------------------
-// New silence code -- seems to actually work! Use it!
-#define USE_SILENCE_CODE
-
// Use special colours for various channels of messages
#define USE_COLOUR_MESSAGES
@@ -300,7 +283,7 @@
// mv: (new 9 Aug 01) turns off missile trails, might be slow on some computers
// #define MISSILE_TRAILS_OFF
-// bwr: allow player to destroy items in inventory (but not equiped items)
+// bwr: allow player to destroy items in inventory (but not equipped items)
// See comment at items.cc::cmd_destroy_item() for details/issues.
// #define ALLOW_DESTROY_ITEM_COMMAND
@@ -315,7 +298,7 @@
#ifdef MULTIUSER
// Define SAVE_DIR to the directory where saves, bones, and score file
- // will go... end it with a '\'. Since all player files will be in the
+ // will go... end it with a '/'. Since all player files will be in the
// same directory, the players UID will be appended when this option
// is set.
//
@@ -323,7 +306,13 @@
// be dumped in the current directory.
//
// #define SAVE_DIR_PATH "/opt/crawl/lib/"
- #define SAVE_DIR_PATH ""
+ // #define SAVE_DIR_PATH ""
+
+ // Define DATA_DIR_PATH to the directory where level-description (.des)
+ // files are stored. NOTE: If you're installing Crawl for a real multiuser
+ // system, you MUST do this. The directory must exist on the filesystem.
+
+ // #define DATA_DIR_PATH "/opt/crawl"
// will make this little thing go away. Define SAVE_PACKAGE_CMD
// to a command to compress and bundle the save game files into a
@@ -334,14 +323,19 @@
// PACKAGE_SUFFIX is used when the package file name is needed
//
// Comment these lines out if you want to leave the save files uncompressed.
- //
- // #define SAVE_PACKAGE_CMD "/usr/bin/zip -m -q -j -1 %s.zip %s.*"
- // #define LOAD_UNPACKAGE_CMD "/usr/bin/unzip -q -o %s.zip -d" SAVE_DIR_PATH
- // #define PACKAGE_SUFFIX ".zip"
+ #define SAVE_PACKAGE_CMD "/usr/bin/zip -m -q -j -1 %s.zip %s.*"
+#ifdef SAVE_DIR_PATH
+ #define LOAD_UNPACKAGE_CMD "/usr/bin/unzip -q -o %s.zip -d" SAVE_DIR_PATH
+#else
+ #define LOAD_UNPACKAGE_CMD "/usr/bin/unzip -q -o %s.zip"
+#endif
+
+#ifdef SAVE_PACKAGE_CMD
+ // This is used to unpack specific files from the archive.
+ #define UNPACK_SPECIFIC_FILE_CMD LOAD_UNPACKAGE_CMD " %s"
+#endif
- // This provides some rudimentary protection against people using
- // save file cheats on multi-user systems.
- #define DO_ANTICHEAT_CHECKS
+ #define PACKAGE_SUFFIX ".zip"
// This defines the chmod permissions for score and bones files.
#define SHARED_FILES_CHMOD_PRIVATE 0664
diff --git a/crawl-ref/source/Crawl.xcodeproj/project.pbxproj b/crawl-ref/source/Crawl.xcodeproj/project.pbxproj
index 418dde20a2..4ae4c17819 100644
--- a/crawl-ref/source/Crawl.xcodeproj/project.pbxproj
+++ b/crawl-ref/source/Crawl.xcodeproj/project.pbxproj
@@ -51,8 +51,6 @@
7B237E950A8EC9D000580F30 /* files.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7B237E0E0A8EC9D000580F30 /* files.cc */; };
7B237E960A8EC9D000580F30 /* direct.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7B237E0F0A8EC9D000580F30 /* direct.cc */; };
7B237E970A8EC9D000580F30 /* dungeon.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7B237E100A8EC9D000580F30 /* dungeon.h */; };
- 7B237E980A8EC9D000580F30 /* wpn-misc.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7B237E110A8EC9D000580F30 /* wpn-misc.h */; };
- 7B237E990A8EC9D000580F30 /* wpn-misc.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7B237E120A8EC9D000580F30 /* wpn-misc.cc */; };
7B237E9A0A8EC9D000580F30 /* view.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7B237E130A8EC9D000580F30 /* view.h */; };
7B237E9B0A8EC9D000580F30 /* view.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7B237E140A8EC9D000580F30 /* view.cc */; };
7B237E9C0A8EC9D000580F30 /* spl-book.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7B237E150A8EC9D000580F30 /* spl-book.cc */; };
@@ -143,6 +141,15 @@
7B237EF10A8EC9D000580F30 /* mt19937ar.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7B237E6A0A8EC9D000580F30 /* mt19937ar.cc */; };
7B237EF20A8EC9D000580F30 /* mstuff2.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7B237E6B0A8EC9D000580F30 /* mstuff2.h */; };
7B237F150A8ECD2E00580F30 /* libncurses.5.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B237F140A8ECD2E00580F30 /* libncurses.5.dylib */; };
+ 7B352EA00B00183400CABB32 /* mapdef.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7B352E9D0B00183400CABB32 /* mapdef.cc */; };
+ 7B352EA10B00183400CABB32 /* mapdef.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7B352E9E0B00183400CABB32 /* mapdef.h */; };
+ 7BBC4A060B0F782800F27D45 /* levcomp.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7B352EEC0B001F4200CABB32 /* levcomp.cc */; };
+ 7BBC4A070B0F783C00F27D45 /* levcomp.lpp in Sources */ = {isa = PBXBuildFile; fileRef = 7B352ED10B001B9E00CABB32 /* levcomp.lpp */; };
+ 7BBC4A080B0F783C00F27D45 /* levcomp.ypp in Sources */ = {isa = PBXBuildFile; fileRef = 7B352ED20B001B9E00CABB32 /* levcomp.ypp */; };
+ 7BC222E70ABBB286003A7D9A /* itemprop.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BC222E50ABBB286003A7D9A /* itemprop.cc */; };
+ 7BC222E80ABBB286003A7D9A /* itemprop.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7BC222E60ABBB286003A7D9A /* itemprop.h */; };
+ 7BD75A350AC214A200B74F6E /* notes.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BD75A330AC214A200B74F6E /* notes.cc */; };
+ 7BD75A360AC214A200B74F6E /* notes.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7BD75A340AC214A200B74F6E /* notes.h */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -175,7 +182,6 @@
7B237E910A8EC9D000580F30 /* player.h in CopyFiles */,
7B237E930A8EC9D000580F30 /* effects.h in CopyFiles */,
7B237E970A8EC9D000580F30 /* dungeon.h in CopyFiles */,
- 7B237E980A8EC9D000580F30 /* wpn-misc.h in CopyFiles */,
7B237E9A0A8EC9D000580F30 /* view.h in CopyFiles */,
7B237E9D0A8EC9D000580F30 /* spells4.h in CopyFiles */,
7B237E9F0A8EC9D000580F30 /* spells3.h in CopyFiles */,
@@ -219,6 +225,9 @@
7B237EEC0A8EC9D000580F30 /* abyss.h in CopyFiles */,
7B237EF00A8EC9D000580F30 /* mt19937ar.h in CopyFiles */,
7B237EF20A8EC9D000580F30 /* mstuff2.h in CopyFiles */,
+ 7BC222E80ABBB286003A7D9A /* itemprop.h in CopyFiles */,
+ 7BD75A360AC214A200B74F6E /* notes.h in CopyFiles */,
+ 7B352EA10B00183400CABB32 /* mapdef.h in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
@@ -269,8 +278,6 @@
7B237E0E0A8EC9D000580F30 /* files.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = files.cc; sourceTree = "<group>"; };
7B237E0F0A8EC9D000580F30 /* direct.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = direct.cc; sourceTree = "<group>"; };
7B237E100A8EC9D000580F30 /* dungeon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dungeon.h; sourceTree = "<group>"; };
- 7B237E110A8EC9D000580F30 /* wpn-misc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "wpn-misc.h"; sourceTree = "<group>"; };
- 7B237E120A8EC9D000580F30 /* wpn-misc.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = "wpn-misc.cc"; sourceTree = "<group>"; };
7B237E130A8EC9D000580F30 /* view.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = view.h; sourceTree = "<group>"; };
7B237E140A8EC9D000580F30 /* view.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = view.cc; sourceTree = "<group>"; };
7B237E150A8EC9D000580F30 /* spl-book.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = "spl-book.cc"; sourceTree = "<group>"; };
@@ -361,6 +368,17 @@
7B237E6A0A8EC9D000580F30 /* mt19937ar.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = mt19937ar.cc; sourceTree = "<group>"; };
7B237E6B0A8EC9D000580F30 /* mstuff2.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mstuff2.h; sourceTree = "<group>"; };
7B237F140A8ECD2E00580F30 /* libncurses.5.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libncurses.5.dylib; path = /usr/lib/libncurses.5.dylib; sourceTree = "<absolute>"; };
+ 7B352E9D0B00183400CABB32 /* mapdef.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = mapdef.cc; sourceTree = "<group>"; };
+ 7B352E9E0B00183400CABB32 /* mapdef.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mapdef.h; sourceTree = "<group>"; };
+ 7B352ED10B001B9E00CABB32 /* levcomp.lpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.lex; name = levcomp.lpp; path = util/levcomp.lpp; sourceTree = "<group>"; };
+ 7B352ED20B001B9E00CABB32 /* levcomp.ypp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.yacc; name = levcomp.ypp; path = util/levcomp.ypp; sourceTree = "<group>"; };
+ 7B352EEC0B001F4200CABB32 /* levcomp.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = levcomp.cc; path = util/levcomp.cc; sourceTree = "<group>"; };
+ 7B352F1F0B00232500CABB32 /* splev.des */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = splev.des; path = dat/splev.des; sourceTree = "<group>"; };
+ 7B352F200B00232500CABB32 /* vaults.des */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = vaults.des; path = dat/vaults.des; sourceTree = "<group>"; };
+ 7BC222E50ABBB286003A7D9A /* itemprop.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = itemprop.cc; sourceTree = "<group>"; };
+ 7BC222E60ABBB286003A7D9A /* itemprop.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = itemprop.h; sourceTree = "<group>"; };
+ 7BD75A330AC214A200B74F6E /* notes.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = notes.cc; sourceTree = "<group>"; };
+ 7BD75A340AC214A200B74F6E /* notes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = notes.h; sourceTree = "<group>"; };
8DD76FB20486AB0100D96B5E /* crawl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = crawl; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
@@ -380,6 +398,7 @@
isa = PBXGroup;
children = (
08FB7795FE84155DC02AAC07 /* Source */,
+ 7B352F1B0B0022C900CABB32 /* Resources */,
7B237F120A8ECCDE00580F30 /* Libraries */,
C6A0FF2B0290797F04C91782 /* Documentation */,
1AB674ADFE9D54B511CA2CBB /* Products */,
@@ -390,159 +409,207 @@
08FB7795FE84155DC02AAC07 /* Source */ = {
isa = PBXGroup;
children = (
- 7B237DE50A8EC9D000580F30 /* maps.h */,
- 7B237DE60A8EC9D000580F30 /* maps.cc */,
- 7B237DE70A8EC9D000580F30 /* mon-pick.h */,
- 7B237DE80A8EC9D000580F30 /* mon-pick.cc */,
- 7B237DE90A8EC9D000580F30 /* misc.h */,
- 7B237DEA0A8EC9D000580F30 /* insult.h */,
- 7B237DEB0A8EC9D000580F30 /* insult.cc */,
- 7B237DEC0A8EC9D000580F30 /* initfile.h */,
- 7B237DED0A8EC9D000580F30 /* overmap.h */,
- 7B237DEE0A8EC9D000580F30 /* overmap.cc */,
- 7B237DEF0A8EC9D000580F30 /* output.h */,
- 7B237DF00A8EC9D000580F30 /* item_use.h */,
- 7B237DF10A8EC9D000580F30 /* initfile.cc */,
- 7B237DF20A8EC9D000580F30 /* hiscores.h */,
- 7B237DF30A8EC9D000580F30 /* hiscores.cc */,
- 7B237DF40A8EC9D000580F30 /* travel.h */,
- 7B237DF50A8EC9D000580F30 /* travel.cc */,
- 7B237DF60A8EC9D000580F30 /* lev-pand.h */,
- 7B237DF70A8EC9D000580F30 /* lev-pand.cc */,
- 7B237DF80A8EC9D000580F30 /* items.h */,
- 7B237DF90A8EC9D000580F30 /* newgame.cc */,
- 7B237DFA0A8EC9D000580F30 /* mutation.h */,
- 7B237DFB0A8EC9D000580F30 /* mutation.cc */,
- 7B237DFC0A8EC9D000580F30 /* misc.cc */,
- 7B237DFD0A8EC9D000580F30 /* message.h */,
- 7B237DFE0A8EC9D000580F30 /* mon-util.h */,
- 7B237DFF0A8EC9D000580F30 /* mon-util.cc */,
- 7B237E000A8EC9D000580F30 /* it_use3.h */,
- 7B237E010A8EC9D000580F30 /* it_use3.cc */,
- 7B237E020A8EC9D000580F30 /* it_use2.h */,
- 7B237E030A8EC9D000580F30 /* itemname.cc */,
- 7B237E040A8EC9D000580F30 /* command.cc */,
- 7B237E050A8EC9D000580F30 /* describe.h */,
- 7B237E060A8EC9D000580F30 /* spl-util.h */,
- 7B237E070A8EC9D000580F30 /* spl-util.cc */,
- 7B237E080A8EC9D000580F30 /* randart.h */,
- 7B237E090A8EC9D000580F30 /* randart.cc */,
- 7B237E0A0A8EC9D000580F30 /* player.h */,
- 7B237E0B0A8EC9D000580F30 /* player.cc */,
- 7B237E0C0A8EC9D000580F30 /* effects.h */,
+ 7B352EF00B001F5B00CABB32 /* Crawl */,
+ 7B352E950B0017CF00CABB32 /* Levcomp */,
+ 7B352EF30B001FA700CABB32 /* Shared */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8DD76FB20486AB0100D96B5E /* crawl */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 7B237F120A8ECCDE00580F30 /* Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 7B237F140A8ECD2E00580F30 /* libncurses.5.dylib */,
+ );
+ name = Libraries;
+ sourceTree = "<group>";
+ };
+ 7B352E950B0017CF00CABB32 /* Levcomp */ = {
+ isa = PBXGroup;
+ children = (
+ 7B352EEC0B001F4200CABB32 /* levcomp.cc */,
+ 7B352ED10B001B9E00CABB32 /* levcomp.lpp */,
+ 7B352ED20B001B9E00CABB32 /* levcomp.ypp */,
+ );
+ name = Levcomp;
+ sourceTree = "<group>";
+ };
+ 7B352EF00B001F5B00CABB32 /* Crawl */ = {
+ isa = PBXGroup;
+ children = (
7B237E0D0A8EC9D000580F30 /* abl-show.cc */,
- 7B237E0E0A8EC9D000580F30 /* files.cc */,
- 7B237E0F0A8EC9D000580F30 /* direct.cc */,
- 7B237E100A8EC9D000580F30 /* dungeon.h */,
- 7B237E110A8EC9D000580F30 /* wpn-misc.h */,
- 7B237E120A8EC9D000580F30 /* wpn-misc.cc */,
- 7B237E130A8EC9D000580F30 /* view.h */,
- 7B237E140A8EC9D000580F30 /* view.cc */,
- 7B237E150A8EC9D000580F30 /* spl-book.cc */,
- 7B237E160A8EC9D000580F30 /* spells4.h */,
- 7B237E170A8EC9D000580F30 /* spells4.cc */,
- 7B237E180A8EC9D000580F30 /* spells3.h */,
- 7B237E190A8EC9D000580F30 /* macro.h */,
- 7B237E1A0A8EC9D000580F30 /* debug.h */,
- 7B237E1B0A8EC9D000580F30 /* direct.h */,
- 7B237E1C0A8EC9D000580F30 /* decks.h */,
- 7B237E1D0A8EC9D000580F30 /* stuff.h */,
- 7B237E1E0A8EC9D000580F30 /* stuff.cc */,
- 7B237E1F0A8EC9D000580F30 /* stash.h */,
- 7B237E200A8EC9D000580F30 /* stash.cc */,
- 7B237E210A8EC9D000580F30 /* transfor.h */,
- 7B237E220A8EC9D000580F30 /* transfor.cc */,
- 7B237E230A8EC9D000580F30 /* tags.h */,
- 7B237E240A8EC9D000580F30 /* tags.cc */,
- 7B237E250A8EC9D000580F30 /* libutil.h */,
- 7B237E260A8EC9D000580F30 /* item_use.cc */,
- 7B237E270A8EC9D000580F30 /* acr.cc */,
- 7B237E280A8EC9D000580F30 /* abyss.cc */,
7B237E290A8EC9D000580F30 /* abl-show.h */,
- 7B237E2A0A8EC9D000580F30 /* chardump.cc */,
- 7B237E2B0A8EC9D000580F30 /* chardump.h */,
+ 7B237E280A8EC9D000580F30 /* abyss.cc */,
+ 7B237E650A8EC9D000580F30 /* abyss.h */,
+ 7B237E270A8EC9D000580F30 /* acr.cc */,
7B237E2C0A8EC9D000580F30 /* beam.cc */,
7B237E2D0A8EC9D000580F30 /* beam.h */,
- 7B237E2E0A8EC9D000580F30 /* spl-cast.h */,
- 7B237E2F0A8EC9D000580F30 /* spl-cast.cc */,
- 7B237E300A8EC9D000580F30 /* spl-book.h */,
- 7B237E310A8EC9D000580F30 /* output.cc */,
- 7B237E320A8EC9D000580F30 /* ouch.h */,
- 7B237E330A8EC9D000580F30 /* ouch.cc */,
- 7B237E340A8EC9D000580F30 /* newgame.h */,
- 7B237E350A8EC9D000580F30 /* message.cc */,
- 7B237E360A8EC9D000580F30 /* menu.h */,
- 7B237E370A8EC9D000580F30 /* menu.cc */,
- 7B237E380A8EC9D000580F30 /* macro.cc */,
- 7B237E390A8EC9D000580F30 /* shopping.cc */,
- 7B237E3A0A8EC9D000580F30 /* religion.h */,
- 7B237E3B0A8EC9D000580F30 /* religion.cc */,
- 7B237E3C0A8EC9D000580F30 /* spells3.cc */,
- 7B237E3D0A8EC9D000580F30 /* spells2.h */,
- 7B237E3E0A8EC9D000580F30 /* spells2.cc */,
- 7B237E3F0A8EC9D000580F30 /* mstuff2.cc */,
- 7B237E400A8EC9D000580F30 /* monstuff.h */,
- 7B237E410A8EC9D000580F30 /* monstuff.cc */,
- 7B237E420A8EC9D000580F30 /* monspeak.h */,
- 7B237E430A8EC9D000580F30 /* delay.h */,
+ 7B237E2A0A8EC9D000580F30 /* chardump.cc */,
+ 7B237E2B0A8EC9D000580F30 /* chardump.h */,
+ 7B237E590A8EC9D000580F30 /* cloud.cc */,
+ 7B237E580A8EC9D000580F30 /* cloud.h */,
+ 7B237E570A8EC9D000580F30 /* clua.cc */,
+ 7B237E560A8EC9D000580F30 /* clua.h */,
+ 7B237E040A8EC9D000580F30 /* command.cc */,
7B237E440A8EC9D000580F30 /* command.h */,
- 7B237E450A8EC9D000580F30 /* spells1.h */,
- 7B237E460A8EC9D000580F30 /* spells1.cc */,
- 7B237E470A8EC9D000580F30 /* skills2.h */,
- 7B237E480A8EC9D000580F30 /* skills2.cc */,
+ 7B237E680A8EC9D000580F30 /* debug.cc */,
+ 7B237E1A0A8EC9D000580F30 /* debug.h */,
7B237E490A8EC9D000580F30 /* decks.cc */,
+ 7B237E1C0A8EC9D000580F30 /* decks.h */,
+ 7B237E660A8EC9D000580F30 /* delay.cc */,
+ 7B237E430A8EC9D000580F30 /* delay.h */,
7B237E4A0A8EC9D000580F30 /* describe.cc */,
- 7B237E4B0A8EC9D000580F30 /* monspeak.cc */,
- 7B237E4C0A8EC9D000580F30 /* monplace.h */,
- 7B237E4D0A8EC9D000580F30 /* monplace.cc */,
- 7B237E4E0A8EC9D000580F30 /* Kills.h */,
- 7B237E4F0A8EC9D000580F30 /* Kills.cc */,
- 7B237E500A8EC9D000580F30 /* files.h */,
- 7B237E510A8EC9D000580F30 /* fight.h */,
+ 7B237E050A8EC9D000580F30 /* describe.h */,
+ 7B237E0F0A8EC9D000580F30 /* direct.cc */,
+ 7B237E1B0A8EC9D000580F30 /* direct.h */,
+ 7B237E670A8EC9D000580F30 /* dungeon.cc */,
+ 7B237E100A8EC9D000580F30 /* dungeon.h */,
7B237E520A8EC9D000580F30 /* effects.cc */,
+ 7B237E0C0A8EC9D000580F30 /* effects.h */,
7B237E530A8EC9D000580F30 /* fight.cc */,
+ 7B237E510A8EC9D000580F30 /* fight.h */,
+ 7B237E0E0A8EC9D000580F30 /* files.cc */,
+ 7B237E500A8EC9D000580F30 /* files.h */,
7B237E540A8EC9D000580F30 /* food.cc */,
7B237E550A8EC9D000580F30 /* food.h */,
- 7B237E560A8EC9D000580F30 /* clua.h */,
- 7B237E570A8EC9D000580F30 /* clua.cc */,
- 7B237E580A8EC9D000580F30 /* cloud.h */,
- 7B237E590A8EC9D000580F30 /* cloud.cc */,
- 7B237E5A0A8EC9D000580F30 /* items.cc */,
- 7B237E5B0A8EC9D000580F30 /* itemname.h */,
- 7B237E5C0A8EC9D000580F30 /* skills.h */,
- 7B237E5D0A8EC9D000580F30 /* skills.cc */,
- 7B237E5E0A8EC9D000580F30 /* shopping.h */,
- 7B237E5F0A8EC9D000580F30 /* it_use2.cc */,
- 7B237E600A8EC9D000580F30 /* invent.h */,
+ 7B237DF30A8EC9D000580F30 /* hiscores.cc */,
+ 7B237DF20A8EC9D000580F30 /* hiscores.h */,
+ 7B237DF10A8EC9D000580F30 /* initfile.cc */,
+ 7B237DEC0A8EC9D000580F30 /* initfile.h */,
+ 7B237DEB0A8EC9D000580F30 /* insult.cc */,
+ 7B237DEA0A8EC9D000580F30 /* insult.h */,
7B237E610A8EC9D000580F30 /* invent.cc */,
- 7B237E620A8EC9D000580F30 /* libutil.cc */,
- 7B237E630A8EC9D000580F30 /* libunix.h */,
+ 7B237E600A8EC9D000580F30 /* invent.h */,
+ 7B237E5F0A8EC9D000580F30 /* it_use2.cc */,
+ 7B237E020A8EC9D000580F30 /* it_use2.h */,
+ 7B237E010A8EC9D000580F30 /* it_use3.cc */,
+ 7B237E000A8EC9D000580F30 /* it_use3.h */,
+ 7B237E260A8EC9D000580F30 /* item_use.cc */,
+ 7B237DF00A8EC9D000580F30 /* item_use.h */,
+ 7B237E030A8EC9D000580F30 /* itemname.cc */,
+ 7B237E5B0A8EC9D000580F30 /* itemname.h */,
+ 7BC222E50ABBB286003A7D9A /* itemprop.cc */,
+ 7BC222E60ABBB286003A7D9A /* itemprop.h */,
+ 7B237E5A0A8EC9D000580F30 /* items.cc */,
+ 7B237DF80A8EC9D000580F30 /* items.h */,
+ 7B237E4F0A8EC9D000580F30 /* Kills.cc */,
+ 7B237E4E0A8EC9D000580F30 /* Kills.h */,
+ 7B237DF70A8EC9D000580F30 /* lev-pand.cc */,
+ 7B237DF60A8EC9D000580F30 /* lev-pand.h */,
7B237E640A8EC9D000580F30 /* libunix.cc */,
- 7B237E650A8EC9D000580F30 /* abyss.h */,
- 7B237E660A8EC9D000580F30 /* delay.cc */,
- 7B237E670A8EC9D000580F30 /* dungeon.cc */,
- 7B237E680A8EC9D000580F30 /* debug.cc */,
- 7B237E690A8EC9D000580F30 /* mt19937ar.h */,
- 7B237E6A0A8EC9D000580F30 /* mt19937ar.cc */,
+ 7B237E630A8EC9D000580F30 /* libunix.h */,
+ 7B237E620A8EC9D000580F30 /* libutil.cc */,
+ 7B237E250A8EC9D000580F30 /* libutil.h */,
+ 7B237E380A8EC9D000580F30 /* macro.cc */,
+ 7B237E190A8EC9D000580F30 /* macro.h */,
+ 7B237DE60A8EC9D000580F30 /* maps.cc */,
+ 7B237DE50A8EC9D000580F30 /* maps.h */,
+ 7B237E370A8EC9D000580F30 /* menu.cc */,
+ 7B237E360A8EC9D000580F30 /* menu.h */,
+ 7B237E350A8EC9D000580F30 /* message.cc */,
+ 7B237DFD0A8EC9D000580F30 /* message.h */,
+ 7B237DFC0A8EC9D000580F30 /* misc.cc */,
+ 7B237DE90A8EC9D000580F30 /* misc.h */,
+ 7B237DE80A8EC9D000580F30 /* mon-pick.cc */,
+ 7B237DE70A8EC9D000580F30 /* mon-pick.h */,
+ 7B237DFF0A8EC9D000580F30 /* mon-util.cc */,
+ 7B237DFE0A8EC9D000580F30 /* mon-util.h */,
+ 7B237E4D0A8EC9D000580F30 /* monplace.cc */,
+ 7B237E4C0A8EC9D000580F30 /* monplace.h */,
+ 7B237E4B0A8EC9D000580F30 /* monspeak.cc */,
+ 7B237E420A8EC9D000580F30 /* monspeak.h */,
+ 7B237E410A8EC9D000580F30 /* monstuff.cc */,
+ 7B237E400A8EC9D000580F30 /* monstuff.h */,
+ 7B237E3F0A8EC9D000580F30 /* mstuff2.cc */,
7B237E6B0A8EC9D000580F30 /* mstuff2.h */,
+ 7B237E6A0A8EC9D000580F30 /* mt19937ar.cc */,
+ 7B237E690A8EC9D000580F30 /* mt19937ar.h */,
+ 7B237DFB0A8EC9D000580F30 /* mutation.cc */,
+ 7B237DFA0A8EC9D000580F30 /* mutation.h */,
+ 7B237DF90A8EC9D000580F30 /* newgame.cc */,
+ 7B237E340A8EC9D000580F30 /* newgame.h */,
+ 7BD75A330AC214A200B74F6E /* notes.cc */,
+ 7BD75A340AC214A200B74F6E /* notes.h */,
+ 7B237E330A8EC9D000580F30 /* ouch.cc */,
+ 7B237E320A8EC9D000580F30 /* ouch.h */,
+ 7B237E310A8EC9D000580F30 /* output.cc */,
+ 7B237DEF0A8EC9D000580F30 /* output.h */,
+ 7B237DEE0A8EC9D000580F30 /* overmap.cc */,
+ 7B237DED0A8EC9D000580F30 /* overmap.h */,
+ 7B237E0B0A8EC9D000580F30 /* player.cc */,
+ 7B237E0A0A8EC9D000580F30 /* player.h */,
+ 7B237E090A8EC9D000580F30 /* randart.cc */,
+ 7B237E080A8EC9D000580F30 /* randart.h */,
+ 7B237E3B0A8EC9D000580F30 /* religion.cc */,
+ 7B237E3A0A8EC9D000580F30 /* religion.h */,
+ 7B237E390A8EC9D000580F30 /* shopping.cc */,
+ 7B237E5E0A8EC9D000580F30 /* shopping.h */,
+ 7B237E5D0A8EC9D000580F30 /* skills.cc */,
+ 7B237E5C0A8EC9D000580F30 /* skills.h */,
+ 7B237E480A8EC9D000580F30 /* skills2.cc */,
+ 7B237E470A8EC9D000580F30 /* skills2.h */,
+ 7B237E460A8EC9D000580F30 /* spells1.cc */,
+ 7B237E450A8EC9D000580F30 /* spells1.h */,
+ 7B237E3E0A8EC9D000580F30 /* spells2.cc */,
+ 7B237E3D0A8EC9D000580F30 /* spells2.h */,
+ 7B237E3C0A8EC9D000580F30 /* spells3.cc */,
+ 7B237E180A8EC9D000580F30 /* spells3.h */,
+ 7B237E170A8EC9D000580F30 /* spells4.cc */,
+ 7B237E160A8EC9D000580F30 /* spells4.h */,
+ 7B237E150A8EC9D000580F30 /* spl-book.cc */,
+ 7B237E300A8EC9D000580F30 /* spl-book.h */,
+ 7B237E2F0A8EC9D000580F30 /* spl-cast.cc */,
+ 7B237E2E0A8EC9D000580F30 /* spl-cast.h */,
+ 7B237E070A8EC9D000580F30 /* spl-util.cc */,
+ 7B237E060A8EC9D000580F30 /* spl-util.h */,
+ 7B237E200A8EC9D000580F30 /* stash.cc */,
+ 7B237E1F0A8EC9D000580F30 /* stash.h */,
+ 7B237E1E0A8EC9D000580F30 /* stuff.cc */,
+ 7B237E1D0A8EC9D000580F30 /* stuff.h */,
+ 7B237E240A8EC9D000580F30 /* tags.cc */,
+ 7B237E230A8EC9D000580F30 /* tags.h */,
+ 7B237E220A8EC9D000580F30 /* transfor.cc */,
+ 7B237E210A8EC9D000580F30 /* transfor.h */,
+ 7B237DF50A8EC9D000580F30 /* travel.cc */,
+ 7B237DF40A8EC9D000580F30 /* travel.h */,
+ 7B237E140A8EC9D000580F30 /* view.cc */,
+ 7B237E130A8EC9D000580F30 /* view.h */,
);
- name = Source;
+ name = Crawl;
sourceTree = "<group>";
};
- 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ 7B352EF30B001FA700CABB32 /* Shared */ = {
isa = PBXGroup;
children = (
- 8DD76FB20486AB0100D96B5E /* crawl */,
+ 7B352E9D0B00183400CABB32 /* mapdef.cc */,
+ 7B352E9E0B00183400CABB32 /* mapdef.h */,
);
- name = Products;
+ name = Shared;
sourceTree = "<group>";
};
- 7B237F120A8ECCDE00580F30 /* Libraries */ = {
+ 7B352F1B0B0022C900CABB32 /* Resources */ = {
isa = PBXGroup;
children = (
- 7B237F140A8ECD2E00580F30 /* libncurses.5.dylib */,
+ 7B352F1E0B0022E100CABB32 /* Levels */,
);
- name = Libraries;
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 7B352F1E0B0022E100CABB32 /* Levels */ = {
+ isa = PBXGroup;
+ children = (
+ 7B352F1F0B00232500CABB32 /* splev.des */,
+ 7B352F200B00232500CABB32 /* vaults.des */,
+ );
+ name = Levels;
sourceTree = "<group>";
};
C6A0FF2B0290797F04C91782 /* Documentation */ = {
@@ -593,6 +660,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 7BBC4A080B0F783C00F27D45 /* levcomp.ypp in Sources */,
+ 7BBC4A070B0F783C00F27D45 /* levcomp.lpp in Sources */,
7B237E6D0A8EC9D000580F30 /* maps.cc in Sources */,
7B237E6F0A8EC9D000580F30 /* mon-pick.cc in Sources */,
7B237E720A8EC9D000580F30 /* insult.cc in Sources */,
@@ -600,6 +669,7 @@
7B237E780A8EC9D000580F30 /* initfile.cc in Sources */,
7B237E7A0A8EC9D000580F30 /* hiscores.cc in Sources */,
7B237E7C0A8EC9D000580F30 /* travel.cc in Sources */,
+ 7BBC4A060B0F782800F27D45 /* levcomp.cc in Sources */,
7B237E7E0A8EC9D000580F30 /* lev-pand.cc in Sources */,
7B237E800A8EC9D000580F30 /* newgame.cc in Sources */,
7B237E820A8EC9D000580F30 /* mutation.cc in Sources */,
@@ -614,7 +684,6 @@
7B237E940A8EC9D000580F30 /* abl-show.cc in Sources */,
7B237E950A8EC9D000580F30 /* files.cc in Sources */,
7B237E960A8EC9D000580F30 /* direct.cc in Sources */,
- 7B237E990A8EC9D000580F30 /* wpn-misc.cc in Sources */,
7B237E9B0A8EC9D000580F30 /* view.cc in Sources */,
7B237E9C0A8EC9D000580F30 /* spl-book.cc in Sources */,
7B237E9E0A8EC9D000580F30 /* spells4.cc in Sources */,
@@ -661,6 +730,9 @@
7B237EEE0A8EC9D000580F30 /* dungeon.cc in Sources */,
7B237EEF0A8EC9D000580F30 /* debug.cc in Sources */,
7B237EF10A8EC9D000580F30 /* mt19937ar.cc in Sources */,
+ 7BC222E70ABBB286003A7D9A /* itemprop.cc in Sources */,
+ 7BD75A350AC214A200B74F6E /* notes.cc in Sources */,
+ 7B352EA00B00183400CABB32 /* mapdef.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -674,7 +746,10 @@
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_OPTIMIZATION_LEVEL = 1;
GCC_PREPROCESSOR_DEFINITIONS = OSX;
+ GCC_WARN_UNUSED_FUNCTION = NO;
+ GCC_WARN_UNUSED_LABEL = NO;
PRODUCT_NAME = crawl;
+ YACC_GENERATED_FILE_STEM = InputFileStem;
ZERO_LINK = YES;
};
name = Development;
@@ -688,17 +763,22 @@
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
+ GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
GCC_WARN_MISSING_PARENTHESES = YES;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
GCC_WARN_PEDANTIC = YES;
- GCC_WARN_SHADOW = NO;
+ GCC_WARN_SHADOW = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_VALUE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET_i386 = 10.4;
+ MACOSX_DEPLOYMENT_TARGET_ppc = 10.3;
PREBINDING = NO;
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
};
@@ -717,7 +797,10 @@
DEBUG_ITEM_SCAN,
FULLDEBUG,
);
+ GCC_WARN_UNUSED_FUNCTION = NO;
+ GCC_WARN_UNUSED_LABEL = NO;
PRODUCT_NAME = crawl;
+ YACC_GENERATED_FILE_STEM = InputFileStem;
ZERO_LINK = YES;
};
name = Debug;
@@ -736,9 +819,23 @@
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
+ GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_MISSING_PARENTHESES = YES;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+ GCC_WARN_PEDANTIC = YES;
+ GCC_WARN_SHADOW = YES;
+ GCC_WARN_SIGN_COMPARE = YES;
+ GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_LABEL = YES;
+ GCC_WARN_UNUSED_VALUE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET_i386 = 10.4;
+ MACOSX_DEPLOYMENT_TARGET_ppc = 10.3;
PREBINDING = NO;
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
};
@@ -756,7 +853,10 @@
DEBUG,
DEBUG_ITEM_SCAN,
);
+ GCC_WARN_UNUSED_FUNCTION = NO;
+ GCC_WARN_UNUSED_LABEL = NO;
PRODUCT_NAME = crawl;
+ YACC_GENERATED_FILE_STEM = InputFileStem;
ZERO_LINK = YES;
};
name = Wizard;
@@ -774,9 +874,23 @@
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
+ GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_MISSING_PARENTHESES = YES;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+ GCC_WARN_PEDANTIC = YES;
+ GCC_WARN_SHADOW = YES;
+ GCC_WARN_SIGN_COMPARE = YES;
+ GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_LABEL = YES;
+ GCC_WARN_UNUSED_VALUE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET_i386 = 10.4;
+ MACOSX_DEPLOYMENT_TARGET_ppc = 10.3;
PREBINDING = NO;
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
};
@@ -793,7 +907,10 @@
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_OPTIMIZATION_LEVEL = 1;
GCC_PREPROCESSOR_DEFINITIONS = OSX;
+ GCC_WARN_UNUSED_FUNCTION = NO;
+ GCC_WARN_UNUSED_LABEL = NO;
PRODUCT_NAME = crawl;
+ YACC_GENERATED_FILE_STEM = InputFileStem;
ZERO_LINK = NO;
};
name = Release;
@@ -810,9 +927,23 @@
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
+ GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_MISSING_PARENTHESES = YES;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+ GCC_WARN_PEDANTIC = YES;
+ GCC_WARN_SHADOW = YES;
+ GCC_WARN_SIGN_COMPARE = YES;
+ GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_LABEL = YES;
+ GCC_WARN_UNUSED_VALUE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET_i386 = 10.4;
+ MACOSX_DEPLOYMENT_TARGET_ppc = 10.3;
PREBINDING = NO;
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
};
diff --git a/crawl-ref/source/FixAry.h b/crawl-ref/source/FixAry.h
index 99f802e2f3..4270949150 100644
--- a/crawl-ref/source/FixAry.h
+++ b/crawl-ref/source/FixAry.h
@@ -3,6 +3,8 @@
* Summary: Fixed size 2D vector class that asserts if you do something bad.
* Written by: Jesse Jones
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> 6/16/00 JDJ Created
diff --git a/crawl-ref/source/FixVec.h b/crawl-ref/source/FixVec.h
index b0afb34e82..176ced5cf4 100644
--- a/crawl-ref/source/FixVec.h
+++ b/crawl-ref/source/FixVec.h
@@ -12,7 +12,8 @@
#ifndef FIXVEC_H
#define FIXVEC_H
-#include <stdarg.h>
+#include <cstdarg>
+#include <cstring>
#include "debug.h"
@@ -39,16 +40,6 @@ public:
typedef TYPE* iterator;
typedef const TYPE* const_iterator;
-#if 0
-#if MSVC >= 1100
- typedef std::reverse_iterator<const_iterator, const TYPE> const_reverse_iterator;
- typedef std::reverse_iterator<iterator, TYPE> reverse_iterator;
-#else
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
-#endif
-#endif
-
//-----------------------------------
// Initialization/Destruction
//
@@ -57,6 +48,10 @@ public:
FixedVector() {}
+ FixedVector(TYPE def) : mData() {
+ init(def);
+ }
+
FixedVector(TYPE value0, TYPE value1, ...);
// Allows for something resembling C array initialization, eg
// instead of "int a[3] = {0, 1, 2}" you'd use "FixedVector<int, 3>
@@ -71,35 +66,31 @@ public:
// API
//
public:
- // ----- Size -----
- bool empty() const {return SIZE == 0;}
- int size() const {return SIZE;}
-
- // ----- Access -----
- TYPE& operator[](unsigned long index) {ASSERT(index < SIZE); return mData[index];}
- const TYPE& operator[](unsigned long index) const {ASSERT(index < SIZE); return mData[index];}
-
- TYPE& front() {ASSERT(SIZE > 0); return mData[0];}
- const TYPE& front() const {ASSERT(SIZE > 0); return mData[0];}
-
- TYPE& back() {ASSERT(SIZE > 0); return mData[SIZE - 1];}
- const TYPE& back() const {ASSERT(SIZE > 0); return mData[SIZE - 1];}
-
- TYPE* buffer() {return mData;}
- const TYPE* buffer() const {return mData;}
-
- // ----- Iterating -----
- iterator begin() {return mData;}
- const_iterator begin() const {return mData;}
-
- iterator end() {return this->begin() + this->size();}
- const_iterator end() const {return this->begin() + this->size();}
-
-// reverse_iterator rbegin() {return reverse_iterator(this->end());}
-// const_reverse_iterator rbegin() const {return const_reverse_iterator(this->end());}
-
-// reverse_iterator rend() {return reverse_iterator(this->begin());}
-// const_reverse_iterator rend() const {return const_reverse_iterator(this->begin());}
+// ----- Size -----
+ bool empty() const {return SIZE == 0;}
+ size_t size() const {return SIZE;}
+
+// ----- Access -----
+ TYPE& operator[](unsigned long index) {ASSERT(index < SIZE); return mData[index];}
+ const TYPE& operator[](unsigned long index) const {ASSERT(index < SIZE); return mData[index];}
+
+ TYPE& front() {ASSERT(SIZE > 0); return mData[0];}
+ const TYPE& front() const {ASSERT(SIZE > 0); return mData[0];}
+
+ TYPE& back() {ASSERT(SIZE > 0); return mData[SIZE - 1];}
+ const TYPE& back() const {ASSERT(SIZE > 0); return mData[SIZE - 1];}
+
+ TYPE* buffer() {return mData;}
+ const TYPE* buffer() const {return mData;}
+
+// ----- Iterating -----
+ iterator begin() {return mData;}
+ const_iterator begin() const {return mData;}
+
+ iterator end() {return this->begin() + this->size();}
+ const_iterator end() const {return this->begin() + this->size();}
+
+ void init(TYPE def);
//-----------------------------------
// Member Data
@@ -115,19 +106,26 @@ protected:
template <class TYPE, int SIZE>
FixedVector<TYPE, SIZE>::FixedVector(TYPE value0, TYPE value1, ...)
{
- mData[0] = value0;
- mData[1] = value1;
+ mData[0] = value0;
+ mData[1] = value1;
+
+ va_list ap;
+ va_start(ap, value1); // second argument is last fixed parameter
- va_list ap;
- va_start(ap, value1); // second argument is last fixed parameter
+ for (int index = 2; index < SIZE; index++) {
+ TYPE value = va_arg(ap, TYPE);
- for (int index = 2; index < SIZE; index++) {
- TYPE value = va_arg(ap, TYPE);
+ mData[index] = value;
+ }
- mData[index] = value;
- }
+ va_end(ap);
+}
- va_end(ap);
+template <class TYPE, int SIZE>
+void FixedVector<TYPE, SIZE>::init(TYPE def)
+{
+ for (int i = 0; i < SIZE; ++i)
+ mData[i] = def;
}
#endif // FIXVEC_H
diff --git a/crawl-ref/source/Kills.cc b/crawl-ref/source/Kills.cc
index 4a1eaa0ebf..bd1936db50 100644
--- a/crawl-ref/source/Kills.cc
+++ b/crawl-ref/source/Kills.cc
@@ -2,18 +2,23 @@
* File: Kills.cc
* Summary: Player kill tracking
* Written by: Darshan Shaligram
+ *
+ * Modified for Crawl Reference by $Author$ on $Date$
*/
#include "AppHdr.h"
+
+#include <algorithm>
+
#include "chardump.h"
#include "describe.h"
#include "mon-util.h"
#include "files.h"
#include "itemname.h"
+#include "misc.h"
#include "travel.h"
#include "tags.h"
#include "Kills.h"
#include "clua.h"
-#include <algorithm>
#define KILLS_MAJOR_VERSION 4
#define KILLS_MINOR_VERSION 1
@@ -22,25 +27,6 @@
static void kill_lua_filltable(std::vector<kill_exp> &v);
#endif
-
-unsigned short get_packed_place( unsigned char branch, int subdepth,
- char level_type )
-{
- unsigned short place = (unsigned short)
- ( (branch << 8) | subdepth );
- if (level_type == LEVEL_ABYSS || level_type == LEVEL_PANDEMONIUM
- || level_type == LEVEL_LABYRINTH)
- place = (unsigned short) ( (level_type << 8) | 0xFF );
- return place;
-}
-
-unsigned short get_packed_place()
-{
- return get_packed_place( you.where_are_you,
- subdungeon_depth(you.where_are_you, you.your_level),
- you.level_type );
-}
-
///////////////////////////////////////////////////////////////////////////
// KillMaster
//
@@ -52,7 +38,7 @@ const char *kill_category_names[] =
"others",
};
-const char *KillMaster::category_name(KillCategory kc) const
+const char *KillMaster::category_name(kill_category kc) const
{
if (kc >= KC_YOU && kc < KC_NCATEGORIES)
return (kill_category_names[kc]);
@@ -95,7 +81,7 @@ void KillMaster::load(FILE *file)
void KillMaster::record_kill(const monsters *mon, int killer, bool ispet)
{
- KillCategory kc =
+ kill_category kc =
(killer == KILL_YOU || killer == KILL_YOU_MISSILE)? KC_YOU :
(ispet)? KC_FRIENDLY :
KC_OTHER;
@@ -134,7 +120,7 @@ std::string KillMaster::kill_info() const
kills,
count,
i == KC_YOU? NULL :
- category_name((KillCategory) i),
+ category_name((kill_category) i),
needseparator );
needseparator = true;
}
@@ -155,13 +141,11 @@ std::string KillMaster::kill_info() const
#endif
{
// We can sum up ourselves, if Lua doesn't want to.
- // FIXME: I'm not happy with the looks/wording of the grand total
- // count.
if (categories > 1)
{
// Give ourselves a newline first
- killtext += EOL;
- killtext += grandt + EOL;
+ killtext += "\n";
+ killtext += grandt + "\n";
}
}
@@ -201,23 +185,23 @@ void KillMaster::add_kill_info(std::string &killtext,
}
#endif
if (separator)
- killtext += EOL;
+ killtext += "\n";
killtext += "Vanquished Creatures";
if (category)
killtext += std::string(" (") + category + ")";
- killtext += EOL;
+ killtext += "\n";
for (int i = 0, sz = kills.size(); i < sz; ++i)
{
killtext += " " + kills[i].desc;
- killtext += EOL;
+ killtext += "\n";
}
{
char numbuf[100];
snprintf(numbuf, sizeof numbuf,
- "%ld creature%s vanquished." EOL, count,
+ "%ld creature%s vanquished." "\n", count,
count > 1? "s" : "");
killtext += numbuf;
}
@@ -240,10 +224,10 @@ void Kills::merge(const Kills &k)
i != k.kills.end(); ++i)
{
const kill_monster_desc &kmd = i->first;
- kill_def &k = kills[kmd];
+ kill_def &ki = kills[kmd];
const kill_def &ko = i->second;
bool uniq = mons_is_unique(kmd.monnum);
- k.merge(ko, uniq);
+ ki.merge(ko, uniq);
}
}
@@ -290,85 +274,13 @@ long Kills::get_kills(std::vector<kill_exp> &all_kills) const
return (count);
}
-// Takes a packed 'place' and returns a compact stringified place name.
-// XXX: This is done in several other places; a unified function to
-// describe places would be nice.
-std::string short_place_name(unsigned short place)
-{
- unsigned char branch = (unsigned char) ((place >> 8) & 0xFF);
- int lev = place & 0xFF;
-
- const char *s;
- bool level_num = false;
- if (lev == 0xFF)
- {
- switch (branch)
- {
- case LEVEL_ABYSS:
- s = "Abyss";
- break;
- case LEVEL_PANDEMONIUM:
- s = "Pan";
- break;
- case LEVEL_LABYRINTH:
- s = "Lab";
- break;
- default:
- s = "Buggy Badlands";
- break;
- }
- }
- else
- {
- switch (branch)
- {
- case BRANCH_VESTIBULE_OF_HELL:
- s = "Hell";
- break;
- case BRANCH_HALL_OF_BLADES:
- s = "Blade";
- break;
- case BRANCH_ECUMENICAL_TEMPLE:
- s = "Temple";
- break;
- default:
- level_num = true;
- s = (branch == BRANCH_DIS) ? "Dis:" :
- (branch == BRANCH_GEHENNA) ? "Geh:" :
- (branch == BRANCH_COCYTUS) ? "Coc:" :
- (branch == BRANCH_TARTARUS) ? "Tar:" :
- (branch == BRANCH_ORCISH_MINES) ? "Orc:" :
- (branch == BRANCH_HIVE) ? "Hive:" :
- (branch == BRANCH_LAIR) ? "Lair:" :
- (branch == BRANCH_SLIME_PITS) ? "Slime:" :
- (branch == BRANCH_VAULTS) ? "Vault:" :
- (branch == BRANCH_CRYPT) ? "Crypt:" :
- (branch == BRANCH_HALL_OF_ZOT) ? "Zot:" :
- (branch == BRANCH_SNAKE_PIT) ? "Snake:" :
- (branch == BRANCH_ELVEN_HALLS) ? "Elf:" :
- (branch == BRANCH_TOMB) ? "Tomb:" :
- (branch == BRANCH_SWAMP) ? "Swamp:" : "D:";
- break;
- }
- }
-
- std::string pl = s;
- if (level_num)
- {
- char buf[20];
- snprintf(buf, sizeof buf, "%d", lev);
- pl += buf;
- }
- return pl;
-}
-
void Kills::save(FILE *file) const
{
// How many kill records do we have?
writeLong(file, kills.size());
- kill_map::const_iterator iter = kills.begin();
- for ( ; iter != kills.end(); ++iter)
+ for ( kill_map::const_iterator iter = kills.begin();
+ iter != kills.end(); ++iter)
{
iter->first.save(file);
iter->second.save(file);
@@ -377,7 +289,7 @@ void Kills::save(FILE *file) const
// How many ghosts do we have?
writeShort(file, ghosts.size());
for (ghost_vec::const_iterator iter = ghosts.begin();
- iter != ghosts.end(); ++iter)
+ iter != ghosts.end(); ++iter)
{
iter->save(file);
}
@@ -407,13 +319,13 @@ void Kills::load(FILE *file)
void Kills::record_ghost_kill(const struct monsters *mon)
{
- kill_ghost ghost(mon);
- ghosts.push_back(ghost);
+ kill_ghost ghostk(mon);
+ ghosts.push_back(ghostk);
}
kill_def::kill_def(const struct monsters *mon) : kills(0), exp(0)
{
- exp = exper_value( (struct monsters *) mon);
+ exp = exper_value(mon);
add_kill(mon, get_packed_place());
}
@@ -460,9 +372,7 @@ static std::string pluralize(const std::string &name,
// whole name is not suffixed by a modifier, such as 'zombie' or 'skeleton'
if ( (pos = name.find(" of ")) != std::string::npos
&& !ends_with(name, no_of) )
- {
return pluralize(name.substr(0, pos)) + name.substr(pos);
- }
else if (ends_with(name, "us"))
// Fungus, ufetubus, for instance.
return name.substr(0, name.length() - 2) + "i";
@@ -704,7 +614,7 @@ void kill_def::load(FILE *file)
kill_ghost::kill_ghost(const struct monsters *mon)
{
- exp = exper_value( (struct monsters *) mon);
+ exp = exper_value(mon);
place = get_packed_place();
ghost_name = ghost.name;
@@ -738,7 +648,6 @@ void kill_ghost::load(FILE *file)
kill_monster_desc::kill_monster_desc(const monsters *mon)
{
- // TODO: We need to understand how shapeshifters are handled.
monnum = mon->type;
modifier = M_NORMAL;
switch (mon->type)
@@ -758,8 +667,8 @@ kill_monster_desc::kill_monster_desc(const monsters *mon)
}
if (modifier != M_NORMAL) monnum = mon->number;
- if (mons_has_ench((struct monsters *) mon, ENCH_SHAPESHIFTER) ||
- mons_has_ench((struct monsters *) mon, ENCH_GLOWING_SHAPESHIFTER))
+ if (mons_has_ench(mon, ENCH_SHAPESHIFTER) ||
+ mons_has_ench(mon, ENCH_GLOWING_SHAPESHIFTER))
modifier = M_SHAPESHIFTER;
// XXX: Ugly hack - merge all mimics into one mimic record.
@@ -907,7 +816,7 @@ static int kill_lualc_holiness(lua_State *ls)
}
else
{
- switch (mons_holiness(ke->monnum))
+ switch (mons_class_holiness(ke->monnum))
{
case MH_HOLY: verdict = "holy"; break;
case MH_NATURAL: verdict = "natural"; break;
@@ -985,7 +894,7 @@ static int kill_lualc_rawwrite(lua_State *ls)
*skill += s;
*skill += "\n";
-
+
return 0;
}
diff --git a/crawl-ref/source/Kills.h b/crawl-ref/source/Kills.h
index 28c30a88c8..f3ada4fe40 100644
--- a/crawl-ref/source/Kills.h
+++ b/crawl-ref/source/Kills.h
@@ -160,7 +160,7 @@ public:
std::string kill_info() const;
private:
- const char *category_name(KillCategory kc) const;
+ const char *category_name(kill_category kc) const;
Kills categorized_kills[KC_NCATEGORIES];
private:
@@ -169,13 +169,6 @@ private:
const;
};
-unsigned short get_packed_place();
-
-unsigned short get_packed_place( unsigned char branch, int subdepth,
- char level_type );
-
-std::string short_place_name(unsigned short place);
-
enum KILL_DUMP_OPTIONS
{
KDO_NO_PLACES, // Don't dump places at all
diff --git a/crawl-ref/source/MacString.cc b/crawl-ref/source/MacString.cc
deleted file mode 100644
index 2d5c14442e..0000000000
--- a/crawl-ref/source/MacString.cc
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * File: MacString.cc
- * Summary: Wrapper around an immutable CFString.
- * Written by: Jesse Jones (jesjones@mindspring.com)
- *
- * Change History (most recent first):
- *
- * <1> 6/04/02 JDJ Created
- */
-
-#include "AppHdr.h"
-#include "MacString.h"
-
-#if macintosh
-
-#include <CoreFoundation/CFString.h>
-
-#include "debug.h"
-
-
-// ========================================================================
-// Internal Functions
-// ========================================================================
-
-//---------------------------------------------------------------
-//
-// ThrowIf
-//
-//---------------------------------------------------------------
-static void ThrowIf(bool predicate, const std::string& text)
-{
- if (predicate)
- throw std::runtime_error(text);
-}
-
-#if __MWERKS__
-#pragma mark -
-#endif
-
-// ============================================================================
-// class MacString
-// ============================================================================
-
-//---------------------------------------------------------------
-//
-// MacString::~MacString
-//
-//---------------------------------------------------------------
-MacString::~MacString()
-{
- CFRelease(mString);
-}
-
-
-//---------------------------------------------------------------
-//
-// MacString::MacString ()
-//
-//---------------------------------------------------------------
-MacString::MacString()
-{
- mString = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, NULL, 0);
- ThrowIf(mString == NULL, "Couldn't create the CFString");
-}
-
-
-//---------------------------------------------------------------
-//
-// MacString::MacString (unsigned char*)
-//
-//---------------------------------------------------------------
-MacString::MacString(const unsigned char* str)
-{
- ASSERT(str != NULL);
-
- CFStringEncoding encoding = CFStringGetSystemEncoding();
- mString = CFStringCreateWithPascalString(kCFAllocatorSystemDefault, str, encoding);
- ThrowIf(mString == NULL, "Couldn't create the CFString");
-}
-
-
-//---------------------------------------------------------------
-//
-// MacString::MacString (char*)
-//
-//---------------------------------------------------------------
-MacString::MacString(const char* str)
-{
- ASSERT(str != NULL);
-
- CFStringEncoding encoding = CFStringGetSystemEncoding();
- mString = CFStringCreateWithCString(kCFAllocatorSystemDefault, str, encoding);
- ThrowIf(mString == NULL, "Couldn't create the CFString");
-}
-
-
-//---------------------------------------------------------------
-//
-// MacString::MacString (CFStringRef)
-//
-//---------------------------------------------------------------
-MacString::MacString(CFStringRef str)
-{
- ASSERT(str != NULL);
-
- mString = str;
- CFRetain(mString);
-}
-
-
-//---------------------------------------------------------------
-//
-// MacString::MacString (CFMutableStringRef)
-//
-//---------------------------------------------------------------
-MacString::MacString(CFMutableStringRef str)
-{
- ASSERT(str != NULL);
-
- mString = CFStringCreateCopy(kCFAllocatorSystemDefault, str);
- ThrowIf(mString == NULL, "Couldn't create the CFString");
-}
-
-
-//---------------------------------------------------------------
-//
-// MacString::MacString (int)
-//
-//---------------------------------------------------------------
-MacString::MacString(int value)
-{
- char buffer[32];
- sprintf(buffer, "%d", value);
-
- CFStringEncoding encoding = CFStringGetSystemEncoding();
- mString = CFStringCreateWithCString(kCFAllocatorSystemDefault, buffer, encoding);
- ThrowIf(mString == NULL, "Couldn't create the CFString");
-}
-
-
-//---------------------------------------------------------------
-//
-// MacString::MacString (MacString)
-//
-//---------------------------------------------------------------
-MacString::MacString(const MacString& str)
-{
- mString = str.mString; // immutable so we can refcount
- CFRetain(mString);
-}
-
-
-//---------------------------------------------------------------
-//
-// MacString::operator= (MacString)
-//
-//---------------------------------------------------------------
-MacString& MacString::operator=(const MacString& rhs)
-{
- if (this != &rhs)
- {
- CFRelease(mString);
-
- mString = rhs.mString; // immutable so we can refcount
- CFRetain(mString);
- }
-
- return *this;
-}
-
-
-//---------------------------------------------------------------
-//
-// MacString::length
-//
-//---------------------------------------------------------------
-size_t MacString::length() const
-{
- size_t len = (size_t) CFStringGetLength(mString);
-
- return len;
-}
-
-
-//---------------------------------------------------------------
-//
-// MacString::CopyTo
-//
-//---------------------------------------------------------------
-void MacString::CopyTo(unsigned char* buffer, CFIndex bytes)
-{
- ASSERT(buffer != NULL || bytes == 0);
-
- bool converted = CFStringGetPascalString(mString, buffer, bytes, CFStringGetSystemEncoding());
- ThrowIf(!converted, "Couldn't convert the CFString into a Pascal string");
-}
-
-
-#endif // macintosh
diff --git a/crawl-ref/source/MacString.h b/crawl-ref/source/MacString.h
deleted file mode 100644
index d2cad4b1be..0000000000
--- a/crawl-ref/source/MacString.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * File: MacString.h
- * Summary: Wrapper around an immutable CFString.
- * Written by: Jesse Jones (jesjones@mindspring.com)
- *
- * Change History (most recent first):
- *
- * <1> 6/04/02 JDJ Created
- */
-
-#ifndef MAC_STRING_H
-#define MAC_STRING_H
-
-#if macintosh
-
-#include <CoreFoundation/CFBase.h>
-
-
-// ============================================================================
-// class MacString
-//! Wrapper around an immutable CFString.
-// ============================================================================
-class MacString {
-
-//-----------------------------------
-// Initialization/Destruction
-//
-public:
- ~MacString();
-
- MacString();
-
- MacString(const char* str);
- MacString(const unsigned char* str);
- /**< Uses default system encoding. */
-
- MacString(CFStringRef str);
- /**< Bumps the ref count. */
-
- MacString(CFMutableStringRef str);
- /**< Makes a copy. */
-
- explicit MacString(int value);
-
- MacString(const MacString& str);
- MacString& operator=(const MacString& rhs);
-
-//-----------------------------------
-// API
-//
-public:
- // ----- Size -----
- size_t length() const;
- size_t size() const {return this->length();}
- bool empty() const {return this->length() == 0;}
-
- // ----- Access -----
- void CopyTo(unsigned char* buffer, CFIndex bytes);
-
- operator CFStringRef() const {return mString;}
-
-//-----------------------------------
-// Member Data
-//
-private:
- CFStringRef mString;
-};
-
-
-#endif // macintosh
-#endif // MAC_STRING_H
diff --git a/crawl-ref/source/abl-show.cc b/crawl-ref/source/abl-show.cc
index 64a1c10e74..d321365e74 100644
--- a/crawl-ref/source/abl-show.cc
+++ b/crawl-ref/source/abl-show.cc
@@ -105,12 +105,11 @@ static const struct ability_def Ability_List[] =
{ ABIL_BREATHE_STICKY_FLAME, "Breathe Sticky Flame", 0, 0, 125, 0, ABFLAG_BREATH },
{ ABIL_BREATHE_STEAM, "Breathe Steam", 0, 0, 75, 0, ABFLAG_BREATH },
- // Handled with breath weapons, but doesn't cause a breathing delay
- { ABIL_SPIT_ACID, "Spit Acid", 0, 0, 125, 0, ABFLAG_NONE },
+ { ABIL_SPIT_ACID, "Spit Acid", 0, 0, 125, 0, ABFLAG_BREATH },
{ ABIL_FLY, "Fly", 3, 0, 100, 0, ABFLAG_NONE },
{ ABIL_SUMMON_MINOR_DEMON, "Summon Minor Demon", 3, 3, 75, 0, ABFLAG_NONE },
- { ABIL_SUMMON_DEMON, "Summon Demon", 5, 5, 150, 0, ABFLAG_NONE },
+ { ABIL_SUMMON_DEMONS, "Summon Demons", 5, 5, 150, 0, ABFLAG_NONE },
{ ABIL_HELLFIRE, "Hellfire", 8, 8, 200, 0, ABFLAG_NONE },
{ ABIL_TORMENT, "Torment", 9, 0, 250, 0, ABFLAG_PAIN },
{ ABIL_RAISE_DEAD, "Raise Dead", 5, 5, 150, 0, ABFLAG_NONE },
@@ -160,7 +159,7 @@ static const struct ability_def Ability_List[] =
{ ABIL_TSO_REPEL_UNDEAD, "Repel Undead", 1, 0, 100, 0, ABFLAG_NONE },
{ ABIL_TSO_SMITING, "Smiting", 3, 0, 50, 2, ABFLAG_NONE },
{ ABIL_TSO_ANNIHILATE_UNDEAD, "Annihilate Undead", 3, 0, 50, 2, ABFLAG_NONE },
- { ABIL_TSO_THUNDERBOLT, "Thunderbolt", 5, 0, 100, 2, ABFLAG_NONE },
+ { ABIL_TSO_CLEANSING_FLAME, "Cleansing Flame", 5, 0, 100, 2, ABFLAG_NONE },
{ ABIL_TSO_SUMMON_DAEVA, "Summon Daeva", 8, 0, 150, 4, ABFLAG_NONE },
// Kikubaaqudgha
@@ -175,9 +174,6 @@ static const struct ability_def Ability_List[] =
{ ABIL_YRED_DRAIN_LIFE, "Drain Life", 6, 0, 200, 2, ABFLAG_NONE },
{ ABIL_YRED_CONTROL_UNDEAD, "Control Undead", 5, 0, 150, 2, ABFLAG_NONE },
- // Vehumet
- { ABIL_VEHUMET_CHANNEL_ENERGY, "Channel Energy", 0, 0, 50, 0, ABFLAG_NONE },
-
// Okawaru
{ ABIL_OKAWARU_MIGHT, "Might", 2, 0, 50, 1, ABFLAG_NONE },
{ ABIL_OKAWARU_HEALING, "Healing", 2, 0, 75, 1, ABFLAG_NONE },
@@ -190,6 +186,7 @@ static const struct ability_def Ability_List[] =
{ ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB, "Greater Servant of Makhleb", 6, 0, 100, 3, ABFLAG_NONE },
// Sif Muna
+ { ABIL_SIF_MUNA_CHANNEL_ENERGY, "Channel Energy", 0, 0, 100, 0, ABFLAG_NONE },
{ ABIL_SIF_MUNA_FORGET_SPELL, "Forget Spell", 5, 0, 0, 8, ABFLAG_NONE },
// Trog
@@ -211,7 +208,6 @@ static const struct ability_def Ability_List[] =
{ ABIL_ROTTING, "Rotting", 4, 4, 0, 2, ABFLAG_NONE },
{ ABIL_TORMENT_II, "Call Torment", 9, 0, 0, 3, ABFLAG_PAIN },
- { ABIL_SHUGGOTH_SEED, "Sow Shuggoth Seed", 12, 8, 0, 6, ABFLAG_NONE },
{ ABIL_RENOUNCE_RELIGION, "Renounce Religion", 0, 0, 0, 0, ABFLAG_NONE },
};
@@ -467,12 +463,10 @@ bool activate_ability(void)
// no turning back now... {dlb}
const struct ability_def abil = get_ability_def(Curr_abil[abil_used].which);
- // currently only delayed fireball is instantaneous -- bwr
- you.turn_is_over = ((abil.flags & ABFLAG_INSTANT) ? 0 : 1);
-
if (random2avg(100, 3) < Curr_abil[abil_used].fail)
{
mpr("You fail to use your ability.");
+ you.turn_is_over = true;
return (false);
}
@@ -576,8 +570,7 @@ bool activate_ability(void)
case ABIL_BREATHE_POWER:
case ABIL_BREATHE_STICKY_FLAME:
case ABIL_BREATHE_STEAM:
- if (you.duration[DUR_BREATH_WEAPON]
- && Curr_abil[abil_used].which != ABIL_SPIT_ACID)
+ if (you.duration[DUR_BREATH_WEAPON])
{
canned_msg(MSG_CANNOT_DO_YET);
return (false);
@@ -643,16 +636,11 @@ bool activate_ability(void)
}
- if (Curr_abil[abil_used].which != ABIL_SPIT_ACID)
- {
- you.duration[DUR_BREATH_WEAPON] = 3 + random2(5)
- + random2(30 - you.experience_level);
- }
+ you.duration[DUR_BREATH_WEAPON] =
+ 3 + random2(4) + random2(30 - you.experience_level) / 2;
if (Curr_abil[abil_used].which == ABIL_BREATHE_STEAM)
- {
you.duration[DUR_BREATH_WEAPON] /= 2;
- }
break;
case ABIL_EVOKE_BLINK: // randarts
@@ -670,8 +658,9 @@ bool activate_ability(void)
return (false);
}
- go_berserk(true);
- exercise( SK_EVOCATIONS, 1 );
+ // only exercise if berserk succeeds
+ if ( go_berserk(true) )
+ exercise( SK_EVOCATIONS, 1 );
break;
// fly (kenku) -- eventually becomes permanent (see acr.cc)
@@ -710,13 +699,15 @@ bool activate_ability(void)
summon_any_demon(DEMON_LESSER) );
break;
- case ABIL_SUMMON_DEMON:
+ case ABIL_SUMMON_DEMONS:
summon_ice_beast_etc( you.experience_level * 4,
summon_any_demon(DEMON_COMMON) );
break;
case ABIL_HELLFIRE:
- your_spells(SPELL_HELLFIRE, 20 + you.experience_level, false);
+ if (your_spells(SPELL_HELLFIRE,
+ 20 + you.experience_level, false) == -1)
+ return (false);
break;
case ABIL_TORMENT:
@@ -726,7 +717,7 @@ bool activate_ability(void)
return (false);
}
- torment(you.x_pos, you.y_pos);
+ torment(TORMENT_GENERIC, you.x_pos, you.y_pos);
break;
case ABIL_RAISE_DEAD:
@@ -873,14 +864,14 @@ bool activate_ability(void)
exercise(SK_INVOCATIONS, 2 + random2(4));
break;
- case ABIL_TSO_THUNDERBOLT:
+ case ABIL_TSO_CLEANSING_FLAME:
if (spell_direction(spd, beam) == -1)
{
canned_msg(MSG_OK);
return (false);
}
- zapping(ZAP_LIGHTNING, you.skills[SK_INVOCATIONS] * 6, beam);
+ zapping(ZAP_CLEANSING_FLAME, 20 + you.skills[SK_INVOCATIONS] * 6, beam);
exercise(SK_INVOCATIONS, 3 + random2(6));
break;
@@ -906,7 +897,8 @@ bool activate_ability(void)
break;
case ABIL_KIKU_INVOKE_DEATH:
- summon_ice_beast_etc(20 + you.skills[SK_INVOCATIONS] * 3, MONS_REAPER);
+ summon_ice_beast_etc(
+ 20 + you.skills[SK_INVOCATIONS] * 3, MONS_REAPER, true);
exercise(SK_INVOCATIONS, 10 + random2(14));
break;
@@ -943,7 +935,7 @@ bool activate_ability(void)
exercise(SK_INVOCATIONS, 3 + random2(4));
break;
- case ABIL_VEHUMET_CHANNEL_ENERGY:
+ case ABIL_SIF_MUNA_CHANNEL_ENERGY:
mpr("You channel some magical energy.");
inc_mp(1 + random2(you.skills[SK_INVOCATIONS] / 4 + 2), false);
@@ -1029,12 +1021,12 @@ bool activate_ability(void)
beam.flavour = BEAM_ELECTRICITY;
beam.target_x = you.x_pos;
beam.target_y = you.y_pos;
- strcpy(beam.beam_name, "blast of lightning");
+ beam.name = "blast of lightning";
beam.colour = LIGHTCYAN;
beam.thrower = KILL_YOU;
beam.aux_source = "Makhleb's lightning strike";
beam.ex_size = 1 + you.skills[SK_INVOCATIONS] / 8;
- beam.isTracer = false;
+ beam.is_tracer = false;
// ... and fire!
explosion(beam);
@@ -1135,7 +1127,9 @@ bool activate_ability(void)
return (false);
}
- your_spells( SPELL_HELLFIRE, 20 + you.experience_level, false );
+ if (your_spells( SPELL_HELLFIRE,
+ 20 + you.experience_level, false ) == -1)
+ return (false);
you.duration[DUR_BREATH_WEAPON] +=
3 + random2(5) + random2(30 - you.experience_level);
@@ -1153,21 +1147,7 @@ bool activate_ability(void)
return (false);
}
- torment(you.x_pos, you.y_pos);
- exercise(SK_INVOCATIONS, 2 + random2(4));
- break;
-
- case ABIL_SHUGGOTH_SEED:
- if (you.duration[DUR_SHUGGOTH_SEED_RELOAD])
- {
- canned_msg(MSG_CANNOT_DO_YET);
- return (false);
- }
-
- cast_shuggoth_seed( you.experience_level * 2
- + you.skills[SK_INVOCATIONS] * 3 );
-
- you.duration[DUR_SHUGGOTH_SEED_RELOAD] = 10 + random2avg(39, 2);
+ torment(TORMENT_GENERIC, you.x_pos, you.y_pos);
exercise(SK_INVOCATIONS, 2 + random2(4));
break;
@@ -1188,6 +1168,9 @@ bool activate_ability(void)
break;
}
+ // currently only delayed fireball is instantaneous -- bwr
+ you.turn_is_over = !(abil.flags & ABFLAG_INSTANT);
+
// All failures should have returned by this point, so we'll
// apply the costs -- its not too neat, but it works for now. -- bwr
const int food_cost = abil.food_cost + random2avg(abil.food_cost, 2);
@@ -1324,7 +1307,7 @@ char show_abilities( void )
if (cost_str.length() > 24)
cost_str = cost_str.substr( 0, 24 );
- cprintf( cost_str.c_str() );
+ cprintf( "%s", cost_str.c_str() );
gotoxy(60, wherey());
@@ -1468,7 +1451,7 @@ bool generate_abilities( void )
insert_ability( ABIL_SUMMON_MINOR_DEMON );
if (you.mutation[MUT_SUMMON_DEMONS])
- insert_ability( ABIL_SUMMON_DEMON );
+ insert_ability( ABIL_SUMMON_DEMONS );
if (you.mutation[MUT_HURL_HELLFIRE])
insert_ability( ABIL_HELLFIRE );
@@ -1532,7 +1515,7 @@ bool generate_abilities( void )
if (you.piety >= 75)
insert_ability( ABIL_TSO_ANNIHILATE_UNDEAD );
if (you.piety >= 100)
- insert_ability( ABIL_TSO_THUNDERBOLT );
+ insert_ability( ABIL_TSO_CLEANSING_FLAME );
if (you.piety >= 120)
insert_ability( ABIL_TSO_SUMMON_DAEVA );
break;
@@ -1602,15 +1585,12 @@ bool generate_abilities( void )
break;
case GOD_SIF_MUNA:
+ if (you.piety >= 30)
+ insert_ability( ABIL_SIF_MUNA_CHANNEL_ENERGY );
if (you.piety >= 50)
insert_ability( ABIL_SIF_MUNA_FORGET_SPELL );
break;
- case GOD_VEHUMET:
- if (you.piety >= 100)
- insert_ability( ABIL_VEHUMET_CHANNEL_ENERGY );
- break;
-
default:
break;
}
@@ -1754,11 +1734,6 @@ void set_god_ability_slots( void )
num_abil = 5;
break;
- case GOD_VEHUMET:
- abil_start = ABIL_VEHUMET_CHANNEL_ENERGY;
- num_abil = 1;
- break;
-
case GOD_OKAWARU:
abil_start = ABIL_OKAWARU_MIGHT;
num_abil = 3;
@@ -1770,8 +1745,8 @@ void set_god_ability_slots( void )
break;
case GOD_SIF_MUNA:
- abil_start = ABIL_SIF_MUNA_FORGET_SPELL;
- num_abil = 1;
+ abil_start = ABIL_SIF_MUNA_CHANNEL_ENERGY;
+ num_abil = 2;
break;
case GOD_TROG:
@@ -1784,6 +1759,7 @@ void set_god_ability_slots( void )
num_abil = 5;
break;
+ case GOD_VEHUMET:
case GOD_NEMELEX_XOBEH:
case GOD_XOM:
default:
@@ -1973,7 +1949,7 @@ static bool insert_ability( int which_ability )
failure = 35 - you.experience_level;
break;
- case ABIL_SUMMON_DEMON:
+ case ABIL_SUMMON_DEMONS:
failure = 40 - you.experience_level;
break;
@@ -2090,7 +2066,7 @@ static bool insert_ability( int which_ability )
failure = 40 - (you.piety / 20) - (5 * you.skills[SK_INVOCATIONS]);
break;
- case ABIL_VEHUMET_CHANNEL_ENERGY:
+ case ABIL_SIF_MUNA_CHANNEL_ENERGY:
invoc = true;
failure = 40 - you.intel - you.skills[SK_INVOCATIONS];
break;
@@ -2113,7 +2089,7 @@ static bool insert_ability( int which_ability )
break;
case ABIL_ZIN_HOLY_WORD:
- case ABIL_TSO_THUNDERBOLT:
+ case ABIL_TSO_CLEANSING_FLAME:
case ABIL_ELYVILON_RESTORATION:
case ABIL_YRED_CONTROL_UNDEAD:
case ABIL_OKAWARU_HASTE:
@@ -2151,11 +2127,6 @@ static bool insert_ability( int which_ability )
failure = 70 - (you.piety / 25) - (you.skills[SK_INVOCATIONS] * 4);
break;
- case ABIL_SHUGGOTH_SEED:
- invoc = true;
- failure = 85 - (you.piety / 25) - (you.skills[SK_INVOCATIONS] * 3);
- break;
-
case ABIL_RENOUNCE_RELIGION:
invoc = true;
perfect = true;
diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc
index 3f48ed7b35..ca7c02b160 100644
--- a/crawl-ref/source/abyss.cc
+++ b/crawl-ref/source/abyss.cc
@@ -3,6 +3,8 @@
* Summary: Misc functions (most of which don't appear to be related to priests).
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <2> 10/11/99 BCR Added Daniel's crash patch
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index d736658d9e..3596b0959b 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -3,6 +3,8 @@
* Summary: Main entry point, event loop, and some initialization functions
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <18> 7/29/00 JDJ values.h isn't included on Macs
@@ -39,7 +41,7 @@
#include <string>
// I don't seem to need values.h for VACPP..
-#if !defined(__IBMCPP__) && !defined(MAC)
+#if !defined(__IBMCPP__)
#include <limits.h>
#endif
@@ -64,16 +66,6 @@
#include <signal.h>
#endif
-#ifdef USE_EMX
-#include <sys/types.h>
-#endif
-
-#ifdef OS9
-#include <stat.h>
-#else
-#include <sys/stat.h>
-#endif
-
#include "externs.h"
#include "abl-show.h"
@@ -97,15 +89,18 @@
#include "it_use2.h"
#include "it_use3.h"
#include "itemname.h"
+#include "itemprop.h"
#include "items.h"
#include "lev-pand.h"
#include "macro.h"
+#include "maps.h"
#include "misc.h"
#include "monplace.h"
#include "monstuff.h"
#include "mon-util.h"
#include "mutation.h"
#include "newgame.h"
+#include "notes.h"
#include "ouch.h"
#include "output.h"
#include "overmap.h"
@@ -126,25 +121,27 @@
#include "transfor.h"
#include "travel.h"
#include "view.h"
-#include "wpn-misc.h"
#include "stash.h"
struct crawl_environment env;
struct player you;
struct system_environment SysEnv;
+std::string init_file_location; // externed in newgame.cc
+
char info[ INFO_SIZE ]; // messaging queue extern'd everywhere {dlb}
-int stealth; // externed in view.h // no it is not {dlb}
+int stealth; // externed in view.cc
char use_colour = 1;
-FixedVector< char, NUM_STATUE_TYPES > Visible_Statue;
+bool just_autoprayed = false;
+bool about_to_autopray = false;
// set to true once a new game starts or an old game loads
bool game_has_started = false;
// Clockwise, around the compass from north (same order as enum RUN_DIR)
-static const struct coord_def Compass[8] =
+const struct coord_def Compass[8] =
{
{ 0, -1 }, { 1, -1 }, { 1, 0 }, { 1, 1 },
{ 0, 1 }, { -1, 1 }, { -1, 0 }, { -1, -1 },
@@ -166,33 +163,25 @@ static const struct coord_def Compass[8] =
*/
-void (*viewwindow) (char, bool);
-
-/* these are all defined in view.cc: */
-extern unsigned char (*mapch) (unsigned char);
-extern unsigned char (*mapch2) (unsigned char);
-unsigned char mapchar(unsigned char ldfk);
-unsigned char mapchar2(unsigned char ldfk);
-unsigned char mapchar3(unsigned char ldfk);
-unsigned char mapchar4(unsigned char ldfk);
-
-/*
- Function pointers are used to make switching between Unix and DOS char sets
- possible as a runtime option (command-line -c)
-*/
-
-// these two are defined in view.cc. What does the player look like?
-// (changed for shapechanging)
-extern unsigned char your_sign;
-extern unsigned char your_colour;
-
// Functions in main module
-static void close_door(char move_x, char move_y);
+static void close_door(int move_x, int move_y);
static void do_berserk_no_combat_penalty(void);
static bool initialise(void);
static void input(void);
-static void move_player(char move_x, char move_y);
-static void open_door(char move_x, char move_y);
+static void move_player(int move_x, int move_y);
+static void open_door(int move_x, int move_y, bool check_confused = true);
+static void start_running( int dir, int mode );
+static void close_door(int move_x, int move_y);
+
+static void init_io();
+static void prep_input();
+static void input();
+static void middle_input();
+static void world_reacts();
+static command_type get_next_cmd();
+typedef int keycode_type;
+static keycode_type get_next_keycode();
+static command_type keycode_to_command( keycode_type key );
/*
It all starts here. Some initialisations are run first, then straight to
@@ -200,18 +189,6 @@ static void open_door(char move_x, char move_y);
*/
int main( int argc, char *argv[] )
{
-#ifdef USE_ASCII_CHARACTERS
- // Default to the non-ibm set when it makes sense.
- viewwindow = &viewwindow3;
- mapch = &mapchar3;
- mapch2 = &mapchar4;
-#else
- // Use the standard ibm default
- viewwindow = &viewwindow2;
- mapch = &mapchar;
- mapch2 = &mapchar2;
-#endif
-
// Load in the system environment variables
get_system_environment();
@@ -239,7 +216,10 @@ int main( int argc, char *argv[] )
}
// Read the init file
- read_init_file();
+ init_file_location = read_init_file();
+
+ // Read special levels and vaults.
+ read_maps();
// now parse the args again, looking for everything else.
parse_args( argc, argv, false );
@@ -251,26 +231,13 @@ int main( int argc, char *argv[] )
exit(0);
}
-#ifdef UNIX
- unixcurses_startup();
-#endif
-
-#ifdef MAC
- init_mac();
-#endif
-
-#ifdef WIN32CONSOLE
- init_libw32c();
-#endif
+ init_io();
#ifdef USE_MACROS
// Load macros
macro_init();
#endif
- init_overmap(); // in overmap.cc (duh?)
- clear_ids(); // in itemname.cc
-
bool game_start = initialise();
if (game_start || Options.always_greet)
@@ -357,16 +324,23 @@ int main( int argc, char *argv[] )
unixcurses_shutdown();
#endif
-#ifdef MAC
- deinit_mac();
+ return 0;
+} // end main()
+
+static void init_io()
+{
+#ifdef UNIX
+ unixcurses_startup();
#endif
-#ifdef USE_EMX
- deinit_emx();
+#ifdef WIN32CONSOLE
+ init_libw32c();
#endif
- return 0;
-} // end main()
+#ifdef DOS
+ init_libdos();
+#endif
+}
#ifdef WIZARD
static void handle_wizard_command( void )
@@ -438,7 +412,7 @@ static void handle_wizard_command( void )
case 'v':
// this command isn't very exciting... feel free to replace
- i = prompt_invent_item( "Value of which item?", -1 );
+ i = prompt_invent_item( "Value of which item?", MT_INVSELECT, -1 );
if (i == PROMPT_ABORT || !is_random_artefact( you.inv[i] ))
{
canned_msg( MSG_OK );
@@ -452,7 +426,8 @@ static void handle_wizard_command( void )
break;
case '+':
- i = prompt_invent_item( "Make an artefact out of which item?", -1 );
+ i = prompt_invent_item(
+ "Make an artefact out of which item?", MT_INVSELECT, -1 );
if (i == PROMPT_ABORT)
{
canned_msg( MSG_OK );
@@ -593,6 +568,22 @@ static void handle_wizard_command( void )
tweak_object();
break;
+ case 'T':
+ debug_make_trap();
+ break;
+
+ case '\\':
+ debug_make_shop();
+ break;
+
+ case 'f':
+ debug_fight_statistics(false);
+ break;
+
+ case 'F':
+ debug_fight_statistics(true);
+ break;
+
case 'm':
create_spec_monster();
break;
@@ -695,7 +686,11 @@ static void handle_wizard_command( void )
break;
case '{':
- magic_mapping(99, 100);
+ magic_mapping(1000, 100);
+ break;
+
+ case '@':
+ debug_set_stats();
break;
case '^':
@@ -765,437 +760,312 @@ static void handle_wizard_command( void )
}
#endif
-// This function creates "equivalence classes" so that undiscovered
-// traps and secret doors aren't running stopping points.
-static char base_grid_type( char grid )
+// Set up the running variables for the current run.
+static void start_running( int dir, int mode )
{
- // Don't stop for undiscovered traps:
- if (grid == DNGN_UNDISCOVERED_TRAP)
- return (DNGN_FLOOR);
-
- // Or secret doors (which currently always look like rock walls):
- if (grid == DNGN_SECRET_DOOR)
- return (DNGN_ROCK_WALL);
-
- return (grid);
+ you.running.initialise(dir, mode);
}
-// Set up the front facing array for detecting terrain based stops
-static void set_run_check( int index, int dir )
+static bool recharge_rod( item_def &rod, bool wielded )
{
- you.run_check[index].dx = Compass[dir].x;
- you.run_check[index].dy = Compass[dir].y;
+ if (!item_is_rod(rod) || rod.plus >= rod.plus2 || !enough_mp(1, true))
+ return (false);
- const int targ_x = you.x_pos + Compass[dir].x;
- const int targ_y = you.y_pos + Compass[dir].y;
+ const int charge = rod.plus / ROD_CHARGE_MULT;
- you.run_check[index].grid = base_grid_type( grd[ targ_x ][ targ_y ] );
-}
+ int rate = ((charge + 1) * ROD_CHARGE_MULT) / 10;
+
+ rate *= (10 + skill_bump( SK_EVOCATIONS ));
+ rate = div_rand_round( rate, 100 );
-// Set up the running variables for the current run.
-static void start_running( int dir, char mode )
-{
- if (dir == RDIR_REST)
+ if (rate < 5)
+ rate = 5;
+ else if (rate > ROD_CHARGE_MULT / 2)
+ rate = ROD_CHARGE_MULT / 2;
+
+ // If not wielded, the rod charges far more slowly.
+ if (!wielded)
+ rate /= 5;
+ // Shields hamper recharging for wielded rods.
+ else if (player_shield())
+ rate /= 2;
+
+ if (rod.plus / ROD_CHARGE_MULT != (rod.plus + rate) / ROD_CHARGE_MULT)
{
- you.run_x = 0;
- you.run_y = 0;
- you.running = mode;
- return;
+ dec_mp(1);
+ if (wielded)
+ you.wield_change = true;
}
- ASSERT( dir >= 0 && dir <= 7 );
-
- you.run_x = Compass[dir].x;
- you.run_y = Compass[dir].y;
- you.running = mode;
+ rod.plus += rate;
+ if (rod.plus > rod.plus2)
+ rod.plus = rod.plus2;
- // Get the compass point to the left/right of intended travel:
- const int left = (dir - 1 < 0) ? 7 : (dir - 1);
- const int right = (dir + 1 > 7) ? 0 : (dir + 1);
+ if (wielded && rod.plus == rod.plus2 && is_resting())
+ stop_running();
- // Record the direction and starting tile type for later reference:
- set_run_check( 0, left );
- set_run_check( 1, dir );
- set_run_check( 2, right );
+ return (true);
}
-// Returns true if one of the front three grids has changed.
-static bool check_stop_running( void )
+static void recharge_rods()
{
- if (env.cgrid[you.x_pos + you.run_x][you.y_pos + you.run_y] != EMPTY_CLOUD)
- return (true);
-
- if (mgrd[you.x_pos + you.run_x][you.y_pos + you.run_y] != NON_MONSTER)
- return (true);
-
- for (int i = 0; i < 3; i++)
+ const int wielded = you.equip[EQ_WEAPON];
+ if (wielded != -1)
{
- const int targ_x = you.x_pos + you.run_check[i].dx;
- const int targ_y = you.y_pos + you.run_check[i].dy;
- const int targ_grid = base_grid_type( grd[ targ_x ][ targ_y ] );
-
- if (you.run_check[i].grid != targ_grid)
- return (true);
+ if (recharge_rod( you.inv[wielded], true ))
+ return ;
}
- return (false);
+ for (int i = 0; i < ENDOFPACK; ++i)
+ {
+ if (i != wielded && is_valid_item(you.inv[i])
+ && one_chance_in(3)
+ && recharge_rod( you.inv[i], false ))
+ return;
+ }
}
+/* used to determine whether to apply the berserk penalty at end
+ of round */
+bool apply_berserk_penalty = false;
+
+/* There is now a distinction between keycodes and commands.
+ A keycode_type gets mapped through keycode_to_command to
+ become a command_type.
+ So a keycode_type could be something like 'H';
+ a command_type would be something like COMMAND_RUN_LEFT.
+*/
/*
This function handles the player's input. It's called from main(), from
inside an endless loop.
- */
-static void input(void)
-{
-
- bool its_quiet; //jmf: for silence messages
- FixedVector < int, 2 > plox;
- char move_x = 0;
- char move_y = 0;
-
- int keyin = 0;
-
-#ifdef UNIX
- // Stuff for the Unix keypad kludge
- bool running = false;
- bool opening = false;
-#endif
-
- you.shield_blocks = 0; // no blocks this round
-
- you.time_taken = player_speed();
-
-#ifdef UNIX
- update_screen();
-#else
- window( 1, 1, 80, get_number_of_lines() );
-#endif
- textcolor(LIGHTGREY);
+ It's now undergone major refactoring. The code path is now:
+ 1. Get next player input item (key)
+ 2. Translate key to command
+ 3. Execute the command
+ 4. Update rest of world if necessary
+ */
+static void input() {
- set_redraw_status( REDRAW_LINE_2_MASK | REDRAW_LINE_3_MASK );
- print_stats();
+ you.turn_is_over = false;
+ prep_input();
- if (you.paralysis)
- {
- keyin = '.'; // end of if you.paralysis == 0
+ /* you.paralysis check */
+ if ( you.paralysis ) {
+ world_reacts();
+ return;
}
- else
- {
-#ifdef STASH_TRACKING
- if (Options.stash_tracking)
- stashes.update_visible_stashes(
- Options.stash_tracking == STM_ALL?
- StashTracker::ST_AGGRESSIVE :
- StashTracker::ST_PASSIVE);
-#endif
- handle_delay();
-
- gotoxy(18, 9);
-
- if (you_are_delayed())
- keyin = '.';
- else if (you.activity)
- {
- keyin = 128;
- you.turn_is_over = 0;
- perform_activity();
- }
- else
- {
- if (you.running < 0) // Travel and explore
- travel(&keyin, &move_x, &move_y);
-
- if (you.running > 0)
- {
- keyin = 128;
+
+ middle_input();
- move_x = you.run_x;
- move_y = you.run_y;
+ handle_delay();
- if (kbhit())
- {
- stop_running();
- goto gutch;
- }
+ gotoxy(18,9);
- if (you.run_x == 0 && you.run_y == 0)
- {
- you.running--;
- keyin = '.';
- }
- }
- else if (!you.running)
- {
+ if ( you_are_delayed() ) {
+ world_reacts();
+ return;
+ }
-#if DEBUG_DIAGNOSTICS
- // save hunger at start of round
- // for use with hunger "delta-meter" in output.cc
- you.old_hunger = you.hunger;
-#endif
+ /* Change from previous code! */
+ if ( you.turn_is_over ) {
+ world_reacts();
+ return;
+ }
-#if DEBUG_ITEM_SCAN
- debug_item_scan();
-#endif
+ command_type cmd = get_next_cmd();
- gutch:
- flush_input_buffer( FLUSH_BEFORE_COMMAND );
- keyin = getch_with_command_macros();
- }
+ // [dshaligram] If get_next_cmd encountered a Lua macro binding, your turn
+ // may be ended by the first invoke of the macro.
+ if (!you.turn_is_over && cmd != CMD_NEXT_CMD)
+ process_command( cmd );
- mesclr();
+ if ( you.turn_is_over ) {
-#ifdef UNIX
- // Kludging running and opening as two character sequences
- // for Unix systems. This is an easy way out... all the
- // player has to do is find a termcap and numlock setting
- // that will get curses the numbers from the keypad. This
- // will hopefully be easy.
+ if ( apply_berserk_penalty )
+ do_berserk_no_combat_penalty();
- if (keyin == '*')
- {
- opening = true;
- keyin = getch();
- }
- else if (keyin == '/')
- {
- running = true;
- keyin = getch();
- }
+ world_reacts();
+ }
+ else
+ viewwindow(true, false);
+}
- // Translate keypad codes into command enums
- keyin = key_to_command(keyin);
-#else
- // Old DOS keypad support
- if (keyin == 0) // ALT also works - see ..\KEYTEST.CPP
- {
- keyin = getch();
- switch (keyin)
- {
- case 'O': move_x = -1; move_y = 1; break;
- case 'P': move_x = 0; move_y = 1; break;
- case 'I': move_x = 1; move_y = -1; break;
- case 'H': move_x = 0; move_y = -1; break;
- case 'G': move_x = -1; move_y = -1; break;
- case 'K': move_x = -1; move_y = 0; break;
- case 'Q': move_x = 1; move_y = 1; break;
- case 'M': move_x = 1; move_y = 0; break;
-
- case 119: open_door(-1, -1); move_x = 0; move_y = 0; break;
- case 141: open_door( 0, -1); move_x = 0; move_y = 0; break;
- case 132: open_door( 1, -1); move_x = 0; move_y = 0; break;
- case 116: open_door( 1, 0); move_x = 0; move_y = 0; break;
- case 118: open_door( 1, 1); move_x = 0; move_y = 0; break;
- case 145: open_door( 0, 1); move_x = 0; move_y = 0; break;
- case 117: open_door(-1, 1); move_x = 0; move_y = 0; break;
- case 115: open_door(-1, 0); move_x = 0; move_y = 0; break;
-
- case 76:
- case 'S':
- keyin = '.';
- goto get_keyin_again;
- }
+static int toggle_flag( bool* flag, const char* flagname ) {
+ char buf[INFO_SIZE];
+ *flag = !(*flag);
+ sprintf( buf, "%s is now %s.", flagname,
+ (*flag) ? "on" : "off" );
+ mpr(buf);
+ return *flag;
+}
- keyin = 128;
- }
-#endif
- }
+static void go_upstairs() {
+ if (grd[you.x_pos][you.y_pos] == DNGN_ENTER_SHOP) {
+ shop();
+ return;
}
-
- if (keyin != 128)
- {
- move_x = 0;
- move_y = 0;
- you.turn_is_over = 0;
+ else if ((grd[you.x_pos][you.y_pos] < DNGN_STONE_STAIRS_UP_I
+ || grd[you.x_pos][you.y_pos] > DNGN_ROCK_STAIRS_UP)
+ && (grd[you.x_pos][you.y_pos] < DNGN_RETURN_FROM_ORCISH_MINES
+ || grd[you.x_pos][you.y_pos] >= 150)) {
+ mpr( "You can't go up here!" );
+ return;
}
-#ifndef UNIX
- get_keyin_again:
-#endif //jmf: just stops an annoying gcc warning
+ tag_followers(); // only those beside us right now can follow
+ start_delay( DELAY_ASCENDING_STAIRS,
+ 1 + (you.burden_state > BS_UNENCUMBERED) );
+}
- if (is_userfunction(keyin))
- {
- run_macro(get_userfunction(keyin));
- keyin = 128;
+static void go_downstairs() {
+
+ if ((grd[you.x_pos][you.y_pos] < DNGN_ENTER_LABYRINTH
+ || grd[you.x_pos][you.y_pos] > DNGN_ROCK_STAIRS_DOWN)
+ && grd[you.x_pos][you.y_pos] != DNGN_ENTER_HELL
+ && ((grd[you.x_pos][you.y_pos] < DNGN_ENTER_DIS
+ || grd[you.x_pos][you.y_pos] > DNGN_TRANSIT_PANDEMONIUM)
+ && grd[you.x_pos][you.y_pos] != DNGN_STONE_ARCH)
+ && !(grd[you.x_pos][you.y_pos] >= DNGN_ENTER_ORCISH_MINES
+ && grd[you.x_pos][you.y_pos] < DNGN_RETURN_FROM_ORCISH_MINES)) {
+ mpr( "You can't go down here!" );
+ return;
}
-
- switch (keyin)
- {
- case CONTROL('Y'):
- case CMD_OPEN_DOOR_UP_RIGHT:
- open_door(-1, -1); move_x = 0; move_y = 0; break;
- case CONTROL('K'):
- case CMD_OPEN_DOOR_UP:
- open_door( 0, -1); move_x = 0; move_y = 0; break;
-
- case CONTROL('U'):
- case CMD_OPEN_DOOR_UP_LEFT:
- open_door( 1, -1); move_x = 0; move_y = 0; break;
-
- case CONTROL('L'):
- case CMD_OPEN_DOOR_RIGHT:
- open_door( 1, 0); move_x = 0; move_y = 0; break;
-
- case CONTROL('N'):
- case CMD_OPEN_DOOR_DOWN_RIGHT:
- open_door( 1, 1); move_x = 0; move_y = 0; break;
-
- case CONTROL('J'):
- case CMD_OPEN_DOOR_DOWN:
- open_door( 0, 1); move_x = 0; move_y = 0; break;
+ tag_followers(); // only those beside us right now can follow
+ start_delay( DELAY_DESCENDING_STAIRS,
+ 1 + (you.burden_state > BS_UNENCUMBERED),
+ you.your_level );
+}
- case CONTROL('B'):
- case CMD_OPEN_DOOR_DOWN_LEFT:
- open_door(-1, 1); move_x = 0; move_y = 0; break;
+static void experience_check() {
+ snprintf( info, INFO_SIZE, "You are a level %d %s %s.",
+ you.experience_level,
+ species_name(you.species,you.experience_level),
+ you.class_name);
+ mpr(info);
+
+ if (you.experience_level < 27) {
+ int xp_needed = (exp_needed(you.experience_level+2)-you.experience)+1;
+ snprintf( info, INFO_SIZE,
+ "Level %d requires %ld experience (%d point%s to go!)",
+ you.experience_level + 1,
+ exp_needed(you.experience_level + 2) + 1,
+ xp_needed,
+ (xp_needed > 1) ? "s" : "");
+ mpr(info);
+ }
+ else {
+ mpr( "I'm sorry, level 27 is as high as you can go." );
+ mpr( "With the way you've been playing, I'm surprised you got this far." );
+ }
- case CONTROL('H'):
- case CMD_OPEN_DOOR_LEFT:
- open_door(-1, 0); move_x = 0; move_y = 0; break;
+ if (you.real_time != -1) {
+ const time_t curr = you.real_time + (time(NULL) - you.start_time);
+ char buff[200];
- case 'b': case CMD_MOVE_DOWN_LEFT: move_x = -1; move_y = 1; break;
- case 'j': case CMD_MOVE_DOWN: move_y = 1; move_x = 0; break;
- case 'u': case CMD_MOVE_UP_RIGHT: move_x = 1; move_y = -1; break;
- case 'k': case CMD_MOVE_UP: move_y = -1; move_x = 0; break;
- case 'y': case CMD_MOVE_UP_LEFT: move_y = -1; move_x = -1; break;
- case 'h': case CMD_MOVE_LEFT: move_x = -1; move_y = 0; break;
- case 'n': case CMD_MOVE_DOWN_RIGHT: move_y = 1; move_x = 1; break;
- case 'l': case CMD_MOVE_RIGHT: move_x = 1; move_y = 0; break;
+ make_time_string( curr, buff, sizeof(buff) );
- case CMD_REST:
- // Yes this is backwards, but everyone here is used to using
- // straight 5s for long rests... might need to define a roguelike
- // rest key and get people switched over. -- bwr
+ snprintf( info, INFO_SIZE, "Play time: %s (%ld turns)",
+ buff, you.num_turns );
-#ifdef UNIX
- if (!running && !opening)
- start_running( RDIR_REST, 100 );
- else
- {
- search_around();
- move_x = 0;
- move_y = 0;
- you.turn_is_over = 1;
- }
+ mpr( info );
+ }
+#ifdef DEBUG_DIAGNOSTICS
+ if (wearing_amulet(AMU_THE_GOURMAND))
+ mprf(MSGCH_DIAGNOSTICS, "Gourmand charge: %d",
+ you.duration[DUR_GOURMAND]);
#endif
- break;
-
- case 'B': case CMD_RUN_DOWN_LEFT:
- start_running( RDIR_DOWN_LEFT, 2 ); break;
-
- case 'J': case CMD_RUN_DOWN:
- start_running( RDIR_DOWN, 2 ); break;
-
- case 'U': case CMD_RUN_UP_RIGHT:
- start_running( RDIR_UP_RIGHT, 2 ); break;
-
- case 'K': case CMD_RUN_UP:
- start_running( RDIR_UP, 2 ); break;
-
- case 'Y': case CMD_RUN_UP_LEFT:
- start_running( RDIR_UP_LEFT, 2 ); break;
+}
- case 'H': case CMD_RUN_LEFT:
- start_running( RDIR_LEFT, 2 ); break;
+/* note that in some actions, you don't want to clear afterwards.
+ e.g. list_jewellery, etc. */
- case 'N': case CMD_RUN_DOWN_RIGHT:
- start_running( RDIR_DOWN_RIGHT, 2 ); break;
+void process_command( command_type cmd ) {
- case 'L': case CMD_RUN_RIGHT:
- start_running( RDIR_RIGHT, 2 ); break;
+ FixedVector < int, 2 > plox;
+ apply_berserk_penalty = true;
+
+ switch ( cmd ) {
+
+ case CMD_OPEN_DOOR_UP_RIGHT: open_door(-1, -1); break;
+ case CMD_OPEN_DOOR_UP: open_door( 0, -1); break;
+ case CMD_OPEN_DOOR_UP_LEFT: open_door( 1, -1); break;
+ case CMD_OPEN_DOOR_RIGHT: open_door( 1, 0); break;
+ case CMD_OPEN_DOOR_DOWN_RIGHT: open_door( 1, 1); break;
+ case CMD_OPEN_DOOR_DOWN: open_door( 0, 1); break;
+ case CMD_OPEN_DOOR_DOWN_LEFT: open_door(-1, 1); break;
+ case CMD_OPEN_DOOR_LEFT: open_door(-1, 0); break;
+
+ case CMD_MOVE_DOWN_LEFT: move_player(-1, 1); break;
+ case CMD_MOVE_DOWN: move_player( 0, 1); break;
+ case CMD_MOVE_UP_RIGHT: move_player( 1, -1); break;
+ case CMD_MOVE_UP: move_player( 0, -1); break;
+ case CMD_MOVE_UP_LEFT: move_player(-1, -1); break;
+ case CMD_MOVE_LEFT: move_player(-1, 0); break;
+ case CMD_MOVE_DOWN_RIGHT: move_player( 1, 1); break;
+ case CMD_MOVE_RIGHT: move_player( 1, 0); break;
-#ifdef UNIX
- // taken care of via key -> command mapping
-#else
- // Old DOS keypad support
- case '1': start_running( RDIR_DOWN_LEFT, 2 ); break;
- case '2': start_running( RDIR_DOWN, 2 ); break;
- case '9': start_running( RDIR_UP_RIGHT, 2 ); break;
- case '8': start_running( RDIR_UP, 2 ); break;
- case '7': start_running( RDIR_UP_LEFT, 2 ); break;
- case '4': start_running( RDIR_LEFT, 2 ); break;
- case '3': start_running( RDIR_DOWN_RIGHT, 2 ); break;
- case '6': start_running( RDIR_RIGHT, 2 ); break;
- case '5': start_running( RDIR_REST, 100 ); break;
+ case CMD_REST:
+ start_running( RDIR_REST, RMODE_REST_DURATION );
+ break;
-#endif
+ case CMD_RUN_DOWN_LEFT:
+ start_running( RDIR_DOWN_LEFT, RMODE_START );
+ break;
+ case CMD_RUN_DOWN:
+ start_running( RDIR_DOWN, RMODE_START );
+ break;
+ case CMD_RUN_UP_RIGHT:
+ start_running( RDIR_UP_RIGHT, RMODE_START );
+ break;
+ case CMD_RUN_UP:
+ start_running( RDIR_UP, RMODE_START );
+ break;
+ case CMD_RUN_UP_LEFT:
+ start_running( RDIR_UP_LEFT, RMODE_START );
+ break;
+ case CMD_RUN_LEFT:
+ start_running( RDIR_LEFT, RMODE_START );
+ break;
+ case CMD_RUN_DOWN_RIGHT:
+ start_running( RDIR_DOWN_RIGHT, RMODE_START );
+ break;
+ case CMD_RUN_RIGHT:
+ start_running( RDIR_RIGHT, RMODE_START );
+ break;
- case CONTROL('A'):
case CMD_TOGGLE_AUTOPICKUP:
- autopickup_on = !autopickup_on;
- strcpy(info, "Autopickup is now ");
- strcat(info, (autopickup_on) ? "on" : "off");
- strcat(info, ".");
- mpr(info);
+ toggle_flag( &Options.autopickup_on, "Autopickup");
break;
- case CONTROL('C'):
- case CMD_CLEAR_MAP:
- if (you.level_type != LEVEL_LABYRINTH && you.level_type != LEVEL_ABYSS)
- {
- mpr("Clearing level map.");
- clear_map();
- }
+ case CMD_TOGGLE_AUTOPRAYER:
+ toggle_flag( &Options.autoprayer_on, "Autoprayer" );
break;
-
- case '<':
- case CMD_GO_UPSTAIRS:
- if (grd[you.x_pos][you.y_pos] == DNGN_ENTER_SHOP)
- {
- shop();
- break;
- }
- else if ((grd[you.x_pos][you.y_pos] < DNGN_STONE_STAIRS_UP_I
- || grd[you.x_pos][you.y_pos] > DNGN_ROCK_STAIRS_UP)
- && (grd[you.x_pos][you.y_pos] < DNGN_RETURN_FROM_ORCISH_MINES
- || grd[you.x_pos][you.y_pos] >= 150))
- {
- mpr( "You can't go up here!" );
- break;
- }
- tag_followers(); // only those beside us right now can follow
- start_delay( DELAY_ASCENDING_STAIRS,
- 1 + (you.burden_state > BS_UNENCUMBERED) );
+ case CMD_TOGGLE_NOFIZZLE:
+ toggle_flag( &Options.fizzlecheck_on, "Fizzle confirmation" );
break;
-
- case '>':
- case CMD_GO_DOWNSTAIRS:
- if ((grd[you.x_pos][you.y_pos] < DNGN_ENTER_LABYRINTH
- || grd[you.x_pos][you.y_pos] > DNGN_ROCK_STAIRS_DOWN)
- && grd[you.x_pos][you.y_pos] != DNGN_ENTER_HELL
- && ((grd[you.x_pos][you.y_pos] < DNGN_ENTER_DIS
- || grd[you.x_pos][you.y_pos] > DNGN_TRANSIT_PANDEMONIUM)
- && grd[you.x_pos][you.y_pos] != DNGN_STONE_ARCH)
- && !(grd[you.x_pos][you.y_pos] >= DNGN_ENTER_ORCISH_MINES
- && grd[you.x_pos][you.y_pos] < DNGN_RETURN_FROM_ORCISH_MINES))
- {
- mpr( "You can't go down here!" );
- break;
- }
-
- tag_followers(); // only those beside us right now can follow
- start_delay( DELAY_DESCENDING_STAIRS,
- 1 + (you.burden_state > BS_UNENCUMBERED),
- you.your_level );
+
+ case CMD_MAKE_NOTE:
+ make_user_note();
break;
- case 'O':
- case CMD_DISPLAY_OVERMAP:
- display_overmap();
+ case CMD_CLEAR_MAP:
+ if (you.level_type != LEVEL_LABYRINTH &&
+ you.level_type != LEVEL_ABYSS) {
+ mpr("Clearing level map.");
+ clear_map();
+ }
break;
- case 'o':
- case CMD_OPEN_DOOR:
- open_door(0, 0);
- break;
- case 'c':
- case CMD_CLOSE_DOOR:
- close_door(0, 0);
- break;
+ case CMD_GO_UPSTAIRS: go_upstairs(); break;
+ case CMD_GO_DOWNSTAIRS: go_downstairs(); break;
+ case CMD_DISPLAY_OVERMAP: display_overmap(); break;
+ case CMD_OPEN_DOOR: open_door(0, 0); break;
+ case CMD_CLOSE_DOOR: close_door(0, 0); break;
- case 'd':
case CMD_DROP:
drop();
#ifdef STASH_TRACKING
@@ -1205,166 +1075,129 @@ static void input(void)
break;
#ifdef STASH_TRACKING
- case CONTROL('F'):
case CMD_SEARCH_STASHES:
stashes.search_stashes();
break;
- case CONTROL('S'):
case CMD_MARK_STASH:
if (Options.stash_tracking >= STM_EXPLICIT)
stashes.add_stash(-1, -1, true);
break;
- case CONTROL('E'):
case CMD_FORGET_STASH:
if (Options.stash_tracking >= STM_EXPLICIT)
stashes.no_stash();
break;
#endif
- case 'D':
case CMD_BUTCHER:
butchery();
break;
- case 'i':
case CMD_DISPLAY_INVENTORY:
get_invent(-1);
break;
- case 'I':
- case CMD_OBSOLETE_INVOKE:
- // We'll leave this message in for a while. Eventually, this
- // might be some special for of inventory command, or perhaps
- // actual god invocations will be split to here from abilities. -- bwr
- mpr( "This command is now 'E'voke wielded item.", MSGCH_WARN );
- break;
-
- case 'E':
case CMD_EVOKE:
if (!evoke_wielded())
flush_input_buffer( FLUSH_ON_FAILURE );
break;
- case 'g':
- case ',':
case CMD_PICKUP:
pickup();
break;
- case ';':
case CMD_INSPECT_FLOOR:
item_check(';');
break;
- case 'w':
case CMD_WIELD_WEAPON:
wield_weapon(false);
break;
- case 't':
case CMD_THROW:
throw_anything();
break;
- case 'f':
case CMD_FIRE:
shoot_thing();
break;
- case 'W':
case CMD_WEAR_ARMOUR:
wear_armour();
break;
- case 'T':
case CMD_REMOVE_ARMOUR:
- {
- int index=0;
+ {
+ int index=0;
- if (armour_prompt("Take off which item?", &index))
- takeoff_armour(index);
- }
- break;
+ if (armour_prompt("Take off which item?", &index, OPER_TAKEOFF))
+ takeoff_armour(index);
+ }
+ break;
- case 'R':
case CMD_REMOVE_JEWELLERY:
remove_ring();
break;
- case 'P':
+
case CMD_WEAR_JEWELLERY:
- puton_ring();
+ puton_ring(-1, false);
break;
- case '=':
case CMD_ADJUST_INVENTORY:
adjust();
- return;
+ break;
- case 'M':
case CMD_MEMORISE_SPELL:
if (!learn_spell())
flush_input_buffer( FLUSH_ON_FAILURE );
break;
- case 'z':
case CMD_ZAP_WAND:
zap_wand();
break;
- case 'e':
case CMD_EAT:
eat_food();
break;
- case 'a':
case CMD_USE_ABILITY:
if (!activate_ability())
flush_input_buffer( FLUSH_ON_FAILURE );
break;
- case 'A':
case CMD_DISPLAY_MUTATIONS:
display_mutations();
redraw_screen();
break;
- case 'v':
case CMD_EXAMINE_OBJECT:
- original_name();
+ examine_object();
break;
- case 'p':
case CMD_PRAY:
pray();
break;
- case '^':
case CMD_DISPLAY_RELIGION:
describe_god( you.religion, true );
redraw_screen();
break;
- case '.':
case CMD_MOVE_NOWHERE:
+ case CMD_SEARCH:
search_around();
- move_x = 0;
- move_y = 0;
- you.turn_is_over = 1;
+ you.turn_is_over = true;
break;
- case 'q':
case CMD_QUAFF:
drink();
break;
- case 'r':
case CMD_READ:
read_scroll();
break;
- case 'x':
case CMD_LOOK_AROUND:
mpr("Move the cursor around to observe a square.", MSGCH_PROMPT);
mpr("Press '?' for a monster description.", MSGCH_PROMPT);
@@ -1376,13 +1209,6 @@ static void input(void)
start_travel( lmove.tx, lmove.ty );
break;
- case 's':
- case CMD_SEARCH:
- search_around();
- you.turn_is_over = 1;
- break;
-
- case 'Z':
case CMD_CAST_SPELL:
/* randart wpns */
if (scan_randarts(RAP_PREVENT_SPELLCASTING))
@@ -1396,23 +1222,20 @@ static void input(void)
flush_input_buffer( FLUSH_ON_FAILURE );
break;
- case '\'':
case CMD_WEAPON_SWAP:
wield_weapon(true);
break;
- // [ds] Waypoints can be added from the level-map, and we need Ctrl+F for
- // nobler things. Who uses waypoints, anyway?
- // Update: Appears people do use waypoints. Reinstating, on CONTROL('W').
- // This means Ctrl+W is no longer a wizmode trigger, but there's
- // always '&'. :-)
+ // [ds] Waypoints can be added from the level-map, and we need
+ // Ctrl+F for nobler things. Who uses waypoints, anyway?
+ // Update: Appears people do use waypoints. Reinstating, on
+ // CONTROL('W'). This means Ctrl+W is no longer a wizmode
+ // trigger, but there's always '&'. :-)
case CMD_FIX_WAYPOINT:
- case CONTROL('W'):
travel_cache.add_waypoint();
break;
case CMD_INTERLEVEL_TRAVEL:
- case CONTROL('G'):
if (!can_travel_interlevel())
{
mpr("Sorry, you can't auto-travel out of here.");
@@ -1422,7 +1245,6 @@ static void input(void)
redraw_screen();
break;
- case CONTROL('O'):
case CMD_EXPLORE:
if (you.level_type == LEVEL_LABYRINTH || you.level_type == LEVEL_ABYSS)
{
@@ -1433,7 +1255,6 @@ static void input(void)
start_explore();
break;
- case 'X':
case CMD_DISPLAY_MAP:
#if (!DEBUG_DIAGNOSTICS)
if (you.level_type == LEVEL_LABYRINTH || you.level_type == LEVEL_ABYSS)
@@ -1443,44 +1264,37 @@ static void input(void)
}
#endif
plox[0] = 0;
- show_map(plox);
+ show_map(plox, true);
redraw_screen();
if (plox[0] > 0)
start_travel(plox[0], plox[1]);
break;
- case '\\':
case CMD_DISPLAY_KNOWN_OBJECTS:
- check_item_knowledge(); //nothing = check_item_knowledge();
- redraw_screen();
+ check_item_knowledge();
break;
#ifdef ALLOW_DESTROY_ITEM_COMMAND
- case CONTROL('D'):
case CMD_DESTROY_ITEM:
cmd_destroy_item();
break;
#endif
- case CONTROL('P'):
case CMD_REPLAY_MESSAGES:
replay_messages();
redraw_screen();
break;
- case CONTROL('R'):
case CMD_REDRAW_SCREEN:
redraw_screen();
break;
- case CONTROL('X'):
case CMD_SAVE_GAME_NOW:
mpr("Saving game... please wait.");
save_game(true);
break;
#ifdef USE_UNIX_SIGNALS
- case CONTROL('Z'):
case CMD_SUSPEND_GAME:
// CTRL-Z suspend behaviour is implemented here,
// because we want to have CTRL-Y available...
@@ -1493,71 +1307,37 @@ static void input(void)
break;
#endif
- case '?':
case CMD_DISPLAY_COMMANDS:
list_commands(false);
redraw_screen();
break;
- case 'C':
case CMD_EXPERIENCE_CHECK:
- snprintf( info, INFO_SIZE, "You are a level %d %s %s.", you.experience_level,
- species_name(you.species,you.experience_level), you.class_name);
- mpr(info);
-
- if (you.experience_level < 27)
- {
- int xp_needed = (exp_needed(you.experience_level+2) - you.experience) + 1;
- snprintf( info, INFO_SIZE, "Level %d requires %ld experience (%d point%s to go!)",
- you.experience_level + 1,
- exp_needed(you.experience_level + 2) + 1,
- xp_needed,
- (xp_needed > 1) ? "s" : "");
- mpr(info);
- }
- else
- {
- mpr( "I'm sorry, level 27 is as high as you can go." );
- mpr( "With the way you've been playing, I'm surprised you got this far." );
- }
-
- if (you.real_time != -1)
- {
- const time_t curr = you.real_time + (time(NULL) - you.start_time);
- char buff[200];
-
- make_time_string( curr, buff, sizeof(buff) );
-
- snprintf( info, INFO_SIZE, "Play time: %s (%ld turns)",
- buff, you.num_turns );
-
- mpr( info );
- }
+ experience_check();
break;
-
- case '!':
case CMD_SHOUT:
yell(); /* in effects.cc */
break;
- case '@':
case CMD_DISPLAY_CHARACTER_STATUS:
display_char_status();
break;
+
+ case CMD_RESISTS_SCREEN:
+ resists_screen();
+ break;
- case 'm':
case CMD_DISPLAY_SKILLS:
show_skills();
redraw_screen();
break;
- case '#':
case CMD_CHARACTER_DUMP:
char name_your[kNameLen+1];
strncpy(name_your, you.your_name, kNameLen);
- name_your[kNameLen] = '\0';
+ name_your[kNameLen] = 0;
if (dump_char( name_your, false ))
strcpy(info, "Char dumped successfully.");
else
@@ -1566,134 +1346,78 @@ static void input(void)
break;
#ifdef USE_MACROS
- case '`':
case CMD_MACRO_ADD:
macro_add_query();
break;
- case '~':
- case CMD_MACRO_SAVE:
- mpr("Saving macros.");
- macro_save();
- break;
#endif
- case ')':
case CMD_LIST_WEAPONS:
list_weapons();
- return;
+ break;
- case ']':
+ case CMD_INSCRIBE_ITEM:
+ inscribe_item();
+ break;
+
case CMD_LIST_ARMOUR:
list_armour();
- return;
+ break;
- case '"':
case CMD_LIST_JEWELLERY:
list_jewellery();
- return;
+ break;
#ifdef WIZARD
case CMD_WIZARD:
- case '&':
handle_wizard_command();
break;
#endif
- case 'S':
case CMD_SAVE_GAME:
- if (yesno("Save game and exit?", false, 'n'))
+ if (yesno("Save game and exit?", true, 'n'))
save_game(true);
break;
- case 'Q':
case CMD_QUIT:
quit_game();
break;
- case 'V':
case CMD_GET_VERSION:
version();
break;
- case 128: // Can't use this char -- it's the special value 128
- break;
-
- default:
case CMD_NO_CMD:
+ default:
mpr("Unknown command.");
break;
}
+}
+static void prep_input() {
+ you.time_taken = player_speed();
+ you.shield_blocks = 0; // no blocks this round
#ifdef UNIX
- // New Unix keypad stuff
- if (running)
- {
- int dir = -1;
-
- // XXX: ugly hack to interface this with the new running code. -- bwr
- for (int i = 0; i < 8; i++)
- {
- if (Compass[i].x == move_x && Compass[i].y == move_y)
- {
- dir = i;
- break;
- }
- }
-
- if (dir != -1)
- {
- start_running( dir, 2 );
- move_x = 0;
- move_y = 0;
- }
- }
- else if (opening)
- {
- open_door(move_x, move_y);
- move_x = 0;
- move_y = 0;
- }
+ update_screen();
+#else
+ window( 1, 1, 80, get_number_of_lines() );
#endif
- if (move_x != 0 || move_y != 0)
- move_player(move_x, move_y);
- else if (you.turn_is_over) // we did something other than move/attack
- do_berserk_no_combat_penalty();
-
- if (!you.turn_is_over)
- {
- viewwindow(1, false);
- return;
- }
-
- if (you.num_turns != -1)
- you.num_turns++;
-
- //if (random2(10) < you.skills [SK_TRAPS_DOORS] + 2) search_around();
-
- stealth = check_stealth();
-
-#if 0
- // too annoying for regular diagnostics
- snprintf( info, INFO_SIZE, "stealth: %d", stealth );
- mpr( info, MSGCH_DIAGNOSTICS );
-#endif
+ textcolor(LIGHTGREY);
- if (you.special_wield != SPWLD_NONE)
- special_wielded();
+ set_redraw_status( REDRAW_LINE_2_MASK | REDRAW_LINE_3_MASK );
+ print_stats();
+}
- if (one_chance_in(10))
- {
- // this is instantaneous
- if (player_teleport() > 0 && one_chance_in(100 / player_teleport()))
- you_teleport2( true );
- else if (you.level_type == LEVEL_ABYSS && one_chance_in(30))
- you_teleport2( false, true ); // to new area of the Abyss
+static void decrement_durations()
+{
+ if (wearing_amulet(AMU_THE_GOURMAND))
+ {
+ if (you.duration[DUR_GOURMAND] < GOURMAND_MAX && coinflip())
+ you.duration[DUR_GOURMAND]++;
}
-
- if (env.cgrid[you.x_pos][you.y_pos] != EMPTY_CLOUD)
- in_a_cloud();
+ else
+ you.duration[DUR_GOURMAND] = 0;
if (you.duration[DUR_REPEL_UNDEAD] > 1)
you.duration[DUR_REPEL_UNDEAD]--;
@@ -1722,7 +1446,7 @@ static void input(void)
const int res_fire = player_res_fire();
mpr( "You are covered in liquid flames!", MSGCH_WARN );
- scrolls_burn(8, OBJ_SCROLLS);
+ expose_player_to_element(BEAM_NAPALM, 12);
if (res_fire > 0)
{
@@ -1733,13 +1457,13 @@ static void input(void)
if (res_fire <= 0)
{
ouch(((random2avg(9, 2) + 1) * you.time_taken) / 10, 0,
- KILLED_BY_BURNING);
+ KILLED_BY_BURNING);
}
if (res_fire < 0)
{
ouch(((random2avg(9, 2) + 1) * you.time_taken) / 10, 0,
- KILLED_BY_BURNING);
+ KILLED_BY_BURNING);
}
if (you.duration[DUR_CONDENSATION_SHIELD] > 0)
@@ -1815,11 +1539,11 @@ static void input(void)
you.duration[DUR_PRAYER]--;
else if (you.duration[DUR_PRAYER] == 1)
{
- god_speaks(you.religion, "Your prayer is over.");
+ mpr( "Your prayer is over.", MSGCH_PRAY, you.religion );
+ about_to_autopray = true;
you.duration[DUR_PRAYER] = 0;
}
-
//jmf: more flexible weapon branding code
if (you.duration[DUR_WEAPON_BRAND] > 1)
you.duration[DUR_WEAPON_BRAND]--;
@@ -1839,16 +1563,11 @@ static void input(void)
switch (temp_effect)
{
case SPWPN_VORPAL:
- if (damage_type(you.inv[you.equip[EQ_WEAPON]].base_type,
- you.inv[you.equip[EQ_WEAPON]].sub_type) != DVORP_CRUSHING)
- {
+ if (get_vorpal_type(you.inv[you.equip[EQ_WEAPON]])
+ == DVORP_SLICING)
strcat(info, " seems blunter.");
- }
else
- {
- //jmf: for Maxwell's Silver Hammer
strcat(info, " feels lighter.");
- }
break;
case SPWPN_FLAMING:
@@ -1865,7 +1584,8 @@ static void input(void)
break;
case SPWPN_DISTORTION:
strcat( info, " seems straighter." );
- miscast_effect( SPTYP_TRANSLOCATION, 9, 90, 100, "a distortion effect" );
+ // [dshaligram] Makes the brand unusable
+ // miscast_effect( SPTYP_TRANSLOCATION, 9, 90, 100, "a distortion effect" );
break;
default:
strcat(info, " seems inexplicably less special.");
@@ -1938,7 +1658,7 @@ static void input(void)
you.duration[DUR_STONEMAIL]--;
if (you.duration[DUR_STONEMAIL] == 6)
{
- mpr("Your scaley stone armour is starting to flake away.", MSGCH_DURATION);
+ mpr("Your scaly stone armour is starting to flake away.", MSGCH_DURATION);
you.redraw_armour_class = 1;
if (coinflip())
you.duration[DUR_STONEMAIL]--;
@@ -1946,7 +1666,7 @@ static void input(void)
}
else if (you.duration[DUR_STONEMAIL] == 1)
{
- mpr("Your scaley stone armour disappears.", MSGCH_DURATION);
+ mpr("Your scaly stone armour disappears.", MSGCH_DURATION);
you.duration[DUR_STONEMAIL] = 0;
you.redraw_armour_class = 1;
burden_change();
@@ -1978,7 +1698,8 @@ static void input(void)
{
you.duration[DUR_CONDENSATION_SHIELD]--;
- scrolls_burn( 1, OBJ_POTIONS );
+ // [dshaligram] Makes this spell useless
+ // scrolls_burn( 1, OBJ_POTIONS );
if (player_res_cold() < 0)
{
@@ -2034,7 +1755,6 @@ static void input(void)
{
mpr("You feel uncertain.", MSGCH_DURATION);
you.duration[DUR_CONTROL_TELEPORT] = 0;
- you.attribute[ATTR_CONTROL_TELEPORT]--;
}
if (you.duration[DUR_RESIST_POISON] > 1)
@@ -2069,20 +1789,6 @@ static void input(void)
you.duration[DUR_DEATH_CHANNEL] = 0;
}
- if (you.duration[DUR_SHUGGOTH_SEED_RELOAD] > 0) //jmf: added
- you.duration[DUR_SHUGGOTH_SEED_RELOAD]--;
-
- if (you.duration[DUR_INFECTED_SHUGGOTH_SEED] > 1)
- you.duration[DUR_INFECTED_SHUGGOTH_SEED]--;
- else if (you.duration[DUR_INFECTED_SHUGGOTH_SEED] == 1)
- {
- //jmf: use you.max_hp instead? or would that be too evil?
- you.duration[DUR_INFECTED_SHUGGOTH_SEED] = 0;
- mpr("A horrible thing bursts from your chest!", MSGCH_WARN);
- ouch(1 + you.hp / 2, 0, KILLED_BY_SHUGGOTH);
- make_shuggoth(you.x_pos, you.y_pos, 1 + you.hp / 2);
- }
-
if (you.invis > 1)
{
you.invis--;
@@ -2139,7 +1845,7 @@ static void input(void)
you.berserker = 0;
//jmf: guilty for berserking /after/ berserk
- naughty( NAUGHTY_STIMULANTS, 6 + random2(6) );
+ did_god_conduct( DID_STIMULANTS, 6 + random2(6) );
//
// Sometimes berserk leaves us physically drained
@@ -2155,23 +1861,55 @@ static void input(void)
// this should make it a bit more interesting for
// Crusaders again.
// - similarly for the amulet
- int chance = 10 + you.mutation[MUT_BERSERK] * 25
- + (wearing_amulet( AMU_RAGE ) ? 10 : 0)
- + (player_has_spell( SPELL_BERSERKER_RAGE ) ? 5 : 0);
-
+ int chances[4];
+ chances[0] = 10;
+ chances[1] = you.mutation[MUT_BERSERK] * 25;
+ chances[2] = (wearing_amulet( AMU_RAGE ) ? 10 : 0);
+ chances[3] = (player_has_spell( SPELL_BERSERKER_RAGE ) ? 5 : 0);
+ const char* reasons[4] = {
+ "You struggle, and manage to stay standing.",
+ "Your mutated body refuses to collapse.",
+ "You feel your neck pulse as blood rushes through your body.",
+ "Your mind masters your body."
+ };
+ const int chance = chances[0] + chances[1] + chances[2] + chances[3];
+
+ if (you.berserk_penalty == NO_BERSERK_PENALTY)
+ mpr("The very source of your rage keeps you on your feet.");
// Note the beauty of Trog! They get an extra save that's at
// the very least 20% and goes up to 100%.
- if (you.berserk_penalty == NO_BERSERK_PENALTY
- || (you.religion == GOD_TROG && you.piety > random2(150))
- || !one_chance_in( chance ))
+ else if ( you.religion == GOD_TROG && you.piety > random2(150) &&
+ !player_under_penance() )
+ mpr("Trog's vigour flows through your veins.");
+ else if ( !one_chance_in(chance) )
{
- mpr("You are exhausted.");
+ // Survived the probabilistic check.
+ // Figure out why.
+
+ int cause = random2(chance); // philosophically speaking...
+ int i;
+ for ( i = 0; i < 4; ++i )
+ {
+ if ( cause < chances[i] )
+ {
+ // only print a reason if it actually exists
+ if ( reasons[i][0] != 0 )
+ mpr(reasons[i]);
+ break;
+ }
+ else
+ cause -= chances[i];
+ }
+ if (i == 4)
+ mpr("Oops. Couldn't find a reason. Well, lucky you.");
}
else
{
mpr("You pass out from exhaustion.", MSGCH_WARN);
you.paralysis += roll_dice( 1, 4 );
}
+ if ( you.paralysis == 0 )
+ mpr("You are exhausted.", MSGCH_WARN);
// this resets from an actual penalty or from NO_BERSERK_PENALTY
you.berserk_penalty = 0;
@@ -2229,20 +1967,8 @@ static void input(void)
burden_change();
you.duration[DUR_CONTROLLED_FLIGHT] = 0;
- if (grd[you.x_pos][you.y_pos] == DNGN_LAVA
- || grd[you.x_pos][you.y_pos] == DNGN_DEEP_WATER
- || grd[you.x_pos][you.y_pos] == DNGN_SHALLOW_WATER)
- {
- if (you.species == SP_MERFOLK
- && grd[you.x_pos][you.y_pos] != DNGN_LAVA)
- {
- mpr("You dive into the water and return to your normal form.");
- merfolk_start_swimming();
- }
-
- if (grd[you.x_pos][you.y_pos] != DNGN_SHALLOW_WATER)
- fall_into_a_pool(true, grd[you.x_pos][you.y_pos]);
- }
+ // re-enter the terrain:
+ move_player_to_grid( you.x_pos, you.y_pos, false, true, true );
}
if (you.rotting > 0)
@@ -2332,6 +2058,47 @@ static void input(void)
more();
}
}
+}
+
+/* Perhaps we should write functions like: update_repel_undead(),
+ update_liquid_flames(), and so on. Even better, we could have a
+ vector of callback functions (or objects) which get installed
+ at some point.
+*/
+
+static void world_reacts() {
+
+ bool its_quiet; //jmf: for silence messages
+
+ if (you.num_turns != -1)
+ you.num_turns++;
+
+ //if (random2(10) < you.skills [SK_TRAPS_DOORS] + 2) search_around();
+
+ stealth = check_stealth();
+
+#if 0
+ // too annoying for regular diagnostics
+ snprintf( info, INFO_SIZE, "stealth: %d", stealth );
+ mpr( info, MSGCH_DIAGNOSTICS );
+#endif
+
+ if (you.special_wield != SPWLD_NONE)
+ special_wielded();
+
+ if (one_chance_in(10))
+ {
+ // this is instantaneous
+ if (player_teleport() > 0 && one_chance_in(100 / player_teleport()))
+ you_teleport2( true );
+ else if (you.level_type == LEVEL_ABYSS && one_chance_in(30))
+ you_teleport2( false, true ); // to new area of the Abyss
+ }
+
+ if (env.cgrid[you.x_pos][you.y_pos] != EMPTY_CLOUD)
+ in_a_cloud();
+
+ decrement_durations();
const int food_use = player_hunger_rate();
@@ -2347,14 +2114,10 @@ static void input(void)
while (tmp >= 100)
{
- if (you.hp >= you.hp_max - 1
- && you.running && you.run_x == 0 && you.run_y == 0)
- {
- stop_running();
- }
-
inc_hp(1, false);
tmp -= 100;
+
+ you.running.check_hp();
}
ASSERT( tmp >= 0 && tmp < 100 );
@@ -2369,19 +2132,18 @@ static void input(void)
while (tmp >= 100)
{
- if (you.magic_points >= you.max_magic_points - 1
- && you.running && you.run_x == 0 && you.run_y == 0)
- {
- stop_running();
- }
-
inc_mp(1, false);
tmp -= 100;
+
+ you.running.check_mp();
}
ASSERT( tmp >= 0 && tmp < 100 );
you.magic_points_regeneration = static_cast< unsigned char >( tmp );
+ // If you're wielding a rod, it'll gradually recharge.
+ recharge_rods();
+
viewwindow(1, true);
handle_monsters();
@@ -2407,46 +2169,6 @@ static void input(void)
if (you.fire_shield > 0)
manage_fire_shield();
- // There used to be signs of intent to have statues as some sort
- // of more complex state machine... I'm boiling them down to bare
- // basics for now. -- bwr
- if (Visible_Statue[ STATUE_SILVER ])
- {
- interrupt_activity( AI_STATUE );
-
- if ((!you.invis && one_chance_in(3)) || one_chance_in(5))
- {
- char wc[30];
-
- weird_colours( random2(256), wc );
- snprintf(info, INFO_SIZE, "The silver statue's eyes glow %s.", wc);
- mpr( info, MSGCH_WARN );
-
- create_monster( summon_any_demon((coinflip() ? DEMON_COMMON
- : DEMON_LESSER)),
- ENCH_ABJ_V, BEH_HOSTILE,
- you.x_pos, you.y_pos,
- MHITYOU, 250 );
- }
-
- Visible_Statue[ STATUE_SILVER ] = 0;
- }
-
- if (Visible_Statue[ STATUE_ORANGE_CRYSTAL ])
- {
- interrupt_activity( AI_STATUE );
-
- if ((!you.invis && coinflip()) || one_chance_in(4))
- {
- mpr("A hostile presence attacks your mind!", MSGCH_WARN);
-
- miscast_effect( SPTYP_DIVINATION, random2(15), random2(150), 100,
- "an orange crystal statue" );
- }
-
- Visible_Statue[ STATUE_ORANGE_CRYSTAL ] = 0;
- }
-
// food death check:
if (you.is_undead != US_UNDEAD && you.hunger <= 500)
{
@@ -2518,20 +2240,284 @@ static void input(void)
if (you.level_type == LEVEL_PANDEMONIUM && one_chance_in(50))
pandemonium_mons();
- // No monsters in the Labyrinth, or Ecumenical Temple
+ // No monsters in the Labyrinth, or the Ecumenical Temple
return;
}
+static command_type get_next_cmd() {
+ if (Options.autoprayer_on && you.duration[DUR_PRAYER] == 0 &&
+ just_autoprayed == false && you.religion != GOD_NO_GOD &&
+ grid_altar_god( grd[you.x_pos][you.y_pos] ) == GOD_NO_GOD &&
+ i_feel_safe())
+ {
+ just_autoprayed = true;
+ about_to_autopray = false;
+ return CMD_PRAY;
+ }
+ if ( just_autoprayed && you.duration[DUR_PRAYER] == 0 )
+ {
+ /* oops */
+ mpr("Autoprayer failed, deactivating.", MSGCH_WARN);
+ Options.autoprayer_on = false;
+ }
+ just_autoprayed = false;
+ if ( Options.autoprayer_on && about_to_autopray &&
+ you.religion != GOD_NO_GOD &&
+ you.duration[DUR_PRAYER] == 0 )
+ {
+ mpr("Autoprayer not resuming prayer.", MSGCH_WARN);
+ about_to_autopray = false;
+ }
+
+#if DEBUG_DIAGNOSTICS
+ // save hunger at start of round
+ // for use with hunger "delta-meter" in output.cc
+ you.old_hunger = you.hunger;
+#endif
+
+#if DEBUG_ITEM_SCAN
+ debug_item_scan();
+#endif
+ keycode_type keyin = get_next_keycode();
+
+ if (is_userfunction(keyin))
+ {
+ run_macro(get_userfunction(keyin));
+ return (CMD_NEXT_CMD);
+ }
+
+ return keycode_to_command(keyin);
+}
+
+/* for now, this is an extremely yucky hack */
+command_type keycode_to_command( keycode_type key ) {
+ switch ( key ) {
+ case 'b': return CMD_MOVE_DOWN_LEFT;
+ case 'h': return CMD_MOVE_LEFT;
+ case 'j': return CMD_MOVE_DOWN;
+ case 'k': return CMD_MOVE_UP;
+ case 'l': return CMD_MOVE_RIGHT;
+ case 'n': return CMD_MOVE_DOWN_RIGHT;
+ case 'u': return CMD_MOVE_UP_RIGHT;
+ case 'y': return CMD_MOVE_UP_LEFT;
+
+ case 'a': return CMD_USE_ABILITY;
+ case 'c': return CMD_CLOSE_DOOR;
+ case 'd': return CMD_DROP;
+ case 'e': return CMD_EAT;
+ case 'f': return CMD_FIRE;
+ case 'g': return CMD_PICKUP;
+ case 'i': return CMD_DISPLAY_INVENTORY;
+ case 'm': return CMD_DISPLAY_SKILLS;
+ case 'o': return CMD_OPEN_DOOR;
+ case 'p': return CMD_PRAY;
+ case 'q': return CMD_QUAFF;
+ case 'r': return CMD_READ;
+ case 's': return CMD_SEARCH;
+ case 't': return CMD_THROW;
+ case 'v': return CMD_EXAMINE_OBJECT;
+ case 'w': return CMD_WIELD_WEAPON;
+ case 'x': return CMD_LOOK_AROUND;
+ case 'z': return CMD_ZAP_WAND;
+
+ case 'B': return CMD_RUN_DOWN_LEFT;
+ case 'H': return CMD_RUN_LEFT;
+ case 'J': return CMD_RUN_DOWN;
+ case 'K': return CMD_RUN_UP;
+ case 'L': return CMD_RUN_RIGHT;
+ case 'N': return CMD_RUN_DOWN_RIGHT;
+ case 'U': return CMD_RUN_UP_RIGHT;
+ case 'Y': return CMD_RUN_UP_LEFT;
+
+ case 'A': return CMD_DISPLAY_MUTATIONS;
+ case 'C': return CMD_EXPERIENCE_CHECK;
+ case 'D': return CMD_BUTCHER;
+ case 'E': return CMD_EVOKE;
+ case 'F': return CMD_NO_CMD;
+ case 'G': return CMD_NO_CMD;
+ case 'I': return CMD_NO_CMD;
+ case 'M': return CMD_MEMORISE_SPELL;
+ case 'O': return CMD_DISPLAY_OVERMAP;
+ case 'P': return CMD_WEAR_JEWELLERY;
+ case 'Q': return CMD_QUIT;
+ case 'R': return CMD_REMOVE_JEWELLERY;
+ case 'S': return CMD_SAVE_GAME;
+ case 'T': return CMD_REMOVE_ARMOUR;
+ case 'V': return CMD_GET_VERSION;
+ case 'W': return CMD_WEAR_ARMOUR;
+ case 'X': return CMD_DISPLAY_MAP;
+ case 'Z': return CMD_CAST_SPELL;
+
+ case '.': return CMD_MOVE_NOWHERE;
+ case '<': return CMD_GO_UPSTAIRS;
+ case '>': return CMD_GO_DOWNSTAIRS;
+ case '@': return CMD_DISPLAY_CHARACTER_STATUS;
+ case '%': return CMD_RESISTS_SCREEN;
+ case ',': return CMD_PICKUP;
+ case ':': return CMD_MAKE_NOTE;
+ case ';': return CMD_INSPECT_FLOOR;
+ case '!': return CMD_SHOUT;
+ case '^': return CMD_DISPLAY_RELIGION;
+ case '#': return CMD_CHARACTER_DUMP;
+ case '=': return CMD_ADJUST_INVENTORY;
+ case '?': return CMD_DISPLAY_COMMANDS;
+ case '~': return CMD_MACRO_ADD;
+ case '&': return CMD_WIZARD;
+ case '"': return CMD_LIST_JEWELLERY;
+ case '{': return CMD_INSCRIBE_ITEM;
+ case '[': return CMD_LIST_ARMOUR;
+ case ']': return CMD_LIST_ARMOUR;
+ case ')': return CMD_LIST_WEAPONS;
+ case '(': return CMD_LIST_WEAPONS;
+ case '\\': return CMD_DISPLAY_KNOWN_OBJECTS;
+ case '\'': return CMD_WEAPON_SWAP;
+
+ case '0': return CMD_NO_CMD;
+
+#ifdef UNIX
+ case '1': return CMD_MOVE_DOWN_LEFT;
+ case '2': return CMD_MOVE_DOWN;
+ case '3': return CMD_MOVE_DOWN_RIGHT;
+ case '4': return CMD_MOVE_LEFT;
+ case '5': return CMD_REST;
+ case '6': return CMD_MOVE_RIGHT;
+ case '7': return CMD_MOVE_UP_LEFT;
+ case '8': return CMD_MOVE_UP;
+ case '9': return CMD_MOVE_UP_RIGHT;
+#else
+ case '1': return CMD_RUN_DOWN_LEFT;
+ case '2': return CMD_RUN_DOWN;
+ case '3': return CMD_RUN_DOWN_RIGHT;
+ case '4': return CMD_RUN_LEFT;
+ case '5': return CMD_REST;
+ case '6': return CMD_RUN_RIGHT;
+ case '7': return CMD_RUN_UP_LEFT;
+ case '8': return CMD_RUN_UP;
+ case '9': return CMD_RUN_UP_RIGHT;
+#endif
+
+ case CONTROL('B'): return CMD_OPEN_DOOR_DOWN_LEFT;
+ case CONTROL('H'): return CMD_OPEN_DOOR_LEFT;
+ case CONTROL('J'): return CMD_OPEN_DOOR_DOWN;
+ case CONTROL('K'): return CMD_OPEN_DOOR_UP;
+ case CONTROL('L'): return CMD_OPEN_DOOR_RIGHT;
+ case CONTROL('N'): return CMD_OPEN_DOOR_DOWN_RIGHT;
+ case CONTROL('U'): return CMD_OPEN_DOOR_UP_LEFT;
+ case CONTROL('Y'): return CMD_OPEN_DOOR_UP_RIGHT;
+
+ case CONTROL('A'): return CMD_TOGGLE_AUTOPICKUP;
+ case CONTROL('C'): return CMD_CLEAR_MAP;
+ case CONTROL('D'): return CMD_NO_CMD;
+ case CONTROL('E'): return CMD_FORGET_STASH;
+ case CONTROL('F'): return CMD_SEARCH_STASHES;
+ case CONTROL('G'): return CMD_INTERLEVEL_TRAVEL;
+ case CONTROL('I'): return CMD_NO_CMD;
+ case CONTROL('M'): return CMD_NO_CMD;
+ case CONTROL('O'): return CMD_EXPLORE;
+ case CONTROL('P'): return CMD_REPLAY_MESSAGES;
+ case CONTROL('Q'): return CMD_NO_CMD;
+ case CONTROL('R'): return CMD_REDRAW_SCREEN;
+ case CONTROL('S'): return CMD_MARK_STASH;
+ case CONTROL('T'): return CMD_TOGGLE_NOFIZZLE;
+ case CONTROL('V'): return CMD_TOGGLE_AUTOPRAYER;
+ case CONTROL('W'): return CMD_FIX_WAYPOINT;
+ case CONTROL('X'): return CMD_SAVE_GAME_NOW;
+ case CONTROL('Z'): return CMD_SUSPEND_GAME;
+ default: return CMD_NO_CMD;
+ }
+}
+
+#ifdef UNIX
+static keycode_type numpad2vi(keycode_type key)
+{
+ if (key >= '1' && key <= '9')
+ {
+ const char *vikeys = "bjnh.lyku";
+ return keycode_type(vikeys[key - '1']);
+ }
+ return (key);
+}
+#endif
+
+keycode_type get_next_keycode() {
+
+ keycode_type keyin;
+
+ flush_input_buffer( FLUSH_BEFORE_COMMAND );
+ keyin = getch_with_command_macros();
+
+#ifdef UNIX
+ // Kludging running and opening as two character sequences
+ // for Unix systems. This is an easy way out... all the
+ // player has to do is find a termcap and numlock setting
+ // that will get curses the numbers from the keypad. This
+ // will hopefully be easy.
+
+ /* can we say yuck? -- haranp */
+ if (keyin == '*')
+ {
+ keyin = getch();
+ // return control-key
+ keyin = CONTROL(toupper(numpad2vi(keyin)));
+ }
+ else if (keyin == '/')
+ {
+ keyin = getch();
+ // return shift-key
+ keyin = toupper(numpad2vi(keyin));
+ }
+#else
+ // Old DOS keypad support
+ if (keyin == 0)
+ {
+ /* FIXME haranp - hackiness */
+ const char DOSidiocy[10] = { "OPQKSMGHI" };
+ const char DOSunidiocy[10] = { "bjnh.lyku" };
+ const int DOScontrolidiocy[9] = {
+ 117, 145, 118, 115, 76, 116, 119, 141, 132
+ };
+ keyin = getch();
+ for (int j = 0; j < 9; ++j ) {
+ if (keyin == DOSidiocy[j]) {
+ keyin = DOSunidiocy[j];
+ break;
+ }
+ if (keyin == DOScontrolidiocy[j]) {
+ keyin = CONTROL(toupper(DOSunidiocy[j]));
+ break;
+ }
+ }
+ }
+#endif
+ mesclr();
+
+ return keyin;
+}
+
+static void middle_input() {
+ if (Options.stash_tracking)
+ stashes.update_visible_stashes(
+ Options.stash_tracking == STM_ALL?
+ StashTracker::ST_AGGRESSIVE :
+ StashTracker::ST_PASSIVE);
+}
+
/*
Opens doors and handles some aspects of untrapping. If either move_x or
move_y are non-zero, the pair carries a specific direction for the door
to be opened (eg if you type ctrl - dir).
*/
-static void open_door(char move_x, char move_y)
+static void open_door(int move_x, int move_y, bool check_confused)
{
struct dist door_move;
int dx, dy; // door x, door y
+ if (check_confused && you.conf && !one_chance_in(3))
+ {
+ move_x = random2(3) - 1;
+ move_y = random2(3) - 1;
+ }
+
door_move.dx = move_x;
door_move.dy = move_y;
@@ -2546,7 +2532,7 @@ static void open_door(char move_x, char move_y)
if (mon != NON_MONSTER && !mons_has_ench( &menv[mon], ENCH_SUBMERGED ))
{
you_attack(mgrd[dx][dy], true);
- you.turn_is_over = 1;
+ you.turn_is_over = true;
if (you.berserk_penalty != NO_BERSERK_PENALTY)
you.berserk_penalty = 0;
@@ -2595,20 +2581,20 @@ static void open_door(char move_x, char move_y)
}
grd[dx][dy] = DNGN_OPEN_DOOR;
- you.turn_is_over = 1;
+ you.turn_is_over = true;
}
else
{
mpr("You swing at nothing.");
make_hungry(3, true);
- you.turn_is_over = 1;
+ you.turn_is_over = true;
}
} // end open_door()
/*
Similar to open_door. Can you spot the difference?
*/
-static void close_door(char door_x, char door_y)
+static void close_door(int door_x, int door_y)
{
struct dist door_move;
int dx, dy; // door x, door y
@@ -2638,7 +2624,8 @@ static void close_door(char door_x, char door_y)
{
if (mgrd[dx][dy] != NON_MONSTER)
{
- // Need to make sure that turn_is_over = 1 if creature is invisible
+ // Need to make sure that turn_is_over is set if creature is
+ // invisible
mpr("There's a creature in the doorway!");
door_move.dx = 0;
door_move.dy = 0;
@@ -2667,7 +2654,7 @@ static void close_door(char door_x, char door_y)
}
grd[dx][dy] = DNGN_CLOSED_DOOR;
- you.turn_is_over = 1;
+ you.turn_is_over = true;
}
else
{
@@ -2684,8 +2671,8 @@ static bool initialise(void)
int i = 0, j = 0; // counter variables {dlb}
- your_sign = '@';
- your_colour = LIGHTGREY;
+ you.symbol = '@';
+ you.colour = LIGHTGREY;
// system initialisation stuff:
textbackground(0);
@@ -2694,19 +2681,19 @@ static bool initialise(void)
directvideo = 1;
#endif
-#ifdef USE_EMX
- init_emx();
-#endif
-
seed_rng();
+ init_overmap(); // in overmap.cc (duh?)
+ clear_ids(); // in itemname.cc
+ init_feature_table();
- mons_init(mcolour); // this needs to be way up top {dlb}
+ init_properties();
+ init_monsters(mcolour); // this needs to be way up top {dlb}
init_playerspells(); // this needs to be way up top {dlb}
clrscr();
// init item array:
- for (i = 1; i < MAX_ITEMS; i++)
+ for (i = 0; i < MAX_ITEMS; i++)
init_item( i );
// empty messaging string
@@ -2748,7 +2735,7 @@ static bool initialise(void)
}
for (i = 0; i < NUM_STATUE_TYPES; i++)
- Visible_Statue[i] = 0;
+ you.visible_statue[i] = 0;
// initialize tag system before we try loading anything!
tag_init();
@@ -2797,8 +2784,12 @@ static bool initialise(void)
// set vision radius to player's current vision
setLOSRadius( you.current_vision );
- viewwindow(1, false); // This just puts the view up for the first turn.
- item();
+
+ if (newc)
+ {
+ // For a new game, wipe out monsters in LOS.
+ zap_los_monsters();
+ }
#ifdef CLUA_BINDINGS
clua.runhook("chk_startgame", "%b", ret);
@@ -2806,15 +2797,20 @@ static bool initialise(void)
read_init_file(true);
strncpy(you.your_name, yname.c_str(), kNameLen);
you.your_name[kNameLen - 1] = 0;
+
+ // In case Lua changed the character set.
+ init_feature_table();
#endif
+ viewwindow(1, false); // This just puts the view up for the first turn.
+ activate_notes(true);
return (ret);
}
// An attempt to tone down berserk a little bit. -- bwross
//
// This function does the accounting for not attacking while berserk
-// This gives a triangluar number function for the additional penalty
+// This gives a triangular number function for the additional penalty
// Turn: 1 2 3 4 5 6 7 8
// Penalty: 1 3 6 10 15 21 28 36
//
@@ -2868,13 +2864,11 @@ static void do_berserk_no_combat_penalty(void)
// Called when the player moves by walking/running. Also calls
// attack function and trap function etc when necessary.
-static void move_player(char move_x, char move_y)
+static void move_player(int move_x, int move_y)
{
bool attacking = false;
bool moving = true; // used to prevent eventual movement (swap)
-
- int i;
- bool trap_known;
+ bool swap = false;
if (you.conf)
{
@@ -2886,224 +2880,84 @@ static void move_player(char move_x, char move_y)
const int new_targ_x = you.x_pos + move_x;
const int new_targ_y = you.y_pos + move_y;
- const unsigned char new_targ_grid = grd[ new_targ_x ][ new_targ_y ];
-
- if (new_targ_grid < MINMOVE)
+ if (!in_bounds(new_targ_x, new_targ_y)
+ || grid_is_solid(grd[new_targ_x][new_targ_y]))
{
- you.turn_is_over = 1;
+ you.turn_is_over = true;
mpr("Ouch!");
+ apply_berserk_penalty = true;
return;
}
+ } // end of if you.conf
- if (new_targ_grid == DNGN_LAVA
- && you.duration[DUR_CONDENSATION_SHIELD] > 0)
- {
- mpr("Your icy shield dissipates!", MSGCH_DURATION);
- you.duration[DUR_CONDENSATION_SHIELD] = 0;
- you.redraw_armour_class = 1;
- }
-
- if ((new_targ_grid == DNGN_LAVA
- || new_targ_grid == DNGN_DEEP_WATER
- || new_targ_grid == DNGN_SHALLOW_WATER)
- && !player_is_levitating())
- {
- if (you.species == SP_MERFOLK && new_targ_grid != DNGN_LAVA)
- {
- mpr("You stumble into the water and return to your normal form.");
- merfolk_start_swimming();
- }
-
- if (new_targ_grid != DNGN_SHALLOW_WATER)
- fall_into_a_pool( false, new_targ_grid );
-
- you.turn_is_over = 1;
- do_berserk_no_combat_penalty();
- return;
- }
- } // end of if you.conf
-
- if (you.running > 0 && you.running != 2 && check_stop_running())
+ if (you.running.check_stop_running())
{
- stop_running();
move_x = 0;
move_y = 0;
- you.turn_is_over = 0;
+ // [ds] Do we need this? Shouldn't it be false to start with?
+ you.turn_is_over = false;
return;
}
const int targ_x = you.x_pos + move_x;
const int targ_y = you.y_pos + move_y;
- const unsigned char old_grid = grd[ you.x_pos ][ you.y_pos ];
const unsigned char targ_grid = grd[ targ_x ][ targ_y ];
const unsigned char targ_monst = mgrd[ targ_x ][ targ_y ];
+ const bool targ_solid = grid_is_solid(targ_grid);
- if (targ_monst != NON_MONSTER)
+ if (targ_monst != NON_MONSTER && !mons_is_submerged(&menv[targ_monst]))
{
struct monsters *mon = &menv[targ_monst];
- if (mons_has_ench( mon, ENCH_SUBMERGED ))
- goto break_out;
-
// you can swap places with a friendly monster if you
// can see it and you're not confused
if (mons_friendly( mon ) && player_monster_visible( mon ) && !you.conf)
{
- if (!swap_places( mon ))
+ if (swap_places( mon ))
+ swap = true;
+ else
moving = false;
-
- goto break_out;
}
-
- you_attack( targ_monst, true );
- you.turn_is_over = 1;
-
- // we don't want to create a penalty if there isn't
- // supposed to be one
- if (you.berserk_penalty != NO_BERSERK_PENALTY)
- you.berserk_penalty = 0;
-
- attacking = true;
- }
-
- break_out:
- if (targ_grid == DNGN_LAVA && you.duration[DUR_CONDENSATION_SHIELD] > 0)
- {
- mpr("Your icy shield dissipates!", MSGCH_DURATION);
- you.duration[DUR_CONDENSATION_SHIELD] = 0;
- you.redraw_armour_class = 1;
- }
-
- // Handle dangerous tiles
- if ((targ_grid == DNGN_LAVA
- || targ_grid == DNGN_DEEP_WATER
- || targ_grid == DNGN_SHALLOW_WATER)
- && !attacking && !player_is_levitating() && moving)
- {
- // Merfold automatically enter deep water... every other case
- // we ask for confirmation.
- if (you.species == SP_MERFOLK && targ_grid != DNGN_LAVA)
+ else // attack!
{
- // Only mention diving if we just entering the water.
- if (!player_in_water())
- {
- mpr("You dive into the water and return to your normal form.");
- merfolk_start_swimming();
- }
- }
- else if (targ_grid != DNGN_SHALLOW_WATER)
- {
- bool enter = yesno("Do you really want to step there?", false, 'n');
+ you_attack( targ_monst, true );
+ you.turn_is_over = true;
- if (enter)
- {
- fall_into_a_pool( false, targ_grid );
- you.turn_is_over = 1;
- do_berserk_no_combat_penalty();
- return;
- }
- else
- {
- canned_msg(MSG_OK);
- return;
- }
+ // we don't want to create a penalty if there isn't
+ // supposed to be one
+ if (you.berserk_penalty != NO_BERSERK_PENALTY)
+ you.berserk_penalty = 0;
+
+ attacking = true;
}
}
- if (!attacking && targ_grid >= MINMOVE && moving)
+ if (!attacking && !targ_solid && moving)
{
- if (targ_grid == DNGN_UNDISCOVERED_TRAP
- && random2(you.skills[SK_TRAPS_DOORS] + 1) > 3)
- {
- strcpy(info, "Wait a moment, ");
- strcat(info, you.your_name);
- strcat(info, "! Do you really want to step there?");
- mpr(info, MSGCH_WARN);
- more();
- you.turn_is_over = 0;
-
- i = trap_at_xy( targ_x, targ_y );
- if (i != -1)
- grd[ targ_x ][ targ_y ] = trap_category(env.trap[i].type);
- return;
- }
-
- you.x_pos += move_x;
- you.y_pos += move_y;
+ you.time_taken *= player_movement_speed();
+ you.time_taken /= 10;
+ move_player_to_grid(targ_x, targ_y, true, false, swap);
- if (targ_grid == DNGN_SHALLOW_WATER && !player_is_levitating())
+ // Returning the random trap scans as a way to get more use from the
+ // skill and acute mutations.
+ if (you.mutation[MUT_ACUTE_VISION] >= 2
+ || (!you.mutation[MUT_BLURRY_VISION]
+ && random2(100) <
+ stat_mult(you.intel, skill_bump(SK_TRAPS_DOORS))))
{
- if (you.species != SP_MERFOLK)
- {
- if (one_chance_in(3) && !silenced(you.x_pos, you.y_pos))
- {
- mpr("Splash!");
- noisy( 10, you.x_pos, you.y_pos );
- }
-
- you.time_taken *= 13 + random2(8);
- you.time_taken /= 10;
-
- if (old_grid != DNGN_SHALLOW_WATER)
- {
- mpr( "You enter the shallow water. "
- "Moving in this stuff is going to be slow." );
-
- if (you.invis)
- mpr( "And don't expect to remain undetected." );
- }
- }
- else if (old_grid != DNGN_SHALLOW_WATER
- && old_grid != DNGN_DEEP_WATER)
- {
- mpr("You return to your normal form as you enter the water.");
- merfolk_start_swimming();
- }
+ search_around();
}
-
move_x = 0;
move_y = 0;
- you.time_taken *= player_movement_speed();
- you.time_taken /= 10;
-
- you.turn_is_over = 1;
- item_check(0);
-
- if (targ_grid >= DNGN_TRAP_MECHANICAL
- && targ_grid <= DNGN_UNDISCOVERED_TRAP)
- {
- if (targ_grid == DNGN_UNDISCOVERED_TRAP)
- {
- i = trap_at_xy(you.x_pos, you.y_pos);
- if (i != -1)
- grd[ you.x_pos ][ you.y_pos ] = trap_category(env.trap[i].type);
- trap_known = false;
- }
- else
- {
- trap_known = true;
- }
-
- i = trap_at_xy( you.x_pos, you.y_pos );
- if (i != -1)
- {
- if (player_is_levitating()
- && trap_category(env.trap[i].type) == DNGN_TRAP_MECHANICAL)
- {
- goto out_of_traps; // can fly over mechanical traps
- }
-
- handle_traps(env.trap[i].type, i, trap_known);
- }
- } // end of if another grd == trap
+ you.turn_is_over = true;
+ item_check( false );
}
- out_of_traps:
// BCR - Easy doors single move
- if (targ_grid == DNGN_CLOSED_DOOR && (Options.easy_open || you.running < 0))
- open_door(move_x, move_y);
- else if (targ_grid <= MINMOVE)
+ if (targ_grid == DNGN_CLOSED_DOOR && Options.easy_open)
+ open_door(move_x, move_y, false);
+ else if (targ_solid)
{
stop_running();
move_x = 0;
@@ -3111,8 +2965,8 @@ static void move_player(char move_x, char move_y)
you.turn_is_over = 0;
}
- if (you.running == 2)
- you.running = 1;
+ if (you.running == RMODE_START)
+ you.running = RMODE_CONTINUE;
if (you.level_type == LEVEL_ABYSS
&& (you.x_pos <= 15 || you.x_pos >= (GXM - 16)
@@ -3150,8 +3004,5 @@ static void move_player(char move_x, char move_y)
#endif
}
- if (!attacking)
- {
- do_berserk_no_combat_penalty();
- }
+ apply_berserk_penalty = !attacking;
} // end move_player()
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index afcbd0445b..d431817532 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -3,6 +3,8 @@
* Summary: Functions related to ranged attacks.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <7> 21mar2001 GDL Replaced all FP arithmetic with integer*100 math
@@ -38,6 +40,7 @@
#include "it_use2.h"
#include "itemname.h"
#include "items.h"
+#include "itemprop.h"
#include "misc.h"
#include "monplace.h"
#include "monstuff.h"
@@ -59,26 +62,19 @@
#define MON_UNAFFECTED 1 // monster unaffected
#define MON_AFFECTED 2 // monster was unaffected
-extern FixedVector< char, NUM_STATUE_TYPES > Visible_Statue; // in acr.cc
-
static int spreadx[] = { 0, 0, 1, -1 };
static int spready[] = { -1, 1, 0, 0 };
static int opdir[] = { 2, 1, 4, 3 };
static FixedArray < bool, 19, 19 > explode_map;
-// helper functions (some of these, esp. affect(), should probably
+// helper functions (some of these, esp. affect(), should probably
// be public):
static void sticky_flame_monster( int mn, bool source, int hurt_final );
static bool affectsWalls(struct bolt &beam);
-static int affect(struct bolt &beam, int x, int y);
-static bool isBouncy(struct bolt &beam);
+static bool isBouncy(struct bolt &beam, unsigned char gridtype);
static void beam_drop_object( struct bolt &beam, item_def *item, int x, int y );
-static bool beam_term_on_target(struct bolt &beam);
+static bool beam_term_on_target(struct bolt &beam, int x, int y);
static void beam_explodes(struct bolt &beam, int x, int y);
-static int bounce(int &step1, int &step2, int w1, int w2, int &n1, int &n2,
- int l1, int l2, int &t1, int &t2, bool topBlocked, bool sideBlocked);
-static bool fuzzyLine(int nx, int ny, int &tx, int &ty, int lx, int ly,
- int stepx, int stepy, bool roundX, bool roundY);
static int affect_wall(struct bolt &beam, int x, int y);
static int affect_place_clouds(struct bolt &beam, int x, int y);
static void affect_place_explosion_clouds(struct bolt &beam, int x, int y);
@@ -92,8 +88,70 @@ static void explosion_map(struct bolt &beam, int x, int y,
int count, int dir, int r);
static void explosion_cell(struct bolt &beam, int x, int y, bool drawOnly);
+static void ench_animation( int flavour, const monsters *mon = NULL, bool force = false);
static void zappy(char z_type, int power, struct bolt &pbolt);
+static bool beam_is_blockable( struct bolt &pbolt )
+{
+ // BEAM_ELECTRICITY is added here because chain lighting is not
+ // a true beam (stops at the first target it gets to and redirects
+ // from there)... but we don't want it shield blockable.
+ return (!pbolt.is_beam && !pbolt.is_explosion
+ && pbolt.flavour != BEAM_ELECTRICITY);
+}
+
+// simple animated flash from Rupert Smith (and expanded to be more generic):
+void zap_animation( int colour, const monsters *mon, bool force )
+{
+ int x = you.x_pos, y = you.y_pos;
+
+ // default to whatever colour magic is today
+ if (colour == -1)
+ colour = element_colour( EC_MAGIC );
+
+ if (mon)
+ {
+ if (!force && !player_monster_visible( mon ))
+ return;
+
+ x = mon->x;
+ y = mon->y;
+ }
+
+ if (!see_grid( x, y ))
+ return;
+
+ const int drawx = x - you.x_pos + 18;
+ const int drawy = y - you.y_pos + 9;
+
+ if (drawx > 8 && drawx < 26 && drawy > 0 && drawy < 18)
+ {
+ textcolor( colour );
+ gotoxy( drawx, drawy );
+ putch( SYM_ZAP );
+
+#ifdef UNIX
+ update_screen();
+#endif
+
+ delay(50);
+ }
+}
+
+// special front function for zap_animation to interpret enchantment flavours
+static void ench_animation( int flavour, const monsters *mon, bool force )
+{
+ const int elem = (flavour == BEAM_HEALING) ? EC_HEAL :
+ (flavour == BEAM_PAIN) ? EC_UNHOLY :
+ (flavour == BEAM_DISPEL_UNDEAD) ? EC_HOLY :
+ (flavour == BEAM_POLYMORPH) ? EC_MUTAGENIC :
+ (flavour == BEAM_TELEPORT
+ || flavour == BEAM_BANISH
+ || flavour == BEAM_BLINK) ? EC_WARP
+ : EC_ENCHANT;
+ zap_animation( element_colour( elem ), mon, force );
+}
+
void zapping(char ztype, int power, struct bolt &pbolt)
{
@@ -103,7 +161,7 @@ void zapping(char ztype, int power, struct bolt &pbolt)
#endif
// GDL: note that rangeMax is set to 0, which means that max range is
- // equal to range. This is OK, since rangeMax really only matters for
+ // equal to range. This is OK, since rangeMax really only matters for
// stuff monsters throw/zap.
// all of the following might be changed by zappy():
@@ -114,11 +172,11 @@ void zapping(char ztype, int power, struct bolt &pbolt)
pbolt.type = 0; // default for "0" beams
pbolt.flavour = BEAM_MAGIC; // default for "0" beams
pbolt.ench_power = power;
- pbolt.obviousEffect = false;
- pbolt.isBeam = false; // default for all beams.
- pbolt.isTracer = false; // default for all player beams
+ pbolt.obvious_effect = false;
+ pbolt.is_beam = false; // default for all beams.
+ pbolt.is_tracer = false; // default for all player beams
pbolt.thrower = KILL_YOU_MISSILE; // missile from player
- pbolt.aux_source = NULL; // additional source info, unused
+ pbolt.aux_source.clear(); // additional source info, unused
// fill in the bolt structure
zappy( ztype, power, pbolt );
@@ -423,29 +481,29 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
switch (z_type)
{
case ZAP_STRIKING: // cap 25
- strcpy(pbolt.beam_name, "force bolt");
+ pbolt.name = "force bolt";
pbolt.colour = BLACK;
pbolt.range = 8 + random2(5);
pbolt.damage = dice_def( 1, 5 ); // dam: 5
pbolt.hit = 8 + power / 10; // 25: 10
pbolt.type = SYM_SPACE;
pbolt.flavour = BEAM_MMISSILE; // unresistable
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
case ZAP_MAGIC_DARTS: // cap 25
- strcpy(pbolt.beam_name, "magic dart");
+ pbolt.name = "magic dart";
pbolt.colour = LIGHTMAGENTA;
pbolt.range = random2(5) + 8;
pbolt.damage = dice_def( 1, 3 + power / 5 ); // 25: 1d8
pbolt.hit = 1500; // hits always
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_MMISSILE; // unresistable
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
case ZAP_STING: // cap 25
- strcpy(pbolt.beam_name, "sting");
+ pbolt.name = "sting";
pbolt.colour = GREEN;
pbolt.range = 8 + random2(5);
pbolt.damage = dice_def( 1, 3 + power / 5 ); // 25: 1d8
@@ -453,11 +511,11 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_POISON; // extra damage
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
case ZAP_ELECTRICITY: // cap 20
- strcpy(pbolt.beam_name, "zap");
+ pbolt.name = "zap";
pbolt.colour = LIGHTCYAN;
pbolt.range = 6 + random2(8); // extended in beam
pbolt.damage = dice_def( 1, 3 + random2(power) / 2 ); // 25: 1d11
@@ -465,12 +523,12 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_ELECTRICITY; // beams & reflects
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_beam = true;
break;
case ZAP_DISRUPTION: // cap 25
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_DISINTEGRATION;
pbolt.range = 7 + random2(8);
pbolt.damage = dice_def( 1, 4 + power / 5 ); // 25: 1d9
@@ -478,7 +536,7 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
break;
case ZAP_PAIN: // cap 25
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_PAIN;
pbolt.range = 7 + random2(8);
pbolt.damage = dice_def( 1, 4 + power / 5 ); // 25: 1d9
@@ -487,7 +545,7 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
break;
case ZAP_FLAME_TONGUE: // cap 25
- strcpy(pbolt.beam_name, "flame");
+ pbolt.name = "flame";
pbolt.colour = RED;
pbolt.range = 1 + random2(2) + random2(power) / 10;
@@ -499,17 +557,17 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_BOLT;
pbolt.flavour = BEAM_FIRE;
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
case ZAP_SMALL_SANDBLAST: // cap 25
- strcpy(pbolt.beam_name, "blast of ");
+ pbolt.name = "blast of ";
temp_rand = random2(4);
- strcat(pbolt.beam_name, (temp_rand == 0) ? "dust" :
- (temp_rand == 1) ? "dirt" :
- (temp_rand == 2) ? "grit" : "sand");
+ pbolt.name += (temp_rand == 0) ? "dust" :
+ (temp_rand == 1) ? "dirt" :
+ (temp_rand == 2) ? "grit" : "sand";
pbolt.colour = BROWN;
pbolt.range = (random2(power) > random2(30)) ? 2 : 1;
@@ -518,11 +576,11 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_BOLT;
pbolt.flavour = BEAM_FRAG; // extra AC resist
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
case ZAP_SANDBLAST: // cap 50
- strcpy(pbolt.beam_name, coinflip() ? "blast of rock" : "rocky blast");
+ pbolt.name = coinflip() ? "blast of rock" : "rocky blast";
pbolt.colour = BROWN;
pbolt.range = 2 + random2(power) / 20;
@@ -534,11 +592,11 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_BOLT;
pbolt.flavour = BEAM_FRAG; // extra AC resist
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
case ZAP_BONE_SHARDS:
- strcpy(pbolt.beam_name, "spray of bone shards");
+ pbolt.name = "spray of bone shards";
pbolt.colour = LIGHTGREY;
pbolt.range = 7 + random2(10);
@@ -551,12 +609,12 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_MAGIC; // unresisted
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_beam = true;
break;
case ZAP_FLAME: // cap 50
- strcpy(pbolt.beam_name, "puff of flame");
+ pbolt.name = "puff of flame";
pbolt.colour = RED;
pbolt.range = 8 + random2(5);
pbolt.damage = dice_def( 2, 4 + power / 10 ); // 25: 2d6 50: 2d9
@@ -564,11 +622,11 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_FIRE;
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
case ZAP_FROST: // cap 50
- strcpy(pbolt.beam_name, "puff of frost");
+ pbolt.name = "puff of frost";
pbolt.colour = WHITE;
pbolt.range = 8 + random2(5);
pbolt.damage = dice_def( 2, 4 + power / 10 ); // 25: 2d6 50: 2d9
@@ -576,11 +634,11 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_COLD;
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
case ZAP_STONE_ARROW: // cap 100
- strcpy(pbolt.beam_name, "stone arrow");
+ pbolt.name = "stone arrow";
pbolt.colour = LIGHTGREY;
pbolt.range = 8 + random2(5);
pbolt.damage = dice_def( 2, 4 + power / 8 ); // 25: 2d7 50: 2d10
@@ -588,11 +646,11 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_MISSILE;
pbolt.flavour = BEAM_MMISSILE; // unresistable
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
case ZAP_STICKY_FLAME: // cap 100
- strcpy(pbolt.beam_name, "sticky flame"); // extra damage
+ pbolt.name = "sticky flame"; // extra damage
pbolt.colour = RED;
pbolt.range = 8 + random2(5);
pbolt.damage = dice_def( 2, 3 + power / 12 ); // 50: 2d7 100: 2d11
@@ -600,11 +658,11 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_FIRE;
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
case ZAP_MYSTIC_BLAST: // cap 100
- strcpy(pbolt.beam_name, "orb of energy");
+ pbolt.name = "orb of energy";
pbolt.colour = LIGHTMAGENTA;
pbolt.range = 8 + random2(5);
pbolt.damage = calc_dice( 2, 15 + (power * 2) / 5 );
@@ -612,11 +670,11 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_MMISSILE; // unresistable
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
case ZAP_ICE_BOLT: // cap 100
- strcpy(pbolt.beam_name, "bolt of ice");
+ pbolt.name = "bolt of ice";
pbolt.colour = WHITE;
pbolt.range = 8 + random2(5);
pbolt.damage = calc_dice( 3, 10 + power / 2 );
@@ -626,7 +684,7 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
break;
case ZAP_DISPEL_UNDEAD: // cap 100
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_DISPEL_UNDEAD;
pbolt.range = 7 + random2(8);
pbolt.damage = calc_dice( 3, 20 + (power * 3) / 4 );
@@ -635,7 +693,7 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
break;
case ZAP_MAGMA: // cap 150
- strcpy(pbolt.beam_name, "bolt of magma");
+ pbolt.name = "bolt of magma";
pbolt.colour = RED;
pbolt.range = 5 + random2(4);
pbolt.damage = calc_dice( 4, 10 + (power * 3) / 5 );
@@ -643,12 +701,12 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_LAVA;
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_beam = true;
break;
case ZAP_FIRE: // cap 150
- strcpy(pbolt.beam_name, "bolt of fire");
+ pbolt.name = "bolt of fire";
pbolt.colour = RED;
pbolt.range = 7 + random2(10);
pbolt.damage = calc_dice( 6, 20 + (power * 3) / 4 );
@@ -656,12 +714,12 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_FIRE;
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_beam = true;
break;
case ZAP_COLD: // cap 150
- strcpy(pbolt.beam_name, "bolt of cold");
+ pbolt.name = "bolt of cold";
pbolt.colour = WHITE;
pbolt.range = 7 + random2(10);
pbolt.damage = calc_dice( 6, 20 + (power * 3) / 4 );
@@ -669,12 +727,12 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_COLD;
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_beam = true;
break;
case ZAP_VENOM_BOLT: // cap 150
- strcpy(pbolt.beam_name, "bolt of poison");
+ pbolt.name = "bolt of poison";
pbolt.colour = LIGHTGREEN;
pbolt.range = 8 + random2(10);
pbolt.damage = calc_dice( 4, 15 + power / 2 );
@@ -682,12 +740,12 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_POISON; // extra damage
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_beam = true;
break;
case ZAP_NEGATIVE_ENERGY: // cap 150
- strcpy(pbolt.beam_name, "bolt of negative energy");
+ pbolt.name = "bolt of negative energy";
pbolt.colour = DARKGREY;
pbolt.range = 7 + random2(10);
pbolt.damage = calc_dice( 4, 15 + (power * 3) / 5 );
@@ -695,46 +753,46 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_NEG; // drains levels
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_beam = true;
break;
case ZAP_IRON_BOLT: // cap 150
- strcpy(pbolt.beam_name, "iron bolt");
+ pbolt.name = "iron bolt";
pbolt.colour = LIGHTCYAN;
pbolt.range = 5 + random2(5);
pbolt.damage = calc_dice( 9, 15 + (power * 3) / 4 );
pbolt.hit = 7 + power / 15; // 50: 10 100: 13
pbolt.type = SYM_MISSILE;
pbolt.flavour = BEAM_MMISSILE; // unresistable
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
case ZAP_POISON_ARROW: // cap 150
- strcpy(pbolt.beam_name, "poison arrow");
+ pbolt.name = "poison arrow";
pbolt.colour = LIGHTGREEN;
pbolt.range = 8 + random2(5);
pbolt.damage = calc_dice( 4, 15 + power );
pbolt.hit = 5 + power / 10; // 50: 10 100: 15
pbolt.type = SYM_MISSILE;
pbolt.flavour = BEAM_POISON_ARROW; // extra damage
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
case ZAP_DISINTEGRATION: // cap 150
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_DISINTEGRATION;
pbolt.range = 7 + random2(8);
pbolt.damage = calc_dice( 3, 15 + (power * 3) / 4 );
pbolt.ench_power *= 5;
pbolt.ench_power /= 2;
- pbolt.isBeam = true;
+ pbolt.is_beam = true;
break;
case ZAP_LIGHTNING: // cap 150
// also for breath (at pow = lev * 2; max dam: 33)
- strcpy(pbolt.beam_name, "bolt of lightning");
+ pbolt.name = "bolt of lightning";
pbolt.colour = LIGHTCYAN;
pbolt.range = 8 + random2(10); // extended in beam
pbolt.damage = calc_dice( 1, 10 + (power * 3) / 5 );
@@ -742,22 +800,23 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_ELECTRICITY; // beams & reflects
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_beam = true;
break;
case ZAP_FIREBALL: // cap 150
- strcpy(pbolt.beam_name, "fireball");
+ pbolt.name = "fireball";
pbolt.colour = RED;
pbolt.range = 8 + random2(5);
pbolt.damage = calc_dice( 3, 10 + power / 2 );
pbolt.hit = 40; // hit: 40
pbolt.type = SYM_ZAP;
- pbolt.flavour = BEAM_EXPLOSION; // fire
+ pbolt.flavour = BEAM_FIRE; // fire
+ pbolt.is_explosion = true;
break;
case ZAP_ORB_OF_ELECTRICITY: // cap 150
- strcpy(pbolt.beam_name, "orb of electricity");
+ pbolt.name = "orb of electricity";
pbolt.colour = LIGHTBLUE;
pbolt.range = 9 + random2(12);
pbolt.damage = calc_dice( 1, 15 + (power * 4) / 5 );
@@ -765,33 +824,35 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.hit = 40; // hit: 40
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_ELECTRICITY;
+ pbolt.is_explosion = true;
break;
case ZAP_ORB_OF_FRAGMENTATION: // cap 150
- strcpy(pbolt.beam_name, "metal orb");
+ pbolt.name = "metal orb";
pbolt.colour = CYAN;
pbolt.range = 9 + random2(7);
pbolt.damage = calc_dice( 3, 30 + (power * 3) / 4 );
pbolt.hit = 20; // hit: 20
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_FRAG; // extra AC resist
+ pbolt.is_explosion = true;
break;
- case ZAP_CLEANSING_FLAME: // cap 200
- strcpy(pbolt.beam_name, "golden flame");
+ case ZAP_CLEANSING_FLAME:
+ pbolt.name = "golden flame";
pbolt.colour = YELLOW;
- pbolt.range = 7 + random2(10);
- pbolt.damage = calc_dice( 6, 30 + power );
- pbolt.hit = 20; // hit: 20
+ pbolt.range = 7;
+ pbolt.damage = calc_dice( 3, 30 + (power * 3) / 4 );
+ pbolt.hit = 150;
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_HOLY;
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_explosion = true;
break;
case ZAP_CRYSTAL_SPEAR: // cap 200
- strcpy(pbolt.beam_name, "crystal spear");
+ pbolt.name = "crystal spear";
pbolt.colour = WHITE;
pbolt.range = 7 + random2(10);
pbolt.damage = calc_dice( 12, 30 + (power * 4) / 3 );
@@ -799,24 +860,24 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_MISSILE;
pbolt.flavour = BEAM_MMISSILE; // unresistable
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
case ZAP_HELLFIRE: // cap 200
- strcpy(pbolt.beam_name, "hellfire");
+ pbolt.name = "hellfire";
pbolt.colour = RED;
pbolt.range = 7 + random2(10);
pbolt.damage = calc_dice( 3, 10 + (power * 3) / 4 );
pbolt.hit = 20 + power / 10; // 50: 25 100: 30
pbolt.type = SYM_ZAP;
- pbolt.flavour = BEAM_EXPLOSION;
+ pbolt.flavour = BEAM_HELLFIRE;
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_explosion = true;
break;
case ZAP_ICE_STORM: // cap 200
- strcpy(pbolt.beam_name, "great blast of cold");
+ pbolt.name = "great blast of cold";
pbolt.colour = BLUE;
pbolt.range = 9 + random2(5);
pbolt.damage = calc_dice( 6, 15 + power );
@@ -825,10 +886,11 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.ench_power = power; // used for radius
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_ICE; // half resisted
+ pbolt.is_explosion = true;
break;
case ZAP_BEAM_OF_ENERGY: // bolt of innacuracy
- strcpy(pbolt.beam_name, "narrow beam of energy");
+ pbolt.name = "narrow beam of energy";
pbolt.colour = YELLOW;
pbolt.range = 7 + random2(10);
pbolt.damage = calc_dice( 12, 40 + (power * 3) / 2 );
@@ -836,13 +898,13 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_ENERGY; // unresisted
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_beam = true;
break;
case ZAP_SPIT_POISON: // cap 50
// max pow = lev + mut * 5 = 42
- strcpy(pbolt.beam_name, "splash of poison");
+ pbolt.name = "splash of poison";
pbolt.colour = GREEN;
pbolt.range = 3 + random2( 1 + power / 2 );
@@ -853,12 +915,12 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.hit = 5 + random2( 1 + power / 3 ); // max hit: 19
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_POISON;
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
case ZAP_BREATHE_FIRE: // cap 50
// max pow = lev + mut * 4 + 12 = 51 (capped to 50)
- strcpy(pbolt.beam_name, "fiery breath");
+ pbolt.name = "fiery breath";
pbolt.colour = RED;
pbolt.range = 3 + random2( 1 + power / 2 );
@@ -870,13 +932,13 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_FIRE;
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_beam = true;
break;
case ZAP_BREATHE_FROST: // cap 50
// max power = lev = 27
- strcpy(pbolt.beam_name, "freezing breath");
+ pbolt.name = "freezing breath";
pbolt.colour = WHITE;
pbolt.range = 3 + random2( 1 + power / 2 );
@@ -888,13 +950,13 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_COLD;
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_beam = true;
break;
case ZAP_BREATHE_ACID: // cap 50
// max power = lev for ability, 50 for minor destruction (max dam: 57)
- strcpy(pbolt.beam_name, "acid");
+ pbolt.name = "acid";
pbolt.colour = YELLOW;
pbolt.range = 3 + random2( 1 + power / 2 );
@@ -906,13 +968,13 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_ACID;
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_beam = true;
break;
case ZAP_BREATHE_POISON: // leaves clouds of gas // cap 50
// max power = lev = 27
- strcpy(pbolt.beam_name, "poison gas");
+ pbolt.name = "poison gas";
pbolt.colour = GREEN;
pbolt.range = 3 + random2( 1 + power / 2 );
@@ -924,12 +986,12 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_POISON;
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_beam = true;
break;
case ZAP_BREATHE_POWER: // cap 50
- strcpy(pbolt.beam_name, "bolt of energy");
+ pbolt.name = "bolt of energy";
// max power = lev = 27
pbolt.colour = BLUE;
@@ -949,13 +1011,13 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_MMISSILE; // unresistable
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_beam = true;
break;
case ZAP_BREATHE_STEAM: // cap 50
// max power = lev = 27
- strcpy(pbolt.beam_name, "ball of steam");
+ pbolt.name = "ball of steam";
pbolt.colour = LIGHTGREY;
pbolt.range = 6 + random2(5);
@@ -965,133 +1027,133 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.damage = dice_def( 3, 4 + power / 5 ); // max dam: 27
pbolt.hit = 10 + random2( 1 + power / 5 );
pbolt.type = SYM_ZAP;
- pbolt.flavour = BEAM_FIRE;
+ pbolt.flavour = BEAM_STEAM;
- pbolt.obviousEffect = true;
- pbolt.isBeam = true;
+ pbolt.obvious_effect = true;
+ pbolt.is_beam = true;
break;
case ZAP_SLOWING:
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_SLOW;
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_HASTING:
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_HASTE;
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_PARALYSIS:
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_PARALYSIS;
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_CONFUSION:
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_CONFUSION;
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_INVISIBILITY:
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_INVISIBILITY;
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_HEALING:
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_HEALING;
pbolt.damage = dice_def( 1, 7 + power / 3 );
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_DIGGING:
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_DIGGING;
// not ordinary "0" beam range {dlb}
pbolt.range = 3 + random2( power / 5 ) + random2(5);
- pbolt.isBeam = true;
+ pbolt.is_beam = true;
break;
case ZAP_TELEPORTATION:
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_TELEPORT;
pbolt.range = 9 + random2(5);
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_POLYMORPH_OTHER:
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_POLYMORPH;
pbolt.range = 9 + random2(5);
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_ENSLAVEMENT:
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_CHARM;
pbolt.range = 7 + random2(5);
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_BANISHMENT:
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_BANISH;
pbolt.range = 7 + random2(5);
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_DEGENERATION:
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_DEGENERATE;
pbolt.range = 7 + random2(5);
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_ENSLAVE_UNDEAD:
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_ENSLAVE_UNDEAD;
pbolt.range = 7 + random2(5);
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_AGONY:
- strcpy(pbolt.beam_name, "0agony");
+ pbolt.name = "0agony";
pbolt.flavour = BEAM_PAIN;
pbolt.range = 7 + random2(8);
pbolt.ench_power *= 5;
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_CONTROL_DEMON:
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_ENSLAVE_DEMON;
pbolt.range = 7 + random2(5);
pbolt.ench_power *= 3;
pbolt.ench_power /= 2;
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_SLEEP: //jmf: added
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_SLEEP;
pbolt.range = 7 + random2(5);
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_BACKLIGHT: //jmf: added
- strcpy(pbolt.beam_name, "0");
+ pbolt.name = "0";
pbolt.flavour = BEAM_BACKLIGHT;
pbolt.colour = BLUE;
pbolt.range = 7 + random2(5);
- // pbolt.isBeam = true;
+ // pbolt.is_beam = true;
break;
case ZAP_DEBUGGING_RAY:
- strcpy( pbolt.beam_name, "debugging ray" );
+ pbolt.name = "debugging ray";
pbolt.colour = random_colour();
pbolt.range = 7 + random2(10);
pbolt.damage = dice_def( 1500, 1 ); // dam: 1500
@@ -1099,11 +1161,11 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_DEBUG;
pbolt.flavour = BEAM_MMISSILE; // unresistable
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
default:
- strcpy(pbolt.beam_name, "buggy beam");
+ pbolt.name = "buggy beam";
pbolt.colour = random_colour();
pbolt.range = 7 + random2(10);
pbolt.damage = dice_def( 1, 0 );
@@ -1111,16 +1173,16 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
pbolt.type = SYM_DEBUG;
pbolt.flavour = BEAM_MMISSILE; // unresistable
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
break;
} // end of switch
} // end zappy()
/* NEW (GDL):
- * Now handles all beamed/thrown items and spells, tracers, and their effects.
+ * Now handles all beamed/thrown items and spells, tracers, and their effects.
* item is used for items actually thrown/launched
*
- * if item is NULL, there is no physical object being thrown that could
+ * if item is NULL, there is no physical object being thrown that could
* land on the ground.
*/
@@ -1140,7 +1202,7 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
* 4. Check for beam termination on target
* 5. Affect the cell which the beam just moved into -> affect()
* 6. Decrease remaining range appropriately
- * 7. Check for early out due to aimedAtFeet
+ * 7. Check for early out due to aimed_at_feet
* 8. Draw the beam
* 9. Drop an object where the beam 'landed'
*10. Beams explode where the beam 'landed'
@@ -1151,78 +1213,48 @@ static void zappy( char z_type, int power, struct bolt &pbolt )
void fire_beam( struct bolt &pbolt, item_def *item )
{
- int dx, dy; // total delta between source & target
- int lx, ly; // last affected x,y
- int stepx, stepy; // x,y increment - FP
- int wx, wy; // 'working' x,y - FP
bool beamTerminate; // has beam been 'stopped' by something?
- int nx, ny; // test(new) x,y - FP
- int tx, ty; // test(new) x,y - integer
- bool roundX, roundY; // which to round?
+ int tx = 0, ty = 0; // test(new) x,y - integer
int rangeRemaining;
- bool fuzzyOK; // fuzzification resulted in OK move
- bool sideBlocked, topBlocked, random_beam;
#if DEBUG_DIAGNOSTICS
- snprintf( info, INFO_SIZE, "%s%s (%d,%d) to (%d,%d): ty=%d col=%d flav=%d hit=%d dam=%dd%d",
- (pbolt.isBeam) ? "beam" : "missile",
- (pbolt.isTracer) ? " tracer" : "",
- pbolt.source_x, pbolt.source_y,
- pbolt.target_x, pbolt.target_y,
- pbolt.type, pbolt.colour, pbolt.flavour,
- pbolt.hit, pbolt.damage.num, pbolt.damage.size );
-
- mpr( info, MSGCH_DIAGNOSTICS );
+ if (pbolt.flavour != BEAM_LINE_OF_SIGHT)
+ {
+ mprf( MSGCH_DIAGNOSTICS,
+ "%s%s%s (%d,%d) to (%d,%d): ty=%d col=%d flav=%d hit=%d dam=%dd%d",
+ (pbolt.is_beam) ? "beam" : "missile",
+ (pbolt.is_explosion) ? "*" :
+ (pbolt.is_big_cloud) ? "+" : "",
+ (pbolt.is_tracer) ? " tracer" : "",
+ pbolt.source_x, pbolt.source_y,
+ pbolt.target_x, pbolt.target_y,
+ pbolt.type, pbolt.colour, pbolt.flavour,
+ pbolt.hit, pbolt.damage.num, pbolt.damage.size );
+ }
#endif
// init
- pbolt.aimedAtFeet = false;
- pbolt.msgGenerated = false;
- pbolt.isExplosion = false;
- roundY = false;
- roundX = false;
-
- // first, calculate beam step
- dx = pbolt.target_x - pbolt.source_x;
- dy = pbolt.target_y - pbolt.source_y;
-
- // check for aim at feet
- if (dx == 0 && dy == 0)
- {
- pbolt.aimedAtFeet = true;
- stepx = 0;
- stepy = 0;
- tx = pbolt.source_x;
- ty = pbolt.source_y;
- }
- else
- {
- if (abs(dx) >= abs(dy))
- {
- stepx = (dx > 0) ? 100 : -100;
- stepy = 100 * dy / (abs(dx));
- roundY = true;
- }
- else
- {
- stepy = (dy > 0) ? 100 : -100;
- stepx = 100 * dx / (abs(dy));
- roundX = true;
- }
- }
+ pbolt.aimed_at_feet =
+ (pbolt.target_x == pbolt.source_x) &&
+ (pbolt.target_y == pbolt.source_y);
+ pbolt.msg_generated = false;
+
+ ray_def ray;
- // give chance for beam to affect one cell even if aimedAtFeet.
+ find_ray( pbolt.source_x, pbolt.source_y, pbolt.target_x, pbolt.target_y,
+ true, ray);
+
+ if ( !pbolt.aimed_at_feet )
+ ray.advance();
+
+ // give chance for beam to affect one cell even if aimed_at_feet.
beamTerminate = false;
- // setup working coords
- lx = pbolt.source_x;
- wx = 100 * lx;
- ly = pbolt.source_y;
- wy = 100 * ly;
+
// setup range
rangeRemaining = pbolt.range;
if (pbolt.rangeMax > pbolt.range)
{
- if (pbolt.isTracer)
+ if (pbolt.is_tracer)
rangeRemaining = pbolt.rangeMax;
else
rangeRemaining += random2((pbolt.rangeMax - pbolt.range) + 1);
@@ -1231,140 +1263,79 @@ void fire_beam( struct bolt &pbolt, item_def *item )
// before we start drawing the beam, turn buffering off
#ifdef WIN32CONSOLE
bool oldValue = true;
- if (!pbolt.isTracer)
+ if (!pbolt.is_tracer)
oldValue = setBuffering(false);
#endif
- // cannot use source_x, source_y, target_x, target_y during
- // step algorithm due to bouncing.
-
- // now, one step at a time, try to move towards target.
while(!beamTerminate)
{
- nx = wx + stepx;
- ny = wy + stepy;
-
- if (roundY)
- {
- tx = nx / 100;
- ty = (ny + 50) / 100;
- }
- if (roundX)
- {
- ty = ny / 100;
- tx = (nx + 50) / 100;
- }
-
- // check that tx, ty are valid. If not, set to last
- // x,y and break.
- if (tx < 0 || tx >= GXM || ty < 0 || ty >= GYM)
- {
- tx = lx;
- ty = ly;
- break;
- }
+ tx = ray.x();
+ ty = ray.y();
// see if tx, ty is blocked by something
- if (grd[tx][ty] < MINMOVE)
+ if (grid_is_solid(grd[tx][ty]))
{
// first, check to see if this beam affects walls.
if (affectsWalls(pbolt))
{
// should we ever get a tracer with a wall-affecting
- // beam (possible I suppose), we'll quit tracing now.
- if (!pbolt.isTracer)
+ // beam (possible I suppose), we'll quit tracing now.
+ if (!pbolt.is_tracer)
rangeRemaining -= affect(pbolt, tx, ty);
// if it's still a wall, quit.
- if (grd[tx][ty] < MINMOVE)
- {
+ if (grid_is_solid(grd[tx][ty]))
break; // breaks from line tracing
- }
}
else
{
- // BEGIN fuzzy line algorithm
- fuzzyOK = fuzzyLine(nx,ny,tx,ty,lx,ly,stepx,stepy,roundX,roundY);
- if (!fuzzyOK)
- {
- // BEGIN bounce case
- if (!isBouncy(pbolt))
- {
- tx = lx;
- ty = ly;
- break; // breaks from line tracing
- }
-
- sideBlocked = false;
- topBlocked = false;
- // BOUNCE -- guaranteed to return reasonable tx, ty.
- // if it doesn't, we'll quit in the next if stmt anyway.
- if (roundY)
- {
- if ( grd[lx + stepx / 100][ly] < MINMOVE)
- sideBlocked = true;
+ // BEGIN bounce case
+ if (!isBouncy(pbolt, grd[tx][ty])) {
+ ray.regress();
+ tx = ray.x();
+ ty = ray.y();
+ break; // breaks from line tracing
+ }
- if (dy != 0)
- {
- if ( grd[lx][ly + (stepy>0?1:-1)] < MINMOVE)
- topBlocked = true;
- }
+ // bounce
+ do {
+ ray.regress();
+ ray.advance_and_bounce();
+ --rangeRemaining;
+ } while ( rangeRemaining > 0 &&
+ grid_is_solid(grd[ray.x()][ray.y()]) );
- rangeRemaining -= bounce(stepx, stepy, wx, wy, nx, ny,
- lx, ly, tx, ty, topBlocked, sideBlocked);
- }
- else
- {
- if ( grd[lx][ly + stepy / 100] < MINMOVE)
- sideBlocked = true;
-
- if (dx != 0)
- {
- if ( grd[lx + (stepx>0?1:-1)][ly] < MINMOVE)
- topBlocked = true;
- }
+ if (rangeRemaining < 1)
+ break;
+ tx = ray.x();
+ ty = ray.y();
- rangeRemaining -= bounce(stepy, stepx, wy, wx, ny, nx,
- ly, lx, ty, tx, topBlocked, sideBlocked);
- }
- // END bounce case - range check
- if (rangeRemaining < 1)
- {
- tx = lx;
- ty = ly;
- break;
- }
- }
} // end else - beam doesn't affect walls
} // endif - is tx, ty wall?
// at this point, if grd[tx][ty] is still a wall, we
// couldn't find any path: bouncy, fuzzy, or not - so break.
- if (grd[tx][ty] < MINMOVE)
- {
- tx = lx;
- ty = ly;
+ if (grid_is_solid(grd[tx][ty]))
break;
- }
-
+
// check for "target termination"
// occurs when beam can be targetted at empty
// cell (e.g. a mage wants an explosion to happen
// between two monsters)
- // in this case, don't affect the cell - players
- // /monsters have no chance to dodge or block such
- // a beam, and we want to avoid silly messages.
+ // in this case, don't affect the cell - players and
+ // monsters have no chance to dodge or block such
+ // a beam, and we want to avoid silly messages.
if (tx == pbolt.target_x && ty == pbolt.target_y)
- beamTerminate = beam_term_on_target(pbolt);
+ beamTerminate = beam_term_on_target(pbolt, tx, ty);
- // affect the cell, except in the special case noted
+ // affect the cell, except in the special case noted
// above -- affect() will early out if something gets
// hit and the beam is type 'term on target'.
- if (!beamTerminate)
+ if (!beamTerminate || !pbolt.is_explosion)
{
// random beams: randomize before affect
- random_beam = false;
+ bool random_beam = false;
if (pbolt.flavour == BEAM_RANDOM)
{
random_beam = true;
@@ -1385,12 +1356,12 @@ void fire_beam( struct bolt &pbolt, item_def *item )
beamTerminate = true;
// special case - beam was aimed at feet
- if (pbolt.aimedAtFeet)
+ if (pbolt.aimed_at_feet)
beamTerminate = true;
// actually draw the beam/missile/whatever,
// if the player can see the cell.
- if (!pbolt.isTracer && pbolt.beam_name[0] != '0' && see_grid(tx,ty))
+ if (!pbolt.is_tracer && pbolt.name[0] != '0' && see_grid(tx,ty))
{
// we don't clean up the old position.
// first, most people like seeing the full path,
@@ -1419,24 +1390,17 @@ void fire_beam( struct bolt &pbolt, item_def *item )
delay(15);
#ifdef MISSILE_TRAILS_OFF
- if (!pbolt.isBeam || pbolt.beam_name[0] == '0')
+ if (!pbolt.is_beam || pbolt.name[0] == '0')
viewwindow(1,false); // mv: added. It's not optimal but
// is usually enough
#endif
}
}
-
- // set some stuff up for the next iteration
- lx = tx;
- ly = ty;
-
- wx = nx;
- wy = ny;
-
+ ray.advance();
} // end- while !beamTerminate
- // the beam has finished, and terminated at tx, ty
+ // the beam has finished, and terminated at tx, ty
// leave an object, if applicable
if (item)
@@ -1450,22 +1414,22 @@ void fire_beam( struct bolt &pbolt, item_def *item )
beam_explodes(pbolt, tx, ty);
- if (pbolt.isTracer)
+ if (pbolt.is_tracer)
{
pbolt.target_x = ox;
pbolt.target_y = oy;
}
// canned msg for enchantments that affected no-one
- if (pbolt.beam_name[0] == '0' && pbolt.flavour != BEAM_DIGGING)
+ if (pbolt.name[0] == '0' && pbolt.flavour != BEAM_DIGGING)
{
- if (!pbolt.isTracer && !pbolt.msgGenerated && !pbolt.obviousEffect)
+ if (!pbolt.is_tracer && !pbolt.msg_generated && !pbolt.obvious_effect)
canned_msg(MSG_NOTHING_HAPPENS);
}
// that's it!
#ifdef WIN32CONSOLE
- if (!pbolt.isTracer)
+ if (!pbolt.is_tracer)
setBuffering(oldValue);
#endif
} // end fire_beam();
@@ -1476,7 +1440,7 @@ void fire_beam( struct bolt &pbolt, item_def *item )
int mons_adjust_flavoured( struct monsters *monster, struct bolt &pbolt,
int hurted, bool doFlavouredEffects )
{
- // if we're not doing flavored effects, must be preliminary
+ // if we're not doing flavored effects, must be preliminary
// damage check only; do not print messages or apply any side
// effects!
int resist;
@@ -1484,6 +1448,7 @@ int mons_adjust_flavoured( struct monsters *monster, struct bolt &pbolt,
switch (pbolt.flavour)
{
case BEAM_FIRE:
+ case BEAM_STEAM:
resist = mons_res_fire(monster);
if (resist > 1)
{
@@ -1580,8 +1545,7 @@ int mons_adjust_flavoured( struct monsters *monster, struct bolt &pbolt,
// Poison arrow can poison any living thing regardless of
// poison resistance. -- bwr
- const int holy = mons_holiness( monster->type );
- if (holy == MH_PLANT || holy == MH_NATURAL)
+ if (mons_has_lifeforce(monster))
poison_monster( monster, YOU_KILL(pbolt.thrower), 2, true );
}
@@ -1623,17 +1587,47 @@ int mons_adjust_flavoured( struct monsters *monster, struct bolt &pbolt,
} // end else
break;
- case BEAM_HOLY: // flame of cleansing
- if (mons_holiness(monster->type) == MH_NATURAL
- || mons_holiness(monster->type) == MH_NONLIVING
- || mons_holiness(monster->type) == MH_PLANT
- || mons_holiness(monster->type) == MH_HOLY)
+ case BEAM_MIASMA:
+ if (mons_res_negative_energy( monster ) >= 3)
{
if (doFlavouredEffects)
simple_monster_message(monster, " appears unharmed.");
hurted = 0;
}
+ else
+ {
+ // early out for tracer/no side effects
+ if (!doFlavouredEffects)
+ return (hurted);
+
+ if (mons_res_poison( monster ) <= 0)
+ poison_monster( monster, YOU_KILL(pbolt.thrower) );
+
+ if (one_chance_in( 3 + 2 * mons_res_negative_energy(monster) ))
+ {
+ struct bolt beam;
+ beam.flavour = BEAM_SLOW;
+ mons_ench_f2( monster, beam );
+ }
+ }
+ break;
+
+ case BEAM_HOLY: // flame of cleansing
+ if (mons_is_unholy( monster ))
+ {
+ if (doFlavouredEffects)
+ simple_monster_message( monster, " writhes in agony!" );
+
+ hurted = (hurted * 3) / 2;
+ }
+ else if (!mons_is_evil( monster ))
+ {
+ if (doFlavouredEffects)
+ simple_monster_message( monster, " appears unharmed." );
+
+ hurted = 0;
+ }
break;
case BEAM_ICE:
@@ -1687,7 +1681,7 @@ int mons_adjust_flavoured( struct monsters *monster, struct bolt &pbolt,
hurted /= 10;
}
}
- else if (stricmp(pbolt.beam_name, "hellfire") == 0)
+ else if (pbolt.name == "hellfire")
{
resist = mons_res_fire(monster);
if (resist > 2)
@@ -1732,7 +1726,7 @@ int mons_adjust_flavoured( struct monsters *monster, struct bolt &pbolt,
bool mass_enchantment( int wh_enchant, int pow, int origin )
{
int i; // loop variable {dlb}
- bool msgGenerated = false;
+ bool msg_generated = false;
struct monsters *monster;
viewwindow(0, false);
@@ -1753,7 +1747,7 @@ bool mass_enchantment( int wh_enchant, int pow, int origin )
if (mons_friendly(monster))
continue;
- if (mons_holiness(monster->type) != MH_UNDEAD)
+ if (mons_class_holiness(monster->type) != MH_UNDEAD)
continue;
if (check_mons_resist_magic( monster, pow ))
@@ -1762,7 +1756,7 @@ bool mass_enchantment( int wh_enchant, int pow, int origin )
continue;
}
}
- else if (mons_holiness(monster->type) == MH_NATURAL)
+ else if (mons_holiness(monster) == MH_NATURAL)
{
if (check_mons_resist_magic( monster, pow ))
{
@@ -1784,7 +1778,7 @@ bool mass_enchantment( int wh_enchant, int pow, int origin )
if (player_monster_visible( monster ))
{
// turn message on
- msgGenerated = true;
+ msg_generated = true;
switch (wh_enchant)
{
case ENCH_FEAR:
@@ -1801,7 +1795,7 @@ bool mass_enchantment( int wh_enchant, int pow, int origin )
break;
default:
// oops, I guess not!
- msgGenerated = false;
+ msg_generated = false;
}
}
@@ -1811,10 +1805,10 @@ bool mass_enchantment( int wh_enchant, int pow, int origin )
}
} // end "for i"
- if (!msgGenerated)
+ if (!msg_generated)
canned_msg(MSG_NOTHING_HAPPENS);
- return (msgGenerated);
+ return (msg_generated);
} // end mass_enchantmenet()
/*
@@ -1832,22 +1826,23 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
switch (pbolt.flavour) /* put in magic resistance */
{
case BEAM_SLOW: /* 0 = slow monster */
- // try to remove haste, if monster is hasted
+ // try to remove haste, if monster is hasted
if (mons_del_ench(monster, ENCH_HASTE))
{
if (simple_monster_message(monster, " is no longer moving quickly."))
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
return (MON_AFFECTED);
}
- // not hasted, slow it
- if (mons_add_ench(monster, ENCH_SLOW))
+ // not hasted, slow it
+ if (!mons_has_ench(monster, ENCH_SLOW)
+ && mons_add_ench(monster, ENCH_SLOW))
{
// put in an exception for fungi, plants and other things you won't
// notice slow down.
if (simple_monster_message(monster, " seems to slow down."))
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
}
return (MON_AFFECTED);
@@ -1855,7 +1850,7 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
if (mons_del_ench(monster, ENCH_SLOW))
{
if (simple_monster_message(monster, " is no longer moving slowly."))
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
return (MON_AFFECTED);
}
@@ -1866,7 +1861,7 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
// put in an exception for fungi, plants and other things you won't
// notice speed up.
if (simple_monster_message(monster, " seems to speed up."))
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
}
return (MON_AFFECTED);
@@ -1877,12 +1872,12 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
{
if (simple_monster_message(monster,
"'s wounds heal themselves!"))
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
}
else
{
if (simple_monster_message(monster, " is healed somewhat."))
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
}
}
return (MON_AFFECTED);
@@ -1891,10 +1886,10 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
monster->speed_increment = 0;
if (simple_monster_message(monster, " suddenly stops moving!"))
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
- if (grd[monster->x][monster->y] == DNGN_LAVA_X
- || grd[monster->x][monster->y] == DNGN_WATER_X)
+ if (grd[monster->x][monster->y] == DNGN_LAVA
+ || grid_is_water(grd[monster->x][monster->y]))
{
if (mons_flies(monster) == 1)
{
@@ -1904,8 +1899,8 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
{
strcpy(info, ptr_monam(monster, DESC_CAP_THE));
strcat(info, " falls into the ");
- strcat(info, (grd[monster->x][monster->y] == DNGN_WATER_X)
- ? "water" : "lava");
+ strcat(info, (grd[monster->x][monster->y] == DNGN_LAVA)
+ ? "lava" : "water");
strcat(info, "!");
mpr(info);
}
@@ -1932,7 +1927,7 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
// put in an exception for fungi, plants and other things you won't
// notice becoming confused.
if (simple_monster_message(monster, " appears confused."))
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
}
return (MON_AFFECTED);
@@ -1952,7 +1947,7 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
mpr( info );
}
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
}
return (MON_AFFECTED);
@@ -1962,7 +1957,7 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
// put in an exception for fungi, plants and other things you won't
// notice becoming charmed.
if (simple_monster_message(monster, " is charmed."))
- pbolt.obviousEffect = true;
+ pbolt.obvious_effect = true;
}
return (MON_AFFECTED);
@@ -1973,6 +1968,56 @@ int mons_ench_f2(struct monsters *monster, struct bolt &pbolt)
return (MON_AFFECTED);
} // end mons_ench_f2()
+// degree is ignored.
+static void slow_monster(monsters *mon, int degree)
+{
+ bolt beam;
+ beam.flavour = BEAM_SLOW;
+ mons_ench_f2(mon, beam);
+}
+
+// Returns true if the curare killed the monster.
+bool curare_hits_monster( const bolt &beam,
+ monsters *monster,
+ bool fromPlayer,
+ int levels )
+{
+ const bool res_poison = mons_res_poison(monster);
+ bool mondied = false;
+
+ poison_monster(monster, fromPlayer, levels, false);
+
+ if (!mons_res_asphyx(monster))
+ {
+ int hurted = roll_dice(2, 6);
+
+ // Note that the hurtage is halved by poison resistance.
+ if (res_poison)
+ hurted /= 2;
+
+ if (hurted)
+ {
+ simple_monster_message(monster, " appears to choke.");
+ if ((monster->hit_points -= hurted) < 1)
+ {
+ const int thrower = YOU_KILL(beam.thrower) ?
+ KILL_YOU_MISSILE : KILL_MON_MISSILE;
+ monster_die(monster, thrower, beam.beam_source);
+ mondied = true;
+ }
+ }
+
+ if (!mondied)
+ slow_monster(monster, levels);
+ }
+
+ // Deities take notice.
+ if (fromPlayer)
+ did_god_conduct( DID_POISON, 5 + random2(3) );
+
+ return (mondied);
+}
+
// actually poisons a monster (w/ message)
void poison_monster( struct monsters *monster, bool fromPlayer, int levels,
bool force )
@@ -2031,10 +2076,7 @@ void poison_monster( struct monsters *monster, bool fromPlayer, int levels,
// finally, take care of deity preferences
if (fromPlayer)
- {
- naughty(NAUGHTY_POISON, 5 + random2(3)); //jmf: TSO now hates poison
- done_good(GOOD_POISON, 5); //jmf: had test god who liked poison
- }
+ did_god_conduct( DID_POISON, 5 + random2(3) );
} // end poison_monster()
// actually napalms a monster (w/ message)
@@ -2080,7 +2122,7 @@ void sticky_flame_monster( int mn, bool fromPlayer, int levels )
mons_del_ench( monster, ENCH_YOUR_STICKY_FLAME_I, ENCH_YOUR_STICKY_FLAME_IV,
true );
- // increase sticky flame strength, cap at 3 (level is 0..3)
+ // increase sticky flame strength, cap at 3 (level is 0..3)
currentStrength += levels;
if (currentStrength > 3)
@@ -2108,42 +2150,59 @@ void sticky_flame_monster( int mn, bool fromPlayer, int levels )
* fr_count, foe_count: a count of how many friends and foes will (probably)
* be hit by this beam
* fr_power, foe_power: a measure of how many 'friendly' hit dice it will
- * affect, and how many 'unfriendly' hit dice.
+ * affect, and how many 'unfriendly' hit dice.
*
- * note that beam properties must be set, as the tracer will take them
- * into account, as well as the monster's intelligence.
+ * note that beam properties must be set, as the tracer will take them
+ * into account, as well as the monster's intelligence.
*
*/
void fire_tracer(struct monsters *monster, struct bolt &pbolt)
{
// don't fiddle with any input parameters other than tracer stuff!
- pbolt.isTracer = true;
+ pbolt.is_tracer = true;
pbolt.source_x = monster->x; // always safe to do.
pbolt.source_y = monster->y;
pbolt.beam_source = monster_index(monster);
- pbolt.canSeeInvis = (mons_see_invis(monster) != 0);
- pbolt.smartMonster = (mons_intel(monster->type) == I_HIGH ||
+ pbolt.can_see_invis = (mons_see_invis(monster) != 0);
+ pbolt.smart_monster = (mons_intel(monster->type) == I_HIGH ||
mons_intel(monster->type) == I_NORMAL);
- pbolt.isFriendly = mons_friendly(monster);
+ pbolt.is_friendly = mons_friendly(monster);
// init tracer variables
pbolt.foe_count = pbolt.fr_count = 0;
pbolt.foe_power = pbolt.fr_power = 0;
- pbolt.foeRatio = 80; // default - see mons_should_fire()
+ pbolt.foe_ratio = 80; // default - see mons_should_fire()
// foe ratio for summon gtr. demons & undead -- they may be
// summoned, but they're hostile and would love nothing better
// than to nuke the player and his minions
- if (monster->attitude != ATT_FRIENDLY)
- pbolt.foeRatio = 25;
+ if (pbolt.is_friendly && monster->attitude != ATT_FRIENDLY)
+ pbolt.foe_ratio = 25;
// fire!
fire_beam(pbolt);
// unset tracer flag (convenience)
- pbolt.isTracer = false;
+ pbolt.is_tracer = false;
} // end tracer_f()
+bool check_line_of_sight( int sx, int sy, int tx, int ty )
+{
+ const int dist = grid_distance( sx, sy, tx, ty );
+
+ // can always see one square away
+ if (dist <= 1)
+ return (true);
+
+ // currently we limit the range to 8
+ if (dist > MONSTER_LOS_RANGE)
+ return (false);
+
+ // Note that we are guaranteed to be within the player LOS range,
+ // so fallback is unnecessary.
+ ray_def ray;
+ return find_ray( sx, sy, tx, ty, false, ray );
+}
/*
When a mimic is hit by a ranged attack, it teleports away (the slow way)
@@ -2158,12 +2217,15 @@ void mimic_alert(struct monsters *mimic)
monster_teleport( mimic, !one_chance_in(3) );
} // end mimic_alert()
-static bool isBouncy(struct bolt &beam)
+static bool isBouncy(struct bolt &beam, unsigned char gridtype)
{
- // at present, only non-enchantment eletrcical beams bounce.
- if (beam.beam_name[0] != '0' && beam.flavour == BEAM_ELECTRICITY)
- return (true);
-
+ if (beam.name[0] == '0')
+ return false;
+ if (beam.flavour == BEAM_ELECTRICITY && gridtype != DNGN_METAL_WALL)
+ return true;
+ if ( (beam.flavour == BEAM_FIRE || beam.flavour == BEAM_COLD) &&
+ (gridtype == DNGN_GREEN_CRYSTAL_WALL) )
+ return true;
return (false);
}
@@ -2178,7 +2240,7 @@ static void beam_explodes(struct bolt &beam, int x, int y)
beam.target_y = y;
// generic explosion
- if (beam.flavour == BEAM_EXPLOSION || beam.flavour == BEAM_HOLY)
+ if (beam.is_explosion) // beam.flavour == BEAM_EXPLOSION || beam.flavour == BEAM_HOLY)
{
explosion1(beam);
return;
@@ -2235,7 +2297,7 @@ static void beam_explodes(struct bolt &beam, int x, int y)
// cloud producer -- POISON BLAST
- if (strcmp(beam.beam_name, "blast of poison") == 0)
+ if (beam.name == "blast of poison")
{
cloud_type = YOU_KILL(beam.thrower) ? CLOUD_POISON : CLOUD_POISON_MON;
big_cloud( cloud_type, x, y, 0, 7 + random2(5) );
@@ -2243,52 +2305,67 @@ static void beam_explodes(struct bolt &beam, int x, int y)
}
// cloud producer -- FOUL VAPOR (SWAMP DRAKE?)
- if (strcmp(beam.beam_name, "foul vapour") == 0)
+ if (beam.name == "foul vapour")
{
cloud_type = YOU_KILL(beam.thrower) ? CLOUD_STINK : CLOUD_STINK_MON;
+ if (beam.flavour == BEAM_MIASMA)
+ cloud_type = YOU_KILL(beam.thrower) ?
+ CLOUD_MIASMA : CLOUD_MIASMA_MON;
big_cloud( cloud_type, x, y, 0, 9 );
return;
}
// special cases - orbs & blasts of cold
- if (strcmp(beam.beam_name, "orb of electricity") == 0
- || strcmp(beam.beam_name, "metal orb") == 0
- || strcmp(beam.beam_name, "great blast of cold") == 0)
+ if (beam.name == "orb of electricity"
+ || beam.name == "metal orb"
+ || beam.name == "great blast of cold")
{
explosion1( beam );
return;
}
// cloud producer only -- stinking cloud
- if (strcmp(beam.beam_name, "ball of vapour") == 0)
+ if (beam.name == "ball of vapour")
{
explosion1( beam );
return;
}
}
-static bool beam_term_on_target(struct bolt &beam)
+static bool beam_term_on_target(struct bolt &beam, int x, int y)
{
+ if (beam.flavour == BEAM_LINE_OF_SIGHT)
+ {
+ beam.foe_count++;
+ return (true);
+ }
// generic - all explosion-type beams can be targetted at empty space,
// and will explode there. This semantic also means that a creature
- // in the target cell will have no chance to dodge or block, so we
+ // in the target cell will have no chance to dodge or block, so we
// DON'T affect() the cell if this function returns true!
- if (beam.flavour == BEAM_EXPLOSION || beam.flavour == BEAM_HOLY)
+ if (beam.is_explosion || beam.is_big_cloud)
return (true);
// POISON BLAST
- if (strcmp(beam.beam_name, "blast of poison") == 0)
+ if (beam.name == "blast of poison")
return (true);
// FOUL VAPOR (SWAMP DRAKE)
- if (strcmp(beam.beam_name, "foul vapour") == 0)
+ if (beam.name == "foul vapour")
return (true);
// STINKING CLOUD
- if (strcmp(beam.beam_name, "ball of vapour") == 0)
+ if (beam.name == "ball of vapour")
+ return (true);
+
+ // [dshaligram] We have to decide what beams are eligible for stopping on
+ // target.
+ /*
+ if (beam.aimed_at_spot && x == beam.target_x && y == beam.target_y)
return (true);
+ */
return (false);
}
@@ -2298,22 +2375,25 @@ static void beam_drop_object( struct bolt &beam, item_def *item, int x, int y )
ASSERT( item != NULL );
// conditions: beam is missile and not tracer.
- if (beam.isTracer || beam.flavour != BEAM_MISSILE)
+ if (beam.is_tracer || beam.flavour != BEAM_MISSILE)
return;
if (YOU_KILL(beam.thrower) // ie if you threw it.
- && (grd[x][y] != DNGN_LAVA && grd[x][y] != DNGN_DEEP_WATER))
+ && (!grid_destroys_items(grd[x][y])))
{
int chance;
- // Using Throwing skill as the fletching/ammo preserving skill. -- bwr
+ // [dshaligram] Removed influence of Throwing on ammo preservation.
+ // The effect is nigh impossible to perceive.
switch (item->sub_type)
{
- case MI_NEEDLE: chance = 6 + you.skills[SK_THROWING] / 6; break;
- case MI_STONE: chance = 3 + you.skills[SK_THROWING] / 4; break;
- case MI_DART: chance = 2 + you.skills[SK_THROWING] / 6; break;
- case MI_ARROW: chance = 2 + you.skills[SK_THROWING] / 4; break;
- case MI_BOLT: chance = 2 + you.skills[SK_THROWING] / 5; break;
+ case MI_NEEDLE:
+ chance = (get_ammo_brand(*item) == SPMSL_CURARE? 3 : 6);
+ break;
+ case MI_STONE: chance = 4; break;
+ case MI_DART: chance = 3; break;
+ case MI_ARROW: chance = 4; break;
+ case MI_BOLT: chance = 4; break;
case MI_LARGE_ROCK:
default:
@@ -2325,206 +2405,83 @@ static void beam_drop_object( struct bolt &beam, item_def *item, int x, int y )
copy_item_to_grid( *item, x, y, 1 );
}
else if (MON_KILL(beam.thrower) // monster threw it.
- && (grd[x][y] != DNGN_LAVA && grd[x][y] != DNGN_DEEP_WATER)
- && coinflip())
+ && !grid_destroys_items(grd[x][y]) && coinflip())
{
copy_item_to_grid( *item, x, y, 1 );
} // if (thing_throw == 2) ...
}
-// somewhat complicated BOUNCE function
-// returns # of times beam bounces during routine (usually 1)
-//
-// step 1 is always the step value from the stepping direction.
-#define B_HORZ 1
-#define B_VERT 2
-#define B_BOTH 3
-
-static int bounce(int &step1, int &step2, int w1, int w2, int &n1, int &n2,
- int l1, int l2, int &t1, int &t2, bool topBlocked, bool sideBlocked)
+// Returns true if the beam hits the player, fuzzing the beam if necessary
+// for monsters without see invis firing tracers at the player.
+static bool found_player(const bolt &beam, int x, int y)
{
- int bounceType = 0;
- int bounceCount = 1;
-
- if (topBlocked) bounceType = B_HORZ;
- if (sideBlocked) bounceType = B_VERT;
- if (topBlocked && sideBlocked)
- {
- // check for veritcal bounce only
- if ((w2 + step2 - 50)/100 == (w2 - 50)/100)
- bounceType = B_VERT;
- else
- bounceType = B_BOTH;
- }
-
- switch (bounceType)
- {
- case B_VERT: // easiest
- n1 = w1;
- n2 = w2 + step2;
- step1 = -step1;
- t1 = n1 / 100;
- t2 = (n2 + 50)/100;
- // check top
- if (t2 != n2/100 && topBlocked)
- t2 = n2/100;
- break;
- case B_HORZ: // a little tricky
- if (step2 > 0)
- n2 = (100 + 200*(w2/100)) - (w2 + step2);
- else
- n2 = (100 + 200*((w2 - 50)/100)) - (w2 + step2);
- n1 = w1 + step1;
- t1 = n1 /100;
- t2 = (n2 + 50) / 100;
- step2 = -step2;
- break;
- case B_BOTH:
- // vertical:
- n1 = w1;
- t1 = l1;
- t2 = l2;
- // horizontal:
- if (step2 > 0)
- n2 = (100 + 200*(w2/100)) - (w2 + step2);
- else
- n2 = (100 + 200*((w2 - 50)/100)) - (w2 + step2);
- // reverse both directions
- step1 =- step1;
- step2 =- step2;
- bounceCount = 2;
- break;
- default:
- bounceCount = 0;
- break;
- }
+ const bool needs_fuzz = beam.is_tracer && !beam.can_see_invis
+ && you.invis;
+ const int dist = needs_fuzz? 2 : 0;
- return (bounceCount);
+ return (grid_distance(x, y, you.x_pos, you.y_pos) <= dist);
}
-static bool fuzzyLine(int nx, int ny, int &tx, int &ty, int lx, int ly,
- int stepx, int stepy, bool roundX, bool roundY)
-{
- bool fuzzyOK = false;
- int fx, fy; // fuzzy x,y
-
- // BEGIN fuzzy line algorithm
- fx = tx;
- fy = ty;
- if (roundY)
- {
- // try up
- fy = (ny + 100) / 100;
- // check for monotonic
- if (fy != ty && ((stepy>0 && fy >= ly)
- || (stepy<0 && fy <= ly)))
- fuzzyOK = true;
- // see if up try is blocked
- if (fuzzyOK && grd[tx][fy] < MINMOVE)
- fuzzyOK = false;
-
- // try down
- if (!fuzzyOK)
- fy = ny / 100;
- // check for monotonic
- if (fy != ty && ((stepy>0 && fy >= ly)
- || (stepy<0 && fy <= ly)))
- fuzzyOK = true;
- if (fuzzyOK && grd[tx][fy] < MINMOVE)
- fuzzyOK = false;
- }
- if (roundX)
- {
- // try up
- fx = (nx + 100) / 100;
- // check for monotonic
- if (fx != tx && ((stepx>0 && fx >= lx)
- || (stepx<0 && fx <= lx)))
- fuzzyOK = true;
- // see if up try is blocked
- if (fuzzyOK && grd[fx][ty] < MINMOVE)
- fuzzyOK = false;
-
- // try down
- if (!fuzzyOK)
- fx = nx / 100;
- // check for monotonic
- if (fx != tx && ((stepx>0 && fx >= lx)
- || (stepx<0 && fx <= lx)))
- fuzzyOK = true;
- if (fuzzyOK && grd[fx][ty] < MINMOVE)
- fuzzyOK = false;
- }
- // END fuzzy line algorithm
-
- if (fuzzyOK)
- {
- tx = fx;
- ty = fy;
- }
-
- return (fuzzyOK);
-}
-
-// affects a single cell.
-// returns the amount of extra range 'used up' by this beam
-// during the affectation.
-//
-// pseudo-code:
-//
-// 1. If wall, and wall affecting non-tracer, affect the wall.
-// 1b. If for some reason the wall-affect didn't make it into
-// a non-wall, return affect_wall()
-// 2. for non-tracers, produce cloud effects affect_place_clouds()
-// 3. if cell holds player, affect player affect_player()
-// 4. if cell holds monster, affect monster affect_monster()
-// 5. return range used affectation.
-
-static int affect(struct bolt &beam, int x, int y)
+int affect(struct bolt &beam, int x, int y)
{
// extra range used by hitting something
int rangeUsed = 0;
- if (grd[x][y] < MINMOVE)
+ // line of sight never affects anything
+ if (beam.flavour == BEAM_LINE_OF_SIGHT)
+ return (0);
+
+ if (grid_is_solid(grd[x][y]))
{
- if (beam.isTracer) // tracers always stop on walls.
+ if (beam.is_tracer) // tracers always stop on walls.
return (BEAM_STOP);
if (affectsWalls(beam))
{
rangeUsed += affect_wall(beam, x, y);
}
- // if it's still a wall, quit - we can't do anything else to
+ // if it's still a wall, quit - we can't do anything else to
// a wall. Otherwise effects (like clouds, etc) are still possible.
- if (grd[x][y] < MINMOVE)
+ if (grid_is_solid(grd[x][y]))
return (rangeUsed);
}
// grd[x][y] will NOT be a wall for the remainder of this function.
// if not a tracer, place clouds
- if (!beam.isTracer)
+ if (!beam.is_tracer)
rangeUsed += affect_place_clouds(beam, x, y);
- // if player is at this location, try to affect unless term_on_target
- if (x == you.x_pos && y == you.y_pos)
+ // if player is at this location, try to affect unless term_on_target
+ if (found_player(beam, x, y))
{
- if (beam_term_on_target(beam) && !beam.isExplosion)
+ // Done this way so that poison blasts affect the target once (via
+ // place_cloud) and explosion spells only affect the target once
+ // (during the explosion phase, not an initial hit during the
+ // beam phase).
+ if (!beam.is_big_cloud
+ && (!beam.is_explosion || beam.in_explosion_phase))
+ {
+ rangeUsed += affect_player( beam );
+ }
+
+ if (beam_term_on_target(beam, x, y))
return (BEAM_STOP);
-
- rangeUsed += affect_player(beam);
}
- // if there is a monster at this location, affect it
+ // if there is a monster at this location, affect it
// submerged monsters aren't really there -- bwr
int mid = mgrd[x][y];
if (mid != NON_MONSTER && !mons_has_ench( &menv[mid], ENCH_SUBMERGED ))
{
- if (beam_term_on_target(beam) && !beam.isExplosion)
+ if (!beam.is_big_cloud
+ && (!beam.is_explosion || beam.in_explosion_phase))
+ {
+ rangeUsed += affect_monster( beam, &menv[mid] );
+ }
+
+ if (beam_term_on_target(beam, x, y))
return (BEAM_STOP);
-
- struct monsters* monster = &menv[mid];
- rangeUsed += affect_monster(beam, monster);
}
return (rangeUsed);
@@ -2534,7 +2491,7 @@ static bool affectsWalls(struct bolt &beam)
{
// don't know of any explosion that affects walls. But change it here
// if there is.
- if (beam.isExplosion)
+ if (beam.is_explosion)
return (false);
// digging
@@ -2546,7 +2503,7 @@ static bool affectsWalls(struct bolt &beam)
if (beam.flavour == BEAM_DISINTEGRATION && beam.damage.num >= 3)
return (true);
- // eye of devestation?
+ // eye of devastation?
if (beam.flavour == BEAM_NUKE)
return (true);
@@ -2574,15 +2531,15 @@ static int affect_wall(struct bolt &beam, int x, int y)
{
grd[x][y] = DNGN_FLOOR;
- if (!beam.msgGenerated)
+ if (!beam.msg_generated)
{
if (!silenced(you.x_pos, you.y_pos))
{
- mpr("You hear a grinding noise.");
- beam.obviousEffect = true;
+ mpr("You hear a grinding noise.", MSGCH_SOUND);
+ beam.obvious_effect = true;
}
- beam.msgGenerated = true;
+ beam.msg_generated = true;
}
}
@@ -2601,22 +2558,25 @@ static int affect_wall(struct bolt &beam, int x, int y)
grd[ x ][ y ] = DNGN_FLOOR;
if (!silenced(you.x_pos, you.y_pos))
{
- mpr("You hear a grinding noise.");
- beam.obviousEffect = true;
+ mpr("You hear a grinding noise.", MSGCH_SOUND);
+ beam.obvious_effect = true;
}
}
- if (targ_grid == DNGN_ORCISH_IDOL || (targ_grid >= DNGN_SILVER_STATUE
- && targ_grid <= DNGN_STATUE_39))
+ if (targ_grid == DNGN_ORCISH_IDOL
+ || targ_grid == DNGN_SILVER_STATUE
+ || targ_grid == DNGN_GRANITE_STATUE
+ || targ_grid == DNGN_ORANGE_CRYSTAL_STATUE)
{
grd[x][y] = DNGN_FLOOR;
if (!silenced(you.x_pos, you.y_pos))
{
if (!see_grid( x, y ))
- mpr("You hear a hideous screaming!");
+ mpr("You hear a hideous screaming!", MSGCH_SOUND);
else
- mpr("The statue screams as its substance crumbles away!");
+ mpr("The statue screams as its substance crumbles away!",
+ MSGCH_SOUND);
}
else
{
@@ -2625,11 +2585,11 @@ static int affect_wall(struct bolt &beam, int x, int y)
}
if (targ_grid == DNGN_SILVER_STATUE)
- Visible_Statue[ STATUE_SILVER ] = 0;
+ you.visible_statue[ STATUE_SILVER ] = 0;
else if (targ_grid == DNGN_ORANGE_CRYSTAL_STATUE)
- Visible_Statue[ STATUE_ORANGE_CRYSTAL ] = 0;
+ you.visible_statue[ STATUE_ORANGE_CRYSTAL ] = 0;
- beam.obviousEffect = 1;
+ beam.obvious_effect = 1;
}
return (BEAM_STOP);
@@ -2642,7 +2602,7 @@ static int affect_place_clouds(struct bolt &beam, int x, int y)
{
int cloud_type;
- if (beam.isExplosion)
+ if (beam.in_explosion_phase)
{
affect_place_explosion_clouds( beam, x, y );
return (0); // return value irrelevant for explosions
@@ -2656,7 +2616,7 @@ static int affect_place_clouds(struct bolt &beam, int x, int y)
env.cloud[ env.cgrid[x][y] ].type = 1 + random2(8);
// now exit (all enchantments)
- if (beam.beam_name[0] == '0')
+ if (beam.name[0] == '0')
return (0);
int clouty = env.cgrid[x][y];
@@ -2673,7 +2633,7 @@ static int affect_place_clouds(struct bolt &beam, int x, int y)
if (!silenced(x, y)
&& !silenced(you.x_pos, you.y_pos))
{
- mpr("You hear a sizzling sound!");
+ mpr("You hear a sizzling sound!", MSGCH_SOUND);
}
delete_cloud( clouty );
@@ -2682,7 +2642,7 @@ static int affect_place_clouds(struct bolt &beam, int x, int y)
}
// POISON BLAST
- if (strcmp(beam.beam_name, "blast of poison") == 0)
+ if (beam.name == "blast of poison")
{
cloud_type = YOU_KILL(beam.thrower) ? CLOUD_POISON : CLOUD_POISON_MON;
@@ -2699,29 +2659,35 @@ static int affect_place_clouds(struct bolt &beam, int x, int y)
}
// ORB OF ENERGY
- if (strcmp(beam.beam_name, "orb of energy") == 0)
+ if (beam.name == "orb of energy")
place_cloud( CLOUD_PURP_SMOKE, x, y, random2(5) + 1 );
// GREAT BLAST OF COLD
- if (strcmp(beam.beam_name, "great blast of cold") == 0)
+ if (beam.name == "great blast of cold")
place_cloud( CLOUD_COLD, x, y, random2(5) + 3 );
// BALL OF STEAM
- if (strcmp(beam.beam_name, "ball of steam") == 0)
+ if (beam.name == "ball of steam")
{
cloud_type = YOU_KILL(beam.thrower) ? CLOUD_STEAM : CLOUD_STEAM_MON;
place_cloud( cloud_type, x, y, random2(5) + 2 );
}
+ if (beam.flavour == BEAM_MIASMA)
+ {
+ cloud_type = YOU_KILL( beam.thrower ) ? CLOUD_MIASMA : CLOUD_MIASMA_MON;
+ place_cloud( cloud_type, x, y, random2(5) + 2 );
+ }
+
// STICKY FLAME
- if (strcmp(beam.beam_name, "sticky flame") == 0)
+ if (beam.name == "sticky flame")
{
place_cloud( CLOUD_BLACK_SMOKE, x, y, random2(4) + 2 );
}
// POISON GAS
- if (strcmp(beam.beam_name, "poison gas") == 0)
+ if (beam.name == "poison gas")
{
cloud_type = YOU_KILL(beam.thrower) ? CLOUD_POISON : CLOUD_POISON_MON;
place_cloud( cloud_type, x, y, random2(4) + 3 );
@@ -2809,18 +2775,18 @@ static void affect_place_explosion_clouds(struct bolt &beam, int x, int y)
}
// then check for more specific explosion cloud types.
- if (stricmp(beam.beam_name, "ice storm") == 0)
+ if (beam.name == "ice storm")
{
place_cloud( CLOUD_COLD, x, y, 2 + random2avg(5, 2) );
}
- if (stricmp(beam.beam_name, "stinking cloud") == 0)
+ if (beam.name == "stinking cloud")
{
duration = 1 + random2(4) + random2( (beam.ench_power / 50) + 1 );
place_cloud( CLOUD_STINK, x, y, duration );
}
- if (strcmp(beam.beam_name, "great blast of fire") == 0)
+ if (beam.name == "great blast of fire")
{
duration = 1 + random2(5) + roll_dice( 2, beam.ench_power / 5 );
@@ -2855,7 +2821,7 @@ static void affect_items(struct bolt &beam, int x, int y)
break;
}
- if (stricmp(beam.beam_name, "hellfire") == 0)
+ if (beam.name == "hellfire")
objs_vulnerable = OBJ_SCROLLS;
if (igrd[x][y] != NON_ITEM)
@@ -2879,11 +2845,16 @@ static void affect_items(struct bolt &beam, int x, int y)
}
}
+static int beam_ouch_agent(const bolt &beam)
+{
+ return YOU_KILL(beam.thrower)? 0 : beam.beam_source;
+}
+
// A little helper function to handle the calling of ouch()...
static void beam_ouch( int dam, struct bolt &beam )
{
// The order of this is important.
- if (YOU_KILL( beam.thrower ) && !beam.aux_source)
+ if (YOU_KILL( beam.thrower ) && beam.aux_source.empty())
{
ouch( dam, 0, KILLED_BY_TARGETTING );
}
@@ -2892,12 +2863,44 @@ static void beam_ouch( int dam, struct bolt &beam )
if (beam.flavour == BEAM_SPORE)
ouch( dam, beam.beam_source, KILLED_BY_SPORE );
else
- ouch( dam, beam.beam_source, KILLED_BY_BEAM, beam.aux_source );
+ ouch( dam, beam.beam_source, KILLED_BY_BEAM,
+ beam.aux_source.c_str() );
}
else // KILL_MISC || (YOU_KILL && aux_source)
{
- ouch( dam, beam.beam_source, KILLED_BY_WILD_MAGIC, beam.aux_source );
+ ouch( dam, beam.beam_source, KILLED_BY_WILD_MAGIC,
+ beam.aux_source.c_str() );
+ }
+}
+
+// [ds] Apply a fuzz if the monster lacks see invisible and is trying to target
+// an invisible player. This makes invisibility slightly more powerful.
+static bool fuzz_invis_tracer(bolt &beem)
+{
+ // Did the monster have a rough idea of where you are?
+ int dist = grid_distance(beem.target_x, beem.target_y,
+ you.x_pos, you.y_pos);
+
+ // No, ditch this.
+ if (dist > 2)
+ return (false);
+
+ // Apply fuzz now.
+ int xfuzz = random_range(-2, 2),
+ yfuzz = random_range(-2, 2);
+
+ const int newx = beem.target_x + xfuzz,
+ newy = beem.target_y + yfuzz;
+ if (in_bounds(newx, newy)
+ && (newx != beem.source_x
+ || newy != beem.source_y))
+ {
+ beem.target_x = newx;
+ beem.target_y = newy;
}
+
+ // Fire away!
+ return (true);
}
// return amount of extra range used up by affectation of the player
@@ -2910,23 +2913,20 @@ static int affect_player( struct bolt &beam )
return (0);
// check for tracer
- if (beam.isTracer)
+ if (beam.is_tracer)
{
// check can see player
- // XXX: note the cheat to allow for ME_ALERT to target the player...
- // replace this with a time since alert system, rather than just
- // peeking to see if the character is still there. -- bwr
- if (beam.canSeeInvis || !you.invis
- || (you.x_pos == beam.target_x && you.y_pos == beam.target_y))
+ if (beam.can_see_invis || !you.invis
+ || fuzz_invis_tracer(beam))
{
- if (beam.isFriendly)
+ if (beam.is_friendly)
{
beam.fr_count += 1;
beam.fr_power += you.experience_level;
}
else
{
- beam.foe_count += 1;
+ beam.foe_count++;
beam.foe_power += you.experience_level;
}
}
@@ -2934,24 +2934,26 @@ static int affect_player( struct bolt &beam )
}
// BEGIN real beam code
- beam.msgGenerated = true;
+ beam.msg_generated = true;
- // use beamHit, NOT beam.hit, for modification of tohit.. geez!
+ // use beamHit, NOT beam.hit, for modification of tohit.. geez!
beamHit = beam.hit;
- if (beam.beam_name[0] != '0')
+ if (beam.name[0] != '0')
{
- if (!beam.isExplosion && !beam.aimedAtFeet)
+ if (!beam.is_explosion && !beam.aimed_at_feet)
{
// BEGIN BEAM/MISSILE
- int dodge = random2limit( player_evasion(), 40 )
+ // [ds] To compensate for the new monster beam hit numbers, allow
+ // for slightly more benefit from evasion (limit was 40)
+ int dodge = random2limit( player_evasion(), 45 )
+ random2( you.dex ) / 3 - 2;
- if (beam.isBeam)
+ if (beam.is_beam)
{
// beams can be dodged
if (player_light_armour()
- && !beam.aimedAtFeet && coinflip())
+ && !beam.aimed_at_feet && coinflip())
{
exercise(SK_DODGING, 1);
}
@@ -2967,34 +2969,34 @@ static int affect_player( struct bolt &beam )
if (beamHit < dodge)
{
- strcpy(info, "The ");
- strcat(info, beam.beam_name);
- strcat(info, " misses you.");
- mpr(info);
+ mprf("The %s misses you.", beam.name.c_str());
return (0); // no extra used by miss!
}
}
- else
+ else if (beam_is_blockable(beam))
{
// non-beams can be blocked or dodged
if (you.equip[EQ_SHIELD] != -1
- && !beam.aimedAtFeet
+ && !beam.aimed_at_feet
&& player_shield_class() > 0)
{
int exer = one_chance_in(3) ? 1 : 0;
- const int hit = random2( beam.hit * 5
- + 10 * you.shield_blocks * you.shield_blocks );
+ // [dshaligram] beam.hit multiplier lowered to 3 - was 5.
+ // In favour of blocking, dex multiplier changed to .25
+ // (was .2), added shield skill into the equation with a
+ // skill bump.
+ const int hit = random2( beam.hit * 3
+ + 5 * you.shield_blocks * you.shield_blocks );
const int block = random2(player_shield_class())
- + (random2(you.dex) / 5) - 1;
+ + (random2(you.dex) / 4)
+ + (random2(skill_bump(SK_SHIELDS)) / 4)
+ - 1;
if (hit < block)
{
you.shield_blocks++;
- snprintf( info, INFO_SIZE, "You block the %s.",
- beam.beam_name );
- mpr( info );
-
+ mprf( "You block the %s.", beam.name.c_str() );
exercise( SK_SHIELDS, exer + 1 );
return (BEAM_STOP);
}
@@ -3003,7 +3005,7 @@ static int affect_player( struct bolt &beam )
exercise( SK_SHIELDS, exer );
}
- if (player_light_armour() && !beam.aimedAtFeet
+ if (player_light_armour() && !beam.aimed_at_feet
&& coinflip())
exercise(SK_DODGING, 1);
@@ -3017,9 +3019,7 @@ static int affect_player( struct bolt &beam )
// miss message
if (beamHit < dodge || you.duration[DUR_DEFLECT_MISSILES])
{
- strcpy(info, "The ");
- strcat(info, beam.beam_name);
- strcat(info, " misses you.");
+ mprf("The %s misses you.", beam.name.c_str());
return (0);
}
}
@@ -3032,63 +3032,70 @@ static int affect_player( struct bolt &beam )
&& beam.flavour != BEAM_INVISIBILITY
&& beam.flavour != BEAM_HEALING
&& ((beam.flavour != BEAM_TELEPORT && beam.flavour != BEAM_BANISH)
- || !beam.aimedAtFeet)
+ || !beam.aimed_at_feet)
&& you_resist_magic( beam.ench_power ))
{
canned_msg(MSG_YOU_RESIST);
return (range_used_on_hit(beam));
}
+ ench_animation( beam.flavour );
+
// these colors are misapplied - see mons_ench_f2() {dlb}
switch (beam.flavour)
{
case BEAM_SLOW:
potion_effect( POT_SLOWING, beam.ench_power );
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
break; // slow
case BEAM_HASTE:
potion_effect( POT_SPEED, beam.ench_power );
contaminate_player( 1 );
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
break; // haste
case BEAM_HEALING:
potion_effect( POT_HEAL_WOUNDS, beam.ench_power );
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
break; // heal (heal wounds potion eff)
case BEAM_PARALYSIS:
potion_effect( POT_PARALYSIS, beam.ench_power );
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
break; // paralysis
case BEAM_CONFUSION:
potion_effect( POT_CONFUSION, beam.ench_power );
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
break; // confusion
case BEAM_INVISIBILITY:
potion_effect( POT_INVISIBILITY, beam.ench_power );
contaminate_player( 1 + random2(2) );
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
break; // invisibility
// 6 is used by digging
case BEAM_TELEPORT:
you_teleport();
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
+ break;
+
+ case BEAM_BLINK:
+ random_blink(0);
+ beam.obvious_effect = true;
break;
case BEAM_POLYMORPH:
mpr("This is polymorph other only!");
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
break;
case BEAM_CHARM:
potion_effect( POT_CONFUSION, beam.ench_power );
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
break; // enslavement - confusion?
case BEAM_BANISH:
@@ -3100,7 +3107,7 @@ static int affect_player( struct bolt &beam )
mpr("You are cast into the Abyss!");
more();
banished(DNGN_ENTER_ABYSS);
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
break; // banishment to the abyss
case BEAM_PAIN: // pain
@@ -3112,11 +3119,11 @@ static int affect_player( struct bolt &beam )
mpr("Pain shoots through your body!");
- if (!beam.aux_source)
+ if (beam.aux_source.empty())
beam.aux_source = "by nerve-wracking pain";
beam_ouch( roll_dice( beam.damage ), beam );
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
break;
case BEAM_DISPEL_UNDEAD:
@@ -3128,21 +3135,21 @@ static int affect_player( struct bolt &beam )
mpr( "You convulse!" );
- if (!beam.aux_source)
+ if (beam.aux_source.empty())
beam.aux_source = "by dispel undead";
beam_ouch( roll_dice( beam.damage ), beam );
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
break;
case BEAM_DISINTEGRATION:
mpr("You are blasted!");
- if (!beam.aux_source)
+ if (beam.aux_source.empty())
beam.aux_source = "disintegration bolt";
beam_ouch( roll_dice( beam.damage ), beam );
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
break;
default:
@@ -3160,12 +3167,12 @@ static int affect_player( struct bolt &beam )
// THE BEAM IS NOW GUARANTEED TO BE A NON-ENCHANTMENT WHICH HIT
- snprintf( info, INFO_SIZE, "The %s %s you!",
- beam.beam_name, (beam.isExplosion ? "engulfs" : "hits") );
- mpr( info );
+ const bool engulfs = (beam.is_explosion || beam.is_big_cloud);
+ mprf( "The %s %s you!",
+ beam.name.c_str(), (engulfs) ? "engulfs" : "hits" );
int hurted = 0;
- int burn_power = (beam.isExplosion) ? 5 : ((beam.isBeam) ? 3 : 2);
+ int burn_power = (beam.is_explosion) ? 5 : ((beam.is_beam) ? 3 : 2);
// Roll the damage
hurted += roll_dice( beam.damage );
@@ -3194,7 +3201,7 @@ static int affect_player( struct bolt &beam )
if (you.equip[EQ_BODY_ARMOUR] != -1)
{
if (!player_light_armour() && one_chance_in(4)
- && random2(1000) <= mass_item( you.inv[you.equip[EQ_BODY_ARMOUR]] ))
+ && random2(1000) <= item_mass( you.inv[you.equip[EQ_BODY_ARMOUR]] ))
{
exercise( SK_ARMOUR, 1 );
}
@@ -3205,21 +3212,38 @@ static int affect_player( struct bolt &beam )
hurted = check_your_resists( hurted, beam.flavour );
+ if (beam.flavour == BEAM_MIASMA && hurted > 0)
+ {
+ if (player_res_poison() <= 0)
+ poison_player(1);
+
+ if (one_chance_in( 3 + 2 * player_prot_life() ))
+ potion_effect( POT_SLOWING, 5 );
+ }
+
// poisoning
- if (strstr(beam.beam_name, "poison") != NULL
+ if (beam.name.find("poison") != std::string::npos
&& beam.flavour != BEAM_POISON
&& beam.flavour != BEAM_POISON_ARROW
&& !player_res_poison())
{
- if (hurted || (strstr( beam.beam_name, "needle" ) != NULL
+ if (hurted || (beam.ench_power == AUTOMATIC_HIT
&& random2(100) < 90 - (3 * player_AC())))
{
poison_player( 1 + random2(3) );
}
}
+ if (beam.name.find("curare") != std::string::npos)
+ {
+ if (random2(100) < 90 - (3 * player_AC()))
+ {
+ curare_hits_player( beam_ouch_agent(beam), 1 + random2(3) );
+ }
+ }
+
// sticky flame
- if (strcmp(beam.beam_name, "sticky flame") == 0
+ if (beam.name == "sticky flame"
&& (you.species != SP_MOTTLED_DRACONIAN
|| you.experience_level < 6))
{
@@ -3227,24 +3251,24 @@ static int affect_player( struct bolt &beam )
you.duration[DUR_LIQUID_FLAMES] += random2avg(7, 3) + 1;
}
- // simple cases for scroll burns
- if (beam.flavour == BEAM_LAVA || stricmp(beam.beam_name, "hellfire") == 0)
- scrolls_burn( burn_power, OBJ_SCROLLS );
+ // simple cases for scroll burns FIXME
+ if (beam.flavour == BEAM_LAVA || beam.name == "hellfire")
+ expose_player_to_element(BEAM_LAVA, burn_power);
// more complex (geez..)
- if (beam.flavour == BEAM_FIRE && strcmp(beam.beam_name, "ball of steam") != 0)
- scrolls_burn( burn_power, OBJ_SCROLLS );
+ if (beam.flavour == BEAM_FIRE && beam.name != "ball of steam")
+ expose_player_to_element(BEAM_FIRE, burn_power);
// potions exploding
if (beam.flavour == BEAM_COLD)
- scrolls_burn( burn_power, OBJ_POTIONS );
+ expose_player_to_element(BEAM_COLD, burn_power);
if (beam.flavour == BEAM_ACID)
splash_with_acid(5);
// spore pops
- if (beam.isExplosion && beam.flavour == BEAM_SPORE)
- scrolls_burn( 2, OBJ_FOOD );
+ if (beam.in_explosion_phase && beam.flavour == BEAM_SPORE)
+ expose_player_to_element(BEAM_SPORE, burn_power);
#if DEBUG_DIAGNOSTICS
snprintf( info, INFO_SIZE, "Damage: %d", hurted );
@@ -3256,10 +3280,21 @@ static int affect_player( struct bolt &beam )
return (range_used_on_hit( beam ));
}
+static int beam_source(const bolt &beam)
+{
+ return MON_KILL(beam.thrower) ? beam.beam_source :
+ beam.thrower == KILL_MISC ? MHITNOT :
+ MHITYOU;
+}
+
// return amount of range used up by affectation of this monster
-static int affect_monster(struct bolt &beam, struct monsters *mon)
+static int affect_monster(struct bolt &beam, struct monsters *mon)
{
- int tid = mgrd[mon->x][mon->y];
+ const int tid = mgrd[mon->x][mon->y];
+ const int mons_type = menv[tid].type;
+ const int thrower = YOU_KILL(beam.thrower)? KILL_YOU_MISSILE
+ : KILL_MON_MISSILE;
+
int hurt;
int hurt_final;
@@ -3268,37 +3303,59 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
return (0);
// fire storm creates these, so we'll avoid affecting them
- if (strcmp(beam.beam_name, "great blast of fire") == 0
+ if (beam.name == "great blast of fire"
&& mon->type == MONS_FIRE_VORTEX)
{
return (0);
}
// check for tracer
- if (beam.isTracer)
+ if (beam.is_tracer)
{
// check can see other monster
- if (!beam.canSeeInvis && mons_has_ench(&menv[tid], ENCH_INVIS))
+ if (!beam.can_see_invis && mons_has_ench(&menv[tid], ENCH_INVIS))
{
// can't see this monster, ignore it
return 0;
}
}
+ else if ((beam.flavour == BEAM_DISINTEGRATION || beam.flavour == BEAM_NUKE)
+ && mons_is_statue(mons_type))
+ {
+ if (!silenced(you.x_pos, you.y_pos))
+ {
+ if (!see_grid( mon->x, mon->y ))
+ mpr("You hear a hideous screaming!", MSGCH_SOUND);
+ else
+ mpr("The statue screams as its substance crumbles away!",
+ MSGCH_SOUND);
+ }
+ else
+ {
+ if (see_grid( mon->x, mon->y ))
+ mpr("The statue twists and shakes as its substance "
+ "crumbles away!");
+ }
+ beam.obvious_effect = true;
+ mon->hit_points = 0;
+ monster_die(mon, thrower, beam.beam_source);
+ return (BEAM_STOP);
+ }
- if (beam.beam_name[0] == '0')
+ if (beam.name[0] == '0')
{
- if (beam.isTracer)
+ if (beam.is_tracer)
{
// enchant case -- enchantments always hit, so update target immed.
- if (beam.isFriendly ^ mons_friendly(mon))
+ if (beam.is_friendly != mons_friendly(mon))
{
beam.foe_count += 1;
- beam.foe_power += mons_power(tid);
+ beam.foe_power += mons_power(mons_type);
}
else
{
beam.fr_count += 1;
- beam.fr_power += mons_power(tid);
+ beam.fr_power += mons_power(mons_type);
}
return (range_used_on_hit(beam));
@@ -3310,16 +3367,20 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
// naughty (even if a monster might resist)
if (nasty_beam(mon, beam))
{
- if (mons_friendly(mon) && YOU_KILL(beam.thrower))
- naughty(NAUGHTY_ATTACK_FRIEND, 5);
+ if (YOU_KILL( beam.thrower ))
+ {
+ if (mons_friendly( mon ))
+ did_god_conduct( DID_ATTACK_FRIEND, 5 );
+
+ if (mons_holiness( mon ) == MH_HOLY)
+ did_god_conduct( DID_ATTACK_HOLY, mon->hit_dice );
+ }
- behaviour_event( mon, ME_ANNOY,
- MON_KILL(beam.thrower) ? beam.beam_source : MHITYOU );
+ behaviour_event( mon, ME_ANNOY, beam_source(beam) );
}
else
{
- behaviour_event( mon, ME_ALERT,
- MON_KILL(beam.thrower) ? beam.beam_source : MHITYOU );
+ behaviour_event( mon, ME_ALERT, beam_source(beam) );
}
// !@#*( affect_monster_enchantment() has side-effects on
@@ -3327,17 +3388,21 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
// so call it now and store.
int rangeUsed = range_used_on_hit(beam);
+ // Doing this here so that the player gets to see monsters
+ // "flicker and vanish" when turning invisible....
+ ench_animation( beam.flavour, mon );
+
// now do enchantment affect
int ench_result = affect_monster_enchantment(beam, mon);
switch(ench_result)
{
case MON_RESIST:
if (simple_monster_message(mon, " resists."))
- beam.msgGenerated = true;
+ beam.msg_generated = true;
break;
case MON_UNAFFECTED:
if (simple_monster_message(mon, " is unaffected."))
- beam.msgGenerated = true;
+ beam.msg_generated = true;
break;
default:
break;
@@ -3349,10 +3414,10 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
// BEGIN non-enchantment (could still be tracer)
- if (mons_has_ench( mon, ENCH_SUBMERGED ) && !beam.aimedAtFeet)
+ if (mons_has_ench( mon, ENCH_SUBMERGED ) && !beam.aimed_at_feet)
return (0); // missed me!
- // we need to know how much the monster _would_ be hurt by this, before
+ // we need to know how much the monster _would_ be hurt by this, before
// we decide if it actually hits.
// Roll the damage:
@@ -3360,7 +3425,7 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
hurt_final = hurt;
- if (beam.isTracer)
+ if (beam.is_tracer)
hurt_final -= mon->armour_class / 2;
else
hurt_final -= random2(1 + mon->armour_class);
@@ -3380,12 +3445,12 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
const int old_hurt = hurt_final;
#endif
- // check monster resists, _without_ side effects (since the
+ // check monster resists, _without_ side effects (since the
// beam/missile might yet miss!)
hurt_final = mons_adjust_flavoured( mon, beam, hurt_final, false );
#if DEBUG_DIAGNOSTICS
- if (!beam.isTracer)
+ if (!beam.is_tracer)
{
snprintf( info, INFO_SIZE,
"Monster: %s; Damage: pre-AC: %d; post-AC: %d; post-resist: %d",
@@ -3395,27 +3460,27 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
}
#endif
- // now, we know how much this monster would (probably) be
+ // now, we know how much this monster would (probably) be
// hurt by this beam.
- if (beam.isTracer)
+ if (beam.is_tracer)
{
if (hurt_final != 0)
{
- // monster could be hurt somewhat, but only apply the
+ // monster could be hurt somewhat, but only apply the
// monster's power based on how badly it is affected.
- // For example, if a fire giant (power 16) threw a
- // fireball at another fire giant, and it only took
- // 1/3 damage, then power of 5 would be applied to
+ // For example, if a fire giant (power 16) threw a
+ // fireball at another fire giant, and it only took
+ // 1/3 damage, then power of 5 would be applied to
// foe_power or fr_power.
- if (beam.isFriendly ^ mons_friendly(mon))
+ if (beam.is_friendly != mons_friendly(mon))
{
beam.foe_count += 1;
- beam.foe_power += hurt_final * mons_power(tid) / hurt;
+ beam.foe_power += 2 * hurt_final * mons_power(mons_type) / hurt;
}
else
{
beam.fr_count += 1;
- beam.fr_power += hurt_final * mons_power(tid) / hurt;
+ beam.fr_power += 2 * hurt_final * mons_power(mons_type) / hurt;
}
}
// either way, we could hit this monster, so return range used
@@ -3428,39 +3493,33 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
// player beams which hit friendly MIGHT annoy them and be considered
// naughty if they do much damage (this is so as not to penalize
// players that fling fireballs into a melee with fire elementals
- // on their side - the elementals won't give a sh*t, after all)
+ // on their side - the elementals won't give a sh*t, after all)
if (nasty_beam(mon, beam))
{
- // could be naughty if it's your beam & the montster is friendly
- if (mons_friendly(mon) && YOU_KILL(beam.thrower))
+ if (YOU_KILL(beam.thrower))
{
- // but did you do enough damage to piss them off?
- if (hurt_final > mon->hit_dice / 3)
- {
- naughty(NAUGHTY_ATTACK_FRIEND, 5);
- behaviour_event( mon, ME_ANNOY, MHITYOU );
- }
- }
- else
- {
- behaviour_event(mon, ME_ANNOY,
- MON_KILL(beam.thrower) ? beam.beam_source : MHITYOU );
+ if (mons_friendly(mon))
+ did_god_conduct( DID_ATTACK_FRIEND, 5 );
+
+ if (mons_holiness( mon ) == MH_HOLY)
+ did_god_conduct( DID_ATTACK_HOLY, mon->hit_dice );
}
+
+ behaviour_event(mon, ME_ANNOY, beam_source(beam) );
}
// explosions always 'hit'
- if (!beam.isExplosion && beam.hit < random2(mon->evasion))
+ const bool engulfs = (beam.is_explosion || beam.is_big_cloud);
+
+ if (!engulfs && beam.hit < random2(mon->evasion))
{
// if the PLAYER cannot see the monster, don't tell them anything!
if (player_monster_visible( &menv[tid] ) && mons_near(mon))
{
- strcpy(info, "The ");
- strcat(info, beam.beam_name);
- strcat(info, " misses ");
- strcat(info, ptr_monam(mon, DESC_NOCAP_THE));
- strcat(info, ".");
- mpr(info);
+ mprf("The %s misses %s.",
+ beam.name.c_str(),
+ ptr_monam(mon, DESC_NOCAP_THE));
}
return (0);
}
@@ -3468,17 +3527,12 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
// the beam hit.
if (mons_near(mon))
{
- strcpy(info, "The ");
- strcat(info, beam.beam_name);
- strcat(info, beam.isExplosion?" engulfs ":" hits ");
-
- if (player_monster_visible( &menv[tid] ))
- strcat(info, ptr_monam(mon, DESC_NOCAP_THE));
- else
- strcat(info, "something");
-
- strcat(info, ".");
- mpr(info);
+ mprf("The %s %s %s.",
+ beam.name.c_str(),
+ engulfs? "engulfs" : "hits",
+ player_monster_visible(&menv[tid])?
+ ptr_monam(mon, DESC_NOCAP_THE)
+ : "something");
}
else
{
@@ -3486,12 +3540,7 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
// if _they_ fired a missile (not beam)
if (!silenced(you.x_pos, you.y_pos) && beam.flavour == BEAM_MISSILE
&& YOU_KILL(beam.thrower))
- {
- strcpy(info, "The ");
- strcat(info, beam.beam_name);
- strcat(info, " hits something.");
- mpr(info);
- }
+ mprf(MSGCH_SOUND, "The %s hits something.", beam.name.c_str());
}
// note that hurt_final was calculated above, so we don't need it again.
@@ -3502,8 +3551,6 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
// now hurt monster
hurt_monster( mon, hurt_final );
- int thrower = YOU_KILL(beam.thrower) ? KILL_YOU_MISSILE : KILL_MON_MISSILE;
-
if (mon->hit_points < 1)
{
monster_die(mon, thrower, beam.beam_source);
@@ -3514,7 +3561,7 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
print_wounds(mon);
// sticky flame
- if (strcmp(beam.beam_name, "sticky flame") == 0)
+ if (beam.name == "sticky flame")
{
int levels = 1 + random2( hurt_final ) / 2;
if (levels > 4)
@@ -3526,11 +3573,12 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
/* looks for missiles which aren't poison but
are poison*ed* */
- if (strstr(beam.beam_name, "poison") != NULL
+ if (beam.name.find("poison") != std::string::npos
&& beam.flavour != BEAM_POISON
&& beam.flavour != BEAM_POISON_ARROW)
{
- if (strstr(beam.beam_name, "needle") != NULL
+ // ench_power == AUTOMATIC_HIT if this is a poisoned needle.
+ if (beam.ench_power == AUTOMATIC_HIT
&& random2(100) < 90 - (3 * mon->armour_class))
{
poison_monster( mon, YOU_KILL(beam.thrower), 2 );
@@ -3541,7 +3589,14 @@ static int affect_monster(struct bolt &beam, struct monsters *mon)
}
}
- if (mons_is_mimic( mon->type ))
+ bool wake_mimic = true;
+ if (beam.name.find("curare") != std::string::npos)
+ {
+ if (curare_hits_monster( beam, mon, YOU_KILL(beam.thrower), 2 ))
+ wake_mimic = false;
+ }
+
+ if (wake_mimic && mons_is_mimic( mon->type ))
mimic_alert(mon);
}
@@ -3553,29 +3608,44 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon)
if (beam.flavour == BEAM_TELEPORT) // teleportation
{
if (check_mons_resist_magic( mon, beam.ench_power )
- && !beam.aimedAtFeet)
+ && !beam.aimed_at_feet)
{
return (MON_RESIST);
}
if (simple_monster_message(mon, " looks slightly unstable."))
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
monster_teleport(mon, false);
return (MON_AFFECTED);
}
+ if (beam.flavour == BEAM_BLINK)
+ {
+ if (!beam.aimed_at_feet
+ && check_mons_resist_magic( mon, beam.ench_power ))
+ {
+ return (MON_RESIST);
+ }
+
+ if (mons_near( mon ) && player_monster_visible( mon ))
+ beam.obvious_effect = true;
+
+ monster_blink( mon );
+ return (MON_AFFECTED);
+ }
+
if (beam.flavour == BEAM_POLYMORPH)
{
- if (mons_holiness( mon->type ) != MH_NATURAL)
+ if (mons_holiness( mon ) != MH_NATURAL)
return (MON_UNAFFECTED);
if (check_mons_resist_magic( mon, beam.ench_power ))
return (MON_RESIST);
if (monster_polymorph(mon, RANDOM_MONSTER, 100))
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
return (MON_AFFECTED);
}
@@ -3592,13 +3662,13 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon)
else
monster_die(mon, KILL_RESET, beam.beam_source);
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
return (MON_AFFECTED);
}
if (beam.flavour == BEAM_DEGENERATE)
{
- if (mons_holiness(mon->type) != MH_NATURAL
+ if (mons_holiness(mon) != MH_NATURAL
|| mon->type == MONS_PULSATING_LUMP)
{
return (MON_UNAFFECTED);
@@ -3608,18 +3678,18 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon)
return (MON_RESIST);
if (monster_polymorph(mon, MONS_PULSATING_LUMP, 100))
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
return (MON_AFFECTED);
}
if (beam.flavour == BEAM_DISPEL_UNDEAD)
{
- if (mons_holiness(mon->type) != MH_UNDEAD)
+ if (mons_holiness(mon) != MH_UNDEAD)
return (MON_UNAFFECTED);
if (simple_monster_message(mon, " convulses!"))
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
hurt_monster( mon, roll_dice( beam.damage ) );
@@ -3627,7 +3697,7 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon)
}
if (beam.flavour == BEAM_ENSLAVE_UNDEAD
- && mons_holiness(mon->type) == MH_UNDEAD)
+ && mons_holiness(mon) == MH_UNDEAD)
{
#if DEBUG_DIAGNOSTICS
snprintf( info, INFO_SIZE, "HD: %d; pow: %d",
@@ -3640,7 +3710,7 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon)
return (MON_RESIST);
simple_monster_message(mon, " is enslaved.");
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
// wow, permanent enslaving
mon->attitude = ATT_FRIENDLY;
@@ -3648,7 +3718,7 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon)
}
if (beam.flavour == BEAM_ENSLAVE_DEMON
- && mons_holiness(mon->type) == MH_DEMONIC)
+ && mons_holiness(mon) == MH_DEMONIC)
{
#if DEBUG_DIAGNOSTICS
snprintf( info, INFO_SIZE, "HD: %d; pow: %d",
@@ -3661,7 +3731,7 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon)
return (MON_RESIST);
simple_monster_message(mon, " is enslaved.");
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
// wow, permanent enslaving
mon->attitude = ATT_FRIENDLY;
@@ -3687,9 +3757,9 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon)
return (MON_UNAFFECTED);
if (simple_monster_message(mon, " convulses in agony!"))
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
- if (strstr( beam.beam_name, "agony" ) != NULL)
+ if (beam.name.find("agony") != std::string::npos)
{
// AGONY
mon->hit_points = mon->hit_points / 2;
@@ -3709,7 +3779,7 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon)
if (beam.flavour == BEAM_DISINTEGRATION) /* disrupt/disintegrate */
{
if (simple_monster_message(mon, " is blasted."))
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
hurt_monster( mon, roll_dice( beam.damage ) );
@@ -3722,11 +3792,11 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon)
if (mons_has_ench( mon, ENCH_SLEEP_WARY )) // slept recently
return (MON_RESIST);
- if (mons_holiness(mon->type) != MH_NATURAL) // no unnatural
+ if (mons_holiness(mon) != MH_NATURAL) // no unnatural
return (MON_UNAFFECTED);
if (simple_monster_message(mon, " looks drowsy..."))
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
mon->behaviour = BEH_SLEEP;
mons_add_ench( mon, ENCH_SLEEP_WARY );
@@ -3738,7 +3808,7 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon)
{
if (backlight_monsters(mon->x, mon->y, beam.hit, 0))
{
- beam.obviousEffect = true;
+ beam.obvious_effect = true;
return (MON_AFFECTED);
}
return (MON_UNAFFECTED);
@@ -3771,11 +3841,11 @@ deathCheck:
static int range_used_on_hit(struct bolt &beam)
{
// non-beams can only affect one thing (player/monster)
- if (!beam.isBeam)
+ if (!beam.is_beam)
return (BEAM_STOP);
// CHECK ENCHANTMENTS
- if (beam.beam_name[0] == '0')
+ if (beam.name[0] == '0')
{
switch(beam.flavour)
{
@@ -3806,11 +3876,11 @@ static int range_used_on_hit(struct bolt &beam)
}
// hellfire stops for nobody!
- if (strcmp( beam.beam_name, "hellfire" ) == 0)
+ if (beam.name == "hellfire")
return (0);
// generic explosion
- if (beam.flavour == BEAM_EXPLOSION)
+ if (beam.is_explosion || beam.is_big_cloud)
return (BEAM_STOP);
// plant spit
@@ -3844,9 +3914,9 @@ static void explosion1(struct bolt &pbolt)
// assume that the player can see/hear the explosion, or
// gets burned by it anyway. :)
- pbolt.msgGenerated = true;
+ pbolt.msg_generated = true;
- if (stricmp(pbolt.beam_name, "hellfire") == 0)
+ if (pbolt.name == "hellfire")
{
seeMsg = "The hellfire explodes!";
hearMsg = "You hear a strangely unpleasant explosion.";
@@ -3855,16 +3925,17 @@ static void explosion1(struct bolt &pbolt)
pbolt.flavour = BEAM_HELLFIRE;
}
- if (stricmp(pbolt.beam_name, "golden flame") == 0)
+ if (pbolt.name == "golden flame")
{
seeMsg = "The flame explodes!";
- hearMsg = "You hear a strange explosion.";
+ hearMsg = "You feel a deep, resonant explosion.";
pbolt.type = SYM_BURST;
- pbolt.flavour = BEAM_HOLY; // same as golden flame? [dlb]
+ pbolt.flavour = BEAM_HOLY;
+ ex_size = 2;
}
-
- if (stricmp(pbolt.beam_name, "fireball") == 0)
+
+ if (pbolt.name == "fireball")
{
seeMsg = "The fireball explodes!";
hearMsg = "You hear an explosion.";
@@ -3874,7 +3945,7 @@ static void explosion1(struct bolt &pbolt)
ex_size = 1;
}
- if (stricmp(pbolt.beam_name, "orb of electricity") == 0)
+ if (pbolt.name == "orb of electricity")
{
seeMsg = "The orb of electricity explodes!";
hearMsg = "You hear a clap of thunder!";
@@ -3886,46 +3957,46 @@ static void explosion1(struct bolt &pbolt)
ex_size = 2;
}
- if (stricmp(pbolt.beam_name, "orb of energy") == 0)
+ if (pbolt.name == "orb of energy")
{
seeMsg = "The orb of energy explodes.";
hearMsg = "You hear an explosion.";
}
- if (stricmp(pbolt.beam_name, "metal orb") == 0)
+ if (pbolt.name == "metal orb")
{
seeMsg = "The orb explodes into a blast of deadly shrapnel!";
hearMsg = "You hear an explosion!";
- strcpy(pbolt.beam_name, "blast of shrapnel");
+ pbolt.name = "blast of shrapnel";
pbolt.type = SYM_ZAP;
pbolt.flavour = BEAM_FRAG; // sets it from pure damage to shrapnel (which is absorbed extra by armour)
}
- if (stricmp(pbolt.beam_name, "great blast of cold") == 0)
+ if (pbolt.name == "great blast of cold")
{
seeMsg = "The blast explodes into a great storm of ice!";
hearMsg = "You hear a raging storm!";
- strcpy(pbolt.beam_name, "ice storm");
+ pbolt.name = "ice storm";
pbolt.damage.num = 6;
pbolt.type = SYM_ZAP;
pbolt.colour = WHITE;
ex_size = 2 + (random2( pbolt.ench_power ) > 75);
}
- if (stricmp(pbolt.beam_name, "ball of vapour") == 0)
+ if (pbolt.name == "ball of vapour")
{
seeMsg = "The ball expands into a vile cloud!";
hearMsg = "You hear a gentle \'poof\'.";
- strcpy(pbolt.beam_name, "stinking cloud");
+ pbolt.name = "stinking cloud";
}
- if (stricmp(pbolt.beam_name, "potion") == 0)
+ if (pbolt.name == "potion")
{
seeMsg = "The potion explodes!";
hearMsg = "You hear an explosion!";
- strcpy(pbolt.beam_name, "cloud");
+ pbolt.name = "cloud";
}
if (seeMsg == NULL)
@@ -3935,7 +4006,7 @@ static void explosion1(struct bolt &pbolt)
}
- if (!pbolt.isTracer)
+ if (!pbolt.is_tracer)
{
// check for see/hear/no msg
if (see_grid(x,y) || (x == you.x_pos && y == you.y_pos))
@@ -3943,9 +4014,9 @@ static void explosion1(struct bolt &pbolt)
else
{
if (!(silenced(x,y) || silenced(you.x_pos, you.y_pos)))
- mpr(hearMsg);
+ mpr(hearMsg, MSGCH_SOUND);
else
- pbolt.msgGenerated = false;
+ pbolt.msg_generated = false;
}
}
@@ -3958,7 +4029,7 @@ static void explosion1(struct bolt &pbolt)
// explosion is considered to emanate from beam->target_x, target_y
// and has a radius equal to ex_size. The explosion will respect
-// boundaries like walls, but go through/around statues/idols/etc.
+// boundaries like walls, but go through/around statues/idols/etc.
// for each cell affected by the explosion, affect() is called.
@@ -3966,8 +4037,8 @@ void explosion( struct bolt &beam, bool hole_in_the_middle )
{
int r = beam.ex_size;
- // beam is now an explosion; set isExplosion.
- beam.isExplosion = true;
+ // beam is now an explosion; set in_explosion_phase
+ beam.in_explosion_phase = true;
#if DEBUG_DIAGNOSTICS
snprintf( info, INFO_SIZE,
@@ -4000,16 +4071,16 @@ void explosion( struct bolt &beam, bool hole_in_the_middle )
// as the recursion runs approximately as R^2
explosion_map(beam, 0, 0, 0, 0, r);
- // go through affected cells, drawing effect and
+ // go through affected cells, drawing effect and
// calling affect() and affect_items() for each.
- // now, we get a bit fancy, drawing all radius 0
+ // now, we get a bit fancy, drawing all radius 0
// effects, then radius 1, radius 2, etc. It looks
// a bit better that way.
// turn buffering off
#ifdef WIN32CONSOLE
bool oldValue = true;
- if (!beam.isTracer)
+ if (!beam.is_tracer)
oldValue = setBuffering(false);
#endif
@@ -4053,7 +4124,7 @@ void explosion( struct bolt &beam, bool hole_in_the_middle )
update_screen();
#endif
// only delay on real explosion
- if (!beam.isTracer && drawing)
+ if (!beam.is_tracer && drawing)
delay(50);
}
@@ -4063,13 +4134,13 @@ void explosion( struct bolt &beam, bool hole_in_the_middle )
// ---------------- end boom --------------------------
#ifdef WIN32CONSOLE
- if (!beam.isTracer)
+ if (!beam.is_tracer)
setBuffering(oldValue);
#endif
// duplicate old behaviour - pause after entire explosion
// has been drawn.
- if (!beam.isTracer)
+ if (!beam.is_tracer)
more();
}
@@ -4095,7 +4166,7 @@ static void explosion_cell(struct bolt &beam, int x, int y, bool drawOnly)
}
// early out for tracer
- if (beam.isTracer)
+ if (beam.is_tracer)
return;
// now affect items
@@ -4136,7 +4207,7 @@ static void explosion_map( struct bolt &beam, int x, int y,
return;
// 3. check to see if we're blocked by something
- // specifically, we're blocked by WALLS. Not
+ // specifically, we're blocked by WALLS. Not
// statues, idols, etc.
int dngn_feat = grd[beam.target_x + x][beam.target_y + y];
@@ -4170,8 +4241,8 @@ static void explosion_map( struct bolt &beam, int x, int y,
// returns true if the beam is harmful (ignoring monster
// resists) -- mon is given for 'special' cases where,
-// for example, "Heal" might actually hurt undead, or
-// "Holy Word" being ignored by holy monsters, etc.
+// for example, "Heal" might actually hurt undead, or
+// "Holy Word" being ignored by holy monsters, etc.
//
// only enchantments should need the actual monster type
// to determine this; non-enchantments are pretty
@@ -4179,18 +4250,18 @@ static void explosion_map( struct bolt &beam, int x, int y,
bool nasty_beam(struct monsters *mon, struct bolt &beam)
{
// take care of non-enchantments
- if (beam.beam_name[0] != '0')
+ if (beam.name[0] != '0')
return (true);
// now for some non-hurtful enchantments
// degeneration / sleep
if (beam.flavour == BEAM_DEGENERATE || beam.flavour == BEAM_SLEEP)
- return (mons_holiness(mon->type) == MH_NATURAL);
+ return (mons_holiness(mon) == MH_NATURAL);
// dispel undead / control undead
if (beam.flavour == BEAM_DISPEL_UNDEAD || beam.flavour == BEAM_ENSLAVE_UNDEAD)
- return (mons_holiness(mon->type) == MH_UNDEAD);
+ return (mons_holiness(mon) == MH_UNDEAD);
// pain/agony
if (beam.flavour == BEAM_PAIN)
@@ -4198,7 +4269,7 @@ bool nasty_beam(struct monsters *mon, struct bolt &beam)
// control demon
if (beam.flavour == BEAM_ENSLAVE_DEMON)
- return (mons_holiness(mon->type) == MH_DEMONIC);
+ return (mons_holiness(mon) == MH_DEMONIC);
// haste
if (beam.flavour == BEAM_HASTE)
@@ -4211,3 +4282,38 @@ bool nasty_beam(struct monsters *mon, struct bolt &beam)
// everything else is considered nasty by everyone
return (true);
}
+
+////////////////////////////////////////////////////////////////////////////
+// bolt
+
+// A constructor for bolt to help guarantee that we start clean (this has
+// caused way too many bugs). Putting it here since there's no good place to
+// put it, and it doesn't do anything other than initialize it's members.
+//
+// TODO: Eventually it'd be nice to have a proper factory for these things
+// (extended from setup_mons_cast() and zapping() which act as limited ones).
+bolt::bolt() : range(0), rangeMax(0), type(SYM_ZAP), colour(BLACK),
+ flavour(BEAM_MAGIC), source_x(0), source_y(0), damage(0,0),
+ ench_power(0), hit(0), target_x(0), target_y(0),
+ thrower(KILL_MISC), ex_size(0), beam_source(MHITNOT), name(),
+ is_beam(false), is_explosion(false), is_big_cloud(false),
+ is_enchant(false), is_energy(false), is_launched(false),
+ is_thrown(false), target_first(false), aimed_at_spot(false),
+ aux_source(), obvious_effect(false), fr_count(0), foe_count(0),
+ fr_power(0), foe_power(0), is_tracer(false),
+ aimed_at_feet(false), msg_generated(false),
+ in_explosion_phase(false), smart_monster(false),
+ can_see_invis(false), is_friendly(false), foe_ratio(0)
+{ }
+
+void bolt::set_target(const dist &d)
+{
+ if (!d.isValid)
+ return;
+
+ target_x = d.tx;
+ target_y = d.ty;
+
+ if (d.isEndpoint)
+ aimed_at_spot = true;
+}
diff --git a/crawl-ref/source/beam.h b/crawl-ref/source/beam.h
index d2935843ec..c529b727fe 100644
--- a/crawl-ref/source/beam.h
+++ b/crawl-ref/source/beam.h
@@ -3,6 +3,8 @@
* Summary: Functions related to ranged attacks.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -82,6 +84,7 @@ void place_cloud(unsigned char cl_type, unsigned char ctarget_x, unsigned char c
* *********************************************************************** */
void fire_tracer( struct monsters *monster, struct bolt &pbolt );
+bool check_line_of_sight( int sx, int sy, int tx, int ty );
/* ***********************************************************************
* called from: monstuff
@@ -91,4 +94,6 @@ void mimic_alert( struct monsters *mimic );
void zapping( char ztype, int power, struct bolt &pbolt );
+int affect(struct bolt &beam, int x, int y);
+
#endif
diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc
index 5fd7b18f57..4bb87f04e5 100644
--- a/crawl-ref/source/chardump.cc
+++ b/crawl-ref/source/chardump.cc
@@ -3,6 +3,8 @@
* Summary: Dumps character info out to the morgue file.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
*
@@ -15,27 +17,18 @@
#include "AppHdr.h"
#include "chardump.h"
+#include "clua.h"
#include <string>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
-#if !(defined(__IBMCPP__) || defined(__BCPLUSPLUS__))
+#if !defined(__IBMCPP__)
#include <unistd.h>
#endif
#include <ctype.h>
-#ifdef USE_EMX
-#include <sys/types.h>
-#endif
-
-#ifdef OS9
-#include <stat.h>
-#else
-#include <sys/stat.h>
-#endif
-
#ifdef DOS
#include <conio.h>
#endif
@@ -45,9 +38,12 @@
#include "debug.h"
#include "describe.h"
#include "itemname.h"
+#include "itemprop.h"
#include "items.h"
#include "macro.h"
+#include "misc.h"
#include "mutation.h"
+#include "notes.h"
#include "output.h"
#include "player.h"
#include "randart.h"
@@ -62,25 +58,198 @@
#include "version.h"
#include "view.h"
-// Defined in view.cc
-extern unsigned char (*mapch2) (unsigned char);
+static bool dump_show_prices = false;
+static bool dump_full_id = false;
+
+static void sdump_header(const std::string &section, std::string &text);
+static void sdump_stats(const std::string &section, std::string &text);
+static void sdump_location(const std::string &section, std::string &text);
+static void sdump_religion(const std::string &section, std::string &text);
+static void sdump_burden(const std::string &section, std::string &text);
+static void sdump_hunger(const std::string &section, std::string &text);
+static void sdump_transform(const std::string &section, std::string &text);
+static void sdump_misc(const std::string &section, std::string &text);
+static void sdump_notes(const std::string &section, std::string &text);
+static void sdump_inventory(const std::string &section, std::string &text);
+static void sdump_skills(const std::string &section, std::string &text);
+static void sdump_spells(const std::string &section, std::string &text);
+static void sdump_mutations(const std::string &section, std::string &text);
+static void sdump_messages(const std::string &section, std::string &text);
+static void sdump_screenshot(const std::string &section, std::string &text);
+static void sdump_kills(const std::string &section, std::string &text);
+static void sdump_newline(const std::string &section, std::string &text);
+static void sdump_separator(const std::string &section, std::string &text);
+#ifdef CLUA_BINDINGS
+static void sdump_lua(const std::string &section, std::string &text);
+#endif
+static bool write_dump(const std::string &fname, const std::string &text,
+ bool full_id);
+static void dump_stats2( std::string & text, bool calc_unid);
+static void dump_stats( std::string & text );
+
+struct dump_section_handler
+{
+ const char *name;
+ void (*handler)(const std::string &section, std::string &text);
+};
+
+static dump_section_handler dump_handlers[] = {
+ { "header", sdump_header },
+ { "stats", sdump_stats },
+ { "location", sdump_location },
+ { "religion", sdump_religion },
+ { "burden", sdump_burden },
+ { "hunger", sdump_hunger },
+ { "transform", sdump_transform },
+ { "misc", sdump_misc },
+ { "notes", sdump_notes },
+ { "inventory", sdump_inventory },
+ { "skills", sdump_skills },
+ { "spells", sdump_spells },
+ { "mutations", sdump_mutations },
+ { "messages", sdump_messages },
+ { "screenshot", sdump_screenshot },
+ { "kills", sdump_kills },
+
+ // Conveniences for the .crawlrc artist.
+ { "", sdump_newline },
+ { "-", sdump_separator },
+
+#ifdef CLUA_BINDINGS
+ { NULL, sdump_lua }
+#else
+ { NULL, NULL }
+#endif
+};
- // ========================================================================
- // Internal Functions
- // ========================================================================
+static void dump_section(const std::string &section, std::string &text)
+{
+ for (int i = 0; ; ++i)
+ {
+ if (!dump_handlers[i].name || section == dump_handlers[i].name)
+ {
+ if (dump_handlers[i].handler)
+ (*dump_handlers[i].handler)(section, text);
+ break;
+ }
+ }
+}
- // fillstring() is a hack to get around a missing constructor in
- // Borland C++ implementation of the STD basic_string. Argh!!!
-static std::string fillstring(size_t strlen, char filler)
+bool dump_char(const std::string &fname, bool show_prices, bool full_id)
{
- std::string s;
+ // start with enough room for 100 80 character lines
+ std::string text;
+ text.reserve(100 * 80);
+
+ dump_show_prices = show_prices;
+ dump_full_id = full_id;
+
+ for (int i = 0, size = Options.dump_order.size(); i < size; ++i)
+ {
+ const std::string &section = Options.dump_order[i];
+ dump_section(section, text);
+ }
+
+ return write_dump(fname, text, full_id);
+}
+
+static void sdump_header(const std::string &, std::string &text)
+{
+ text += " " CRAWL " version " VERSION " character file.\n\n";
+}
+
+static void sdump_stats(const std::string &, std::string &text)
+{
+ if (Options.detailed_stat_dump)
+ dump_stats2(text, dump_full_id);
+ else
+ dump_stats(text);
+}
- for (size_t i=0; i<strlen; i++)
- s += filler;
+static void sdump_burden(const std::string &, std::string &text)
+{
+ switch (you.burden_state)
+ {
+ case BS_OVERLOADED:
+ text += "You are overloaded with stuff.\n";
+ break;
+ case BS_ENCUMBERED:
+ text += "You are encumbered.\n";
+ break;
+ }
+}
- return s;
+static void sdump_hunger(const std::string &, std::string &text)
+{
+ text += std::string("You are ") + hunger_level() + ".\n\n";
}
+static void sdump_transform(const std::string &, std::string &text)
+{
+ if (you.attribute[ATTR_TRANSFORMATION])
+ {
+ switch (you.attribute[ATTR_TRANSFORMATION])
+ {
+ case TRAN_SPIDER:
+ text += "You are in spider-form.";
+ break;
+ case TRAN_BLADE_HANDS:
+ text += "Your hands are blades.";
+ break;
+ case TRAN_STATUE:
+ text += "You are a stone statue.";
+ break;
+ case TRAN_ICE_BEAST:
+ text += "You are a creature of crystalline ice.";
+ break;
+ case TRAN_DRAGON:
+ text += "You are a fearsome dragon!";
+ break;
+ case TRAN_LICH:
+ text += "You are in lich-form.";
+ break;
+ case TRAN_SERPENT_OF_HELL:
+ text += "You are a huge, demonic serpent!";
+ break;
+ case TRAN_AIR:
+ text += "You are a cloud of diffuse gas.";
+ break;
+ }
+
+ text += "\n\n";
+ }
+}
+
+static void sdump_misc(const std::string &s, std::string &text)
+{
+ sdump_location(s, text);
+ sdump_religion(s, text);
+ sdump_burden(s, text);
+ sdump_hunger(s, text);
+ sdump_transform(s, text);
+}
+
+static void sdump_newline(const std::string &s, std::string &text)
+{
+ text += "\n";
+}
+
+static void sdump_separator(const std::string &s, std::string &text)
+{
+ text += std::string(79, '-') + "\n";
+}
+
+#ifdef CLUA_BINDINGS
+// Assume this is an arbitrary Lua function name, call the function and
+// dump whatever it returns.
+static void sdump_lua(const std::string &s, std::string &text)
+{
+ std::string luatext;
+ clua.callfn(s.c_str(), ">s", &luatext);
+ text += luatext;
+}
+#endif
+
//---------------------------------------------------------------
//
// munge_description
@@ -95,6 +264,7 @@ static std::string fillstring(size_t strlen, char filler)
std::string munge_description(const std::string & inStr)
{
std::string outStr;
+ std::string eol = "\n";
outStr.reserve(inStr.length() + 32);
@@ -103,7 +273,7 @@ std::string munge_description(const std::string & inStr)
long i = 0;
- outStr += fillstring(kIndent, ' ');
+ outStr += std::string(kIndent, ' ');
while (i < (long) inStr.length())
{
@@ -111,9 +281,9 @@ std::string munge_description(const std::string & inStr)
if (ch == '$')
{
- outStr += EOL;
+ outStr += eol;
- outStr += fillstring(kIndent, ' ');
+ outStr += std::string(kIndent, ' ');
lineLen = kIndent;
while (inStr[++i] == '$')
@@ -123,8 +293,8 @@ std::string munge_description(const std::string & inStr)
{
if (lineLen >= 79)
{
- outStr += EOL;
- outStr += fillstring(kIndent, ' ');
+ outStr += eol;
+ outStr += std::string(kIndent, ' ');
lineLen = kIndent;
}
@@ -148,8 +318,8 @@ std::string munge_description(const std::string & inStr)
if (lineLen + word.length() >= 79)
{
- outStr += EOL;
- outStr += fillstring(kIndent, ' ');
+ outStr += eol;
+ outStr += std::string(kIndent, ' ');
lineLen = kIndent;
}
@@ -158,148 +328,27 @@ std::string munge_description(const std::string & inStr)
}
}
- outStr += EOL;
+ outStr += eol;
return (outStr);
} // end munge_description()
- //---------------------------------------------------------------
- //
- // dump_screenshot
- //
- // Grabs a screenshot and appends the text into the given std::string,
- // using several ugly hacks in the process.
- //---------------------------------------------------------------
-static void dump_screenshot( std::string &text )
+static void sdump_messages(const std::string &, std::string &text)
{
// A little message history:
if (Options.dump_message_count > 0)
{
- text += " Last Messages" EOL EOL;
+ text += "Message History\n\n";
text += get_last_messages(Options.dump_message_count);
}
+}
- FixedVector < char, 1500 > buffy; //[800]; //392];
- int bufcount = 0;
- unsigned short ch, color;
- int count_x, count_y;
-
- // Urg, ugly screen capture. CVS Crawl may have a better way of doing this,
- // but until the next release...
- for (count_y = (you.y_pos - 8); (count_y < you.y_pos + 9); count_y++)
- {
- bufcount += 8;
- for (count_x = (you.x_pos - 8); (count_x < you.x_pos + 9); count_x++)
- {
- if (count_x == you.x_pos && count_y == you.y_pos)
- {
- extern unsigned char your_sign;
- ch = your_sign;
- }
- else
- {
- unsigned int object = env.show[count_x - you.x_pos + 9]
- [count_y - you.y_pos + 9];
- get_non_ibm_symbol(object, &ch, &color);
- }
-
- buffy[bufcount++] = (char) ch;
- }
- bufcount += 8;
- }
-
- int maxbuf = bufcount;
- bufcount = 0;
-
- for (count_y = 0; count_y < 17; count_y++)
- {
- for (count_x = 0; count_x < 33; count_x++)
- {
- if (count_x + you.x_pos - 17 < 3
- || count_y + you.y_pos - 9 < 3
- || count_x + you.x_pos - 14 > (GXM - 3)
- || count_y + you.y_pos - 9 > (GYM - 3))
- {
- buffy[bufcount++] = ' ';
- continue;
- }
-
- if (count_x >= 8 && count_x <= 24 && count_y >= 0
- && count_y <= 16 && buffy[bufcount] != 0)
- {
- bufcount++;
- continue;
- }
-
- unsigned char envc = (unsigned char)
- env.map[count_x + you.x_pos - 17]
- [count_y + you.y_pos - 9];
- if (envc)
- {
- // If it's printable, use it directly.
- if (envc < 127 && envc >= 32)
- ch = envc;
- else
- {
- // Otherwise get what's on the grid and get an ASCII
- // character for that.
- unsigned int object = grd[count_x + you.x_pos - 16]
- [count_y + you.y_pos - 8];
-
- // Special case secret doors so that monsters that open
- // doors out of hero's LOS don't reveal the secret door in
- // the dump
- if (envc == mapch2(DNGN_SECRET_DOOR))
- object = DNGN_SECRET_DOOR;
-
- get_non_ibm_symbol(object, &ch, &color);
- }
-
- buffy[bufcount++] = (char) ch;
- }
- else
- {
- buffy[bufcount++] = ' ';
- }
- }
- }
-
- if (bufcount > maxbuf) maxbuf = bufcount;
-
- while (maxbuf > 0 && (!buffy[maxbuf - 1] || buffy[maxbuf - 1] == ' '))
- --maxbuf;
-
- // 33 columns and a null terminator. More hardcoding. :-(
- char buf[34];
- char *s = buf;
- bool leadblanks = true;
- for (int i = 0; i < maxbuf; )
- {
- *s++ = buffy[i]? buffy[i] : ' ';
-
- ++i;
- if (!(i % 33) || i >= maxbuf)
- {
- *s = 0;
- while (s > buf && *--s == ' ')
- *s = 0;
-
- if (s == buf && !*s && leadblanks)
- continue;
-
- leadblanks = false;
- text += buf;
- text += EOL;
- s = buf;
- }
- }
+static void sdump_screenshot(const std::string &, std::string &text)
+{
+ text += screenshot();
+ text += "\n\n";
}
- //---------------------------------------------------------------
- //
- // dump_stats
- //
- //---------------------------------------------------------------
static void dump_stats( std::string & text )
{
char st_prn[20];
@@ -311,7 +360,7 @@ static void dump_stats( std::string & text )
text += " (";
text += species_name(you.species, you.experience_level);
text += ")";
- text += EOL;
+ text += "\n";
text += "(Level ";
itoa(you.experience_level, st_prn, 10);
@@ -319,7 +368,7 @@ static void dump_stats( std::string & text )
text += " ";
text += you.class_name;
text += ")";
- text += EOL EOL;
+ text += "\n\n";
if (you.real_time != -1)
{
@@ -334,7 +383,7 @@ static void dump_stats( std::string & text )
text += " Number of turns: ";
itoa( you.num_turns, st_prn, 10 );
text += st_prn;
- text += EOL EOL;
+ text += "\n\n";
}
text += "Experience : ";
@@ -343,7 +392,7 @@ static void dump_stats( std::string & text )
text += "/";
itoa(you.experience, st_prn, 10);
text += st_prn;
- text += EOL;
+ text += "\n\n";
text += "Strength ";
itoa(you.strength, st_prn, 10);
@@ -374,7 +423,7 @@ static void dump_stats( std::string & text )
itoa(you.max_intel, st_prn, 10);
text += st_prn;
}
- text += EOL;
+ text += "\n";
text += "Hit Points : ";
itoa(you.hp, st_prn, 10);
@@ -412,7 +461,7 @@ static void dump_stats( std::string & text )
itoa(you.max_magic_points, st_prn, 10);
text += st_prn;
}
- text += EOL;
+ text += "\n";
text += "AC : ";
itoa(player_AC(), st_prn, 10);
@@ -425,13 +474,13 @@ static void dump_stats( std::string & text )
text += " Shield : ";
itoa(player_shield_class(), st_prn, 10);
text += st_prn;
- text += EOL;
+ text += "\n";
text += "GP : ";
itoa( you.gold, st_prn, 10 );
text += st_prn;
- text += EOL;
- text += EOL;
+ text += "\n";
+ text += "\n";
} // end dump_stats()
//---------------------------------------------------------------
@@ -441,38 +490,52 @@ static void dump_stats( std::string & text )
//---------------------------------------------------------------
static void dump_stats2( std::string & text, bool calc_unid)
{
- char buffer[25*3][45];
+ char buffer[24*3][45];
char str_pass[80];
char* ptr_n;
get_full_detail(&buffer[0][0], calc_unid);
- for (int i = 0; i < 25; i++)
+ for (int i = 0; i < 24; i++)
{
ptr_n = &buffer[i][0];
- if (buffer[i+25][0] == '\0' && buffer[i+50][0] == '\0')
+ if (buffer[i+24][0] == 0 && buffer[i+24*2][0] == 0)
snprintf(&str_pass[0], 45, "%s", ptr_n);
else
snprintf(&str_pass[0], 45, "%-32s", ptr_n);
text += str_pass;
- ptr_n = &buffer[i+25][0];
- if (buffer[i+50][0] == '\0')
+ ptr_n = &buffer[i+24][0];
+ if (buffer[i+24*2][0] == 0)
snprintf(&str_pass[0], 45, "%s", ptr_n);
else
snprintf(&str_pass[0], 45, "%-20s", ptr_n);
text += str_pass;
- ptr_n = &buffer[i+50][0];
- if (buffer[i+50][0] != '\0')
+ ptr_n = &buffer[i+24*2][0];
+ if (buffer[i+24*2][0] != 0)
{
snprintf(&str_pass[0], 45, "%s", ptr_n);
text += str_pass;
}
- text += EOL;
+ text += "\n";
}
- text += EOL EOL;
+ text += "\n" "\n";
+}
+
+static void sdump_notes(const std::string &, std::string& text)
+{
+ if ( note_list.size() == 0 || Options.use_notes == false )
+ return;
+
+ text += "\nNotes\n| Turn |Location | Note\n";
+ text += "--------------------------------------------------------------\n";
+ for ( unsigned i = 0; i < note_list.size(); ++i ) {
+ text += describe_note(note_list[i]);
+ text += "\n";
+ }
+ text += "\n";
}
//---------------------------------------------------------------
@@ -480,88 +543,27 @@ static void dump_stats2( std::string & text, bool calc_unid)
// dump_location
//
//---------------------------------------------------------------
-static void dump_location( std::string & text )
+static void sdump_location(const std::string &, std::string & text)
{
- if (you.level_type != LEVEL_DUNGEON || you.your_level != -1)
- text += "You are ";
-
- if (you.level_type == LEVEL_PANDEMONIUM)
- text += "in Pandemonium";
- else if (you.level_type == LEVEL_ABYSS)
- text += "in the Abyss";
- else if (you.level_type == LEVEL_LABYRINTH)
- text += "in a labyrinth";
- else if (you.where_are_you == BRANCH_DIS)
- text += "in Dis";
- else if (you.where_are_you == BRANCH_GEHENNA)
- text += "in Gehenna";
- else if (you.where_are_you == BRANCH_VESTIBULE_OF_HELL)
- text += "in the Vestibule of Hell";
- else if (you.where_are_you == BRANCH_COCYTUS)
- text += "in Cocytus";
- else if (you.where_are_you == BRANCH_TARTARUS)
- text += "in Tartarus";
- else if (you.where_are_you == BRANCH_INFERNO)
- text += "in the Inferno";
- else if (you.where_are_you == BRANCH_THE_PIT)
- text += "in the Pit";
- else if (you.where_are_you == BRANCH_ORCISH_MINES)
- text += "in the Mines";
- else if (you.where_are_you == BRANCH_HIVE)
- text += "in the Hive";
- else if (you.where_are_you == BRANCH_LAIR)
- text += "in the Lair";
- else if (you.where_are_you == BRANCH_SLIME_PITS)
- text += "in the Slime Pits";
- else if (you.where_are_you == BRANCH_VAULTS)
- text += "in the Vaults";
- else if (you.where_are_you == BRANCH_CRYPT)
- text += "in the Crypt";
- else if (you.where_are_you == BRANCH_HALL_OF_BLADES)
- text += "in the Hall of Blades";
- else if (you.where_are_you == BRANCH_HALL_OF_ZOT)
- text += "in the Hall of Zot";
- else if (you.where_are_you == BRANCH_ECUMENICAL_TEMPLE)
- text += "in the Ecumenical Temple";
- else if (you.where_are_you == BRANCH_SNAKE_PIT)
- text += "in the Snake Pit";
- else if (you.where_are_you == BRANCH_ELVEN_HALLS)
- text += "in the Elven Halls";
- else if (you.where_are_you == BRANCH_TOMB)
- text += "in the Tomb";
- else if (you.where_are_you == BRANCH_SWAMP)
- text += "in the Swamp";
+ if (you.your_level == -1
+ && you.where_are_you == BRANCH_MAIN_DUNGEON
+ && you.level_type == LEVEL_DUNGEON)
+ text += "You escaped";
else
- {
- if (you.your_level == -1)
- text += "You escaped";
- else
- {
- text += "on level ";
-
- char st_prn[20];
- itoa(you.your_level + 1, st_prn, 10);
- text += st_prn;
- }
- }
+ text += "You are " + prep_branch_level_name();
text += ".";
- text += EOL;
+ text += "\n";
} // end dump_location()
- //---------------------------------------------------------------
- //
- // dump_religion
- //
- //---------------------------------------------------------------
-static void dump_religion( std::string & text )
+static void sdump_religion(const std::string &, std::string & text)
{
if (you.religion != GOD_NO_GOD)
{
text += "You worship ";
text += god_name(you.religion);
text += ".";
- text += EOL;
+ text += "\n";
if (!player_under_penance())
{
@@ -577,17 +579,17 @@ static void dump_religion( std::string & text )
(you.piety <= 130) ? "extremely pleased with you"
: "exalted by your worship");
text += ".";
- text += EOL;
+ text += "\n";
}
}
else
{
text += god_name(you.religion);
text += " is demanding penance.";
- text += EOL;
+ text += "\n";
}
}
-} // end dump_religion()
+}
extern char id[4][50]; // itemname.cc
static bool dump_item_origin(const item_def &item, int value)
@@ -645,7 +647,7 @@ static bool dump_item_origin(const item_def &item, int value)
// dump_inventory
//
//---------------------------------------------------------------
-static void dump_inventory( std::string & text, bool show_prices )
+static void sdump_inventory(const std::string &, std::string & text)
{
int i, j;
char temp_id[4][50];
@@ -683,12 +685,12 @@ static void dump_inventory( std::string & text, bool show_prices )
if (!inv_count)
{
text += "You aren't carrying anything.";
- text += EOL;
+ text += "\n";
}
else
{
text += " Inventory:";
- text += EOL;
+ text += "\n";
for (i = 0; i < OBJ_GOLD; i++)
{
@@ -713,7 +715,7 @@ static void dump_inventory( std::string & text, bool show_prices )
default:
DEBUGSTR("Bad item class");
}
- text += EOL;
+ text += "\n";
for (j = 0; j < ENDOFPACK; j++)
{
@@ -727,7 +729,7 @@ static void dump_inventory( std::string & text, bool show_prices )
inv_count--;
int ival = -1;
- if (show_prices)
+ if (dump_show_prices)
{
text += " (";
@@ -742,7 +744,7 @@ static void dump_inventory( std::string & text, bool show_prices )
if (origin_describable(you.inv[j])
&& dump_item_origin(you.inv[j], ival))
{
- text += EOL " (" + origin_desc(you.inv[j]) + ")";
+ text += "\n" " (" + origin_desc(you.inv[j]) + ")";
}
if (is_dumpable_artifact( you.inv[j],
@@ -756,13 +758,14 @@ static void dump_inventory( std::string & text, bool show_prices )
}
else
{
- text += EOL;
+ text += "\n";
}
}
}
}
}
}
+ text += "\n\n";
} // end dump_inventory()
//---------------------------------------------------------------
@@ -770,14 +773,19 @@ static void dump_inventory( std::string & text, bool show_prices )
// dump_skills
//
//---------------------------------------------------------------
-static void dump_skills( std::string & text )
+static void sdump_skills(const std::string &, std::string & text)
{
char tmp_quant[20];
- text += EOL;
- text += EOL;
+ text += " You have ";
+ itoa( you.exp_available, tmp_quant, 10 );
+ text += tmp_quant;
+ text += " experience left.";
+
+ text += "\n";
+ text += "\n";
text += " Skills:";
- text += EOL;
+ text += "\n";
for (unsigned char i = 0; i < 50; i++)
{
@@ -792,12 +800,12 @@ static void dump_skills( std::string & text )
text += tmp_quant;
text += " ";
text += skill_name(i);
- text += EOL;
+ text += "\n";
}
}
- text += EOL;
- text += EOL;
+ text += "\n";
+ text += "\n";
} // end dump_skills()
//---------------------------------------------------------------
@@ -805,24 +813,24 @@ static void dump_skills( std::string & text )
// Return string of the i-th spell type, with slash if required
//
//---------------------------------------------------------------
-static std::string spell_type_name(int spell_class, bool slash)
+static std::string spell_type_shortname(int spell_class, bool slash)
{
std::string ret;
if (slash)
ret = "/";
- ret += spelltype_name(spell_class);
+ ret += spelltype_short_name(spell_class);
return (ret);
-} // end spell_type_name()
+} // end spell_type_shortname()
//---------------------------------------------------------------
//
// dump_spells
//
//---------------------------------------------------------------
-static void dump_spells( std::string & text )
+static void sdump_spells(const std::string &, std::string & text)
{
char tmp_quant[20];
@@ -860,20 +868,20 @@ static void dump_spells( std::string & text )
text += " spell levels left.";
}
- text += EOL;
+ text += "\n";
if (!you.spell_no)
{
text += "You don't know any spells.";
- text += EOL;
+ text += "\n";
}
else
{
- text += "You know the following spells:" EOL;
- text += EOL;
+ text += "You know the following spells:" "\n";
+ text += "\n";
- text += " Your Spells Type Success Level" EOL;
+ text += " Your Spells Type Power Success Level" "\n";
for (int j = 0; j < 52; j++)
{
@@ -882,20 +890,17 @@ static void dump_spells( std::string & text )
if (spell != SPELL_NO_SPELL)
{
- std::string spell_line = " ";
+ std::string spell_line;
- char strng[2];
- strng[0] = letter;
- strng[1] = '\0';
-
- spell_line += strng;
+ spell_line += letter;
spell_line += " - ";
spell_line += spell_title( spell );
- for (int i = spell_line.length(); i < 34; i++)
- {
- spell_line += ' ';
- }
+ if ( spell_line.length() > 24 )
+ spell_line = spell_line.substr(0, 24);
+
+ for (int i = spell_line.length(); i < 26; i++)
+ spell_line += ' ';
bool already = false;
@@ -903,18 +908,30 @@ static void dump_spells( std::string & text )
{
if (spell_typematch( spell, spell_type_index[i] ))
{
- spell_line +=
- spell_type_name(spell_type_index[i], already);
+ spell_line += spell_type_shortname(spell_type_index[i],
+ already);
already = true;
}
}
- if (spell_line.length() > 57)
- spell_line = spell_line.substr(0, 57);
- for (int i = spell_line.length(); i < 58; i++)
- {
- spell_line += ' ';
- }
+ for (int i = spell_line.length(); i < 41; ++i )
+ spell_line += ' ';
+
+ int spell_p = calc_spell_power( spell, true );
+ spell_line += ( (spell_p > 100) ? "Enormous" :
+ (spell_p > 90) ? "Huge" :
+ (spell_p > 80) ? "Massive" :
+ (spell_p > 70) ? "Major" :
+ (spell_p > 60) ? "Impressive" :
+ (spell_p > 50) ? "Reasonable" :
+ (spell_p > 40) ? "Moderate" :
+ (spell_p > 30) ? "Adequate" :
+ (spell_p > 20) ? "Mediocre" :
+ (spell_p > 10) ? "Minor"
+ : "Negligible");
+
+ for (int i = spell_line.length(); i < 56; ++i )
+ spell_line += ' ';
int fail_rate = spell_fail( spell );
@@ -931,12 +948,12 @@ static void dump_spells( std::string & text )
(fail_rate > 0) ? "Excellent"
: "Perfect";
- for (int i = spell_line.length(); i < 70; i++)
+ for (int i = spell_line.length(); i < 68; i++)
spell_line += ' ';
itoa((int) spell_difficulty( spell ), tmp_quant, 10 );
spell_line += tmp_quant;
- spell_line += EOL;
+ spell_line += "\n";
text += spell_line;
}
@@ -945,22 +962,12 @@ static void dump_spells( std::string & text )
} // end dump_spells()
-//---------------------------------------------------------------
-//
-// dump_kills
-//
-//---------------------------------------------------------------
-static void dump_kills( std::string & text )
+static void sdump_kills(const std::string &, std::string & text)
{
text += you.kills.kill_info();
}
-//---------------------------------------------------------------
-//
-// dump_mutations
-//
-//---------------------------------------------------------------
-static void dump_mutations( std::string & text )
+static void sdump_mutations(const std::string &, std::string & text)
{
// Can't use how_mutated() here, as it doesn't count demonic powers
int xz = 0;
@@ -974,9 +981,9 @@ static void dump_mutations( std::string & text )
if (xz > 0)
{
text += "";
- text += EOL;
+ text += "\n";
text += " Mutations & Other Weirdness";
- text += EOL;
+ text += "\n";
for (int j = 0; j < 100; j++)
{
@@ -986,16 +993,13 @@ static void dump_mutations( std::string & text )
text += "* ";
text += mutation_name(j);
- text += EOL;
+ text += "\n";
}
}
}
+ text += "\n\n";
} // end dump_mutations()
-#if MAC
-#pragma mark -
-#endif
-
// ========================================================================
// Public Functions
// ========================================================================
@@ -1008,168 +1012,36 @@ const char *hunger_level(void)
(you.hunger < 11000) ? "full" : "completely stuffed");
}
-//---------------------------------------------------------------
-//
-// dump_char
-//
-// Creates a disk record of a character. Returns true if the
-// character was successfully saved.
-//
-//---------------------------------------------------------------
-bool dump_char( const char fname[30], bool show_prices ) // $$$ a try block?
+static bool write_dump(
+ const std::string &fname,
+ const std::string &text,
+ bool full_id)
{
bool succeeded = false;
- std::string text;
-
- // start with enough room for 100 80 character lines
- text.reserve(100 * 80);
-
- text += " Dungeon Crawl version " VERSION " character file.";
- text += EOL;
- text += EOL;
-
- if (Options.detailed_stat_dump)
- dump_stats2(text, show_prices);
- else
- dump_stats(text);
-
- dump_location(text);
- dump_religion(text);
-
- switch (you.burden_state)
- {
- case BS_OVERLOADED:
- text += "You are overloaded with stuff.";
- text += EOL;
- break;
- case BS_ENCUMBERED:
- text += "You are encumbered.";
- text += EOL;
- break;
- }
-
- text += "You are ";
-
- text += hunger_level();
-
- text += ".";
- text += EOL;
- text += EOL;
-
- if (you.attribute[ATTR_TRANSFORMATION])
- {
- switch (you.attribute[ATTR_TRANSFORMATION])
- {
- case TRAN_SPIDER:
- text += "You are in spider-form.";
- break;
- case TRAN_BLADE_HANDS:
- text += "Your hands are blades.";
- break;
- case TRAN_STATUE:
- text += "You are a stone statue.";
- break;
- case TRAN_ICE_BEAST:
- text += "You are a creature of crystalline ice.";
- break;
- case TRAN_DRAGON:
- text += "You are a fearsome dragon!";
- break;
- case TRAN_LICH:
- text += "You are in lich-form.";
- break;
- case TRAN_SERPENT_OF_HELL:
- text += "You are a huge, demonic serpent!";
- break;
- case TRAN_AIR:
- text += "You are a cloud of diffuse gas.";
- break;
- }
-
- text += EOL;
- text += EOL;
- }
-
- dump_inventory(text, show_prices);
-
- char tmp_quant[20];
-
- text += EOL;
- text += EOL;
- text += " You have ";
- itoa( you.exp_available, tmp_quant, 10 );
- text += tmp_quant;
- text += " experience left.";
-
- dump_skills(text);
- dump_spells(text);
- dump_mutations(text);
-
- text += EOL;
- text += EOL;
-
- dump_screenshot(text);
- text += EOL EOL;
-
- dump_kills(text);
-
- char file_name[kPathLen] = "\0";
-
+ std::string file_name;
if (SysEnv.crawl_dir)
- strncpy(file_name, SysEnv.crawl_dir, kPathLen);
+ file_name += SysEnv.crawl_dir;
- strncat(file_name, fname, kPathLen);
+ file_name += fname;
#ifdef STASH_TRACKING
- char stash_file_name[kPathLen] = "";
- strncpy(stash_file_name, file_name, kPathLen);
-#endif
- if (strcmp(fname, "morgue.txt") != 0)
- {
- strncat(file_name, ".txt", kPathLen);
-#ifdef STASH_TRACKING
- strncat(stash_file_name, ".lst", kPathLen);
- stashes.dump(stash_file_name);
-#endif
- }
-#ifdef STASH_TRACKING
- else
- {
- // Grr. Filename is morgue.txt, it needs to be morgue.lst
- int len = strlen(stash_file_name);
- stash_file_name[len - 3] = 'l';
- stash_file_name[len - 2] = 's';
- // Fully identified stash dump.
- stashes.dump(stash_file_name, true);
- }
+ std::string stash_file_name;
+ stash_file_name = file_name;
+ stash_file_name += ".lst";
+ stashes.dump(stash_file_name.c_str(), full_id);
#endif
- FILE *handle = fopen(file_name, "wb");
+ file_name += ".txt";
+ FILE *handle = fopen(file_name.c_str(), "w");
#if DEBUG_DIAGNOSTICS
- strcpy( info, "File name: " );
- strcat( info, file_name );
- mpr( info, MSGCH_DIAGNOSTICS );
+ mprf(MSGCH_DIAGNOSTICS, "File name: %s", file_name.c_str());
#endif
if (handle != NULL)
{
- size_t begin = 0;
- size_t end = text.find(EOL);
-
- while (end != std::string::npos)
- {
- end += strlen(EOL);
-
- size_t len = end - begin;
-
- fwrite(text.c_str() + begin, len, 1, handle);
-
- begin = end;
- end = text.find(EOL, end);
- }
-
+ fputs(text.c_str(), handle);
fclose(handle);
succeeded = true;
}
@@ -1178,3 +1050,73 @@ bool dump_char( const char fname[30], bool show_prices ) // $$$ a try block?
return (succeeded);
} // end dump_char()
+
+static void set_resist_dump_color( const char* data ) {
+ while ( *data && *data != ':' )
+ ++data;
+ if ( *data == 0 )
+ return;
+ ++data;
+ int pluscount = 0;
+ while ( *data ) {
+ if ( *data == '+' )
+ ++pluscount;
+ if ( *data == 'x' )
+ --pluscount;
+ ++data;
+ }
+ switch ( pluscount ) {
+ case 3:
+ case 2:
+ textcolor(LIGHTGREEN);
+ break;
+ case 1:
+ textcolor(GREEN);
+ break;
+ case -1:
+ textcolor(RED);
+ break;
+ case -2:
+ case -3:
+ textcolor(LIGHTRED);
+ break;
+ default:
+ textcolor(LIGHTGREY);
+ break;
+ }
+}
+
+void resists_screen() {
+#ifdef DOS_TERM
+ char dosbuffer[4000];
+ gettext( 1, 1, 80, 25, dosbuffer );
+ window( 1, 1, 80, 25 );
+#endif
+ clrscr();
+ textcolor(LIGHTGREY);
+ char buffer[24*3][45];
+
+ get_full_detail(&buffer[0][0], false);
+
+ for (int line = 0; line < 24; ++line ) {
+ for ( int block = 0; block < 3; ++block ) {
+ const int idx = block * 24 + line;
+ if ( buffer[idx][0] ) {
+ gotoxy( block == 2 ? 53 : block * 32 + 1, line+1 );
+ /* FIXME - hack - magic number 14 */
+ if ( block != 0 && line < 14 )
+ set_resist_dump_color(buffer[idx]);
+ cprintf("%s", buffer[idx] );
+ textcolor(LIGHTGREY);
+ }
+ }
+ }
+
+ getch();
+#ifdef DOS_TERM
+ puttext(1, 1, 80, 25, dosbuffer);
+ window(1, 1, 80, 25);
+#endif
+
+ redraw_screen();
+}
diff --git a/crawl-ref/source/chardump.h b/crawl-ref/source/chardump.h
index 22b03ac8d3..1603ae9f75 100644
--- a/crawl-ref/source/chardump.h
+++ b/crawl-ref/source/chardump.h
@@ -3,6 +3,8 @@
* Summary: Dumps character info out to the morgue file.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> 4/20/99 JDJ Reformatted, uses string objects, split out
@@ -15,11 +17,11 @@
#include <string>
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: acr - ouch
- * *********************************************************************** */
-bool dump_char( const char fname[30], bool show_prices );
+bool dump_char(const std::string &fname,
+ bool show_prices,
+ bool full_id = false);
+
+void resists_screen();
std::string munge_description(const std::string &inStr);
diff --git a/crawl-ref/source/cloud.cc b/crawl-ref/source/cloud.cc
index 808c4cce02..7217240c57 100644
--- a/crawl-ref/source/cloud.cc
+++ b/crawl-ref/source/cloud.cc
@@ -3,6 +3,8 @@
* Summary: Functions related to clouds.
* Written by: Brent Ross
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Creating a cloud module so all the cloud stuff can be isolated.
*
* Change History (most recent first):
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc
index 21f2566c15..9885fc05d3 100644
--- a/crawl-ref/source/clua.cc
+++ b/crawl-ref/source/clua.cc
@@ -1,3 +1,7 @@
+/*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ */
+
#include "AppHdr.h"
#ifdef CLUA_BINDINGS
@@ -7,10 +11,12 @@
#include "abl-show.h"
#include "command.h"
#include "chardump.h"
+#include "delay.h"
#include "food.h"
#include "invent.h"
#include "initfile.h"
#include "itemname.h"
+#include "itemprop.h"
#include "items.h"
#include "item_use.h"
#include "libutil.h"
@@ -23,7 +29,6 @@
#include "skills2.h"
#include "spl-util.h"
#include "stuff.h"
-#include "wpn-misc.h"
#include <cstring>
@@ -297,7 +302,7 @@ void CLua::vfnreturns(const char *format, va_list args)
}
static void push_monster(lua_State *ls, monsters *mons);
-static int push_activity_interrupt(lua_State *ls, activity_interrupt_t *t);
+static int push_activity_interrupt(lua_State *ls, activity_interrupt_data *t);
int CLua::push_args(lua_State *ls, const char *format, va_list args,
va_list *targ)
{
@@ -346,7 +351,7 @@ int CLua::push_args(lua_State *ls, const char *format, va_list args,
break;
case 'A':
argc += push_activity_interrupt(
- ls, va_arg(args, activity_interrupt_t *));
+ ls, va_arg(args, activity_interrupt_data *));
break;
default:
--argc;
@@ -376,7 +381,7 @@ int CLua::return_count(lua_State *ls, const char *format)
// blowing the stack.
if (ci < 0)
ci = 0;
- else if (ci > 5)
+ else if (ci > 10)
ci = 10;
return (ci);
}
@@ -1239,22 +1244,25 @@ static int l_item_equip_type(lua_State *ls)
if (!item || !is_valid_item(*item))
return (0);
- int eq = -1;
+ equipment_type eq = EQ_NONE;
+
if (item->base_type == OBJ_WEAPONS || item->base_type == OBJ_STAVES)
eq = EQ_WEAPON;
else if (item->base_type == OBJ_ARMOUR)
- eq = armour_equip_slot(*item);
+ eq = get_armour_slot(*item);
else if (item->base_type == OBJ_JEWELLERY)
eq = item->sub_type >= AMU_RAGE? EQ_AMULET : EQ_RINGS;
- if (eq != -1)
+ if (eq != EQ_NONE)
+ {
lua_pushnumber(ls, eq);
- else
- lua_pushnil(ls);
- if (eq != -1)
lua_pushstring(ls, equip_slot_to_name(eq));
+ }
else
+ {
+ lua_pushnil(ls);
lua_pushnil(ls);
+ }
return (2);
}
@@ -1264,12 +1272,15 @@ static int l_item_weap_skill(lua_State *ls)
if (!item || !is_valid_item(*item))
return (0);
- int skill = weapon_skill( item->base_type, item->sub_type );
+ int skill = range_skill(*item);
+ if (skill == SK_RANGED_COMBAT)
+ skill = weapon_skill(*item);
if (skill == SK_FIGHTING)
return (0);
lua_pushstring(ls, skill_name(skill));
- return (1);
+ lua_pushnumber(ls, skill);
+ return (2);
}
static int l_item_artifact(lua_State *ls)
@@ -1407,7 +1418,7 @@ static bool eat_item(const item_def &item)
{
eat_from_inventory(item.link);
burden_change();
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return (true);
}
@@ -1444,42 +1455,6 @@ static int food_eat(lua_State *ls)
return (1);
}
-// Giving away chunk type information is spoily.
-/*
-static int food_chunktype(lua_State *ls)
-{
- LUA_ITEM(item, 1);
- if (item && item->base_type == OBJ_FOOD && item->sub_type == FOOD_CHUNK)
- {
- int mons_type = item->plus;
- int chunk_type = mons_corpse_thingy(mons_type);
- const char *schunktype = "unknown";
- switch (chunk_type)
- {
- case CE_HCL:
- case CE_MUTAGEN_GOOD:
- case CE_MUTAGEN_BAD:
- case CE_MUTAGEN_RANDOM:
- schunktype = "mutagenic";
- break;
- case CE_POISONOUS:
- schunktype = "poisonous";
- break;
- case CE_CONTAMINATED:
- schunktype = "contaminated";
- break;
- case CE_CLEAN:
- schunktype = "clean";
- break;
- }
- lua_pushstring(ls, schunktype);
- }
- else
- lua_pushnil(ls);
- return (1);
-}
-*/
-
static int food_rotting(lua_State *ls)
{
LUA_ITEM(item, 1);
@@ -1557,7 +1532,7 @@ static int crawl_c_input_line(lua_State *ls)
{
char linebuf[500];
- bool valid = cancelable_get_line(linebuf, sizeof linebuf);
+ bool valid = !cancelable_get_line(linebuf, sizeof linebuf);
if (valid)
lua_pushstring(ls, linebuf);
else
@@ -1903,9 +1878,15 @@ static option_handler handlers[] =
{ "show_uncursed", &Options.show_uncursed, option_hboolean },
{ "always_greet", &Options.always_greet, option_hboolean },
{ "easy_open", &Options.easy_open, option_hboolean },
- { "easy_armour", &Options.easy_armour, option_hboolean },
+ { "easy_armour", &Options.easy_unequip, option_hboolean },
+ { "easy_unequip", &Options.easy_unequip, option_hboolean },
{ "easy_butcher", &Options.easy_butcher, option_hboolean },
{ "terse_hand", &Options.terse_hand, option_hboolean },
+ { "increasing_skill_progress", &Options.increasing_skill_progress, option_hboolean },
+ { "confirm_self_target", &Options.confirm_self_target, option_hboolean },
+ { "safe_autopickup", &Options.safe_autopickup, option_hboolean },
+ { "note_skill_max", &Options.note_skill_max, option_hboolean },
+ { "use_notes", &Options.use_notes, option_hboolean },
{ "delay_message_clear", &Options.delay_message_clear, option_hboolean },
{ "no_dark_brand", &Options.no_dark_brand, option_hboolean },
{ "auto_list", &Options.auto_list, option_hboolean },
@@ -1913,9 +1894,11 @@ static option_handler handlers[] =
option_hboolean },
{ "pickup_thrown", &Options.pickup_thrown, option_hboolean },
{ "pickup_dropped", &Options.pickup_dropped, option_hboolean },
+ { "sort_menus", &Options.sort_menus, option_hboolean },
{ "show_waypoints", &Options.show_waypoints, option_hboolean },
{ "item_colour", &Options.item_colour, option_hboolean },
{ "target_zero_exp", &Options.target_zero_exp, option_hboolean },
+ { "safe_zero_exp", &Options.safe_zero_exp, option_hboolean },
{ "target_wrap", &Options.target_wrap, option_hboolean },
{ "easy_exit_menu", &Options.easy_exit_menu, option_hboolean },
{ "dos_use_background_intensity", &Options.dos_use_background_intensity,
@@ -2066,7 +2049,7 @@ static int monster_set(lua_State *ls)
return (0);
}
-static int push_activity_interrupt(lua_State *ls, activity_interrupt_t *t)
+static int push_activity_interrupt(lua_State *ls, activity_interrupt_data *t)
{
if (!t->data)
{
diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc
index 25644bdb0b..437192ad34 100644
--- a/crawl-ref/source/command.cc
+++ b/crawl-ref/source/command.cc
@@ -3,6 +3,8 @@
* Summary: Misc commands.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <4> 10/12/99 BCR BUILD_DATE is now used in version()
@@ -25,17 +27,23 @@
#include "itemname.h"
#include "item_use.h"
#include "items.h"
+#include "libutil.h"
#include "menu.h"
#include "ouch.h"
#include "spl-cast.h"
#include "spl-util.h"
#include "stuff.h"
#include "version.h"
-#include "wpn-misc.h"
+#include "view.h"
static void adjust_item(void);
static void adjust_spells(void);
static void adjust_ability(void);
+static void list_wizard_commands();
+#ifdef OBSOLETE_COMMAND_HELP
+static const char *command_string( int i );
+#endif
+static const char *wizard_string( int i );
void quit_game(void)
{
@@ -64,7 +72,7 @@ static const char *features[] = {
void version(void)
{
- mpr( "This is Dungeon Crawl " VERSION " (Last build " BUILD_DATE ")." );
+ mpr( "This is " CRAWL " " VERSION " (" BUILD_DATE ")." );
std::string feats = "Features: ";
for (int i = 1, size = sizeof features / sizeof *features; i < size; ++i)
@@ -140,7 +148,7 @@ static void adjust_item(void)
return;
}
- from_slot = prompt_invent_item( "Adjust which item?", -1 );
+ from_slot = prompt_invent_item( "Adjust which item?", MT_INVSELECT, -1 );
if (from_slot == PROMPT_ABORT)
{
canned_msg( MSG_OK );
@@ -150,7 +158,12 @@ static void adjust_item(void)
in_name( from_slot, DESC_INVENTORY_EQUIP, str_pass );
mpr( str_pass );
- to_slot = prompt_invent_item( "Adjust to which letter?", -1, false, false );
+ to_slot = prompt_invent_item(
+ "Adjust to which letter?",
+ MT_INVSELECT,
+ -1,
+ false,
+ false );
if (to_slot == PROMPT_ABORT)
{
canned_msg( MSG_OK );
@@ -551,3 +564,492 @@ void list_weapons(void)
mpr( info, MSGCH_EQUIPMENT, menu_colour(info) );
} // end list_weapons()
+
+static void cmdhelp_showline(int index, const MenuEntry *me)
+{
+ static_cast<formatted_string *>(me->data)->display();
+}
+
+static int cmdhelp_keyfilter(int keyin)
+{
+ switch (keyin)
+ {
+ case CK_DOWN:
+ case '+':
+ case '=':
+ return ('>');
+ case CK_UP:
+ case '-':
+ case '_':
+ return ('<');
+ case 'x':
+ return (CK_ESCAPE);
+ default:
+ return (keyin);
+ }
+}
+
+static bool cmdhelp_textfilter(const std::string &tag)
+{
+#ifdef STASH_TRACKING
+ if (tag == "s")
+ return (true);
+#endif
+#ifdef WIZARD
+ if (tag == "wiz")
+ return (true);
+#endif
+ return (false);
+}
+
+static const char *level_map_help =
+ "<h>Level Map ('<w>X</w><h>' in main screen):\n"
+ "<w>Esc</w> : leave level map (also Space)\n"
+ "<w>Dir.</w>: move cursor\n"
+ "<w>/ Dir.</w>, <w>Shift-Dir.</w>: move cursor far\n"
+ "<w>+</w>/<w>-</w> : scroll level map up/down\n"
+ "<w>.</w> : travel (also Enter and , and ;)\n"
+ " (moves cursor to last travel\n"
+ " destination if still on @)\n"
+ "<w><<</w>/<w>></w> : cycle through up/down stairs\n"
+ "<w>^</w> : cycle through traps\n"
+ "<w>Tab</w> : cycle through shops and portals\n"
+ "<w>X</w> : cycle through travel eXclusions\n"
+ "<w>W</w> : cycle through waypoints\n"
+ "<w>I</w> : cycle through stashes\n"
+ "<w>Ctrl-X</w> : set travel eXclusion\n"
+ "<w>Ctrl-E</w> : Erase all travel exclusions\n"
+ "<w>Ctrl-W</w> : set Waypoint\n"
+ "<w>Ctrl-C</w> : Clear level and main maps\n";
+
+static void show_keyhelp_menu(const std::vector<formatted_string> &lines)
+{
+ Menu cmd_help;
+
+ // Set flags, and don't use easy exit.
+ cmd_help.set_flags(
+ MF_NOSELECT | MF_ALWAYS_SHOW_MORE | MF_NOWRAP,
+ false);
+
+ // FIXME: Allow for hiding Page down when at the end of the listing, ditto
+ // for page up at start of listing.
+ cmd_help.set_more(
+ formatted_string::parse_string(
+ "<cyan>[ + : Page down. - : Page up."
+ " Esc/x exits.]"));
+ cmd_help.f_drawitem = cmdhelp_showline;
+ cmd_help.f_keyfilter = cmdhelp_keyfilter;
+
+ std::vector<MenuEntry*> entries;
+
+ for (unsigned i = 0, size = lines.size(); i < size; ++i)
+ {
+ MenuEntry *me = new MenuEntry;
+ me->data = new formatted_string(lines[i]);
+ entries.push_back(me);
+
+ cmd_help.add_entry(me);
+ }
+
+ cmd_help.show();
+
+ for (unsigned i = 0, size = entries.size(); i < size; ++i)
+ delete static_cast<formatted_string*>( entries[i]->data );
+}
+
+void show_levelmap_help()
+{
+ std::vector<std::string> lines =
+ split_string("\n", level_map_help, false, true);
+ std::vector<formatted_string> formatted_lines;
+ for (int i = 0, size = lines.size(); i < size; ++i)
+ formatted_lines.push_back(
+ formatted_string::parse_string(
+ lines[i], true, cmdhelp_textfilter));
+ show_keyhelp_menu(formatted_lines);
+}
+
+void list_commands(bool wizard)
+{
+ if (wizard)
+ {
+ list_wizard_commands();
+ return;
+ }
+
+ // 2 columns, split at column 40.
+ column_composer cols(2, 41);
+ // Page size is number of lines - one line for --more-- prompt.
+ cols.set_pagesize(get_number_of_lines() - 1);
+
+ cols.add_formatted(
+ 0,
+ "<h>Movement:\n"
+ "To move in a direction or to attack, use\n"
+ "the numpad (try Numlock both off and on)\n"
+ "or vi keys:\n"
+ " <w>1 2 3 y k u\n"
+ " \\|/ \\|/\n"
+ " <w>4</w>-<w>5</w>-<w>6</w>"
+ " <w>h</w>-<w>.</w>-<w>l</w>\n"
+ " /|\\ /|\\\n"
+ " <w>7 8 9 b j n\n",
+ true, true, cmdhelp_textfilter);
+
+ cols.add_formatted(
+ 0,
+ "<h>Rest/Search:\n"
+ "<w>5</w> (numpad), <w>.</w>, <w>s</w>, <w>Del</w>: "
+ "rest one turn and\n"
+ " search adjacent squares.\n"
+ "<w>Shift-5</w> (numpad), <w>5</w>: rest until HP/MP are\n"
+ "full or something found or 100 turns over\n",
+ true, true, cmdhelp_textfilter);
+
+ cols.add_formatted(
+ 0,
+ "<h>Dungeon Interaction and Information:\n"
+ "<w>o</w>/<w>c</w> : Open/Close door\n"
+ "<w><<</w>/<w>></w> : use staircase (<w><<</w> also enters shop)\n"
+ "<w>;</w> : examine occupied tile\n"
+ "<w>x</w> : eXamine surroundings/targets\n"
+ "<w>X</w> : eXamine level map\n"
+ "<w>O</w> : show dungeon Overview\n",
+ true, true, cmdhelp_textfilter);
+
+ cols.add_formatted(
+ 0,
+ "<h>Item Interaction (inventory):\n"
+ "<w>v</w> : View item description\n"
+ "<w>{</w> : inscribe item\n"
+ "<w>t</w> : Throw/shoot an item\n"
+ "<w>f</w> : Fire first available missile\n"
+ "<w>q</w> : Quaff a potion\n"
+ "<w>e</w> : Eat food (but tries floor first)\n"
+ "<w>z</w> : Zap a wand\n"
+ "<w>r</w> : Read a scroll or book\n"
+ "<w>M</w> : Memorise a spell from a book\n"
+ "<w>w</w> : Wield an item ( - for none)\n"
+ "<w>'</w> : wield item a, or switch to b\n"
+ "<w>E</w> : Evoke power of wielded item\n"
+ "<w>W</w> : Wear armour\n"
+ "<w>T</w> : Take off armour\n"
+ "<w>P</w> : Put on jewellery\n"
+ "<w>R</w> : Remove jewellery\n",
+ true, true, cmdhelp_textfilter);
+
+ cols.add_formatted(
+ 0,
+ "<h>Other Gameplay Actions:\n"
+ "<w>a</w> : use special Ability\n"
+ "<w>p</w> : Pray\n"
+ "<w>Z</w> : cast a spell\n"
+ "<w>!</w> : shout or command allies\n",
+ true, true, cmdhelp_textfilter);
+
+ cols.add_formatted(
+ 0,
+ "<h>In-game Toggles:\n"
+ "<w>Ctrl-A</w> : toggle Autopickup\n"
+ "<w>Ctrl-V</w> : toggle auto-prayer\n"
+ "<w>Ctrl-T</w> : toggle spell fizzle check\n",
+ true, true, cmdhelp_textfilter);
+
+ cols.add_formatted(
+ 0,
+ level_map_help,
+ true, true, cmdhelp_textfilter);
+
+ cols.add_formatted(
+ 1,
+ "<h>Extended Movement:\n"
+ "<w>Ctrl-G</w> : interlevel travel\n"
+ "<w>Ctrl-O</w> : auto-explore\n"
+ "<w>Ctrl-W</w> : set Waypoint\n"
+ "<w>/ Dir., Shift-Dir.</w>: long walk\n"
+ "<w>* Dir., Ctrl-Dir.</w> : untrap, attack\n"
+ " without move, open door\n",
+ true, true, cmdhelp_textfilter, 45);
+
+
+ cols.add_formatted(
+ 1,
+ "<h>Game Saving and Quitting:\n"
+ "<w>S</w> : Save game and exit \n"
+ "<w>Q</w> : Quit without saving\n"
+ "<w>Ctrl-X</w> : save game without query\n",
+ true, true, cmdhelp_textfilter, 45);
+
+ cols.add_formatted(
+ 1,
+ "<h>Player Character Information:\n"
+ "<w>@</w> : display character status\n"
+ "<w>[</w> : display worn armour\n"
+ "<w>\"</w> : display worn jewellery\n"
+ "<w>C</w> : display experience info\n"
+ "<w>^</w> : show religion screen\n"
+ "<w>A</w> : show Abilities/mutations\n"
+ "<w>\\</w> : show item knowledge\n"
+ "<w>m</w> : show skill screen\n"
+ "<w>i</w> : show Inventory list\n"
+ "<w>%</w> : show resistances\n",
+ true, true, cmdhelp_textfilter, 45);
+
+ cols.add_formatted(
+ 1,
+ "<h>Item Interaction (floor):\n"
+ "<w>,</w> : pick up items (also <w>g</w>) \n"
+ " (press twice for pick up menu) \n"
+ "<w>d</w> : Drop an item\n"
+ "<w>d#</w>: Drop exact number of items \n"
+ "<w>D</w> : Dissect a corpse \n"
+ "<w>e</w> : Eat food from floor \n"
+ "<w>z</w> : Zap a wand \n"
+ "<w>r</w> : Read a scroll or book \n"
+ "<w>M</w> : Memorise a spell from a book \n"
+ "<w>w</w> : Wield an item ( - for none) \n"
+ "<w>'</w> : wield item a, or switch to b \n"
+ "<w>E</w> : Evoke power of wielded item\n",
+ true, true, cmdhelp_textfilter);
+
+ cols.add_formatted(
+ 1,
+ "<h>Non-Gameplay Commands / Info\n"
+ "<w>V</w> : display Version information\n"
+ "<w>Ctrl-P</w> : show Previous messages\n"
+ "<w>Ctrl-R</w> : Redraw screen\n"
+ "<w>Ctrl-C</w> : Clear main and level maps\n"
+ "<w>#</w> : dump character to file\n"
+ "<w>:</w> : add note to dump file\n"
+ "<w>`</w> : add macro\n"
+ "<w>~</w> : save macros\n"
+ "<w>=</w> : reassign inventory/spell letters\n",
+ true, true, cmdhelp_textfilter);
+
+ cols.add_formatted(
+ 1,
+ "<?s><h>Stash Management Commands:\n"
+ "<?s><w>Ctrl-S</w> : mark Stash\n"
+ "<?s><w>Ctrl-E</w> : Erase stash (ignore square)\n"
+ "<?s><w>Ctrl-F</w> : Find (in stashes and shops)\n",
+ true, true, cmdhelp_textfilter);
+
+ cols.add_formatted(
+ 1,
+ "<h>Targeting, Surroundings ('<w>x</w><h>' in main):\n"
+ " <w>x</w> : stop targeting (also <w>Esc</w> and <w>Space</w>)\n"
+ " <w>+</w> : cycle monsters forward\n"
+ " <w>-</w> : cycle monsters backward\n"
+ " <w>*</w> : cycle objects forward (also ')\n"
+ " <w>/</w> : cycle objects backward (also ;)\n"
+ " <w>.</w> : choose target/move (also Enter)\n"
+ " <w>?</w> : describe monster under cursor\n"
+ "<w><<</w>/<w>></w> : cycle through up/down stairs\n",
+ true, true, cmdhelp_textfilter);
+
+ cols.add_formatted(
+ 1,
+ "<h>Shortcuts in Lists (like multidrop):\n"
+ "<w>(</w>/<w>)</w> : selects all missiles/hand weapons\n"
+ "<w>%</w>/<w>&</w> : selects all food/carrion\n"
+ "<w>+</w>/<w>?</w> : selects all books/scrolls\n"
+ "<w>/</w>/<w>\\</w> : selects all wands/staves\n"
+ "<w>!</w>/<w>\"</w> : selects all potions/jewellry\n"
+ "<w>[</w>/<w>}</w> : selects all armour/misc. items\n"
+ "<w>,</w>/<w>-</w> : global select/deselect\n"
+ "<w>*</w> : invert selection\n",
+ true, true, cmdhelp_textfilter);
+
+ show_keyhelp_menu(cols.formatted_lines());
+}
+
+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
+ int moreLength = (get_number_of_lines() - 1) * 2;
+
+ for (int i = 0; i < 500; i++)
+ {
+ line = wizard_string( i );
+
+ if (strlen( line ) != 0)
+ {
+ // BCR - If we've reached the end of the screen, clear
+ if (j == moreLength)
+ {
+ gotoxy(2, j / 2 + 1);
+ cprintf("More...");
+ getch();
+ clrscr();
+ j = 0;
+ }
+
+ gotoxy( ((j % 2) ? 40 : 2), ((j / 2) + 1) );
+ cprintf( "%s", line );
+
+ j++;
+ }
+ }
+
+ getch();
+
+#ifdef DOS_TERM
+ puttext(1, 1, 80, 25, buffer);
+#endif
+
+ return;
+} // end list_commands()
+
+static const char *wizard_string( int i )
+{
+ UNUSED( i );
+
+#ifdef WIZARD
+ return((i == 10) ? "a : acquirement" :
+ (i == 13) ? "A : set all skills to level" :
+ (i == 15) ? "b : controlled blink" :
+ (i == 20) ? "B : banish yourself to the Abyss" :
+ (i == 30) ? "g : add a skill" :
+ (i == 35) ? "G : remove all monsters" :
+ (i == 40) ? "h/H : heal yourself (super-Heal)" :
+ (i == 50) ? "i/I : identify/unidentify inventory":
+ (i == 70) ? "l : make entrance to labyrinth" :
+ (i == 80) ? "m/M : create monster by number/name":
+ (i == 90) ? "o/% : create an object" :
+ (i == 100) ? "p : make entrance to pandemonium" :
+ (i == 110) ? "x : gain an experience level" :
+ (i == 115) ? "r : change character's species" :
+ (i == 120) ? "s : gain 20000 skill points" :
+ (i == 130) ? "S : set skill to level" :
+ (i == 140) ? "t : tweak object properties" :
+ (i == 150) ? "X : Receive a gift from Xom" :
+ (i == 160) ? "z/Z : cast any spell by number/name":
+ (i == 200) ? "$ : get 1000 gold" :
+ (i == 210) ? "</> : create up/down staircase" :
+ (i == 220) ? "u/d : shift up/down one level" :
+ (i == 230) ? "~/\" : goto a level" :
+ (i == 240) ? "( : create a feature" :
+ (i == 250) ? "] : get a mutation" :
+ (i == 260) ? "[ : get a demonspawn mutation" :
+ (i == 270) ? ": : find branch" :
+ (i == 280) ? "{ : magic mapping" :
+ (i == 290) ? "^ : gain piety" :
+ (i == 300) ? "_ : gain religion" :
+ (i == 310) ? "\' : list items" :
+ (i == 320) ? "? : list wizard commands" :
+ (i == 330) ? "| : acquire all unrand artefacts" :
+ (i == 340) ? "+ : turn item into random artefact" :
+ (i == 350) ? "= : sum skill points"
+ : "");
+
+#else
+ return ("");
+#endif
+} // end wizard_string()
+
+#ifdef OBSOLETE_COMMAND_HELP
+static const char *command_string( int i )
+{
+ /*
+ * BCR - Command printing, case statement
+ * Note: The numbers in this case indicate the order in which the
+ * commands will be printed out. Make sure none of these
+ * numbers is greater than 500, because that is the limit.
+ *
+ * Arranged alpha lower, alpha upper, punctuation, ctrl.
+ *
+ */
+
+ return((i == 10) ? "a : use special ability" :
+ (i == 20) ? "d(#) : drop (exact quantity of) items" :
+ (i == 30) ? "e : eat food" :
+ (i == 40) ? "f : fire first available missile" :
+ (i == 50) ? "i : inventory listing" :
+ (i == 55) ? "m : check skills" :
+ (i == 60) ? "o/c : open / close a door" :
+ (i == 65) ? "p : pray" :
+ (i == 70) ? "q : quaff a potion" :
+ (i == 80) ? "r : read a scroll or book" :
+ (i == 90) ? "s : search adjacent tiles" :
+ (i == 100) ? "t : throw/shoot an item" :
+ (i == 110) ? "v : view item description" :
+ (i == 120) ? "w : wield an item" :
+ (i == 130) ? "x : examine visible surroundings" :
+ (i == 135) ? "z : zap a wand" :
+ (i == 140) ? "A : list abilities/mutations" :
+ (i == 141) ? "C : check experience" :
+ (i == 142) ? "D : dissect a corpse" :
+ (i == 145) ? "E : evoke power of wielded item" :
+ (i == 150) ? "M : memorise a spell" :
+ (i == 155) ? "O : overview of the dungeon" :
+ (i == 160) ? "P/R : put on / remove jewellery" :
+ (i == 165) ? "Q : quit without saving" :
+ (i == 168) ? "S : save game and exit" :
+ (i == 179) ? "V : version information" :
+ (i == 200) ? "W/T : wear / take off armour" :
+ (i == 210) ? "X : examine level map" :
+ (i == 220) ? "Z : cast a spell" :
+ (i == 240) ? ",/g : pick up items" :
+ (i == 242) ? "./del: rest one turn" :
+ (i == 250) ? "</> : ascend / descend a staircase" :
+ (i == 270) ? "; : examine occupied tile" :
+ (i == 280) ? "\\ : check item knowledge" :
+#ifdef WIZARD
+ (i == 290) ? "& : invoke your Wizardly powers" :
+#endif
+ (i == 300) ? "+/- : scroll up/down [level map only]" :
+ (i == 310) ? "! : shout or command allies" :
+ (i == 325) ? "^ : describe religion" :
+ (i == 337) ? "@ : status" :
+ (i == 340) ? "# : dump character to file" :
+ (i == 350) ? "= : reassign inventory/spell letters" :
+ (i == 360) ? "\' : wield item a, or switch to b" :
+ (i == 370) ? ": : make a note" :
+#ifdef USE_MACROS
+ (i == 380) ? "` : add macro" :
+ (i == 390) ? "~ : save macros" :
+#endif
+ (i == 400) ? "] : display worn armour" :
+ (i == 410) ? "\" : display worn jewellery" :
+ (i == 415) ? "{ : inscribe an item" :
+ (i == 420) ? "Ctrl-P : see old messages" :
+#ifdef PLAIN_TERM
+ (i == 430) ? "Ctrl-R : Redraw screen" :
+#endif
+ (i == 440) ? "Ctrl-A : toggle autopickup" :
+ (i == 445) ? "Ctrl-M : toggle autoprayer" :
+ (i == 447) ? "Ctrl-T : toggle fizzle" :
+ (i == 450) ? "Ctrl-X : Save game without query" :
+
+#ifdef ALLOW_DESTROY_ITEM_COMMAND
+ (i == 451) ? "Ctrl-D : Destroy inventory item" :
+#endif
+ (i == 453) ? "Ctrl-G : interlevel travel" :
+ (i == 455) ? "Ctrl-O : explore" :
+
+#ifdef STASH_TRACKING
+ (i == 456) ? "Ctrl-S : mark stash" :
+ (i == 457) ? "Ctrl-E : forget stash" :
+ (i == 458) ? "Ctrl-F : search stashes" :
+#endif
+
+ (i == 460) ? "Shift & DIR : long walk" :
+ (i == 465) ? "/ DIR : long walk" :
+ (i == 470) ? "Ctrl & DIR : door; untrap; attack" :
+ (i == 475) ? "* DIR : door; untrap; attack" :
+ (i == 478) ? "Shift & 5 on keypad : rest 100 turns"
+ : "");
+} // end command_string()
+#endif // OBSOLETE_COMMAND_HELP
diff --git a/crawl-ref/source/command.h b/crawl-ref/source/command.h
index 7bdd3a9e85..54424d4045 100644
--- a/crawl-ref/source/command.h
+++ b/crawl-ref/source/command.h
@@ -3,6 +3,8 @@
* Summary: Misc commands.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -12,6 +14,7 @@
#ifndef COMMAND_H
#define COMMAND_H
+#include "enum.h"
// last updated 12may2000 {dlb}
/* ***********************************************************************
@@ -57,4 +60,9 @@ void list_jewellery(void);
void swap_inv_slots(int slot1, int slot2, bool verbose);
+void show_levelmap_help();
+
+// Actually defined in acr.cc; we may want to move this to command.cc
+void process_command(command_type cmd);
+
#endif
diff --git a/crawl-ref/source/dat/levdes.vim b/crawl-ref/source/dat/levdes.vim
new file mode 100644
index 0000000000..c489be52a7
--- /dev/null
+++ b/crawl-ref/source/dat/levdes.vim
@@ -0,0 +1,75 @@
+" levdes.vim:
+"
+" Basic Vim syntax highlighting for Dungeon Crawl Stone Soup level design
+" (.des) files.
+
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+syn case match
+
+setlocal iskeyword+=:
+setlocal iskeyword+=-
+
+syn keyword desDeclarator NAME: ORIENT: DEPTH: PLACE: MONS: FLAGS: SYMBOL: default-depth: TAGS: CHANCE:
+syn keyword desOrientation encompass north south east west northeast northwest southeast southwest
+
+syn match desComment "^\s*#.*$"
+
+syn keyword desMapBookend MAP ENDMAP contained
+syn match desMapFloor /\./ contained
+syn match desMapWall /x/ contained
+syn match desMapDoor /[+=]/ contained
+syn match desMapStoneWall /c/ contained
+syn match desMapCrystalWall /b/ contained
+syn match desMapMetalWall /v/ contained
+syn match desMapWaxWall /a/ contained
+syn match desMapMonst /[0-9]/ contained
+syn match desMapGold /\$/ contained
+syn match desMapLava /l/ contained
+syn match desMapWater /w/ contained
+syn match desMapEntry /@/ contained
+syn match desMapTrap /\^/ contained
+
+syn match desMapValuable /[R%*|]/ contained
+syn match desMapRune /[PO]/ contained
+syn match desMapOrb /Z/ contained
+
+syn cluster desMapElements contains=desMapBookend,desMapWall,desMapFloor
+syn cluster desMapElements add=desMapMonst,desMapCrystalWall,desMapGold
+syn cluster desMapElements add=desMapLava,desMapMetalWall,desMapDoor
+syn cluster desMapElements add=desMapStoneWall,desMapWater,desMapTrap
+syn cluster desMapElements add=desMapEntry,desMapWaxWall
+
+syn cluster desMapElements add=desMapRune,desMapOrb,desMapValuable
+
+syn region desMap start=/^\s*\<MAP\>\s*$/ end=/^\s*\<ENDMAP\>\s*$/ contains=@desMapElements keepend
+
+hi link desDeclarator Statement
+hi link desMapBookend Statement
+hi link desComment Comment
+hi link desMap String
+hi link desOrientation Type
+
+hi desMapWall guifg=darkgrey term=bold gui=bold
+hi desMapCrystalWall guifg=#009040 term=bold gui=bold
+hi desMapStoneWall guifg=black gui=bold
+hi desMapMetalWall guifg=#004090 term=bold gui=bold
+hi desMapWaxWall guifg=#a0a000 gui=bold
+hi desMapFloor guifg=#008000
+hi desMapMonst guifg=red
+hi desMapLava guifg=red gui=bold
+hi desMapTrap guifg=red gui=bold
+hi desMapWater guifg=lightblue
+hi desMapGold guifg=#c09000
+hi desMapDoor guifg=brown gui=bold
+hi desMapEntry guifg=black guibg=white gui=bold
+
+hi desMapValuable guifg=darkgreen gui=bold
+hi desMapRune guifg=orange gui=bold
+hi desMapOrb guibg=gold guifg=black
+
+syn sync minlines=45
diff --git a/crawl-ref/source/dat/splev.des b/crawl-ref/source/dat/splev.des
new file mode 100644
index 0000000000..96c2ee5f81
--- /dev/null
+++ b/crawl-ref/source/dat/splev.des
@@ -0,0 +1,1563 @@
+##############################################################################
+# splev.des: special levels definitions.
+#
+# If you want to define random vaults and minivaults, they should go
+# to vaults.des.
+#
+# key:
+# x - DNGN_ROCK_WALL
+# X - DNGN_PERMAROCK_WALL -> should always be undiggable! -- bwr
+# c - DNGN_STONE_WALL
+# v - DNGN_METAL_WALL
+# b - DNGN_GREEN_CRYSTAL_WALL
+# a - DNGN_WAX_WALL
+# . - DNGN_FLOOR
+# + - DNGN_CLOSED_DOOR
+# = - DNGN_SECRET_DOOR
+# @ - entry point - must be on outside and on a particular side - see templates
+# w - water
+# l - lava
+# >< - extra stairs - you can leave level by these but will never be placed on
+# them from another level
+# }{ - stairs 82/86 - You must be able to reach these from each other
+# )( - stairs 83/87
+# ][ - stairs 84/88
+# I - orcish idol (does nothing)
+# ^ - random trap
+#
+# A - Vestibule gateway (opened by Horn). Can also be put on other levels for
+# colour, where it won't do anything.
+# B - Altar. These are assigned specific types (eg of Zin etc) in dungeon.cc,
+# in order.
+# C - Random Altar.
+# F - Typically a Granite Statue, but may be Orange or Silver (1 in 100)
+# G - Granite statue (does nothing)
+# H - orange crystal statue (attacks mind)
+# S - Silver statue (summons demons). Avoid using (rare).
+# T - Water fountain
+# U - Magic fountain
+# V - Permanently dry fountain
+#
+# Statues can't be walked over and are only destroyed by disintegration
+#
+# $ - gold
+# % - normal item
+# * - higher level item (good)
+# | - acquirement-level item (almost guaranteed excellent)
+# O - place an appropriate rune here
+# P - maybe place a rune here (50%)
+# R - honeycomb (2/3) or royal jelly (1/3)
+# Z - the Orb of Zot
+#
+# 0 - normal monster
+# 9 - +5 depth monster
+# 8 - (+2) * 2 depth monster (aargh!). Can get golden dragons and titans
+# this way.
+# 1-7 - monster array monster
+# used to allocate specific monsters for a vault.
+# is filled with RANDOM_MONSTER if monster not specified
+#
+# note that a lot of the vaults are in there mainly to add some interest to the
+# scenery, and are not the lethal treasure-fests you find in Angband
+# (not that there's anything wrong with that)
+#
+# Guidelines for creating new vault maps:
+#
+# [ds] If your map is not a minivault, make sure the side(s) that form the
+# border have a rock wall padding at least 6 deep. For instance, if your map
+# is ORIENT: north, you must have a 6 deep border of rock wall (or any
+# other kind of wall) along the northern, eastern, and western edges of the
+# map. If you're doing a fullscreen map (encompass), you must pad all around
+# the map with 6 layers of wall.
+#
+# Basically you can just let your creativity run wild. You do not have
+# to place all of the stairs unless the level is full screen, in which
+# case you must place all except the extra stairs (> and <). The <> stairs
+# can be put anywhere and in any quantities but do not have to be there. Any
+# of the other stairs which are not present in the vault will be randomly
+# placed outside it. Also generally try to avoid rooms with no exit.
+#
+# You can use the templates below to build vaults. The entry point '@' must be
+# present (except full-screen vaults where it must not) and be on the same
+# side of the vault as it is on the template, but can be anywhere along that
+# side.
+#
+# I think that's all. Have fun!
+#
+# ps - remember to add one to the monster array value when placing monsters
+# on each map (it is 1-7, not 0-6) {dlb}
+#
+# [dshaligram] All special levels MUST have an ORIENT: attribute; if there's
+# no ORIENT: attribute, the level is considered to be a minivault, which is
+# usually not what you want.
+#
+# Special levels are selected either by PLACE: (for most special levels) or
+# TAGS: (for the Pandemonium demon lords). If you want to define alternate
+# levels, duplicate the selector and use different names. For instance, to
+# define an alternate Vestibule level, you could use something like this:
+#
+# NAME: vestibule_of_hell_alternate
+# PLACE: Hell
+#
+# To define an alternate level for Cerebov, you could do:
+#
+# NAME: cerebov_alternate
+# TAGS: cerebov
+#
+# You can also use CHANCE: to control the weight a level is assigned. For
+# instance, if you want to make cerebov_alternate five times more likely than
+# the standard cerebov level, you'd do:
+#
+# NAME: cerebov_alternate
+# TAGS: cerebov
+# CHANCE: 50
+#
+# (The default weight is 10 if CHANCE: is omitted.)
+#
+##############################################################################
+
+NAME: vestibule_of_hell
+PLACE: Hell
+ORIENT: encompass
+
+# [dshaligram] If modifying the Vestibule, ensure that:
+#
+# * The portal to Dis is surrounded by floor squares and nothing but floor
+# squares.
+# * The portal to Tartarus is surrounded only by floor, doors of any kind, and
+# at least one rock wall.
+# * The portal to Gehenna is surrounded by nothing but floor and at least one
+# lava square.
+# * The portal to Cocytus is surrounded by nothing but floor and at least one
+# water square.
+#
+# If you don't do this, the portals will not be unbarred correctly when
+# Geryon's horn is sounded.
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxvvvvvvvxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..v.....v..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.....v.....v.....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxx........v.....v........xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxx..........v..A..v..........xxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxx............v.....v............xxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxx.............v.....v.............xxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxx..............vvv+vvv..............xxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxx.....................................xxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxx.......................................xxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxx.........................................xxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxx...........................................xxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxx.............................................xxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx...............................................xxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxx.................................................xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxx...................................................xxxxxxxxxxxxxxx
+xxxxxxxxxxxxx.....................................................xxxxxxxxxxxxxx
+xxxxxxxxxxxxx.....................................................xxxxxxxxxxxxxx
+xxxxxxxxxxxx.......................................................xxxxxxxxxxxxx
+xxxxxxxxxxxx.......................................................xxxxxxxxxxxxx
+xxxxxxxxxxx.........................................................xxxxxxxxxxxx
+xxxxxxxxxxx............................{............................xxxxxxxxxxxx
+xxxxxxxxxxx.........................................................xxxxxxxxxxxx
+xxxxxxxxxx...l.l.....................................................xxxxxxxxxxx
+xxxxxxxxxx..l.l.l.l..................................................xxxxxxxxxxx
+xxxxxxxxxx.l.l.l.l.l.................................................xxxxxxxxxxx
+xxxxxxxxx.l.l.l.l.l...................................................xxxxxxxxxx
+xxxxxxxxxl.l.l.l.l.l..................................................xxxxxxxxxx
+xxxxxxxxx.l.l.l.A.l.l.................}1].............................=Axxxxxxxx
+xxxxxxxxxl.l.l.l.l.l.l.................)..............................xxxxxxxxxx
+xxxxxxxxx.l.l.l.l.l.l.................................................xxxxxxxxxx
+xxxxxxxxxx.l.l.l.l.l.l...............................................xxxxxxxxxxx
+xxxxxxxxxx..l.l.l.l..................................................xxxxxxxxxxx
+xxxxxxxxxx.....l.l...................................................xxxxxxxxxxx
+xxxxxxxxxxx......................[...........(......................xxxxxxxxxxxx
+xxxxxxxxxxx.........................................................xxxxxxxxxxxx
+xxxxxxxxxxx.........................................................xxxxxxxxxxxx
+xxxxxxxxxxxx.......................................................xxxxxxxxxxxxx
+xxxxxxxxxxxx.......................................................xxxxxxxxxxxxx
+xxxxxxxxxxxxx.....................................................xxxxxxxxxxxxxx
+xxxxxxxxxxxxx.....................................................xxxxxxxxxxxxxx
+xxxxxxxxxxxxxx...................................................xxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxx....................wwwww........................xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx..................wwwwwwww.....................xxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxx..............wwwwwwwwwwwww..................xxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxx...........w..wwww..wwwww..w...............xxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxx..........w...ww.....ww..wwwww...........xxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxx.........ww......ww....wwwwwwwww.......xxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxx.........ww....wwww...wwwwwwwwww.....xxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxx.........ww....ww....wwwwwwwwwww...xxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxx........wwww.......wwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxx......wwwwwww....wwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxx...wwwwwwwwwwAwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxwwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: Geryon
+MONS: random, random, random, random, random, random
+
+#############################################################################
+# Dispater's castle - rest of level filled up with plan_4 (irregular city)
+#
+
+NAME: castle_dis
+PLACE: Dis:7
+TAGS: dis
+ORIENT: north
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvxxxxxxxx
+xxxxxxxxv..............................................................vxxxxxxxx
+xxxxxxxxv..vvvvvvvvv........................................vvvvvvvvv..vxxxxxxxx
+xxxxxxxxv..v3.....|v........................................v|.....2v..vxxxxxxxx
+xxxxxxxxv..v.vv+vvvv.v.v.v.v.v.v.v.v.v..v.v.v.v.v.v.v.v.v.v.vvvv+vv.v..vxxxxxxxx
+xxxxxxxxv..v.v.....vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv.....v.v..vxxxxxxxx
+xxxxxxxxv..v|v.....+$$v$$+$$v||vvvvvvvvvvvvvvvvv$$$$v4.4.v$$v.....v|v..vxxxxxxxx
+xxxxxxxxv..vvvv+vvvv$$+$$v$$+||v...............v$$$$+.4.4+$$v+vv+vvvv..vxxxxxxxx
+xxxxxxxxv....vv.vvvvvvvvvvvvvvvv.v..v..v..v..v.v$$$$v4.4.v$$+||v.vv5...vxxxxxxxx
+xxxxxxxxv...vvv................v...............vvvvvvvvvvvvvvvvv.vvv...vxxxxxxxx
+xxxxxxxxv...5vv................+...............+.................vv....vxxxxxxxx
+xxxxxxxxv...vvv+vvvvvvvvvvvvvvvv.v..v..v..v..v.vvvvvvvvvvvvvvvvv.vvv...vxxxxxxxx
+xxxxxxxxv....vv..v.+$$$$$v.....v...............vvvvvvvvvvvvvvvvv.vv5...vxxxxxxxx
+xxxxxxxxv...vvv..v.v$$$$$v.....v...............vv|$|$|vv|$|$|$vv.vvv...vxxxxxxxx
+xxxxxxxxv...5vv..v.vvvvvvv.....vvvvv.......vvvvvv$|$|$++$|$|$|vv.vv....vxxxxxxxx
+xxxxxxxxv...vvv..v...............v.vvvv+vvvvvvvvvvvvvvvvvvvvv+vv.vvv...vxxxxxxxx
+xxxxxxxxv....vvv+v..........vvvvv.4vvv...vvvvvvvvvvvvvvvvvvvv+vv.vv5...vxxxxxxxx
+xxxxxxxxv...vvv..v.v..v..v....2vvv+vv5...5vvvvvvv.4.4.vv.4.4.4vv.vvv...vxxxxxxxx
+xxxxxxxxv...5vv.................vv|vvv...vvvvv.++4.4.4++4.4.4.vv.vv....vxxxxxxxx
+xxxxxxxxv...vvv.................1vOvv5...5vvvv.vvvvvvvvvvvvvvvvv.vvv...vxxxxxxxx
+xxxxxxxxv....vv.................vv|vvv...vvvvv.vvvvvvvvvvvvvvvvv.vv5...vxxxxxxxx
+xxxxxxxxv...vvv.v..v..v..v....3vvv+vv5...5vvvv...................vvv...vxxxxxxxx
+xxxxxxxxv...5vv.............vvvvv.4vvv...vvvvvvvvvvvvvvvvvvvvvvv.vv....vxxxxxxxx
+xxxxxxxxv..vvvv+vvvv.............v.vv5...5vvvvvvvvvvvvvvvvvvvvvv+vvvv..vxxxxxxxx
+xxxxxxxxv..v|v.....vvvvvvvvvvvvvvvvvvv...vvvvvvvvvvvvvvvvvvvv.....v|v..vxxxxxxxx
+xxxxxxxxv..v.v.....vvvvvvvvvvvvvvvvvvvv+vvvvvvvvvvvvvvvvvvvvv.....v.v..vxxxxxxxx
+xxxxxxxxv..v.vv+vvvv5.............5.........5..............5vvvv+vv.v..vxxxxxxxx
+xxxxxxxxv..v2.....|v........................................v|.....3v..vxxxxxxxx
+xxxxxxxxv..vvvvvvvvv........................................vvvvvvvvv..vxxxxxxxx
+xxxxxxxxv............................{.[.(.............................vxxxxxxxx
+ENDMAP
+
+MONS: Dispater, Fiend, Ice Fiend, iron devil, metal gargoyle
+MONS: random, random
+
+#############################################################################
+# Asmodeus
+#
+
+NAME: asmodeus
+PLACE: Geh:7
+ORIENT: encompass
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxx....xxxxxxxxxxxxxxx.xxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxx............................xxxxxxxxxxxxxx..xxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxx..............................xxxxxxxxxx....xxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxx...xxx................................xxxxxx....xxxxxxxxxxx
+xxxxxxxxxxxx.x.xxxxx.........................................xxx....xxxxxxxxxxxx
+xxxxxxxxxxxx....xx.....................4......................xx...xxxxxxxxxxxxx
+xxxxxxxxxxx......x......................llllllllllllll.........x..xxxxxxxxxxxxxx
+xxxxxxxxxxx..xx..................lllllllllllllllllllllllll........xxxxxxxxxxxxxx
+xxxxxxxxxx...xxx....0..........llllllllllllllllllllllllll........xx...xxxxxxxxxx
+xxxxxxxxx....xxx.............llllllllllllllllllllllllllll..............xxxxxxxxx
+xxxxxxxxxx....xx...........lllllllllllllllllllllllllllll...............xxxxxxxxx
+xxxxxxxxxxxx..............llllllllllllllllllllllllllllll...2..xx...0...xxxxxxxxx
+xxxxxxxxxxxxx...........lllllllllllllllllll.......llllll......xx......xxxxxxxxxx
+xxxxxxxxxxxxxx.......llllllllllllllllll............llllll.............xxxxxxxxxx
+xxxxxxxxxxxxxxx......lllllllll..........4.........4.lllllll..........xxxxxxxxxxx
+xxxxxxxxxx...xx...ll3lllll......4...................llllllll......x.xxxxxxxxxxxx
+xxxxxxxxx.......lllll.l................................llll.......xxxxxxxxxxxxxx
+xxxxxxxxxx..4..llllll...cccccccc+c+c+c+c+c+c+c+c+c+c....lll......xxxxxxxxxxxxxxx
+xxxxxxxxxxx..lllllll..4.c.....c....................c....llll.....xxxxxxxxxxxxxxx
+xxxxxxxxxx...llllll.....c.V.V.+....0.....3.....0...c.....llll....x..xxxxxxxxxxxx
+xxxxxxxxx...llllll...l..c.....c....................c....lllll........xxxxxxxxxxx
+xxxxxxxxxx...lllll..ll..c..5..cccccccccccccccccccccc.4..llllll........xxxxxxxxxx
+xxxxxxxxx...lllll..llll.c.....c...............c....c....lllllll.......xxxxxxxxxx
+xxxxxxxxx...lllll..llll.c.V.V.c.......0.......c....c....lllllll.......xxxxxxxxxx
+xxxxxxxxxx...lllll..lll.c.....+...............+....c...lllllll........xxxxxxxxxx
+xxxxxxxxxxx..lllll...ll.cccccccccc....0.......c....c...llllllll........xxxxxxxxx
+xxxxxxxxxx...lllll..4...c|$$||$$|c............c.0..c...llllllll........xxxxxxxxx
+xxxxxxxxx...lllll.......c$$$$$$$$cccccccccccccc....c...lllllll.........xxxxxxxxx
+xxxxxxxxx...lllll.......c$$|2|$$|c..0.........+....c...lllllll........xxxxxxxxxx
+xxxxxxxxxx.lllllll......c|$$$$$$$c........9...c....c....llllllll.....xxxxxxxxxxx
+xxxxxxxxxx.lllllll......c$|$|$$|$c+ccccccccccccccccc....lllllll......xxxxxxxxxxx
+xxxxxxxxxx..llllll......cccccccc+c.....9.......c.........llllll......x.xxxxxxxxx
+xxxxxxxxxx..lllllll.....c$$$$$$+3c.....8...3...c.....4...llllll........xxxxxxxxx
+xxxxxxxxxx..llllllll....c$$$$$$c.c.....9.......c..ll....llllll.........xxxxxxxxx
+xxxxxxxxxx...llllll..4..c$$2$$$c.ccccccccccccc+c.lll...lllllll...0....xxxxxxxxxx
+xxxxxxxxxxx..llllll.....c$$$$$$c..+............c.ll...lllllll..........xxxxxxxxx
+xxxxxxxxxxx..llllllll...ccccccccc+cccccccccccccc.....lllllll...........xxxxxxxxx
+xxxxxxxxxxxx..llllllll.........cc..........cc........lllllll.......x..xxxxxxxxxx
+xxxxxxxxxxxxx.llllllllll.......ccc.........cc......lllllllll.......xxxxxxxxxxxxx
+xxxxxxxxxx....lllllllllll...4...cc.....2.2.cc....llllllllll.4.......xxxxxxxxxxxx
+xxxxxxxxx....4.lllllllllllll....cccccccc+cccc..lllllllllll.....xx....xxxxxxxxxxx
+xxxxxxxxxx.....llllllllllllll...cccccccc+cccc..llllllllll......xx....xxxxxxxxxxx
+xxxxxxxxxxx.....lllllllllllllll..cc......cc...lllllllllll...........xxxxxxxxxxxx
+xxxxxxxxxxx.....llllllllllllll...ccO1....cc.4..lllllllll...........xxxxxxxxxxxxx
+xxxxxxxxxxxx.....lllllllllllll...cc......cc....lllllllll.......xx.xxxxxxxxxxxxxx
+xxxxxxxxxxxx.......llllllllllll..cccccccccc...lllllllll........xxxxxxxxxxxxxxxxx
+xxxxxxxxx.........llllllllllllll.cccccccccc.lllllllllll.......xxxxxxxxxxxxxxxxxx
+xxxxxxxxxx....0...llllllllllllll............lllllllll....0....xxxxxxxxxxxxxxxxxx
+xxxxxxxxxx.......4.lllllllllllllll..4....lllllllll...........xxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx..........llllllllllllll....lllllll....4.....x........xxxxxxxxxxxxxxx
+xxxxxxxxxxx...xx.........lllllllllllllllll...................xx{xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxx..xx................lllllll.....................xxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxx.........xxx.................xxxxxx......xxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxx....xxxxxxxx...xxx......xxxxxxxxxx.......xxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxx(xxxxxxxxxxxx[xxxxx...xxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: Asmodeus, Fiend, Balrug, molten gargoyle
+MONS: Serpent of Hell, random, random
+
+############################################################################
+# Antaeus; bottom of Cocytus. This needs work.
+#
+
+NAME: antaeus
+PLACE: Coc:7
+ORIENT: encompass
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxx........................xxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxx..........................xxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxx............................xxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxx..............................xxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxx................................xxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxx....cccccccccccc..cccccccccccc....xxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxx....ccccccccccccc2.ccccccccccccc....xxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxx....cc..........................cc....xxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxx....cc............................cc....xxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxx....cc...wwwwwwwwwwwwwwwwwwwwwwww...cc....xxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxx....cc...wwwwwwwwwwwwwwwwwwwwwwwwww...cc....xxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxx....cc...wwwwwwwwwwwwwwwwwwwwwwwwwwww...cc....xxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx....cc...ww.......3..........3.......ww...cc....xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxx....cc...ww............................ww...cc....xxxxxxxxxxxxxxx
+xxxxxxxxxxxxxx....cc...ww....cccccccccccccccccccccc....ww...cc....xxxxxxxxxxxxxx
+xxxxxxxxxxxxx....cc...ww....cccccccccccccccccccccccc....ww...cc....xxxxxxxxxxxxx
+xxxxxxxxxxxx....cc...ww....cc......................cc....ww...cc....xxxxxxxxxxxx
+xxxxxxxxxxx....cc...ww....cc...T................T...cc....ww...cc....xxxxxxxxxxx
+xxxxxxxxxx....cc...ww....cc..........wwwwww..........cc....ww...cc....xxxxxxxxxx
+xxxxxxxxx....cc...ww....cc.......wwwwwwwwwwwwww.......cc....ww...cc....xxxxxxxxx
+xxxxxxxxx....cc...ww...cc.....wwwwwwwwwwwwwwwwwwww.....cc...ww...cc....xxxxxxxxx
+xxxxxxxxx....cc..www..cc....wwwwwwwwwccccccwwwwwwwww....cc..www..cc....xxxxxxxxx
+xxxxxxxxx....cc..www.cc....wwwwwwwwccc2O12cccwwwwwwww....cc.www..cc....xxxxxxxxx
+xxxxxxxxx....cc..www.cc...wwwwwwwwcc2+....+2ccwwwwwwww...cc.www..cc....xxxxxxxxx
+xxxxxxxxx....cc..www.cc...wwwwwwwwcc+cc++cc+ccwwwwwwww...cc.www..cc....xxxxxxxxx
+xxxxxxxxx....cc..www..c..wwwwwwwwwc|||c..c$$$cwwwwwwwww..c..www..cc....xxxxxxxxx
+xxxxxxxxx....cc..wwww.c.wwwwwwwwwwc|||c..c$$$cwwwwwwwwww.c.wwww..cc....xxxxxxxxx
+xxxxxxxxx....cc..wwww.c.wwwwwwwwwwcc||c..c$$ccwwwwwwwwww.c.wwww..cc....xxxxxxxxx
+xxxxxxxxx....cc..wwww.c.wwwwwwwwwwwcccc++ccccwwwwwwwwwww.c.wwww..cc....xxxxxxxxx
+xxxxxxxxx....cc..www..c..wwwwwwwwwwwwww..wwwwwwwwwwwwww..c..www..cc....xxxxxxxxx
+xxxxxxxxx....cc..www.cc...wwwwwwwwwwwwwwwwwwwwwwwwwwww...cc.www..cc....xxxxxxxxx
+xxxxxxxxx....cc..www.cc....wwwwwwwwwwwwwwwwwwwwwwwwwww...cc.www..cc....xxxxxxxxx
+xxxxxxxxx....cc..www.cc....wwwwwwwwwwwwwwwwwwwwwwwwww....cc.www..cc....xxxxxxxxx
+xxxxxxxxx....cc..www..cc....wwwwwwwwwwwwwwwwwwwwwwww....cc..www..cc....xxxxxxxxx
+xxxxxxxxx....cc...ww...cc.....wwwwwwwwwwwwwwwwwwww.....cc...ww...cc....xxxxxxxxx
+xxxxxxxxx....cc...ww....cc.......wwwwwwwwwwwwww.......cc....ww...cc....xxxxxxxxx
+xxxxxxxxxx....cc...ww....cc..........wwwwww..........cc....ww...cc....xxxxxxxxxx
+xxxxxxxxxxx....cc...ww....cc...T................T...cc....ww...cc....xxxxxxxxxxx
+xxxxxxxxxxxx....cc...ww....cc......................cc....ww...cc....xxxxxxxxxxxx
+xxxxxxxxxxxxx....cc...ww....ccccccccccc..ccccccccccc....ww...cc....xxxxxxxxxxxxx
+xxxxxxxxxxxxxx....cc...ww....cccccccccc2.cccccccccc....ww...cc....xxxxxxxxxxxxxx
+xxxxxxxxxxxxxxx....cc...ww............................ww...cc....xxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx....cc...ww..........................ww...cc....xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxx....cc...wwwwwwwwwwwww..wwwwwwwwwwwww...cc....xxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxx....cc...wwwwwwwwwwww..wwwwwwwwwwww...cc....xxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxx....cc...wwwwwwwwwww..wwwwwwwwwww...cc....xxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxx....cc............................cc....xxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxx....cc..........................cc....xxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxx....cccccccccccccccccccccccccccc....xxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxx....cccccccccccccccccccccccccc....xxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxx................................xxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxx..............................xxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxx............................xxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxx..........{.(.[...........xxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: Antaeus, Ice Fiend, ice dragon
+MONS: random, random, random, random
+
+##############################################################################
+# Ereshkigal (Tartarus)
+#
+
+NAME: ereshkigal
+PLACE: Tar:7
+ORIENT: encompass
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx.................cccc..........ccc............................xxxxxxxxx
+xxxxxxxxx.............ccccc..cccc.....ccc.cccc.........................xxxxxxxxx
+xxxxxxxxx...........ccc.........ccccccc.....cc.........................xxxxxxxxx
+xxxxxxxxx.........ccc.......2............V..cc.........................xxxxxxxxx
+xxxxxxxxx........cc4........................cc...........xxxxxxxx......xxxxxxxxx
+xxxxxxxxx........cc44xxx==xxx...............cc..........xx......xx.....xxxxxxxxx
+xxxxxxxxx........ccxxx......xxx.......ccc++ccc.........xx........xx....xxxxxxxxx
+xxxxxxxxx........cxx..........xxx.....ccc44ccc.........x..........x....xxxxxxxxx
+xxxxxxxxx........cx............xx....cccc44cc.........xx..........xx...xxxxxxxxx
+xxxxxxxxx.......ccx.G........G.xxx7ccc..c44c..........x.....|......x...xxxxxxxxx
+xxxxxxxxx.......cxx............xxxcc..................x......7.....x...xxxxxxxxx
+xxxxxxxxx......ccx..............xxc...................xx..........xx...xxxxxxxxx
+xxxxxxxxx......ccx..G........G..xxc..x.........x.......x..........x....xxxxxxxxx
+xxxxxxxxx......ccx..............xcc....................xx........xx....xxxxxxxxx
+xxxxxxxxx.......cxx............xxc......................xx......xx.....xxxxxxxxx
+xxxxxxxxx.......ccx.F........F.xcc.......................xxxxxxxx......xxxxxxxxx
+xxxxxxxxx........cx............xc......................................xxxxxxxxx
+xxxxxxxxx........cxx....17....xxc....x.........x.......................xxxxxxxxx
+xxxxxxxxx........ccxxx......xxxcc......................................xxxxxxxxx
+xxxxxxxxx........cccc=xxxxxx=cccc......................................xxxxxxxxx
+xxxxxxxxx........cc||cccccccc||cc......................................xxxxxxxxx
+xxxxxxxxx.........cc||||O|||||cc.......................................xxxxxxxxx
+xxxxxxxxx..........cccccccccccc......x.........x............V..........xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx...........................................xxxxxxxxxxxxxxxx...xxxxxxxxx
+xxxxxxxxx...........................................xxxxxxxxxxxxxxxx...xxxxxxxxx
+xxxxxxxxx...........................................xx$$$$xxx|||||xx...xxxxxxxxx
+xxxxxxxxx.......V........V...........x.........x....xx$$$$xxx|||||xx...xxxxxxxxx
+xxxxxxxxx...........................................xxxxxxxxxxxxxxxx...xxxxxxxxx
+xxxxxxxxx...........................................xxxxxxxxxxxxxxxx...xxxxxxxxx
+xxxxxxxxx...........................................xx44444xx22222xx...xxxxxxxxx
+xxxxxxxxx.......xxxxxxxxx+xxxxxxxxx.................xx44444xx22222xx...xxxxxxxxx
+xxxxxxxxx.......x3.2..........3...x..x.........x..xxxxxxxxxxxxxxxxxx...xxxxxxxxx
+xxxxxxxxx.......x.x.x.x.x.x.x.x.x.x.................xxxxxxxxxxxxxxxx...xxxxxxxxx
+xxxxxxxxx.......x...2.3..4..5..4..x......................=.......xxx...xxxxxxxxx
+xxxxxxxxx.......xx.x.x.x.x.x.x.x.xx......................=.......xxx...xxxxxxxxx
+xxxxxxxxx.......x..65..3..6.6...5.x.................xxxxxxxxxxxxxxxx...xxxxxxxxx
+xxxxxxxxx.......x.x.x.x.x.x.x.x.x.x..x.........x..xxxxxxxxxxxxxxxxxx...xxxxxxxxx
+xxxxxxxxx.......x...4...3.....4...x.................xx.....xx555555x...xxxxxxxxx
+xxxxxxxxx.......xx=xxxxx.x.xxxxxxxx.................xx.....xx555555x...xxxxxxxxx
+xxxxxxxxx.......x$$$$$$x.25.x$$$||x.................xxxxxxxxxxxxxxxx...xxxxxxxxx
+xxxxxxxxx.......x$x$$x$xx.x.x$x$x|x.................xxxxxxxxxxxxxxxx...xxxxxxxxx
+xxxxxxxxx.......x||||||x.556=$$$||x..x.........x....xx$$xx56565xx$|x...xxxxxxxxx
+xxxxxxxxx.......xxxxxxxxxxxxxxxxxxx.................xx$$xx65656xx|7x...xxxxxxxxx
+xxxxxxxxx...........................................xxxxxxxxxxxxxxxx...xxxxxxxxx
+xxxxxxxxx...........................................xxxxxxxxxxxxxxxx...xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx........(...........................................[.........xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx..............................{...............................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: Ereshkigal, necrophage, wraith, shadow, small zombie
+MONS: small skeleton, Shadow Fiend
+
+
+###########################################################################
+# mnoleg.
+#
+# NOTE: The Pandemonium demonlord levels are requested by tag; if you change
+# the tag, also update dungeon.cc.
+#
+# You can define alternate levels for a Pandemonium lord by using the same
+# TAGS: and a different NAME:
+#
+
+NAME: mnoleg
+TAGS: mnoleg
+ORIENT: northeast
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+x.................2............xxxxxxxxx
+x.....2........................xxxxxxxxx
+x..cccccccc...ccccccc..ccccccc.xxxxxxxxx
+x..ccccccccc.2.ccccccc..cccccc.xxxxxxxxx
+x..cccccccccc...ccccccc..ccccc.xxxxxxxxx
+x..ccccccccccc.1.ccccccc..cccc.xxxxxxxxx
+x2.cccccccccc.2..Occccccc2.ccc.xxxxxxxxx
+x..ccccccccc.....ccccccccc..cc.xxxxxxxxx
+x..cccccccc...c...ccccccccc..c.xxxxxxxxx
+x..ccccccc...ccc...ccccccccc...xxxxxxxxx
+x..cccccc...ccccc...ccccccccc..xxxxxxxxx
+x..ccccc...ccccccc...ccccccccc.xxxxxxxxx
+x..cccc...ccccccccc...ccccccc..xxxxxxxxx
+x..ccc.2.ccccccccccc.2.ccccc...xxxxxxxxx
+x..cc.....ccccccccccc...ccc....xxxxxxxxx
+x..c...c...ccccccccccc...c.2...xxxxxxxxx
+x.....ccc.2.ccccccccccc......c.xxxxxxxxx
+x....ccccc...ccccccccccc....cc.xxxxxxxxx
+x.2.ccccccc...ccccccccccc..ccc.xxxxxxxxx
+x.................2.......cccc.xxxxxxxxx
+x...c..ccccccc.ccccccc...ccccc.xxxxxxxxx
+x..ccc......2c.c2cccc...cccccc.xxxxxxxxx
+x.ccccc..ccc.c.c2ccc.2.ccccccc.xxxxxxxxx
+x.cccccc..cc.c.c.cc...cccccccc.xxxxxxxxx
+x.ccccccc..c.c.c.c...ccccccccc.xxxxxxxxx
+x.cccccccc...c.c....cccccccccc.xxxxxxxxx
+x.ccccccccc..c.c...ccccccccccc.xxxxxxxxx
+x..............................xxxxxxxxx
+xxxxxxxxxxxxxx@xxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: Mnoleg, neqoxec
+MONS: random, random, random, random, random
+
+#######################################################################
+# lom_lobon
+#
+
+NAME: lom_lobon
+TAGS: lom_lobon
+ORIENT: north
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxwwwwwwwwwwww.......wwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxwwwwwwwwwwwwbbbwwwwwww.......wwwwwwwxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxwwwwwwwwwwwwbbbbbbbbbbbwwwwww.........wwwwwwxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxwwwwwwwwwwwwbbbbwwwwwwwwwbbbbwwwwww.........wwwwwwxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxwwwwwwwbbbbbbbbwwwwwwwwwwwwwwwbbbwwwww...........wwwwwxxxxxxxxxxxxx
+xxxxxxxxxxxxwwwwwbbbb......bbbwwwwwwwwwwww...bbwwwww.............wwwxxxxxxxxxxxx
+xxxxxxxxxxxxwwwbbb...........bbbwwwwww........bbwwwww.............wwxxxxxxxxxxxx
+xxxxxxxxxxxwwwbb...............bbwwww..........bwwwwww.............wwxxxxxxxxxxx
+xxxxxxxxxxxwwbb........1O.......bbww...........bbwwww..............wwxxxxxxxxxxx
+xxxxxxxxxxwwwb...................bw......2......bwww.....U....2.....wwxxxxxxxxxx
+xxxxxxxxxxwwbb...................bb.............bww.................wwxxxxxxxxxx
+xxxxxxxxxxwwbb..3................bbb............bbw..............4..wwxxxxxxxxxx
+xxxxxxxxxwwbbb...................b.b............4....................wwxxxxxxxxx
+xxxxxxxxxwwbwbb.................bb.......U......4..........U..........wxxxxxxxxx
+xxxxxxxxxwwbwwbb...............bb..b............bbw..............4.....xxxxxxxxx
+xxxxxxxxxwwbbwwbbb...........bbb..bb............bwww...................xxxxxxxxx
+xxxxxxxxxwwwbwwwwb..b..2..bbbb....b.............bwww...................xxxxxxxxx
+xxxxxxxxxxwwbwwww...bbbbbbb.......bw.....3.....bbwwww...U.....3.......xxxxxxxxxx
+xxxxxxxxxxwwbbww.................bbww........wwbwwwww.................xxxxxxxxxx
+xxxxxxxxxxwwwbbw................bbwwwww....wwwbbwwww..................xxxxxxxxxx
+xxxxxxxxxxwwwwbb...4...U........bwwwwwwwwwwwwbbwww....................xxxxxxxxxx
+xxxxxxxxxxxwwwwbbb...........bbbbbwwwwwwwwwbbbwww....................xxxxxxxxxxx
+xxxxxxxxxxxwwwwwwbbbb.....bbbbwwwbbbbwwwbbbbwwww....................xxxxxxxxxxxx
+xxxxxxxxxxxwwwwwwwwwbbbbbbbwwwwwwwwwbbbbbwwwww......4.....4........xxxxxxxxxxxxx
+xxxxxxxxxxxxwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww......................xxxxxxxxxxxxxx
+xxxxxxxxxxxxwwwwwwwwwwwwwwwwwwwwwwwwwwwww.......................xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxwwwwwwwwwwwwwwwwwwwww........................xxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxwwwwwww......................xxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...@.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: Lom Lobon, giant orange brain, rakshasa, wizard
+MONS: random, random, random
+
+#############################################################################
+# cerebov
+
+NAME: cerebov
+TAGS: cerebov
+ORIENT: northeast
+
+# you might not want to teleport too much on this level - unless you can
+# reliably teleport away again.
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+...............................xxxxxxxxx
+.............vvvvv.............xxxxxxxxx
+.............v$$$v.............xxxxxxxxx
+.............v|||v.............xxxxxxxxx
+.............v$$$v.............xxxxxxxxx
+.vvvvv...vvvvvvvvvvvvv...vvvvv.xxxxxxxxx
+.v|$|vvvvv...........vvvvv$|$v.xxxxxxxxx
+.v$|$v.....vvvvvvvvv.....v|$|v.xxxxxxxxx
+.v|$|v.vvvvvvvvOvvvvvvvv.v$|$v.xxxxxxxxx
+.vvvvv.vvvvvv..3..vvvvvv.vvvvv.xxxxxxxxx
+...v...vv.....vvv.....vv...v...xxxxxxxxx
+...v.vvvv....vv1vv....vvvv.v...xxxxxxxxx
+...v.vv......v...v......vv.v...xxxxxxxxx
+...v.vvvv.............vvvv.v...xxxxxxxxx
+...v...vv..2.......2..vv...v...xxxxxxxxx
+.vvvvv.vv..2.......2..vv.vvvvv.xxxxxxxxx
+.v|$|v.vv.............vv.v$|$v.xxxxxxxxx
+.v|$|v.vv...vv...vv...vv.v$|$v.xxxxxxxxx
+.v|$|v.vv...vv+++vv...vv.v$|$v.xxxxxxxxx
+.vvvvv.vvvvvvv...vvvvvvv.vvvvv.xxxxxxxxx
+....v..vvvvvvv...vvvvvvv..v....xxxxxxxxx
+....vv...................vv....xxxxxxxxx
+.....vv.vvvvv..2..vvvvv.vv.....xxxxxxxxx
+......vvv|||v.....v$$$vvv......xxxxxxxxx
+........v|$|vv...vv$|$v........xxxxxxxxx
+........v|||v.....v$$$v........xxxxxxxxx
+........vvvvv.....vvvvv........xxxxxxxxx
+...............................xxxxxxxxx
+...............@...............xxxxxxxxx
+ENDMAP
+
+MONS: Cerebov, Balrug, Pit Fiend
+MONS: random, random, random, random
+
+
+##############################################################################
+# Gloorx Vloq
+
+NAME: gloorx_vloq
+TAGS: gloorx_vloq
+ORIENT: southwest
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxx@.xxxxxxxxxxxxxxx
+xxxxxxxxx..............................x
+xxxxxxxxx..............................x
+xxxxxxxxx..............................x
+xxxxxxxxx.x.x.x.x.x.x.x..x.x.x.x.x.x.x.x
+xxxxxxxxx..............................x
+xxxxxxxxx.x.xxxx=xxxxxxxxxxxx=xxxxxx.x.x
+xxxxxxxxx...xx....................xx...x
+xxxxxxxxx.x.x..ccccc..4..4..ccccc..x.x.x
+xxxxxxxxx...x.cc.3............3.cc.x...x
+xxxxxxxxx.x.x.c..ccccc.cc.ccccc..c.x.x.x
+xxxxxxxxx...x.c.cc.....cc.....cc.c.x...x
+xxxxxxxxx.x.x.c.c.2...cccc...2.c.c.x.x.x
+xxxxxxxxx...x...c...ccc..ccc...c...=...x
+xxxxxxxxx.x.x.3.....2..1O..2.....3.x.x.x
+xxxxxxxxx...=...c...ccc..ccc...c...x...x
+xxxxxxxxx.x.x.c.c.2...cccc...2.c.c.x.x.x
+xxxxxxxxx...x.c.cc.....cc.....cc.c.x...x
+xxxxxxxxx.x.x.c..ccccc.cc.ccccc..c.x.x.x
+xxxxxxxxx...x.cc.3............3.cc.x...x
+xxxxxxxxx.x.x..ccccc..4..4..ccccc..=.x.x
+xxxxxxxxx...xx....................xx...x
+xxxxxxxxx.x.xxxx=xxxx=xxxxxxxx=xxxxx.x.x
+xxxxxxxxx..............................x
+xxxxxxxxx.x.x.x.x.x.x.x..x.x.x.x.x.x.x.x
+xxxxxxxxx..............................x
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: Gloorx Vloq, Executioner, demonic crawler, shadow demon
+MONS: random, random, random
+
+############################################################################
+# Hive:4 beehive
+
+NAME: beehive
+PLACE: Hive:4
+ORIENT: encompass
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxaaaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxaaaaaaaaaaaRaaaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxaaaaaaaaaaRa2aaR1RaaRa2aaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxaaaaaaaaaaRa2a3R3aRaRaRaaaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxaaaaRaRaRaaa3aaa3aRa.a.aaaaaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxaaaaaaRa.aRa2a2a2a2aRaRa.a.a3aaaaaaaaaaaaaaxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxx4aaaaaaaaa.aaRaRaa2aa2aaRaaa.aa3a33aaaaaaaaaa.44xxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx.4aaaaaaa.222a3a.aaaRaaa.aaa.R3aa3a3aaaaaaaa.....4xxxxxxxxxxxxxxxxxxx
+xxxxxxxxxx....aaaaaaa.aRa.a3aRaRa.a3a.a.a.a.aRa2aaaaaa....xxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx...aaaaaa3a3a.a.a.a3aRa2aRa3a.a.aRaRa.aaaaa...xxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxx...aa2aRa3a3a3aRa.a3a.a.a.a.a.a.a.a3a.aaa...xxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxx...aaa.a.a.a2a.aaa.aRaRa2a.a2a3a.a2aaaa..T..xxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx.....a2a.a2a.aRaaaaa3a.a.aaa3a3a3a3a.a.........xxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx.4...aaRRaa.a2a.a3a3a3a.aaa.a.aRa.a.aa..4.......xxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxx......a.a.aaa.a3a.a.a.a.aaa2a.a2a.a.aRaa.....4...xxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxx.....aa3a2aaa.a.a.a3a3a3a3aRaaa.a2a.a2aa........xxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx...aaaa.a2aRa.a.a2aaa.a.a.a.aaa.a.aaaa.....xxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxx..aaa.a.a.a.a.a.a.aaa2a.a3a2a.a2aaa.....xxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxx.aaaa3a.a2aRa.a.aaaRa.a.aa.a.aaa....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxx...aaaaRa.a3a3a.a.a.aaa.aa.aa....4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxx........aa.a2a.a.aaa2aa.aa.aaa....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxx....4.....a.a2a2a.a2a.a2a.......4.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx.............a.a.a.a.a.a.....4....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxx..............4..a.a.a......4...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxx.................a.a.........xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx........................xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx.....4...T............xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx.......................xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxx.........................xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxx.................T.........xxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxx.......4.....................xxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx..............xx...............xxxxxx....xxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx............xxxxx........4......xxxx..4....xxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx..T..........xxx................xxxxx...T.xxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx............xxx........T.........xxx........xxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx....4........xx....................x..........xxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxx...............x.x...xxx...............xx.xxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxx.........4...........xxx..................xxxxxxxxxxxxxxxxxxaaaaaxxxxx
+xxxxxxxxx.....4.....................4......4...........4...xxxxxxxxxxaa5a5aaxxxx
+xxxxxxxxx.................................................wwwwwwwwxxxa5*|*5axxxx
+xxxxxxxxx............x...x...T.....xxxx.................wwwwwwwwwwwwxaa*|*aaxxxx
+xxxxxxxxxx.........xx.............xxxxx................wwwwwwwwwwwwwwxaa5aaxxxxx
+xxxxxxxxxxx.......x..................xxx....4..........wwwwwwwwwwwwwwwxa5axxxxxx
+xxxxxxxxxxx.....xxx...4...........................xxxx.4wwwwwwwwwwwwwwwa=axxxxxx
+xxxxxxxxxxxx..xxx.............xx....(.........xxxxxxxx....wwwwwwwwwwwwwwaaxxxxxx
+xxxxxxxxxxxxxxxx.............xxxx..................xxxx......wwwwwwwwwwxxxxxxxxx
+xxxxxxxxxxxxxxxxx....{..}..xxxxxx..]......xxx...........4.wwwwwwwwwwwwxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxx........xxx........xxxxxx....4....wwwwwwwwwwwwwwxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxx..[.xxx........xxx)....wwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxx.........xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: queen bee, killer bee, killer bee larva, plant, yellow wasp
+MONS: random, random
+
+############################################################################
+# Vault:8 last level of the vaults -- dungeon.cc will change all these 'x's
+#
+
+NAME: vaults_vault
+PLACE: Vault:8
+ORIENT: encompass
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxxxx....xxxxxxxxxxxxxxxxxxxxxxxxxxx..xxxxxxxxx
+xxxxxxxxx..x.........................x....xxxxxxxxxxxxxxxxxxxxxxxxxxx..xxxxxxxxx
+xxxxxxxxx..x.xxxxxxxxxxx..xxxxxxxxxx.x....xxxxx.................xxxxx..xxxxxxxxx
+xxxxxxxxx..x.x*.*.*.*.*x..x........x.x....xxx..........8..........xxx..xxxxxxxxx
+xxxxxxxxx..x.x.*.*.*.*.x..x........x.x....xxx.....................xxx..xxxxxxxxx
+xxxxxxxxx..x.x*.*.*.*.*x..x...||...x.x....xx......9........9.......xx..xxxxxxxxx
+xxxxxxxxx..x.x.*.*.*.*.x..x...||...x.x....xx.......................xx..xxxxxxxxx
+xxxxxxxxx..x.x*.*.*.*.*x..x...||...x.x....xx......xxxxxxxxxxx......xx..xxxxxxxxx
+xxxxxxxxx..x.x.*.*.*.*.x..x........x.x....xx......x.........x......xx..xxxxxxxxx
+xxxxxxxxx..x.x*.*.*.*.*+..+........x.x....xx....xxx..........xx....xx..xxxxxxxxx
+xxxxxxxxx..x.x.*.*.*.*.xxxxxxxxxxxxx.x....xx.9..x....xxxxx....x..8.xx..xxxxxxxxx
+xxxxxxxxx..x.xxxxxxxxxxx9998.........x....xx....x...xx$$$xx...x....xx..xxxxxxxxx
+xxxxxxxxx..x...........899xxxxxxxxxx.x....xx....x..xx$***$xx..x....xx..xxxxxxxxx
+xxxxxxxxx..x.xxxxxxxxxxx99x........x.x....xx....x..x$$*|*$$x..x....xx..xxxxxxxxx
+xxxxxxxxx..x.x.....|...x88x.$$$$$$.x.x....xx..8.x..xx$***$xx..x....xx..xxxxxxxxx
+xxxxxxxxx..x.x.|..|..|.x..x.$$$$$$.x.x....xx....x....x$$$xx...x..9.xx..xxxxxxxxx
+xxxxxxxxx..x.x.........x..x.$$$$$$.x.x....xx....xxx..xxxxx..xxx....xx..xxxxxxxxx
+xxxxxxxxx..x.x.|..|..|.x..x.$$$$$$.x.x....xx......x.........x......xx..xxxxxxxxx
+xxxxxxxxx..x.x.........x..x.$$$$$$.x.x....xx......xxxxxxxxxxx......xx..xxxxxxxxx
+xxxxxxxxx..x.x|..|..|..x..x.$$$$$$.x.x....xxx.....................xxx..xxxxxxxxx
+xxxxxxxxx..x.x.........x..+........x.x....xxx......9.........9....xxx..xxxxxxxxx
+xxxxxxxxx..x.xxxxxxxxx+x..xxxxxxxxxx.xx.11....xx................xxxxx..xxxxxxxxx
+xxxxxxxxx..x...........x..x...........x1111...xxxxxxxxxxxxxxxxxxxxxxx..xxxxxxxxx
+xxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxx..1....1..xxxxxxxxxxxxxxxxxxxxxxx..xxxxxxxxx
+xxxxxxxxx..........................xx1..(}..1..........................xxxxxxxxx
+xxxxxxxxx...........................11.[..{.11.........................xxxxxxxxx
+xxxxxxxxx............................1..])..1..........................xxxxxxxxx
+xxxxxxxxx.............................1....1...........................xxxxxxxxx
+xxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxx.....1111..x.xxx.xxxxxxxxxxxxxxxxxx..xxxxxxxxx
+xxxxxxxxx..xx.x.x.x.x.x.x.x.x.x.x.x.....11..........................x..xxxxxxxxx
+xxxxxxxxx..x.x.x.x.x.x.x.x|x.x.x.x.x................................x..xxxxxxxxx
+xxxxxxxxx..xx.x|x.x.x.x.x.x.x.x.x.x.x.....x.........................x..xxxxxxxxx
+xxxxxxxxx..x.x.x.x.x.x.x.x9x.x.x.x.x.x..........8..........9........x..xxxxxxxxx
+xxxxxxxxx..xx.x.x.x.x.x.x.x.x.x.x.x.xx....x..9......................x..xxxxxxxxx
+xxxxxxxxx..x.x.x.x.x.x.x.x.x.x|x.x.x.x....x.........................x..xxxxxxxxx
+xxxxxxxxx..xx.x8x.x.x|x.x.x.x.x.x.x.xx....x..............9...9......x..xxxxxxxxx
+xxxxxxxxx..x.x.x.x.x9x.x.x.x.x.x.x.x.x...........8..................x..xxxxxxxxx
+xxxxxxxxx..xx.x.x.x.x.x.x.x.x.x.x.x.xx....x..9......................x..xxxxxxxxx
+xxxxxxxxx..x.x.x.x.x.x.x.x.x|x.x9x.x.x....x.........................x..xxxxxxxxx
+xxxxxxxxx..xx.x.x.x.x.x.x.x.x.x.x.x.xx....x...................9.....x..xxxxxxxxx
+xxxxxxxxx..x.x.x9x.x.x.x.x.x.x.x.x.x.x....x....9......8.............x..xxxxxxxxx
+xxxxxxxxx..xx.x.x.x.x.x.x9x.x.x.x.x.xx....x.........................x..xxxxxxxxx
+xxxxxxxxx..x.x.x.x.x.x.x.x.x.x.x.x.x.x....x.........................x..xxxxxxxxx
+xxxxxxxxx..xx.x.x.x.x.x.x.x.x.x.x.x.xx....x.......9......9..........x..xxxxxxxxx
+xxxxxxxxx..x.x.x.x.x.x.x.x.x.x8x.x.x.x....x.....................8...x..xxxxxxxxx
+xxxxxxxxx..xx.x8x.x.x.x.x.x.x.x.x.x.xx....x.....................||.|x..xxxxxxxxx
+xxxxxxxxx..x.x|x.x.x.x.x.x.x|x.x.x.x.x....x.....................|...x..xxxxxxxxx
+xxxxxxxxx..xx.x.x.x.x.x.x8x.x.x.x.x.xx....x......8..................x..xxxxxxxxx
+xxxxxxxxx..x.x.x.x.x.x.x.x.x.x.x.x.x.x....x..........8..8...8.....||x..xxxxxxxxx
+xxxxxxxxx..xO.x.x.x.x.x.x.x.x.x.x|x.xx....x.....................|.||x..xxxxxxxxx
+xxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxxxx....xxxxxxxxxxxxxxxxxxxxxxxxxxx..xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: vault guard
+MONS: random, random, random, random, random, random
+
+############################################################################
+# snake_pit
+
+NAME: snake_pit
+PLACE: Snake:5
+ORIENT: southwest
+
+# Rotation makes this look really bad if the console font is not square.
+FLAGS: no_rotate
+
+# Hey, this looks a bit like a face ...
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxx..@.xxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxx.............xxxxxxxx
+xxxxxxxxxxxxxx....x.............x..xxxxx
+xxxxxxxxxxxx....2.x.............x.2..xxx
+xxxxxxxxxxx.....2.x....x.....x..x..3.xxx
+xxxxxxxxxxx.....22x.............xx.2..xx
+xxxxxxxxxxx.......xx..x........xx..3..xx
+xxxxxxxxxx.....x23.xx....T...xxx.44...xx
+xxxxxxxxxx......4.4.x.........x.333....x
+xxxxxxxxxx......3.x4...x.......4x4.....x
+xxxxxxxxxx.......3.......x.............x
+xxxxxxxxxx..c......3.........x.......c.x
+xxxxxxxxx...cc...................3..cc.x
+xxxxxxxxx...cc..........4.4.........cc.x
+xxxxxxxxx...cc...3...x........2.....cc.x
+xxxxxxxxx...cc.........1...1.......cc..x
+xxxxxxxxxx..cc.....1.....1.....1..ccc.xx
+xxxxxxxxxx...ccc..................cc..xx
+xxxxxxxxxx....cccc....3333333.....cc..xx
+xxxxxxxxxx.....ccccccc...........cc...xx
+xxxxxxxxxx........cccccccO...ccccc....xx
+xxxxxxxxxxx........cccccccccccccc....xxx
+xxxxxxxxxxx.........cccccccccccc.....xxx
+xxxxxxxxxxxxx.......................xxxx
+xxxxxxxxxxxxxxxx..................xxxxxx
+xxxxxxxxxxxxxxxxxxxxx.......xxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: greater naga, naga, naga mage, naga warrior
+MONS: random, random, random
+
+############################################################################
+# elf_hall
+
+NAME: elf_hall
+PLACE: Elf:7
+ORIENT: northwest
+FLAGS: no_rotate
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxcccccccccccccccccxxxxx
+xxxxxxxxxxxxxxxxxcc*|*|*|**|||||c$ccxxxx
+xxxxxxxxxxxxxxxxcc*$*|*|*|*|||||c$$ccxxx
+xxxxxxxxxxxxxxxcc*$|*$***$$|||||c|$$ccxx
+xxxxxxxxxxxxxxcc*$*|**ccccccccccc$$$$ccx
+xxxxxxxxxxxxxxc*|*$*$ccc.....2..c+$|$$cx
+xxxxxxxxxxxxxxc$*$*ccc...........c$$$$cx
+xxxxxxxxxxxxxxc||**cc...5.......4cc$|$cx
+xxxxxxxxxxxxxxc*$$cc........3..ccccccccx
+xxxxxxxxxxxxxxc$+ccc.....2....cc.....5cx
+xxxxxxxxxxxxxxc$c....5.......cc.......cx
+xxxxxxxxxxxxxxccc......5....cc..2....ccx
+xxxxxxxxxxxxxxxxc..........cc.......ccxx
+xxxxxxxxxxxxxxxcc..1..U..........4..ccxx
+xxxxxxxxxxxxxxcc.....................ccx
+xxxxxxxxxxxxxxc...........3...........cx
+xxxxxxxxxxxxxxc.......2.......3.......cx
+xxxxxxxxxxxxxxc..2................2..5cx
+xxxxxxxxxxxxxxc......x.........x......cx
+xxxxxxxxxxxxxxc.....xx.........xx.....cx
+xxxxxxxxxxxxxxc2...xxx....1....xxx.4..cx
+xxxxxxxxxxxxxxc..xxxx...........xxxx..cx
+xxxxxxxxxxxxxxc.xxx.....cc.cc.....xxx.cx
+xxxxxxxxxxxxxxc.x.....cccc.cccc.....x.cx
+xxxxxxxxxxxxxxc.3...cccxxc.cxxccc.3...cx
+xxxxxxxxxxxxxxc...cccxxxxc.cxxxxccc...cx
+xxxxxxxxxxxxxxc.cccxxxxxxc.cxxxxxxccc.cx
+xxxxxxxxxxxxxxcccxxxxxxxxc.cxxxxxxxxcccx
+xxxxxxxxxxxxxxxxxxxxxxxxxx@xxxxxxxxxxxxx
+ENDMAP
+
+MONS: deep elf high priest, deep elf demonologist
+MONS: deep elf annihilator, deep elf sorcerer
+MONS: deep elf death mage
+MONS: random, random
+
+##############################################################################
+# slime_pit
+
+NAME: slime_pit
+PLACE: Slime:$
+ORIENT: encompass
+
+# Slime pit take is reduced pending an increase in difficulty of this
+# subdungeon. -- bwr
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..xxxx.........xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxx....................xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxx......................xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxx..........................x.xxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxx............................xxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxx.............................xxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxx.................................xxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxx..................................xxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxx....(................................xxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxx......................................xxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxx..........................................xxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxx..........................................xxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxx............................................xxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxx............................................xxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxx.....................ccc..ccc............]......xxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxx...................cccc2ccccc...................xxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxx...................cc*cc..cc*cc....................xxxxxxxxxxxxxxx
+xxxxxxxxxxxxxx..................cc***cc4c***cc..................xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxx..................cc*|*cc..cc*|*cc..................xxxxxxxxxxxxxxx
+xxxxxxxxxxxxx.................cc*|P|*c4cc*|P|*cc.................xxxxxxxxxxxxxxx
+xxxxxxxxxxxxx.................cc**|*cc..cc*|**cc....................xxxxxxxxxxxx
+xxxxxxxxxxxx..................ccc**c|cc4c|c**ccc...................xxxxxxxxxxxxx
+xxxxxxxxxxxx..................cccccccc..cccccccc....................xxxxxxxxxxxx
+xxxxxxxxxxx...................c.4.c.4.1..4.c.4.c.....................xxxxxxxxxxx
+xxxxxxxxxxx...................2.c.4.c..3.c.4.c.2.....................xxxxxxxxxxx
+xxxxxxxxxxx..........)........cccccccc..cccccccc.....................xxxxxxxxxxx
+xxxxxxxxxxx...................ccc**c|cc4c|c**ccc.....................xxxxxxxxxxx
+xxxxxxxxxx....................cc**|*cc..cc*|**cc....................xxxxxxxxxxxx
+xxxxxxxxxx....................cc*|P|*c4cc*|P|*cc....................xxxxxxxxxxxx
+xxxxxxxxxx.....................cc*|*cc..cc*|*cc....................xxxxxxxxxxxxx
+xxxxxxxxxxx.....................cc***cc4c***cc.....................xxxxxxxxxxxxx
+xxxxxxxxxxxx.....................cc*cc..cc*cc......................xxxxxxxxxxxxx
+xxxxxxxxxxxxx.....................cccc2ccccc......................xxxxxxxxxxxxxx
+xxxxxxxxxxxxxx.....................ccc..ccc.......................xxxxxxxxxxxxxx
+xxxxxxxxxxxxxx...........................................[.........xxxxxxxxxxxxx
+xxxxxxxxxxxxx......................................................xxxxxxxxxxxxx
+xxxxxxxxxxxxx..............................................xxxxx...xxxxxxxxxxxxx
+xxxxxxxxxxxxxx...........................................xxxxxxxx.xxxxxxxxxxxxxx
+xxxxxxxxxxxxxx..........................................xxxxxxxxx.xxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx........................................xxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx.........................................xxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxx.......................................xxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxx......................................xxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxx......................................xxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxx.....................................xxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxx.............................}......xxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxx.................................xxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxx..............................xxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxx..............................xxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxx............................xxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxx...........{........xxx..xxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx................xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.........xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: royal jelly, acid blob, great orb of eyes
+MONS: random, random, random, random
+
+
+##############################################################################
+# The Hall of Blades
+
+NAME: hall_of_blades
+PLACE: Blade
+ORIENT: north
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxxxxx
+xxxxxxxxccc....cccc.cccc.cccc.cccc.cccc.cccc.cccc.cccc.cccc.cccc.....cccxxxxxxxx
+xxxxxxxxcc......cc...cc...cc...cc...cc...cc...cc...cc...cc...cc.......ccxxxxxxxx
+xxxxxxxxc..............................................................cxxxxxxxx
+xxxxxxxxc..........c..............c..............c..............c......cxxxxxxxx
+xxxxxxxxc.........ccc............ccc............ccc............ccc.....cxxxxxxxx
+xxxxxxxxc........ccccc..........ccccc..........ccccc..........ccccc....cxxxxxxxx
+xxxxxxxxc.........ccc............ccc............ccc...........ccccc....cxxxxxxxx
+xxxxxxxxc..........c..............c..............c.............ccc.....cxxxxxxxx
+xxxxxxxxc......................................................ccc.....cxxxxxxxx
+xxxxxxxxc.......................................................c......cxxxxxxxx
+xxxxxxxxc..............................................................cxxxxxxxx
+xxxxxxxxc..............................................................cxxxxxxxx
+xxxxxxxxc..............................................................cxxxxxxxx
+xxxxxxxxc..............................................................cxxxxxxxx
+xxxxxxxxc..............................................................cxxxxxxxx
+xxxxxxxxc..............................................................cxxxxxxxx
+xxxxxxxxc.......................................................c......cxxxxxxxx
+xxxxxxxxc......................................................ccc.....cxxxxxxxx
+xxxxxxxxc..........c..............c..............c.............ccc.....cxxxxxxxx
+xxxxxxxxc.........ccc............ccc............ccc...........ccccc....cxxxxxxxx
+xxxxxxxxc........ccccc..........ccccc..........ccccc..........ccccc....cxxxxxxxx
+xxxxxxxxc.........ccc............ccc............ccc............ccc.....cxxxxxxxx
+xxxxxxxxc..........c..............c..............c..............c......cxxxxxxxx
+xxxxxxxxc..............................................................cxxxxxxxx
+xxxxxxxxc.......cc...cc...cc...cc...cc...cc...cc...cc...cc...cc.......ccxxxxxxxx
+xxxxxxxxcc.....cccc.cccc.cccc.cccc.cccc.cccc.cccc.cccc.cccc.cccc.....cccxxxxxxxx
+xxxxxxxxccc...ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxxxxx
+xxxxxxxxcccc.............................cccccccccccccccccccccccccccccccxxxxxxxx
+xxxxxxxxcccccccccccccccccccccccccccccc.@.cccccccccccccccccccccccccccccccxxxxxxxx
+ENDMAP
+
+MONS: dancing weapon
+MONS: random, random, random, random, random, random
+
+##############################################################################
+# hall_of_Zot
+
+NAME: hall_of_Zot
+PLACE: Zot:5
+ORIENT: north
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccccccccccccccccxxxxxxxxxxxxxxxxxxxxxxxccccccccccccccxxxxxxxxxxxxx
+xxxxxxxxxxxcccc..............ccccxxxxxxxxxxxxxxxxxcccc............ccccxxxxxxxxxx
+xxxxxxxxxxcc....................cccxxxxxxxxxxxxxccc..................ccxxxxxxxxx
+xxxxxxxxxcc...........3...........ccxxxxxxxxxxxcc...........3.........ccxxxxxxxx
+xxxxxxxxxc..8......................cXXXXXXXXXXXc....................8..cxxxxxxxx
+xxxxxxxxxc...................8.....XXX...1...XXX....8..................cxxxxxxxx
+xxxxxxxxxcc........................XX..1...1..XX......................ccxxxxxxxx
+xxxxxxxxxxcc.......................X1.........1X.....................ccxxxxxxxxx
+xxxxxxxxxxxcc.....4....2..............1..Z..1............2....4.....ccxxxxxxxxxx
+xxxxxxxxxxcc.......................X1.........1X.....................ccxxxxxxxxx
+xxxxxxxxxcc........................XX..1...1..XX......................ccxxxxxxxx
+xxxxxxxxxc...................8.....XXX...1...XXX....8..................cxxxxxxxx
+xxxxxxxxxc...8.....................cXXXXXXXXXXXc...................8...cxxxxxxxx
+xxxxxxxxxcc..........8............ccccccccccccccc..........8..........ccxxxxxxxx
+xxxxxxxxxxcc....................ccccccccccccccccccc..................ccxxxxxxxxx
+xxxxxxxxxxxcc................ccccccccccccccccccccccccc..............ccxxxxxxxxxx
+xxxxxxxxxxxxccF111FcccccccccccccccccccccccccccccccccccccccccccF111Fccxxxxxxxxxxx
+xxxxxxxxxxxcc................^^1.ccccccccccccccccc.1^^..............ccxxxxxxxxxx
+xxxxxxxxxxcc.................cc1...ccccccccccccc...1cc...............ccxxxxxxxxx
+xxxxxxxxxcc.............8.....ccc...ccccccccccc...ccc...8.............ccxxxxxxxx
+xxxxxxxxxc....8................ccc...............ccc...........8...8...cxxxxxxxx
+xxxxxxxxxc.......8.....8...8...cxcc.............ccxc...................cxxxxxxxx
+xxxxxxxxxc.....................cxxc.............cxxc.......8...........cxxxxxxxx
+xxxxxxxxxc.....................cxxcc.1...1...1.ccxxc............8....8.cxxxxxxxx
+xxxxxxxxxc.......8....8.....8..cxxxc...........cxxxc....8..............cxxxxxxxx
+xxxxxxxxxc.....................cxxcc...........ccxxc..........8........cxxxxxxxx
+xxxxxxxxxcc...5...............ccxxc.............cxxcc..............8..ccxxxxxxxx
+xxxxxxxxxxcc........8........ccxxcc.............ccxxcc....8....5.....ccxxxxxxxxx
+xxxxxxxxxxxcc...............ccxxxc...............cxxxcc.............ccxxxxxxxxxx
+xxxxxxxxxxxxcccccccccccccccccxxxxcccccccc@ccccccccxxxxcccccccccccccccxxxxxxxxxxx
+ENDMAP
+
+MONS: Orb Guardian, Killer Klown, electric golem, orb of fire
+MONS: ancient lich
+MONS: random, random
+
+
+##########################################################################
+# Ecumenical temple
+
+NAME: temple
+PLACE: Temple
+ORIENT: encompass
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxccccccccccccccccccccccccccxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxcc............<............cxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxcc...........................cxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxcc.............................cxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxcc...............................cxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxcc.................................cxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxcc...................................cxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxcc.....................................cxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxcc.......................................cxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxcc.........................................cxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxcc...........................................cxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxcc.............................................cxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc...............................................cxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxcc.................................................cxxxxxxxxxxxxxxx
+xxxxxxxxxxxxcc...................................................cxxxxxxxxxxxxxx
+xxxxxxxxxxxcc..........................B..........................cxxxxxxxxxxxxx
+xxxxxxxxxxcc.......................................................cxxxxxxxxxxxx
+xxxxxxxxxcc.....................B.............B.....................cxxxxxxxxxxx
+xxxxxxxxcc...........................................................cxxxxxxxxxx
+xxxxxxxxc.............................................................cxxxxxxxxx
+xxxxxxxxc.............................................................cxxxxxxxxx
+xxxxxxxxc.................B.........................B.................cxxxxxxxxx
+xxxxxxxxc..............................T..............................cxxxxxxxxx
+xxxxxxxxc.............................................................cxxxxxxxxx
+xxxxxxxxc.............................................................cxxxxxxxxx
+xxxxxxxxc.............................................................cxxxxxxxxx
+xxxxxxxxc.............................................................cxxxxxxxxx
+xxxxxxxxc.............................................................cxxxxxxxxx
+xxxxxxxxc..............B...............................B..............cxxxxxxxxx
+xxxxxxxxc(....................T.................T....................{cxxxxxxxxx
+xxxxxxxxc.............................................................cxxxxxxxxx
+xxxxxxxxc.............................................................cxxxxxxxxx
+xxxxxxxxc.............................................................cxxxxxxxxx
+xxxxxxxxc.............................................................cxxxxxxxxx
+xxxxxxxxc.............................................................cxxxxxxxxx
+xxxxxxxxc.............................................................cxxxxxxxxx
+xxxxxxxxc................B...........................B................cxxxxxxxxx
+xxxxxxxxcc...........................................................ccxxxxxxxxx
+xxxxxxxxxcc............................T............................ccxxxxxxxxxx
+xxxxxxxxxxcc.......................................................ccxxxxxxxxxxx
+xxxxxxxxxxxcc.....................................................ccxxxxxxxxxxxx
+xxxxxxxxxxxxcc...................................................ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxcc.................................................ccxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc...............B................B..............ccxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxcc.............................................ccxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxcc.....................B.....................ccxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxcc.........................................ccxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxcc.......................................ccxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxcc.....................................ccxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxcc...................................ccxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxcc.................................ccxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxcc...............................ccxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxcc.............................ccxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxcc...........................ccxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxcc............[............ccxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxcccccccccccccccccccccccccccxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+##############################################################################
+# Tomb:1
+
+NAME: tomb_1
+PLACE: Tomb:1
+ORIENT: encompass
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxx(.............................[..............................{xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx..........ccccccccccccccccccccccccccccccccccccccccccc.........xxxxxxxxx
+xxxxxxxxx..........ccccccccccccccccccccccccccccccccccccccccccc.........xxxxxxxxx
+xxxxxxxxx..........cc..........................^............cc.........xxxxxxxxx
+xxxxxxxxx..........cc.........^....................^........cc.........xxxxxxxxx
+xxxxxxxxx..........cc..ccccccccccccccccccccccccccccccccccc..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c....^....^..c................c.^)c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c..ccccccccc.c..3.............c.^.c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c..c222c111c.c...............5c..^c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c..c2c222c.^.c......2.........+cccc..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c..ccccccccccc..........3......5..c.^cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c.................................c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c..........................3......c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc^.cccccccccccccc.......2............c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c............c....................c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c............c.................3..c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c..cccccccc..c..........2.........c^5cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c..c.^.c11c..c....................c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c..c.c.c11c..c...3................c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c..c^c.11cc..c..............2.....c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c..c.cccccc..c.......2............c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c..c..^..^...c.................2..c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc5^c..ccccccccccc....................c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c.................................c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c.................................c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..cccccccccccccc..^.^..cccccccccccccc..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c...........ccc+++++ccc........^..c.^cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c.^.....^...cc.2...2.cc......^....c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c..ccccccc..cc.F...F.cc..ccccccc..c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c..cc.322c..cc.......cc..c22..cc..c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c..c].c22c..cc.......cc..c22c.}c^.c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c..cccc..c.^cc.G...G.cc..c3.cccc..c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c.....^..c..cc.......cc.^c........c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc..c........c..cc.......cc..c....^...c..cc.........xxxxxxxxx
+xxxxxxxxx..........cc^.cccccccccc..cc.G...G.cc..cccccccccc.^cc.........xxxxxxxxx
+xxxxxxxxx..........cc......^.......cc.......cc..........^...cc.........xxxxxxxxx
+xxxxxxxxx..........cc...........^..cc.......cc.....^........cc.........xxxxxxxxx
+xxxxxxxxx..........cccccccccccccccccc.G...G.cccccccccccccccccc.........xxxxxxxxx
+xxxxxxxxx..........cccccccccccccccccc.......cccccccccccccccccc.........xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx.............................G...G............................xxxxxxxxx
+xxxxxxxxx...........................4.......4..........................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx...........................4..V.V..4..........................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx...........................4.......4..........................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: mummy, guardian mummy, mummy priest, sphinx, greater mummy
+MONS: random, random
+
+###############################################################################
+# Tomb:2
+
+NAME: tomb_2
+PLACE: Tomb:2
+
+# Can be rotated!
+ORIENT: encompass
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc{...c......c.....3....c........c.......ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....c.....^c^........^c......2^c.......ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....c...2.^+..2.....2^+^..2....+.......ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc.3.^c^.....c^.........c^2.....^c^......ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc...^+^.....c..........c........c...2...ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccccc+ccccccccccccccccccccccccccccccc....ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc..^.c.............................c....ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....c.............................c..3.ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....c..ccc4.................4ccc..c....ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....c..ccc...................ccc..c..2.ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....c..ccc.........1.........ccc..c)..}ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc.3..c..ccc.....2.......2.....ccc..cccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....c.............................c....ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....c.............................c^2..ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....c........c...........c........+....ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc]...c.............................c^2..ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccccccc.....3........(........3.....c....ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....c.............................c.^.^ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc...^c........c...........c........ccc+cccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....+.............................c..^.ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc...^c.............................c....ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....c..ccc.....2.......2.....ccc..c..2.ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccccccc..ccc.........1.........ccc..c....ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....c..ccc...................ccc..c....ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc...^+..ccc4.................4ccc..c2...ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....c.............................c....ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccccccc.............................c..2.ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....c.............................ccc+cccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc....+cccc+ccccccccccccccc+ccccccccc.^.^ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc.1.^^.c.^..c............c^.......c.3...ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc...2..c.1..c.....1.1....c.....2..c.....ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc......c....c..1......1.^c..2.....c...2.ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc..3...c.1..c...1...1..1^+........c.....ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc......c....c[...........c.......3c.....ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: mummy, guardian mummy, mummy priest, greater mummy
+MONS: random, random, random
+
+#############################################################################
+# Tomb:3
+
+NAME: tomb_3
+PLACE: Tomb:3
+ORIENT: encompass
+
+# Unless you have a square aspect ratio, Tomb:3 looks utterly lame when
+# rotated.
+FLAGS: no_rotate
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccccccc.............................cccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccc...............cccccc..............ccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccc...............cccccccc..............cccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccc.......4......ccccO4cccc......4......cccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccc............cccc......cccc...........cccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc............cccc........cccc...........ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc............cccc........cccc...........ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc...........cccc..444444..cccc..........ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc.......................................ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc.......................................ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcc.................222222................ccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccc................223322...............cccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccc...3............223322............3..cccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccc...............222222..............ccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccc....2..........................2...ccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccccc....2......................2....cccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccccccc............................cccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccccccccc+ccc..................ccc+ccccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccccccc....cc................cc....cccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccccc.......cc22222222222222cc......$cccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccc....^.....cc............cc..^.....$ccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccc.^.........cc..........cc.....^.^.$ccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccc$...^...^..^.cc........cc..........$$cccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccc$$$...........cc222222cc.^........$$$cccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccc|$$$...........c......c.....^...$$$$$cccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccc||$$$$...^.....c......c^......$$$$$$$cccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccc|||||$$.....^..c......c......$$$$$$$$cccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccc|||||$........c......c...^.$$$$$$$$ccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccccc||||$$..^....c......c.....$$$$$$$cccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccccc||||$.......c......c.....$$$$$$ccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccccccc|||$$....^.c......c.^.^$$$$$$cccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccccccc|||$^....cc..{...cc...$$$$$ccccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxccccccccc||$.....cc...(..cc..$$$$$cccccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccccccccc|$...cccc..[...cccc$$$$ccccccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: mummy, guardian mummy, mummy priest, greater mummy
+MONS: random, random
+
+#############################################################################
+# Swamp:5
+
+NAME: swamp
+PLACE: Swamp:5
+ORIENT: southeast
+
+# NB - most of the 'x's here will be set to water in dungeon.cc
+
+MAP
+xxxxxxxxxxx@xxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx2xxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxx2x.xxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxcc.ccxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxcc...ccxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxcc3.2..ccxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxcc.1.3.2.ccxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxccc....1.1cccxxxxxxxxxxxxxxxxxxxxxx
+xxxxxcc.1.32....ccxxxxxxxxxxxxxxxxxxxxxx
+xxxxxcc...3..1.3ccxxxxxxxxxxxxxxxxxxxxxx
+xxxxxcc2.1.3..2.ccxxxxxxxxxxxxxxxxxxxxxx
+xxxxxccc33..1..cccxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxcccc3O3ccccxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxcccccccccxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxcccccccxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxcccxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: swamp dragon, swamp drake, hydra
+MONS: random, random, random, random
diff --git a/crawl-ref/source/dat/vaults.des b/crawl-ref/source/dat/vaults.des
new file mode 100644
index 0000000000..0cc79560ab
--- /dev/null
+++ b/crawl-ref/source/dat/vaults.des
@@ -0,0 +1,1689 @@
+##############################################################################
+# Random vaults and minivaults; special levels (including V:8!) should go to
+# splev.des. Do NOT put special levels here, or they could be selected when the
+# game looks for random vaults.
+#
+# key:
+# x - DNGN_ROCK_WALL
+# X - DNGN_PERMAROCK_WALL -> should always be undiggable! -- bwr
+# c - DNGN_STONE_WALL
+# v - DNGN_METAL_WALL
+# b - DNGN_GREEN_CRYSTAL_WALL
+# a - DNGN_WAX_WALL
+# . - DNGN_FLOOR
+# + - DNGN_CLOSED_DOOR
+# = - DNGN_SECRET_DOOR
+# @ - entry point - must be on outside and on a particular side - see templates
+# w - water
+# l - lava
+# >< - extra stairs - you can leave level by these but will never be placed on
+# them from another level
+# }{ - stairs 82/86 - You must be able to reach these from each other
+# )( - stairs 83/87
+# ][ - stairs 84/88
+# I - orcish idol (does nothing)
+# ^ - random trap
+#
+# A - Vestibule gateway (opened by Horn). Can also be put on other levels for
+# colour, where it won't do anything.
+# B - Altar. These are assigned specific types (eg of Zin etc) in dungeon.cc,
+# in order.
+# C - Random Altar.
+# F - Typically a Granite Statue, but may be Orange or Silver (1 in 100)
+# G - Granite statue (does nothing)
+# H - orange crystal statue (attacks mind)
+# S - Silver statue (summons demons). Avoid using (rare).
+# T - Water fountain
+# U - Magic fountain
+# V - Permanently dry fountain
+#
+# Statues can't be walked over and are only destroyed by disintegration
+#
+# $ - gold
+# % - normal item
+# * - higher level item (good)
+# | - acquirement-level item (almost guaranteed excellent)
+# O - place an appropriate rune here
+# P - maybe place a rune here (50%)
+# R - honeycomb (2/3) or royal jelly (1/3)
+# Z - the Orb of Zot
+#
+# 0 - normal monster
+# 9 - +5 depth monster
+# 8 - (+2) * 2 depth monster (aargh!). Can get golden dragons and titans
+# this way.
+# 1-7 - monster array monster
+# used to allocate specific monsters for a vault.
+# is filled with RANDOM_MONSTER if monster not specified
+#
+# note that a lot of the vaults are in there mainly to add some interest to the
+# scenery, and are not the lethal treasure-fests you find in Angband
+# (not that there's anything wrong with that)
+#
+# Guidelines for creating new vault maps:
+#
+# [ds] If your map is not a minivault, make sure the side(s) that form the
+# border have a rock wall padding at least 6 deep. For instance, if your map
+# is ORIENT: north, you must have a 6 deep border of rock wall (or any
+# other kind of wall) along the northern, eastern, and western edges of the
+# map. If you're doing a fullscreen map (encompass), you must pad all around
+# the map with 6 layers of wall.
+#
+# Basically you can just let your creativity run wild. You do not have
+# to place all of the stairs unless the level is full screen, in which
+# case you must place all except the extra stairs (> and <). The <> stairs
+# can be put anywhere and in any quantities but do not have to be there. Any
+# of the other stairs which are not present in the vault will be randomly
+# placed outside it. Also generally try to avoid rooms with no exit.
+#
+# You can use the templates below to build vaults. The entry point '@' must be
+# present (except full-screen vaults where it must not) and be on the same
+# side of the vault as it is on the template, but can be anywhere along that
+# side.
+#
+# I think that's all. Have fun!
+#
+# ps - remember to add one to the monster array value when placing monsters
+# on each map (it is 1-7, not 0-6) {dlb}
+#
+# [dshaligram] All vaults MUST have an ORIENT: attribute; if there's no
+# ORIENT: attribute, the vault is considered to be a minivault, which is
+# usually not what you want.
+#
+##############################################################################
+
+default-depth: 1-27
+
+NAME: vault_1
+ORIENT: north
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxx....x........x........x.................................xxxxxxxxxxxx
+xxxxxxxxxx|=8...x........+........x......x....x1...x2...x2...x3...x...xxxxxxxxxx
+xxxxxxxxxx|x....x........x........x....................................xxxxxxxxx
+xxxxxxxxxxxxxxxx+xxx+xxxxxxxxxxxxxx..................................xxxxxxxxxxx
+xxxxxxxxx.......x.................+...................................8xxxxxxxxx
+xxxxxxxxx.......x.................x..................................xxxxxxxxxxx
+xxxxxxxxx.......+........3........xx+xx................................xxxxxxxxx
+xxxxxxxxx.......x.................x...x..x....x1...x2...x2...x3...x...xxxxxxxxxx
+xxxxxxxxx.......x.................x...x.............................xxxxxxxxxxxx
+xxxxxxxxxx+xxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxx.........................x.S.x...xxxxxx..................|||||xxxxxxxxx
+xxxxxxxxx....xxxxxxxxxxxxxxxxxx...x...x......xxxxxx..................||xxxxxxxxx
+xxxxxxxxx....x...$$$$x****.999x...x...x.........xxxxxx.................xxxxxxxxx
+xxxxxxxxx....+...$$$$x****....x...x...+............xxxxxx.........8....xxxxxxxxx
+xxxxxxxxx....x...$$$$x****....+...x...x...............xxxxxx...........xxxxxxxxx
+xxxxxxxxx....x...$$$$x****....x...x999x..................xxxxxx........xxxxxxxxx
+xxxxxxxxx....xxxxxxxxxxxxxxxxxx...x...xxx...................xxxxxx.....xxxxxxxxx
+xxxxxxxxx.........................x...xxxxxx...................xxxxxx..xxxxxxxxx
+xxxxxxxxxxxxx+xxxxxxxx+xxxxxxx+xxxx...xxxxxx+xxxxxxxx+xxxxxxxx+xxxxxxx=xxxxxxxxx
+xxxxxxxxx.........x.......x.......x...x.........x........x.............xxxxxxxxx
+xxxxxxxxx.........x.......x.......x...x.........x........x.............xxxxxxxxx
+xxxxxxxxx.........x.......x.......x...x.........x........x.............xxxxxxxxx
+xxxxxxxxx....1....x...2...x...3...x...x....3....x....2...x......1......xxxxxxxxx
+xxxxxxxxx.........x.......x.......x...x.........x........x.............xxxxxxxxx
+xxxxxxxxx.........x.......x.......x...x.........x........x.............xxxxxxxxx
+xxxxxxxxx.........x.......x.......x...x.........x........x.............xxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: shapeshifter, shapeshifter, glowing shapeshifter
+
+##############################################################################
+# A cell vault
+
+NAME: vault_2
+ORIENT: northwest
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxcccccccccccccccccccccccccccccccc
+xxxxxxxxccw......^......w......^......wc
+xxxxxxxxcc.ccccccccccccc.ccccccccccccc.c
+xxxxxxxxcc.c....c.c....c.c....c.c....c.c
+xxxxxxxxcc.c.8..+.c....c.c....+.c..9.c.c
+xxxxxxxxcc.c....c.+..9.c.c.9..c.+....c.c
+xxxxxxxxcc.c....c.c....c.c....c.c....c.c
+xxxxxxxxcc.cccccc.cccccc.cccccc.cccccc.c
+xxxxxxxxcc^c....c.c....c.c....c.c....c.c
+xxxxxxxxcc.c....c.c....c.c....+.c....c.c
+xxxxxxxxcc.c8...+.+..8.c.c.8..c.+....c.c
+xxxxxxxxcc.c....c.c....c.c....c.c....c.c
+xxxxxxxxcc.cccccc.cccccc.cccccc.cccccc.c
+xxxxxxxxcc.c....c.c....c.c....c.c....c.c
+xxxxxxxxcc.c....+.c....c.c.0..c.c....c.c
+xxxxxxxxcc.c..9.c.+.8..c^c....+.+.0..c.c
+xxxxxxxxcc.c....c.c....c.c....c.c....c.c
+xxxxxxxxcc.cccccc.cccccc.cccccc.cccccc.c
+xxxxxxxxcc.c....c.c....c.c....c.c....c.c
+xxxxxxxxcc.c.0..+.+.0..c.c....+.+....c.c
+xxxxxxxxcc.c....c.c....c.c.0..c.c.8..c.c
+xxxxxxxxcc.cccccc.c....c.c....c.cccccc.c
+xxxxxxxxcc.c....c.cccccc.cccccc.c....c^c
+xxxxxxxxcc.c....c.c....c.c..9.+.+....c.c
+xxxxxxxxcc.c.0..+.+....c.c9...c.c.0..c.c
+xxxxxxxxcc.c....c.c.8..c.c....c.c....c.c
+xxxxxxxxcc.cccccc^cccccc.cccccc^cccccc.c
+xxxxxxxxccw.......Twwwwc.cwwwwT.......wc
+xxxxxxxxcccccccccccccccc.ccccccccccccccc
+xxxxxxxxxxxxxxxxxxxxxxxc@cxxxxxxxxxxxxxx
+ENDMAP
+
+##############################################################################
+# A little maze vault
+
+NAME: vault_3
+ORIENT: northeast
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+x900x..............x..........xxxxxxxxxx
+x999x.xxxxxxxxxxxx.x.xxxxxxxx.xxxxxxxxxx
+x000x.x............x.x......x.xxxxxxxxxx
+xx.xx.xxxxxxxxxxxxxx.x.xxxx.x.xxxxxxxxxx
+xx.x..............xx.x.88|x.x.xxxxxxxxxx
+xx.x.x.xxxxxxxxxx.xx.xxxxxx.x.xxxxxxxxxx
+xx.x.x.x........x...........x.xxxxxxxxxx
+xx.x.x.x.xxxxxx.xxxxxxxxxxxxx.xxxxxxxxxx
+xx.xxx.x.x$$$$x...............xxxxxxxxxx
+xx.....x.x$$$$x.xxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxx.x$$$$x...............xxxxxxxxxx
+x........x$$$$x.xxxxxxxxxxxxx.xxxxxxxxxx
+x.xxxxxx.xxxx.x.............x.xxxxxxxxxx
+x.xxxxxx.xxxx.xxxxxxxxxxxxx.x.xxxxxxxxxx
+x.x.......xxx.x...........x.x.xxxxxxxxxx
+x.x.xxxxx.....x.x.xxxxx...x.x.xxxxxxxxxx
+x.x.x999xxxxxxx.x.x***x...x.x.xxxxxxxxxx
+x.x.x889........x.x|||xxxxx.x.xxxxxxxxxx
+x.x.x899x.xxxxx.x.x***xxxxx.x.xxxxxxxxxx
+x.x.xxxxx.xxxxx.x.xx.xxxxxx.x.xxxxxxxxxx
+x.x..........xx.x.xx........x.xxxxxxxxxx
+x.xxxxxxx.xx.xx.x.xxxxx.xxxxx.xxxxxxxxxx
+x.xxx000x.xx.xx.x.x$$$x.xxxxx.xxxxxxxxxx
+x|||x000x.x$$$x.x.x$$$x%%x%%%.xxxxxxxxxx
+x|||x000..x$8$x.x.x$$$x%%x%8%xxxxxxxxxxx
+x|||xxxxxxx$$$x.x..$$$xxxx%%%xxxxxxxxxxx
+xxxxxxxxxxxxxxx@xxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+##############################################################################
+# thingy vault.
+
+NAME: vault_4
+ORIENT: southwest
+FLAGS: no_rotate
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxx@xxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxx^xxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxx.....xxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxx.....xxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxx.........xxxxxxxxxx
+xxxxxxxxxxxxxxxxx......0...0......xxxxxx
+xxxxxxxxxxxxxx.......................xxx
+xxxxxxxxxxxxxx.........0...0.........xxx
+xxxxxxxxxxxxx8......0.........0......8xx
+xxxxxxxxxxxxxx.........0...0.........xxx
+xxxxxxxxxxxxxx.......................xxx
+xxxxxxxxxxxxxxx........0...0........xxxx
+xxxxxxxxxxxxxxxxxxxx...........xxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxx.....xxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxx...............xxxxxxx
+xxxxxxxxxxxxxxxx8.................8xxxxx
+xxxxxxxxxxxxxxxxxxx.............xxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxx999xxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+
+##############################################################################
+# hourglass vault.
+
+NAME: vault_5
+ORIENT: southeast
+FLAGS: no_rotate
+
+MAP
+xxxxxxxxxxxxxx@xxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxx.................xxxxxxxxxxxxxxxxx
+xxxxx...................xxxxxxxxxxxxxxxx
+xxxxx...................xxxxxxxxxxxxxxxx
+xxxxxx.................xxxxxxxxxxxxxxxxx
+xxxxxx.................xxxxxxxxxxxxxxxxx
+xxxxxx.................xxxxxxxxxxxxxxxxx
+xxxxxxx...............xxxxxxxxxxxxxxxxxx
+xxxxxxx...............xxxxxxxxxxxxxxxxxx
+xxxxxxxx.............xxxxxxxxxxxxxxxxxxx
+xxxxxxxxx.....8.....xxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxx...999...xxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxx00000xxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxx===xxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxx.....xxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxx.........xxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxx...........xxxxxxxxxxxxxxxxxxxx
+xxxxxxxx......|......xxxxxxxxxxxxxxxxxxx
+xxxxxxx...............xxxxxxxxxxxxxxxxxx
+xxxxxxx...............xxxxxxxxxxxxxxxxxx
+xxxxxx........$........xxxxxxxxxxxxxxxxx
+xxxxxx.......$$$.......xxxxxxxxxxxxxxxxx
+xxxxxx....$$$$$$$$$....xxxxxxxxxxxxxxxxx
+xxxxx$$$$$$$$$$$$$$$$$$$xxxxxxxxxxxxxxxx
+xxxxx$$$$$$$$$$$$$$$$$$$xxxxxxxxxxxxxxxx
+xxxxxx$$$$$$$$$$$$$$$$$xxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+##########################################################################
+# A more Angbandy vault
+
+NAME: vault_6
+ORIENT: northeast
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ccccccccccccccccccccccccccccccccxxxxxxxx
+c*******cc..9...cc.+8c0c*c.c*c8cxxxxxxxx
+c******cc..cc..cc..cc0c.c.c.c8ccxxxxxxxx
+c*****cc..cc..cc..cc.c$c.c.c8c.cxxxxxxxx
+c****cc9.cc..cc8.cc|c.c|c.c*c0ccxxxxxxxx
+c***cc..cc..cc..cc.c.c.c.c.c.c$cxxxxxxxx
+c**cc..cc8.cc..cc.c*c.c.c.c.c.ccxxxxxxxx
+c+cc9.cc..cc..cc.c.c.c.c*c.c.c.cxxxxxxxx
+c^c..cc..cc..cc.c$c.c.c.c.c.c*ccxxxxxxxx
+c...cc..cc..cc.c.c.c9c$c.c.c.c9cxxxxxxxx
+c..cc..cc..cc$c.c.c*c.c.c.c9c9ccxxxxxxxx
+c.cc..cc..cc.c.c|c.c.c.c.c$c.c9cxxxxxxxx
+ccc..cc..cc.c.c.c.c.c.c.c.c.cc+cxxxxxxxx
+cc..cc..cc.c*c.c.c.c.c.c$c.cc..cxxxxxxxx
+c0.cc..cc.c.c.c.c8c.c*c.c.cc0.ccxxxxxxxx
+c.cc..cc*c.c.c.c.c$c.c.c.cc..cccxxxxxxxx
+c^c..cc.c.c9c.c.c.c.c.c.cc..cc.cxxxxxxxx
+c0..cc$c.c.c*c0c.c.c.c.cc..cc.0cxxxxxxxx
+c..cc.c.c9c.c.c.c$c.c.cc.9cc...cxxxxxxxx
+c.cc9c.c.c.c.c.c.c.c.cc..cc..c^cxxxxxxxx
+ccc.c.c$c.c.c.c.c.c$cc..cc..cc^cxxxxxxxx
+cc$c.c.c.c.c$c.c0c.cc..cc..cc..cxxxxxxxx
+c.c.c.c.c.c.c.c.c.cc9.cc..cc..ccxxxxxxxx
+cc.c8c.c.c$c.c.c.cc..cc..cc0.cccxxxxxxxx
+c.c$c.c$c0c.c.c.cc..cc..cc..cc$cxxxxxxxx
+cc.c.c.c.c.c*c.cc..cc..cc..cc$$cxxxxxxxx
+c.c.c.c.c.c.c.cc..cc0.cc..cc$$$cxxxxxxxx
+cc.c.c.c.c.c$cc..cc..cc..cc$$$$cxxxxxxxx
+c.c.c.c.c.c.cc.8.^..cc....+$$$$cxxxxxxxx
+cccc@cccccccccccccccccccccccccccxxxxxxxx
+ENDMAP
+
+############################################################################
+# four-leaf vault
+
+NAME: vault_7
+ORIENT: northwest
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxx.........^..^.........xxxxx
+xxxxxxxxxxxx...xxxxxxxx..xxxxxxxx...xxxx
+xxxxxxxxxxx...xxxxxxxxx..xxxxxxxxx...xxx
+xxxxxxxxxx...xx$*....xx..xx....$$xx...xx
+xxxxxxxxx...xx$*$....xx..xx....$*$xx...x
+xxxxxxxxx..xx*$*$....xx..xx....*$$$xx..x
+xxxxxxxxx..xx$$$.00..xx..xx..00.*$*xx..x
+xxxxxxxxx..xx....09..xx..xx..90....xx..x
+xxxxxxxxx..xx......+xx....xx+......xx..x
+xxxxxxxxx..xx......x^......^x......xx..x
+xxxxxxxxx..xxxxxxxxx........xxxxxxxxx..x
+xxxxxxxxx..xxxxxxxx..........xxxxxxxx..x
+xxxxxxxxx..............TT..............x
+xxxxxxxxx..............TT..............x
+xxxxxxxxx..xxxxxxxx..........xxxxxxxx..x
+xxxxxxxxx..xxxxxxxxx........xxxxxxxxx..x
+xxxxxxxxx..xx......x^......^x......xx..x
+xxxxxxxxx..xx......+xx....xx+......xx..x
+xxxxxxxxx..xx....09..xx..xx..90....xx..x
+xxxxxxxxx..xx$$*.00..xx..xx..00.*$$xx..x
+xxxxxxxxx..xx*$*$....xx..xx....*$$*xx..x
+xxxxxxxxx...xx*$*....xx..xx....$$$xx...x
+xxxxxxxxxx...xx*$....xx..xx....*$xx...xx
+xxxxxxxxxxx...xxxxxxxxx..xxxxxxxxx...xxx
+xxxxxxxxxxxx...xxxxxxxx..xxxxxxxx...xxxx
+xxxxxxxxxxxxx..^................^..xxxxx
+xxxxxxxxxxxxxxxxxxxxxxx^^xxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxx++xxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxx@xxxxxxxxxxxxxxxx
+ENDMAP
+
+############################################################################
+# Cross-vault
+
+NAME: vault_8
+ORIENT: northwest
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxx............xxxxxxxxxx
+xxxxxxxxxxxxxxx..................xxxxxxx
+xxxxxxxxxxxxx......................xxxxx
+xxxxxxxxxxxx..........w..w..........xxxx
+xxxxxxxxxxx........wwww++wwww........xxx
+xxxxxxxxxxx......wwwvvv^^vvvwww......xxx
+xxxxxxxxxx......wwwwv.9..9.vwwww......xx
+xxxxxxxxxx.....wwwwwv......vwwwww.....xx
+xxxxxxxxxx....wwwwwvv......vvwwwww....xx
+xxxxxxxxx....wwwwwvv........vvwwwww....x
+xxxxxxxxx....wwvvvv....vv....vvvvww....x
+xxxxxxxxx...wwwv......vvvv......vwww...x
+xxxxxxxxx...wwwv....vv8vv8vv....vwww...x
+xxxxxxxxx..wwwwv...vvvv||vvvv...vwwww..x
+xxxxxxxxx^^wwwwv...vvvv||vvvv...vwwww^^x
+xxxxxxxxx..wwwwv....vv8vv8vv....vwwww..x
+xxxxxxxxx...wwwv......vvvv......vwww...x
+xxxxxxxxx...wwwvvvv....vv....vvvvwww...x
+xxxxxxxxx....wwwwwvv........vvwwwww....x
+xxxxxxxxxx...wwwwwwvv......vvwwwwww...xx
+xxxxxxxxxx....wwwwwwv......vwwwwww....xx
+xxxxxxxxxx.....wwwwwv......vwwwww.....xx
+xxxxxxxxxxx.....wwwwvvvvvvvvwwww.....xxx
+xxxxxxxxxxx.......wwwwwwwwwwww.......xxx
+xxxxxxxxxxxx.........wwwwww.........xxxx
+xxxxxxxxxxxxx.........^..^.........xxxxx
+xxxxxxxxxxxxxxx.......x++x.......xxxxxxx
+xxxxxxxxxxxxxxxxxx...xx..xx...xxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxx..@.xxxxxxxxxxxxxx
+ENDMAP
+
+############################################################################
+# Another thingy vault
+
+NAME: vault_9
+ORIENT: southeast
+
+MAP
+xxxxxxxxxxxxxxx@xxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxx^xxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxx
+xx.....^...............^.....xxxxxxxxxxx
+x..bb..xxxxxxxxxxxxxxxxx..bb..xxxxxxxxxx
+x..b...xxxxxxxxxxxxxxxxx...b..xxxxxxxxxx
+x...b..xxxxbbbbbbbbbxxxx..b...xxxxxxxxxx
+x..bb..xxbbb.......bbbxx..bb..xxxxxxxxxx
+x......xxb....9.9....bxx......xxxxxxxxxx
+x..bb..xbb..%$$$$$%..bbx..bb..xxxxxxxxxx
+x...b..xb..0%$***$%0..bx..b...xxxxxxxxxx
+x..b...xb..0%$*H*$%0..bx...b..xxxxxxxxxx
+x...b..xb..0%$***$%0..bx..b...xxxxxxxxxx
+x..b...xb...%$$$$$%...bx...b..xxxxxxxxxx
+x...b..xbb.900000009.bbx..b...xxxxxxxxxx
+x..b...xxb...........bxx...b..xxxxxxxxxx
+x..bb..xxbbb..9.9..bbbxx..bb..xxxxxxxxxx
+x......xxxxbbbb.bbbbxxxx......xxxxxxxxxx
+x..bb..xxxxxxxb=bxxxxxxx..bb..xxxxxxxxxx
+x..b...xxxxxxxx=xxxxxxxx...b..xxxxxxxxxx
+x...b..xxxxxxxx^xxxxxxxx..b...xxxxxxxxxx
+x..b....xxxxxxx=xxxxxxx....b..xxxxxxxxxx
+x...b...^.............^...b...xxxxxxxxxx
+x..b....xxxxxxxxxxxxxxx....b..xxxxxxxxxx
+x..bb..xxxxxxxxxxxxxxxxx..bb..xxxxxxxxxx
+xx....xxxxxxxxxxxxxxxxxxx....xxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+############################################################################
+# Impenetrable vault
+
+NAME: vault_10
+ORIENT: southeast
+
+MAP
+..............@................xxxxxxxxx
+...............................xxxxxxxxx
+...............................xxxxxxxxx
+...............................xxxxxxxxx
+...............................xxxxxxxxx
+.....cccccccccccccccc..........xxxxxxxxx
+.....c[^...........9cc.........xxxxxxxxx
+.....c^xxxxx=xxxxxx..cc........xxxxxxxxx
+.....c.x9..^^^...9xx..cc.......xxxxxxxxx
+.....c.x.xxx=xxxx..xx..cc......xxxxxxxxx
+.....c.x^x$$$$$$xx..xx.9c......xxxxxxxxx
+.....c.=^=$*|||*$xx..xx.c......xxxxxxxxx
+.....c.x^xx$*|||*$xx.9x.c......xxxxxxxxx
+.....c.x9.xx$*|||*$xx^x.c......xxxxxxxxx
+.....c.xx..xx$*|||*$=^=.c......xxxxxxxxx
+.....c9.xx..xx$$$$$$x^x.c......xxxxxxxxx
+.....cc..xx..xxxx=xxx.x.c......xxxxxxxxx
+......cc..xx9...^^^..9x.c......xxxxxxxxx
+.......cc..xxxxxx=xxxxx^c......xxxxxxxxx
+........cc9...........^]c......xxxxxxxxx
+.........cccccccccccccccc......xxxxxxxxx
+...............................xxxxxxxxx
+...............................xxxxxxxxx
+...............................xxxxxxxxx
+...............................xxxxxxxxx
+...............................xxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+#########################################################################
+# Orc temple
+
+NAME: orc_temple
+ORIENT: southwest
+FLAGS: no_rotate
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxx@xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxx4.4xxxxxxxxxxxxxxx
+xxxxxxxxx**..........x414x..........**xx
+xxxxxxxxx**..........x4.4x..........**xx
+xxxxxxxxx............+...+....4.......xx
+xxxxxxxxx....4..4....x...x............xx
+xxxxxxxxx............x...x.......4....xx
+xxxxxxxxx............xx.xx............xx
+xxxxxxxxx...4......xxxx+xxxx......6...xx
+xxxxxxxxx........xxx.......xxx........xx
+xxxxxxxxxxx...xxxx..2.....2..xxxx...xxxx
+xxxxxxxxxxxx+xxxx.............xxxx+xxxxx
+xxxxxxxxxxx...xxx.............xxx...xxxx
+xxxxxxxxx......x...............x......xx
+xxxxxxxxx..4...x...2...I...2...x...5..xx
+xxxxxxxxx......x...............x......xx
+xxxxxxxxx...4..xx.............xx..5...xx
+xxxxxxxxx$......x....2...2....x......$xx
+xxxxxxxxx$6..5..xx.....3.....xx.5...7$xx
+xxxxxxxxx$$$.....xxx.......xxx.....$$$xx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: orc warlord, orc priest, orc high priest, orc warrior, orc wizard
+MONS: orc knight, orc sorcerer
+
+#############################################################################
+# Matthew Ludivico (my_map)
+
+NAME: my_map
+ORIENT: southwest
+
+# The hell hounds can be deadly at lower levels.
+DEPTH: 18-27
+
+MAP
+xxxxxxxxxx.@.xxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxx..........................xx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..xx
+xxxxxxxxx.^^..........................xx
+xxxxxxxxxx.^^xx+xxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxx.^...11....xxxxxxxx..xxxxxxxx
+xxxxxxxxxxxx..x.1..6..xxx........xx..xxx
+xxxxxxxxxxxxx.xxxxxxxxx...vvvvv...x...xx
+xxxxxxxxx6..1...x.........+1..v.......xx
+xxxxxxxxx..1....x.........vvvvv........x
+xxxxxxxxx..5...xx......................x
+xxxxxxxxxxxxxx^++...........vvvvvvv....x
+xxxxxxxxxxxxxx^xx...xx=xx...vv$%$vvvvv.x
+xxxxxxxxxxxxxx^x...xxv1vxx...vvv*2...v.x
+xxxxxxxxxxxxxx^x..vvvv7.vvvv...vv.vv+v^x
+xxxxxxxxx..xxx^..vvvb....bvvv...vvv^...x
+xxxxxxxxx%%.xx..vvvvb....bvvvv.......xxx
+xxxxxxxxxx.....vvbbb......bbbvv.....xxxx
+xxxxxxxxxxx....vvb....66....bvvxxxxxxxxx
+xxxxxxxxxxxxxxvvvb..llllll..bvvvxxxxxxxx
+xxxxxxxxxvvvvvvvvb..ll45ll..bvvvvvvvvxxx
+xxxxxxxxxccc***+== .l3.2.l..cccccccccxxx
+xxxxxxxxxccc+cccbb....ll....c..$$$$+$*cx
+xxxxxxxxxcc|||cbb...3llll2...cc%*%*c$|cx
+xxxxxxxxxcccccccbbbbbbbbbbbccccccccccccx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: hell hound, necromancer, wizard, orange demon, rotting devil
+MONS: hell knight, great orb of eyes
+
+###########################################################################
+# Farm and country (Matthew Ludivico)
+
+NAME: farm_and_country
+ORIENT: encompass
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxx..........................................xxxxxxxx}.xxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxx............xxxxxx....xxx.......xx...........xxxx..]xxxxxxxxx
+xxxxxxxxxxxxxxx***x...........xxx..xxx............xxxx...........xx..xxxxxxxxxxx
+xxxxxxxxxxxxxxx|*$=...xx.xxxxxxx....xxxxxxxxxx......xx................xxxxxxxxxx
+xxxxxxxxxxxxxxxxxxx....xxxxxxxx......3..xxx.................x..........xxxxxxxxx
+xxxxxxxxxxxxxxxxxx......x........x......xx.........w...................xxxxxxxxx
+xxxxxxxxxxx)......xx...xxx.....xxx......x........www3....3.............xxxxxxxxx
+xxxxxxxxxxxx=xxxxxxxxxxx...xxxxxxxxx..xxx.....wwwww....%%%.............xxxxxxxxx
+xxxxxxxxxx......xxx.......xx.xxxx.x...xxxxxxxwwwwwww..5%%%..........xx.xxxxxxxxx
+xxxxxxxxx.........x..xxxxxxxx.....x........3wwwwwwwww..%%%........xxx..xxxxxxxxx
+xxxxxxxxx....5...xx..x.xxxxx.....xxx........wwwwwwwww..%%%..........xx.xxxxxxxxx
+xxxxxxxxxxx.....xxx..xx..xx........xxxxxxxxxwwwwwwwww..............xxx.xxxxxxxxx
+xxxxxxxxxx........x..x...............xx..xxxxwwwwwwwwwwwwww............xxxxxxxxx
+xxxxxxxxx.............................x.....xxwwwwww3wwwwww............xxxxxxxxx
+xxxxxxxxxxx...x...........5.....7...............ww.......ww.....44....xxxxxxxxxx
+xxxxxxxxxwxx..xx.....622...2.26...6.2...22.6...62..2..226ww.....44xx...xxxxxxxxx
+xxxxxxxxxwwxxxx......2....2.22....2..2...2.2.......22...2ww....xxxx..xxxxxxxxxxx
+xxxxxxxxxwwwwxxx......2...2.2.2...2.22..2.22...22.2.2..22ww.....xxx....xxxxxxxxx
+xxxxxxxxxwwwwwx....4..2...2...........22...277..2..2.2.22ww...........xxxxxxxxxx
+xxxxxxxxxwwwwwxx....42..2....22.4..2..2...2.4..2.22..22.2ww............xxxxxxxxx
+xxxxxxxxxwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww.wwwwwwwwwwwww..2.........xxxxxxxxx
+xxxxxxxxxwwwwwxx.....62....2.26...62.2.2..26...6...22..26..............xxxxxxxxx
+xxxxxxxxxwwwww.........................................................xxxxxxxxx
+xxxxxxxxxwwwwwxx....222.2.22..2.7.......7..............................xxxxxxxxx
+xxxxxxxxxwwwww...........ccccccc+ccccccc...ccc......cc+ccc...xxxxx.....xxxxxxxxx
+xxxxxxxxxwwwwwxx.........c$$*.c$$5$+.5.c...+5c......c%%%%c......xxx3...xxxxxxxxx
+xxxxxxxxxwwwwwx....2.....c$.c+cccccc.%.c...ccc......c%%%%c....xxxxx....xxxxxxxxx
+xxxxxxxxxwwwwwx..........c..c..........c............cccccc......xxx....xxxxxxxxx
+xxxxxxxxxwwxxxxxxx.......ccccc+ccccccccc.........................xx....xxxxxxxxx
+xxxxxxxxxwxx.....xxxx........c...c.................2...................xxxxxxxxx
+xxxxxxxxxxx.........xxxx...........2....xxxx...........................xxxxxxxxx
+xxxxxxxxx..............xxxx..........xxxx..x...........................xxxxxxxxx
+xxxxxxxxx.................xxxxx++xxxxx.....xx............xx...x........xxxxxxxxx
+xxxxxxxxx.....................c..c..........xxxxx..........xxxxx.......xxxxxxxxx
+xxxxxxxxx.......cccc..........c..c...cccc......xxx...........x.........xxxxxxxxx
+xxxxxxxxx.......c..c..........c++c...c..c........xxx.........x.........xxxxxxxxx
+xxxxxxxxx.......c..c..........c..c...c..c..........xxx.................xxxxxxxxx
+xxxxxxxxx....cccc++cccccccccccc++ccccc..ccccccc......xxx...............xxxxxxxxx
+xxxxxxxxx....c..........1.....................c........xxx.............xxxxxxxxx
+xxxxxxxxx.cccc.....w....w....%1.....w.....%...c..........xxx...........xxxxxxxxx
+xxxxxxxxx.c1.+....www..www..%%%....www...%%%1.c...........xxxxxxxxx....xxxxxxxxx
+xxxxxxxxx.cccc.....w....w....%......w.....%...c..................xxx...xxxxxxxxx
+xxxxxxxxx....c.......5........................c....................xxxxxxxxxxxxx
+xxxxxxxxx....ccc....%%%%%....cccccccccccccccccc........................xxxxxxxxx
+xxxxxxxxx......cc...........cc.........................................xxxxxxxxx
+xxxxxxxxx.......cccccc+cccccc..........................................xxxxxxxxx
+xxxxxxxxx........cc.......cc...........................................xxxxxxxxx
+xxxxxxxxx.........cc.....cc.....................cccccccccccccccccccccccxxxxxxxxx
+xxxxxxxxx..........ccc+ccc......................c......vvv.............xxxxxxxxx
+xxxxxxxxx..........ccc.c........................c......v5+...vvvvv.....xxxxxxxxx
+xxxxxxxxx..........ccc.c........................c......vvv...v.5.v.....xxxxxxxxx
+xxxxxxxxxccccccccccccc.ccc......................c............v..5v.....xxxxxxxxx
+xxxxxxxxx..........c.....cccccccccccccccccccccccccccc..........vv+vv...xxxxxxxxx
+xxxxxxxxx..........c............................+................5111..xxxxxxxxx
+xxxxxxxxx..........c.{([.c......................+................5.....xxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: death yak, plant, griffon, killer bee, ogre, oklob plant
+MONS: wandering mushroom
+
+#############################################################################
+# Fort Yaktaur (Matthew Ludivico)
+
+NAME: fort_yaktaur
+ORIENT: southeast
+
+MAP
+.........@....wwwwwwwwwwwwwwwwwxxxxxxxxx
+.ccccc.......ww....wwww....wwwwxxxxxxxxx
+.c$c%c......ww.ccccccccc.......xxxxxxxxx
+.c+c+c......ww.c.%$....ccccccccxxxxxxxxx
+.c...+......ww.c*.115..c$$+|*|cxxxxxxxxx
+.c1..c.....ww..c...55+ccc+cxx=cxxxxxxxxx
+.ccccc.....ww..ccccccc....c|=*cxxxxxxxxx
+............ww.......c5...cxx=cxxxxxxxxx
+....6.ccccc.ww.w...2.+51..c|1.cxxxxxxxxx
+....63+...c..wwww..21+51..c2.2cxxxxxxxxx
+....6.ccccc..wwwwww..c5...cc+ccxxxxxxxxx
+............wwwwwww..c........cxxxxxxxxx
+............wwwwwww..ccccccccccxxxxxxxxx
+...........ww1w..www...........xxxxxxxxx
+.......566.www.....www.........xxxxxxxxx
+.........1ww....ccccc..........xxxxxxxxx
+.....566.w......+...c..........xxxxxxxxx
+.........www....ccccc..........xxxxxxxxx
+...........ww............wwwwwwxxxxxxxxx
+.......3....wwwww......www.....xxxxxxxxx
+......666.......ww...www.......xxxxxxxxx
+.....cc+cc.......wwwww.........xxxxxxxxx
+.....c...c.....................xxxxxxxxx
+.....ccccc.....................xxxxxxxxx
+...............................xxxxxxxxx
+...............................xxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+MONS: yaktaur, death yak, minotaur, random
+MONS: yak, gnoll, random
+
+########################################################################
+# box level (John Savard)
+#
+
+NAME: box_level
+ORIENT: encompass
+
+MAP
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxx.................xx.............x...................^.........xxxxxxxxx
+xxxxxxxxx.................xx...xxxxxx....x.xxxxxxx.xxxxxxxxxxxxxxxxxxx.xxxxxxxxx
+xxxxxxxxx.................xx...xx.0......x.x........x......x.........x.xxxxxxxxx
+xxxxxxxxx..$..............xx...xx........x.x........x.....%x.x..*..xxx.xxxxxxxxx
+xxxxxxxxx......................xx........x.x........x.xxxxxx.x.....x...xxxxxxxxx
+xxxxxxxxx......................xx....%...x.x........x.x......xxxxxxx.x.xxxxxxxxx
+xxxxxxxxx.................xx...xx........x.x........x.x.xxxxxx.......x.xxxxxxxxx
+xxxxxxxxx.................xx...xx........x.x..{.....x.x..............x.xxxxxxxxx
+xxxxxxxxx.............0...xx...xxxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxxxxxxxx.xxxxxxxxx
+xxxxxxxxx.................xx...........................................xxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxx}x.........................>=........xxxxxxxxx
+xxxxxxxxx..................x...xxx.x.xxx+xxxxxxxxxxxxxxxx+xxxxx........xxxxxxxxx
+xxxxxxxxx..xxxxxxxxxxxxxx..x...xxx.x.x0...x..0..............0.x........xxxxxxxxx
+xxxxxxxxx..x............x..x...xxx.x.x....x...................x........xxxxxxxxx
+xxxxxxxxx....xxxxxxxxx..x..x...xxx.x.x....x...................x......8*xxxxxxxxx
+xxxxxxxxx..x.x....0..x..x..x...xxx...x...%x...................x......*|xxxxxxxxx
+xxxxxxxxx..x.x..........x..x...xxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxx..x.x*......x..x..x..........x...........0...x...%............xxxxxxxxx
+xxxxxxxxx..x.xxxxxxxxx..x..=..........x.xxxxxxxxxxxxx.x................xxxxxxxxx
+xxxxxxxxx..x......0.....xxxxxxx.......x.x...x...x...x.x................xxxxxxxxx
+xxxxxxxxx..xxxxxxxxxxxxxxxxxxxx..0....x...x.x.x.x.x.x.x......0.........xxxxxxxxx
+xxxxxxxxx..........^.........xx.......x.x.x.x.x.x.x...+................xxxxxxxxx
+xxxxxxxxxcccccccccccccccccc..xx.......x.x$x...x...xxxxx................xxxxxxxxx
+xxxxxxxxxc...........9....c..xx.......x.x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxc......c............xx.......x.x.x...x..0.....................xxxxxxxxx
+xxxxxxxxxc.....|c............xx.......x.x.x.x.x........................xxxxxxxxx
+xxxxxxxxxc...........9....c..xx.......x.x...x.x........................xxxxxxxxx
+xxxxxxxxxcccccccccccccccccc..xx.......x.xxxxx.x........................xxxxxxxxx
+xxxxxxxxx....................xx.......x.x.....=....................*...xxxxxxxxx
+xxxxxxxxx....................xx.......x.x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.......x.x.x...........................(xxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxx.x$x..xxxx.xxxxxxxxxxxxxxxxxxxx.xxxxxxxxx
+xxxxxxxxx...............................x.x..x.......................x.xxxxxxxxx
+xxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.x..x.xxxxxxxxxxxxx.........x.xxxxxxxxx
+xxxxxxxxx.............)xxx................x..x.xxxxxxxxxxxxx.........x.xxxxxxxxx
+xxxxxxxxx..............xxx.xxxxxxxxxxxxxxxx..x.xxxxxxxxxxxxx.........x.xxxxxxxxx
+xxxxxxxxx..............xxx...................x.x...........xxxxx+xxxxx.xxxxxxxxx
+xxxxxxxxx..............xxxxxxxxxxxxxxxxxxxxxxx.x..$........x.........x.xxxxxxxxx
+xxxxxxxxx......9.......xxxxxxxxxxxxxxxxxxxxxxx.x...........x........%x.xxxxxxxxx
+xxxxxxxxx..............xxxxxxxxxxxxxxxxxxxxxxx.x.0.........x0........x.xxxxxxxxx
+xxxxxxxxx..............xxxxxxxxxxxxxxxxxxxxxxx.x.......$...x.........x.xxxxxxxxx
+xxxxxxxxx..............xxxxxxxxxxxxxxxxxxxxxxx.x...........xxxxxxxxxxx.xxxxxxxxx
+xxxxxxxxx..............xxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxx.x...........xxxxxxxxx
+xxxxxxxxx..............xxxxxxxxxxxxxxxxxxxxxxx.............x...........xxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx+xxxxxxxxxxxxxxxxxx
+xxxxxxxxx..............................................................xxxxxxxxx
+xxxxxxxxx.xxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxx.xxxxxxx=xxxxxx.xxxxxx.xxxxxxxxx
+xxxxxxxxx.....xx.................xxxxxxxxxxx.......x........x.....x....xxxxxxxxx
+xxxxxxxxx....0xx.................xxxxxxxxxxx.%.....x.0......x...0.x....xxxxxxxxx
+xxxxxxxxx.....xx.9...............xxxxxxxxxxx.......x........x.%...x..$.xxxxxxxxx
+xxxxxxxxx.....xx.................xxxxxxxxxxx.......x........x.....x....xxxxxxxxx
+xxxxxxxxx.....xx.................xxxxxxxxxxx.......x........x.....x..0.xxxxxxxxx
+xxxxxxxxx....0xx.................xxxxxxxxxxx.......x$.......x.....x....xxxxxxxxx
+xxxxxxxxx]....xx................*xxxxxxxxxxx......[x........x.....x$...xxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+
+##############################################################################
+# Minivaults
+##############################################################################
+#
+# NOTE: *Cannot* place 8,9 or 0 monsters in branch vaults which neither use the
+# normal mons_level function or are around level 35, or generation will crash.
+#
+# [dshaligram] Minivaults were traditionally drawn after rotating the vault by
+# 90 degrees anticlockwise. Under the new dungeon vault handling, the map may
+# be freely rotated and mirrored to any position (20061105).
+#
+# Minivaults are traditionally 12x12 (hardcoded limitation in dungeon.cc). Under
+# the new rules they can be any size, but the smaller the better. I'd recommend
+# no larger than 35x30 or so.
+#
+# NOTE: Minivaults must NOT have an ORIENT: attribute. Including an ORIENT:
+# attribute makes the map a normal vault, and mayhem can result.
+
+NAME: minivault_1
+
+MAP
+............
+..xxxx=xxx..
+.xx..x...xx.
+.x....x...x.
+.x...x....x.
+.xx.x*x.x.=.
+.=.x.x*x.xx.
+.x....x...x.
+.x...x....x.
+.xx...x..xx.
+..xxx=xxxx..
+............
+ENDMAP
+
+###################################
+
+NAME: minivault_2
+
+MAP
+............
+..xxxx.xxxx.
+..xx.....xx.
+..x.......x.
+..x.......x.
+......C.....
+..x.......x.
+..x.......x.
+..xx.....xx.
+..xxxx.xxxx.
+............
+............
+ENDMAP
+
+###################################
+
+NAME: minitemple
+
+# More common than the others.
+CHANCE: 20
+
+MAP
+............
+.cccccccccc.
+.cccccccccc.
+.cBcBcBcBcc.
+.G.c.c.c.Bc.
+.........Bc.
+.........Bc.
+.G.c.c.c.Bc.
+.cBcBcBcBcc.
+.cccccccccc.
+.cccccccccc.
+............
+ENDMAP
+
+###################################
+
+NAME: minivault_4
+
+MAP
+............
+....xwxx....
+..xxxwwxwx..
+..xwwwwwwx..
+.xwwxwwxwxx.
+.xwwwwwwwwx.
+.xwwxwwwxww.
+.xxwwwwwwxx.
+..wwwwxwwx..
+..xxxwwxxw..
+....xxww....
+............
+ENDMAP
+
+###################################
+
+NAME: minivault_5
+
+MAP
+............
+.x.xxxxxxxx.
+.x.x......x.
+.x.x.xxxx.x.
+.x.x.x**x.x.
+.x.x.x**x.x.
+.x.x.xx.x.x.
+.x.x....x.x.
+.x.xxxxxx.x.
+.x........x.
+.xxxxxxxxxx.
+............
+ENDMAP
+
+###################################
+# Wizard's laboratory
+NAME: minivault_6
+
+MAP
+............
+.ccccccc+cc.
+.c........c.
+.c........c.
+.c..1.....c.
+.c........c.
+.cc+ccccccc.
+.c***c3232c.
+.c|**+2223c.
+.c||*c3322c.
+.cccccccccc.
+............
+ENDMAP
+
+MONS: wizard, small abomination, large abomination
+
+###################################
+# Beehive minivault
+
+NAME: minivault_7
+
+MAP
+............
+....aaaa....
+..a2a2aaaa..
+..aaRa3a2a..
+.aa2aRa2aaa.
+.a3aRa1aRa2.
+.aa3aRaRa2a.
+.aaa2a2a3aa.
+..a3aRa2aa..
+...aa2aa2a..
+....aaaa....
+............
+ENDMAP
+
+MONS: queen bee, killer bee, killer bee larva
+
+###################################
+# Lava pond
+NAME: minivault_8
+
+MAP
+x.x.x.x.x.x.
+.c.c.c.c.c.x
+x...l1l...c.
+.c.llllll..x
+x.lllllll1c.
+.c.llFGll..x
+x..llGFll.c.
+.c1lllllll.x
+x..llllll.c.
+.c...l1l...x
+x.c.c.c.c.c.
+.x.x.x.x.x.x
+ENDMAP
+
+MONS: molten gargoyle
+
+###################################
+# Evil zoo
+
+NAME: minivault_9
+DEPTH: 15-27
+
+MAP
+............
+.==========.
+.==========.
+.==========.
+.===8888===.
+.===8998===.
+.===8998===.
+.===8888===.
+.==========.
+.==========.
+.==========.
+............
+ENDMAP
+
+###################################
+
+NAME: minivault_10
+
+MAP
+............
+.xxxx..xxxx.
+.x**x..x**x.
+.x**+..+**x.
+.xx+x..x+xx.
+............
+............
+.xx+x..x+xx.
+.x**+..+**x.
+.x**x..x**x.
+.xxxx..xxxx.
+............
+ENDMAP
+
+###################################
+# Multicoloured onion
+
+NAME: minivault_11
+
+MAP
+............
+.+xxxxxxxx+.
+.x........x.
+.x.+cccc+.x.
+.x.c....c.x.
+.x.c.bb.c.x.
+.x.c.bb.c.x.
+.x.c....c.x.
+.x.+cccc+.x.
+.x........x.
+.+xxxxxxxx+.
+............
+ENDMAP
+
+###################################
+# Closed-box minivault
+
+NAME: minivault_12
+
+MAP
+............
+.xxxxxxxxxx.
+.x>9$9$9$<x.
+.x.$9$9$.$x.
+.x$.****$.x.
+.x.$*||*.$x.
+.x$.*||*$.x.
+.x.$****.$x.
+.x$9$9$9$.x.
+.x<$9$9$9>x.
+.xxxxxxxxxx.
+............
+ENDMAP
+
+###################################
+# Little trap spiral
+
+NAME: minivault_13
+
+MAP
+............
+.xxxxxxxxxx.
+.=.^x..=.9x.
+.x.$=.^x..x.
+.xxxxxxxx=x.
+.x.8+|0x8.x.
+.x8$x.|x..x.
+.xx=xxxx=xx.
+.x.9=^.x..x.
+.x..x.^=9.x.
+.xxxxxxxxxx.
+............
+ENDMAP
+
+###################################
+# Water cross
+
+NAME: minivault_14
+
+MAP
+............
+.wwwww.wwww.
+.wwwww.wwww.
+.wwwww.wwww.
+.wwwww.wwww.
+.......wwww.
+.wwww.......
+.wwww.wwwww.
+.wwww.wwwww.
+.wwww.wwwww.
+.wwww.wwwww.
+............
+ENDMAP
+
+###################################
+# Lava pond
+
+NAME: minivault_15
+
+MAP
+............
+............
+....lll.....
+...vvlvv....
+..lv|*|vl...
+..ll*S*ll...
+..lv|*|vl...
+...vvlvv....
+....lll.....
+............
+............
+............
+ENDMAP
+
+###################################
+
+NAME: minivault_16
+
+MAP
+............
+............
+............
+............
+............
+............
+......S.....
+............
+............
+............
+............
+............
+ENDMAP
+
+###################################
+
+NAME: minivault_17
+
+MAP
+............
+............
+............
+............
+............
+.....F......
+............
+............
+............
+............
+............
+............
+ENDMAP
+
+###################################
+
+NAME: minivault_18
+
+MAP
+............
+............
+............
+............
+............
+.....H......
+............
+............
+............
+............
+............
+............
+ENDMAP
+
+###################################
+
+NAME: minivault_19
+
+MAP
+............
+.xx......xx.
+.xxx....xxx.
+..xxx..xxx..
+...xxxxxx...
+....xxxx....
+....xxxx....
+...xxxxxx...
+..xxx..xxx..
+.xxx....xxx.
+.xx......xx.
+............
+ENDMAP
+
+###################################
+
+NAME: minivault_20
+MAP
+............
+.xxxx..xxxx.
+.x........x.
+.x..xxxx..x.
+.x.x....x.x.
+...x.x9.x...
+...x.9x.x...
+.x.x....x.x.
+.x..xxxx..x.
+.x........x.
+.xxxx..xxxx.
+............
+ENDMAP
+
+###################################
+
+NAME: minivault_21
+
+MAP
+............
+.^xxxxxxxx^.
+.x........x.
+.x.cccccc.x.
+.x.c|..<c.x.
+.x.c.**.c.x.
+.x.c.**.c.x.
+.x.c>..|c.x.
+.x.cccccc.x.
+.x........x.
+.^xxxxxxxx^.
+............
+ENDMAP
+
+###################################
+
+NAME: minivault_22
+
+MAP
+............
+.....xx.....
+...xxxxxx...
+..x^x..x^x..
+..xx.xx.xx..
+.xx.x$$x.xx.
+.xx.x$$x.xx.
+..xx.xx.xx..
+..x^x..x^x..
+...xxxxxx...
+.....xx.....
+............
+ENDMAP
+
+###################################
+
+NAME: minivault_23
+
+MAP
+x.x.x.x.x.x.
+.x.x.x.x.x.x
+x.x.x.x.x.x.
+.x.x.x.x.x.x
+x.x.x.x.x.x.
+.x.x.x.x.x.x
+x.x.x.x.x.x.
+.x.x.x.x.x.x
+x.x.x.x.x.x.
+.x.x.x.x.x.x
+x.x.x.x.x.x.
+.x.x.x.x.x.x
+ENDMAP
+
+###################################
+
+NAME: minivault_24
+
+MAP
+............
+....xxxx....
+....xxxx....
+....xxxx....
+.xxxx.x.xxx.
+.xxx.x.xxxx.
+.xxxx.x.xxx.
+.xxx.x.xxxx.
+....xxxx....
+....xxxx....
+....xxxx....
+............
+ENDMAP
+
+###################################
+
+NAME: minivault_25
+
+MAP
+............
+.xx+xxxxxxx.
+.x........x.
+.x........+.
+.x........x.
+.x........x.
+.x........x.
+.x........x.
+.+........x.
+.x........x.
+.xxxxxxx+xx.
+............
+ENDMAP
+
+###################################
+
+NAME: minivault_26
+
+MAP
+c..........c
+.c...cc...c.
+..c..cc..c..
+...c....c...
+....c..c....
+.cc..cc..cc.
+.cc..cc..cc.
+....c..c....
+...c....c...
+..c..cc..c..
+.c...cc...c.
+c..........c
+ENDMAP
+
+###################################
+
+NAME: minivault_27
+
+MAP
+............
+.x.xxxxxxxx.
+.x........x.
+.xxxxxxxx.x.
+.x........x.
+.x.xxxxxxxx.
+.x........x.
+.xxxxxxxx.x.
+.x........x.
+.x.xxxxxxxx.
+............
+............
+ENDMAP
+
+###################################
+
+NAME: minivault_28
+
+MAP
+............
+.xxxx.xxxx..
+.x.......x..
+.x..999..x..
+.x.9...9.x..
+...9.I.9....
+.x.9...9.x..
+.x..999..x..
+.x.......x..
+.xxxx.xxxx..
+............
+............
+ENDMAP
+
+###################################
+# Anthill
+
+NAME: minivault_29
+
+MAP
+.3......3...
+...x.xx.x.2.
+.xxx2xxxxx..
+.xxxx42xxx2.
+.2xx243432x3
+.xx421424xx.
+3xx423242x..
+.x2x3243xxx.
+.x2xx42422x.
+..xxxxxxxx2.
+...x2xxxx3..
+.3.......33.
+ENDMAP
+
+MONS: queen ant, soldier ant, giant ant, ant larva
+
+###################################
+# Solitary fountain
+
+NAME: minivault_30
+
+MAP
+............
+............
+............
+............
+............
+.....?......
+............
+............
+............
+............
+............
+............
+ENDMAP
+
+SYMBOL: TUV
+
+###################################
+# jmf: Multi-god temple thing
+
+NAME: multi_god_temple
+
+MAP
+............
+.=xxxxxxxx=.
+.x9......9x.
+.xT......Tx.
+.x..C..C..x.
+.xT......Tx.
+.xxxxxxxxxx.
+.xxx$$$$xxx.
+.xx8....8xx.
+..xx....xx..
+...xG..Gx...
+............
+ENDMAP
+
+###################################
+# jmf: Another multi-god temple thing
+
+NAME: multi_god_temple2
+
+MAP
+............
+..vvvvvvvv..
+.vv......vv.
+.v..x..x..v.
+.v.Cx..xC.v.
+.v..x..x..v.
+.vT8x..x8Tv.
+.vvvx==xvvv.
+...Gx99xG...
+...+*99*+...
+...GxxxxG...
+............
+ENDMAP
+
+#############################################################################
+# Pandemonium lesser demon vaults
+#############################################################################
+# Pandemonium demon vaults are selected by tag. They must have the tag "pan",
+# or they won't even be considered. Tags are case-sensitive.
+#
+# Tagging these levels also ensures they won't be generated in the main
+# dungeon.
+
+NAME: rand_demon_1
+TAGS: pan
+MONS: pandemonium demon, random, random, random, random, random
+
+MAP
+............
+.xx.xx.x.xx.
+..x.x..x.x..
+..x.x..x.x..
+..x.x..x.x..
+..x.x..x.x..
+..x.x1.x.x..
+..x.x..x.x..
+..x.x..x.x..
+..x.x..x.x..
+.xx.x.xx.xx.
+............
+ENDMAP
+
+###################################
+
+NAME: rand_demon_2
+TAGS: pan
+MONS: pandemonium demon, greater demon, common demon
+MONS: common demon, random, random
+
+MAP
+............
+.xxxxxxxx3x.
+.3.....xx.x.
+.xxxxxx4x.x.
+.xx4x..xx.x.
+.x.x.22.x.x.
+.x.x.12.x.x.
+.x.xx..x4xx.
+.x.x4xxxxxx.
+.x.xx.....3.
+.x3xxxxxxxx.
+............
+ENDMAP
+
+###################################
+
+NAME: rand_demon_3
+TAGS: pan
+MONS: pandemonium demon, common demon, common demon
+
+MAP
+............
+.x.x.x3x.x..
+..x.x3x3x.x.
+.x.x.x2x.x..
+..x3x2x2x3x.
+.x3x2x1x2x3.
+..x3x2x2x3x.
+.x.x.x2x3x..
+..x.x3x3x.x.
+.x.x.x3x.x..
+..x.x.x.x.x.
+............
+ENDMAP
+
+###################################
+
+NAME: rand_demon_4
+TAGS: pan
+MONS: pandemonium demon, any demon, any demon
+
+MAP
+............
+.xxxxxxxxx..
+.x$=*=3=|x..
+.xxxxxxx=x..
+.x2=3=2x|x..
+.x=xxxxx=x..
+.x3=*x1=Px..
+.x=x=xxxxx..
+.x*x2=3=2=..
+.xxxxxxxxx..
+............
+............
+ENDMAP
+
+###################################
+
+NAME: rand_demon_5
+TAGS: pan
+MONS: pandemonium demon, any demon, any demon
+
+MAP
+............
+...xxxxxx...
+..xx....xx..
+.xx......xx.
+.x..3232..x.
+.x..2|P3..x.
+.x..3P|2..x.
+.x..2123..x.
+.xx......xx.
+..xx....xx..
+...xxxxxx...
+............
+ENDMAP
+
+###################################
+
+NAME: rand_demon_6
+TAGS: pan
+MONS: pandemonium demon, any demon, any demon
+
+MAP
+............
+............
+......2.....
+............
+.3..........
+..........2.
+.....1......
+............
+............
+.2.......3..
+............
+............
+ENDMAP
+
+###################################
+
+NAME: rand_demon_7
+TAGS: pan
+MONS: pandemonium demon, any demon, greater demon
+
+MAP
+............
+.xxx....xxx.
+.x|xx=xxx|x.
+.xx=....=xx.
+..x.x==x.x..
+..x.=12=.=..
+..=.=23=.x..
+..x.x==x.x..
+.xx=....=xx.
+.x|xxx=xx|x.
+.xxx....xxx.
+............
+ENDMAP
+
+###################################
+
+NAME: rand_demon_8
+TAGS: pan
+MONS: pandemonium demon, greater demon, any demon
+
+MAP
+............
+....xxxxxxx.
+..xxx....1x.
+.xx..2....x.
+.x........x.
+.xx.......x.
+..xx33..2.x.
+....33...xx.
+.....x...x..
+..F..xx.xx..
+......xxx...
+............
+ENDMAP
+
+###################################
+
+NAME: rand_demon_9
+TAGS: pan
+MONS: pandemonium demon, any demon, greater demon
+
+MAP
+............
+.xxxxxxxxxx.
+.x2=3=3=3xx.
+.x=xxxxxx2x.
+.x3x^^^^x=x.
+.x=x^P^^x2x.
+.x3x^^1^x=x.
+.x=x^^^^x3x.
+.x2xxxx=x=x.
+.xx2=2=3x3x.
+.xxxxxxxx=x.
+............
+ENDMAP
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index 8bfdb776d8..545ec6ffc3 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -3,6 +3,8 @@
* Summary: Debug and wizard related functions.
* Written by: Linley Henzell and Jesse Jones
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <4> 14/12/99 LRH Added cast_spec_spell_name()
@@ -19,8 +21,13 @@
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
+#include <time.h>
#include <ctype.h>
+#ifdef UNIX
+#include <errno.h>
+#endif
+
#ifdef DOS
#include <conio.h>
#endif
@@ -28,9 +35,13 @@
#include "externs.h"
#include "direct.h"
+#include "describe.h"
#include "dungeon.h"
+#include "fight.h"
#include "invent.h"
#include "itemname.h"
+#include "itemprop.h"
+#include "item_use.h"
#include "items.h"
#include "misc.h"
#include "monplace.h"
@@ -45,10 +56,8 @@
#include "spl-cast.h"
#include "spl-util.h"
#include "stuff.h"
-
-#ifndef WIZARD
-#define WIZARD
-#endif
+#include "travel.h"
+#include "version.h"
#if DEBUG && WIN
#define MyDebugBreak() _asm {int 3}
@@ -74,23 +83,11 @@ static HANDLE sConsole = NULL;
static void BreakStrToDebugger(const char *mesg)
{
-#if OSX
+#if OSX || defined(__MINGW32__)
fprintf(stderr, mesg);
// raise(SIGINT); // this is what DebugStr() does on OS X according to Tech Note 2030
int* p = NULL; // but this gives us a stack crawl...
*p = 0;
-#elif MAC
- unsigned char s[50];
-
- int len = strlen(mesg);
-
- if (len > 255)
- len = 255;
-
- s[0] = (Byte) len;
- BlockMoveData(mesg, s + 1, len);
-
- DebugStr(s);
#elif WIN
MSG msg; // remove pending quit messages so the message box displays
@@ -309,10 +306,6 @@ static void TraceString(const char *mesg)
}
#endif
-#if MAC
-#pragma mark -
-#endif
-
// ========================================================================
// Global Functions
// ========================================================================
@@ -327,10 +320,6 @@ void AssertFailed(const char *expr, const char *file, int line)
{
char mesg[512];
-#if MAC
- sprintf(mesg, "ASSERT(%s) in %s at line %d failed.", expr, file, line);
-
-#else
const char *fileName = file + strlen(file); // strip off path
while (fileName > file && fileName[-1] != '\\')
@@ -338,7 +327,6 @@ void AssertFailed(const char *expr, const char *file, int line)
sprintf(mesg, "ASSERT(%s) in '%s' at line %d failed.", expr, fileName,
line);
-#endif
BreakStrToDebugger(mesg);
}
@@ -386,17 +374,11 @@ void TRACE(const char *format, ...)
}
#endif // DEBUG
-//---------------------------------------------------------------
-//
-// debug_prompt_for_monster
-//
-//---------------------------------------------------------------
#ifdef WIZARD
+
static int debug_prompt_for_monster( void )
{
char specs[80];
- char obj_name[ ITEMNAME_SIZE ];
- char *ptr;
mpr( "(Hint: 'generated' names, eg 'orc zombie', won't work)", MSGCH_PROMPT );
mpr( "Which monster by name? ", MSGCH_PROMPT );
@@ -405,28 +387,7 @@ static int debug_prompt_for_monster( void )
if (specs[0] == '\0')
return (-1);
- int mon = -1;
-
- for (int i = 0; i < NUM_MONSTERS; i++)
- {
- moname( i, true, DESC_PLAIN, obj_name );
-
- ptr = strstr( strlwr(obj_name), strlwr(specs) );
- if (ptr != NULL)
- {
- mpr( obj_name );
- if (ptr == obj_name)
- {
- // we prefer prefixes over partial matches
- mon = i;
- break;
- }
- else
- mon = i;
- }
- }
-
- return (mon);
+ return (get_monster_by_name(specs));
}
#endif
@@ -494,7 +455,7 @@ void debug_change_species( void )
int sp = -1;
- for (int i = SP_HUMAN; i < NUM_SPECIES; i++)
+ for (i = SP_HUMAN; i < NUM_SPECIES; i++)
{
char sp_name[80];
strncpy( sp_name, species_name(i, you.experience_level), sizeof( sp_name ) );
@@ -626,7 +587,8 @@ void create_spec_monster(void)
if (mon == -1)
canned_msg( MSG_OK );
else
- create_monster( mon, 0, BEH_SLEEP, you.x_pos, you.y_pos, MHITNOT, 250 );
+ create_monster( mon, 0, BEH_SLEEP,
+ you.x_pos, you.y_pos, MHITNOT, 250, true );
} // end create_spec_monster()
#endif
@@ -650,7 +612,8 @@ void create_spec_monster_name(void)
}
else
{
- create_monster(mon, 0, BEH_SLEEP, you.x_pos, you.y_pos, MHITNOT, 250);
+ create_monster(mon, 0, BEH_SLEEP,
+ you.x_pos, you.y_pos, MHITNOT, 250, false);
}
} // end create_spec_monster_name()
#endif
@@ -736,7 +699,7 @@ void create_spec_object(void)
MSGCH_PROMPT);
mpr("= - jewellery ! - potions : - books | - staves 0 - The Orb",
MSGCH_PROMPT);
- mpr("} - miscellany X - corpses %% - food $ - gold ESC - exit",
+ mpr("} - miscellany X - corpses % - food $ - gold ESC - exit",
MSGCH_PROMPT);
mpr("What class of item? ", MSGCH_PROMPT);
@@ -814,7 +777,7 @@ void create_spec_object(void)
{
mon = debug_prompt_for_monster();
- if (mon == -1)
+ if (mon == -1 || mon == MONS_PROGRAM_BUG)
{
mpr( "No such monster." );
return;
@@ -825,7 +788,7 @@ void create_spec_object(void)
mitm[thing_created].plus = mon;
mitm[thing_created].plus2 = 0;
mitm[thing_created].special = 210;
- mitm[thing_created].colour = mons_colour(mon);;
+ mitm[thing_created].colour = mons_class_colour(mon);;
mitm[thing_created].quantity = 1;
mitm[thing_created].flags = 0;
}
@@ -856,13 +819,11 @@ void create_spec_object(void)
{
if (strstr( "naga barding", specs ))
{
- mitm[thing_created].sub_type = ARM_BOOTS;
- mitm[thing_created].plus2 = TBOOT_NAGA_BARDING;
+ mitm[thing_created].sub_type = ARM_NAGA_BARDING;
}
else if (strstr( "centaur barding", specs ))
{
- mitm[thing_created].sub_type = ARM_BOOTS;
- mitm[thing_created].plus2 = TBOOT_CENTAUR_BARDING;
+ mitm[thing_created].sub_type = ARM_CENTAUR_BARDING;
}
else if (strstr( "wizard's hat", specs ))
{
@@ -972,6 +933,14 @@ void create_spec_object(void)
mitm[thing_created].plus = 24;
break;
+ case OBJ_STAVES:
+ if (item_is_rod( mitm[thing_created] ))
+ {
+ mitm[thing_created].plus = MAX_ROD_CHARGE * ROD_CHARGE_MULT;
+ mitm[thing_created].plus2 = MAX_ROD_CHARGE * ROD_CHARGE_MULT;
+ }
+ break;
+
case OBJ_MISCELLANY:
// Runes to "demonic", decks have 50 cards, ignored elsewhere?
mitm[thing_created].plus = 50;
@@ -1012,7 +981,7 @@ void tweak_object(void)
char specs[50];
char keyin;
- int item = prompt_invent_item( "Tweak which item? ", -1 );
+ int item = prompt_invent_item("Tweak which item? ", MT_INVSELECT, -1);
if (item == PROMPT_ABORT)
{
canned_msg( MSG_OK );
@@ -1031,7 +1000,7 @@ void tweak_object(void)
item_name( you.inv[item], DESC_INVENTORY_EQUIP, info );
mpr( info );
- mpr( "a - plus b - plus2 c - special d - quantity ESC - exit",
+ mpr( "a - plus b - plus2 c - special d - quantity e - flags ESC - exit",
MSGCH_PROMPT );
mpr( "Which field? ", MSGCH_PROMPT );
@@ -1045,6 +1014,8 @@ void tweak_object(void)
field_ptr = &(you.inv[item].special);
else if (keyin == 'd')
field_ptr = &(you.inv[item].quantity);
+ else if (keyin == 'e')
+ field_ptr = &(you.inv[item].flags);
else if (keyin == ESCAPE || keyin == ' '
|| keyin == '\r' || keyin == '\n')
{
@@ -1052,11 +1023,11 @@ void tweak_object(void)
return;
}
- if (keyin >= 'a' && keyin <= 'd')
+ if (keyin >= 'a' && keyin <= 'e')
break;
}
- if (keyin != 'c')
+ if (keyin != 'c' && keyin != 'e')
{
const short *const ptr = static_cast< short * >( field_ptr );
snprintf( info, INFO_SIZE, "Old value: %d (0x%04x)", *ptr, *ptr );
@@ -1081,7 +1052,7 @@ void tweak_object(void)
if (new_value == 0 && end == specs)
return;
- if (keyin != 'c')
+ if (keyin != 'c' && keyin != 'e')
{
short *ptr = static_cast< short * >( field_ptr );
*ptr = new_value;
@@ -1708,3 +1679,571 @@ void error_message_to_player(void)
mpr("I suggest you leave this level then save as soon as possible.");
} // end error_message_to_player()
+
+#ifdef WIZARD
+
+static int create_fsim_monster(int mtype, int hp)
+{
+ const int mi =
+ create_monster( mtype, 0, BEH_HOSTILE, you.x_pos, you.y_pos,
+ MHITNOT, 250 );
+
+ if (mi == -1)
+ return (mi);
+
+ monsters *mon = &menv[mi];
+ mon->hit_points = mon->max_hit_points = hp;
+ return (mi);
+}
+
+static skill_type fsim_melee_skill(const item_def *item)
+{
+ skill_type sk = SK_UNARMED_COMBAT;
+ if (item)
+ sk = weapon_skill(*item);
+ return (sk);
+}
+
+static void fsim_set_melee_skill(int skill, const item_def *item)
+{
+ you.skills[fsim_melee_skill(item)] = skill;
+ you.skills[SK_FIGHTING] = skill * 15 / 27;
+}
+
+static void fsim_set_ranged_skill(int skill, const item_def *item)
+{
+ you.skills[range_skill(*item)] = skill;
+ you.skills[SK_RANGED_COMBAT] = skill * 15 / 27;
+}
+
+static void fsim_item(FILE *out,
+ bool melee,
+ const item_def *weap,
+ int wskill, unsigned long damage,
+ long iterations, long hits,
+ int maxdam, unsigned long time)
+{
+ double hitdam = hits? double(damage) / hits : 0.0;
+ int avspeed = (int) (time / iterations);
+ fprintf(out, " %2d | %3ld%% | %5.2f | %5.2f | %5.2f | %3d | %2ld\n",
+ wskill,
+ 100 * hits / iterations,
+ double(damage) / iterations,
+ hitdam,
+ double(damage) * player_speed() / avspeed / iterations,
+ maxdam,
+ time / iterations);
+}
+
+static bool fsim_ranged_combat(FILE *out, int wskill, int mi,
+ const item_def *item, int missile_slot)
+{
+ monsters &mon = menv[mi];
+ unsigned long cumulative_damage = 0L;
+ unsigned long time_taken = 0L;
+ long hits = 0L;
+ int maxdam = 0;
+
+ const int thrown = missile_slot == -1? get_fire_item_index() : missile_slot;
+ if (thrown == ENDOFPACK || thrown == -1)
+ {
+ mprf("No suitable missiles for combat simulation.");
+ return (false);
+ }
+
+ fsim_set_ranged_skill(wskill, item);
+
+ no_messages mx;
+ const long iter_limit = Options.fsim_rounds;
+ const int hunger = you.hunger;
+ for (long i = 0; i < iter_limit; ++i)
+ {
+ mon.hit_points = mon.max_hit_points;
+ bolt beam;
+ you.time_taken = player_speed();
+ if (throw_it(beam, thrown, &mon))
+ hits++;
+ you.hunger = hunger;
+ time_taken += you.time_taken;
+
+ int damage = (mon.max_hit_points - mon.hit_points);
+ cumulative_damage += damage;
+ if (damage > maxdam)
+ maxdam = damage;
+ }
+ fsim_item(out, false, item, wskill, cumulative_damage,
+ iter_limit, hits, maxdam, time_taken);
+
+ return (true);
+}
+
+static bool fsim_melee_combat(FILE *out, int wskill, int mi,
+ const item_def *item)
+{
+ monsters &mon = menv[mi];
+ unsigned long cumulative_damage = 0L;
+ unsigned long time_taken = 0L;
+ long hits = 0L;
+ int maxdam = 0;
+
+ fsim_set_melee_skill(wskill, item);
+
+ no_messages mx;
+ const long iter_limit = Options.fsim_rounds;
+ const int hunger = you.hunger;
+ for (long i = 0; i < iter_limit; ++i)
+ {
+ mon.hit_points = mon.max_hit_points;
+ you.time_taken = player_speed();
+ if (you_attack(mi, true))
+ hits++;
+
+ you.hunger = hunger;
+ time_taken += you.time_taken;
+
+ int damage = (mon.max_hit_points - mon.hit_points);
+ cumulative_damage += damage;
+ if (damage > maxdam)
+ maxdam = damage;
+ }
+ fsim_item(out, true, item, wskill, cumulative_damage, iter_limit, hits,
+ maxdam, time_taken);
+
+ return (true);
+}
+
+static bool debug_fight_simulate(FILE *out, int wskill, int mi, int miss_slot)
+{
+ int weapon = you.equip[EQ_WEAPON];
+ const item_def *iweap = weapon != -1? &you.inv[weapon] : NULL;
+
+ if (iweap && iweap->base_type == OBJ_WEAPONS
+ && is_range_weapon(*iweap))
+ return fsim_ranged_combat(out, wskill, mi, iweap, miss_slot);
+ else
+ return fsim_melee_combat(out, wskill, mi, iweap);
+}
+
+static const item_def *fsim_weap_item()
+{
+ const int weap = you.equip[EQ_WEAPON];
+ if (weap == -1)
+ return NULL;
+
+ return &you.inv[weap];
+}
+
+static std::string fsim_wskill()
+{
+ const item_def *iweap = fsim_weap_item();
+ return iweap && iweap->base_type == OBJ_WEAPONS
+ && is_range_weapon(*iweap)?
+ skill_name( range_skill(*iweap) ) :
+ iweap? skill_name( fsim_melee_skill(iweap) ) :
+ skill_name( SK_UNARMED_COMBAT );
+}
+
+static std::string fsim_weapon(int missile_slot)
+{
+ char item_buf[ITEMNAME_SIZE];
+ if (you.equip[EQ_WEAPON] != -1)
+ {
+ const item_def &weapon = you.inv[ you.equip[EQ_WEAPON] ];
+ item_name(weapon, DESC_PLAIN, item_buf, true);
+
+ if (is_range_weapon(weapon))
+ {
+ const int missile =
+ missile_slot == -1? get_fire_item_index() :
+ missile_slot;
+ if (missile < ENDOFPACK)
+ {
+ std::string base = item_buf;
+ base += " with ";
+ in_name(missile, DESC_PLAIN, item_buf, true);
+ return (base + item_buf);
+ }
+ }
+ }
+ else
+ {
+ strncpy(item_buf, "unarmed", sizeof item_buf);
+ }
+ return (item_buf);
+}
+
+static std::string fsim_time_string()
+{
+ time_t curr_time = time(NULL);
+ struct tm *ltime = localtime(&curr_time);
+ if (ltime)
+ {
+ char buf[100];
+ snprintf(buf, sizeof buf, "%4d%02d%02d/%2d:%02d:%02d",
+ ltime->tm_year + 1900,
+ ltime->tm_mon + 1,
+ ltime->tm_mday,
+ ltime->tm_hour,
+ ltime->tm_min,
+ ltime->tm_sec);
+ return (buf);
+ }
+ return ("");
+}
+
+static void fsim_mon_stats(FILE *o, const monsters &mon)
+{
+ char buf[ITEMNAME_SIZE];
+ fprintf(o, "Monster : %s\n",
+ moname(mon.type, true, DESC_PLAIN, buf));
+ fprintf(o, "HD : %d\n", mon.hit_dice);
+ fprintf(o, "AC : %d\n", mon.armour_class);
+ fprintf(o, "EV : %d\n", mon.evasion);
+}
+
+static void fsim_title(FILE *o, int mon, int ms)
+{
+ char buf[ITEMNAME_SIZE];
+ fprintf(o, CRAWL " version " VERSION "\n\n");
+ fprintf(o, "Combat simulation: %s %s vs. %s (%ld rounds) (%s)\n",
+ species_name(you.species, you.experience_level),
+ you.class_name,
+ moname(menv[mon].type, true, DESC_PLAIN, buf),
+ Options.fsim_rounds,
+ fsim_time_string().c_str());
+ fprintf(o, "Experience: %d\n", you.experience_level);
+ fprintf(o, "Strength : %d\n", you.strength);
+ fprintf(o, "Intel. : %d\n", you.intel);
+ fprintf(o, "Dexterity : %d\n", you.dex);
+ fprintf(o, "Base speed: %d\n", player_speed());
+ fprintf(o, "\n");
+ fsim_mon_stats(o, menv[mon]);
+ fprintf(o, "\n");
+ fprintf(o, "Weapon : %s\n", fsim_weapon(ms).c_str());
+ fprintf(o, "Skill : %s\n", fsim_wskill().c_str());
+ fprintf(o, "\n");
+ fprintf(o, "Skill | Accuracy | Av.Dam | Av.HitDam | Eff.Dam | Max.Dam | Av.Time\n");
+}
+
+static int cap_stat(int stat)
+{
+ return (stat < 1 ? 1 :
+ stat > 127 ? 127 :
+ stat);
+}
+
+static bool debug_fight_sim(int mindex, int missile_slot)
+{
+ FILE *ostat = fopen("fight.stat", "a");
+ if (!ostat)
+ {
+ // I'm not sure what header provides errno on djgpp,
+ // and it's insufficiently important for a wizmode-only
+ // feature.
+#ifndef DOS
+ mprf("Can't write fight.stat: %s", strerror(errno));
+#endif
+ return (false);
+ }
+
+ bool success = true;
+ FixedVector<unsigned char, 50> skill_backup = you.skills;
+ int ystr = you.strength,
+ yint = you.intel,
+ ydex = you.dex;
+ int yxp = you.experience_level;
+
+ for (int i = SK_FIGHTING; i < NUM_SKILLS; ++i)
+ you.skills[i] = 0;
+
+ you.experience_level = Options.fsim_xl;
+ if (you.experience_level < 1)
+ you.experience_level = 1;
+ if (you.experience_level > 27)
+ you.experience_level = 27;
+
+ you.strength = cap_stat(Options.fsim_str);
+ you.intel = cap_stat(Options.fsim_int);
+ you.dex = cap_stat(Options.fsim_dex);
+
+ fsim_title(ostat, mindex, missile_slot);
+ for (int wskill = 0; wskill <= 27; ++wskill)
+ {
+ mesclr();
+ mprf("Calculating average damage for %s at skill %d",
+ fsim_weapon(missile_slot).c_str(), wskill);
+ if (!debug_fight_simulate(ostat, wskill, mindex, missile_slot))
+ goto done_combat_sim;
+
+ fflush(ostat);
+ // Not checking in the combat loop itself; that would be more responsive
+ // for the user, but slow down the sim with all the calls to kbhit().
+ if (kbhit() && getch() == 27)
+ {
+ success = false;
+ mprf("Canceling simulation\n");
+ goto done_combat_sim;
+ }
+ }
+ you.skills = skill_backup;
+ you.strength = ystr;
+ you.intel = yint;
+ you.dex = ydex;
+ you.experience_level = yxp;
+
+ mprf("Done fight simulation with %s", fsim_weapon(missile_slot).c_str());
+
+done_combat_sim:
+ fprintf(ostat, "-----------------------------------\n\n");
+ fclose(ostat);
+
+ return (success);
+}
+
+int fsim_kit_equip(const std::string &kit)
+{
+ int missile_slot = -1;
+ char item_buf[ITEMNAME_SIZE];
+
+ std::string::size_type ammo_div = kit.find("/");
+ std::string weapon = kit;
+ std::string missile;
+ if (ammo_div != std::string::npos)
+ {
+ weapon = kit.substr(0, ammo_div);
+ missile = kit.substr(ammo_div + 1);
+ trim_string(weapon);
+ trim_string(missile);
+ }
+
+ for (int i = 0; i < ENDOFPACK; ++i)
+ {
+ if (!is_valid_item(you.inv[i]))
+ continue;
+
+ in_name(i, DESC_PLAIN, item_buf, true);
+ if (std::string(item_buf).find(weapon) != std::string::npos)
+ {
+ if (i != you.equip[EQ_WEAPON])
+ {
+ wield_weapon(true, i, false);
+ if (i != you.equip[EQ_WEAPON])
+ return -100;
+ }
+ break;
+ }
+ }
+
+ if (!missile.empty())
+ {
+ for (int i = 0; i < ENDOFPACK; ++i)
+ {
+ if (!is_valid_item(you.inv[i]))
+ continue;
+
+ in_name(i, DESC_PLAIN, item_buf, true);
+ if (std::string(item_buf).find(missile) != std::string::npos)
+ {
+ missile_slot = i;
+ break;
+ }
+ }
+ }
+
+ return (missile_slot);
+}
+
+// Writes statistics about a fight to fight.stat in the current directory.
+// For fight purposes, a punching bag is summoned and given lots of hp, and the
+// average damage the player does to the p. bag over 10000 hits is noted,
+// advancing the weapon skill from 0 to 27, and keeping fighting skill to 2/5
+// of current weapon skill.
+void debug_fight_statistics(bool use_defaults)
+{
+ int punching_bag = get_monster_by_name(Options.fsim_mons);
+ if (punching_bag == -1 || punching_bag == MONS_PROGRAM_BUG)
+ punching_bag = MONS_WORM;
+
+ int mindex = create_fsim_monster(punching_bag, 500);
+ if (mindex == -1)
+ {
+ mprf("Failed to create punching bag");
+ return;
+ }
+
+ if (!use_defaults)
+ {
+ debug_fight_sim(mindex, -1);
+ goto fsim_mcleanup;
+ }
+
+ for (int i = 0, size = Options.fsim_kit.size(); i < size; ++i)
+ {
+ int missile = fsim_kit_equip(Options.fsim_kit[i]);
+ if (missile == -100)
+ {
+ mprf("Aborting sim on %s", Options.fsim_kit[i].c_str());
+ goto fsim_mcleanup;
+ }
+ if (!debug_fight_sim(mindex, missile))
+ break;
+ }
+fsim_mcleanup:
+ monster_die(&menv[mindex], KILL_DISMISSED, 0);
+}
+
+static int find_trap_slot()
+{
+ for (int i = 0; i < MAX_TRAPS; ++i)
+ {
+ if (env.trap[i].type == TRAP_UNASSIGNED)
+ return (i);
+ }
+ return (-1);
+}
+
+void debug_make_trap()
+{
+ char requested_trap[80];
+ int trap_slot = find_trap_slot();
+ trap_type trap = TRAP_UNASSIGNED;
+ int gridch = grd[you.x_pos][you.y_pos];
+
+ if (trap_slot == -1)
+ {
+ mpr("Sorry, this level can't take any more traps.");
+ return;
+ }
+
+ if (gridch != DNGN_FLOOR)
+ {
+ mpr("You need to be on a floor square to make a trap.");
+ return;
+ }
+
+ mprf(MSGCH_PROMPT, "What kind of trap? ");
+ get_input_line( requested_trap, sizeof( requested_trap ) );
+ if (!*requested_trap)
+ return;
+
+ strlwr(requested_trap);
+ for (int t = TRAP_DART; t < NUM_TRAPS; ++t)
+ {
+ if (strstr(requested_trap,
+ trap_name(trap_type(t))))
+ {
+ trap = trap_type(t);
+ break;
+ }
+ }
+
+ if (trap == TRAP_UNASSIGNED)
+ {
+ mprf("I know no traps named \"%s\"", requested_trap);
+ return;
+ }
+
+ place_specific_trap(you.x_pos, you.y_pos, trap);
+
+ mprf("Created a %s trap, marked it undiscovered",
+ trap_name(trap));
+
+ // Also tell travel that its world-view must change.
+ travel_init_new_level();
+}
+
+static const char *shop_types[] = {
+ "weapon",
+ "armour",
+ "antique weapon",
+ "antique armour",
+ "antiques",
+ "jewellery",
+ "wand",
+ "book",
+ "food",
+ "distillery",
+ "scroll",
+ "general"
+};
+
+void debug_make_shop()
+{
+ char requested_shop[80];
+ int gridch = grd[you.x_pos][you.y_pos];
+ bool have_shop_slots = false;
+ int new_shop_type = SHOP_UNASSIGNED;
+ bool representative = false;
+
+ if (gridch != DNGN_FLOOR)
+ {
+ mpr("Insufficient floor-space for new Wal-Mart.");
+ return;
+ }
+
+ for (int i = 0; i < MAX_SHOPS; ++i)
+ {
+ if (env.shop[i].type == SHOP_UNASSIGNED)
+ {
+ have_shop_slots = true;
+ break;
+ }
+ }
+
+ if (!have_shop_slots)
+ {
+ mpr("There are too many shops on this level.");
+ return;
+ }
+
+ mprf(MSGCH_PROMPT, "What kind of shop? ");
+ get_input_line( requested_shop, sizeof( requested_shop ) );
+ if (!*requested_shop)
+ return;
+
+ strlwr(requested_shop);
+ for (unsigned i = 0; i < sizeof(shop_types) / sizeof (*shop_types); ++i)
+ {
+ if (strstr(requested_shop, shop_types[i]))
+ {
+ new_shop_type = i;
+ break;
+ }
+ }
+
+ if (new_shop_type == SHOP_UNASSIGNED)
+ {
+ mprf("Bad shop type: \"%s\"", requested_shop);
+ return;
+ }
+
+ representative = !!strchr(requested_shop, '*');
+
+ place_spec_shop(you.your_level, you.x_pos, you.y_pos,
+ new_shop_type, representative);
+ link_items();
+ mprf("Done.");
+}
+
+void debug_set_stats()
+{
+ char buf[80];
+ mprf(MSGCH_PROMPT, "Enter values for Str, Int, Dex (space separated): ");
+ if (cancelable_get_line(buf, sizeof buf))
+ return;
+
+ int sstr = you.strength,
+ sdex = you.dex,
+ sint = you.intel;
+ sscanf(buf, "%d %d %d", &sstr, &sint, &sdex);
+
+ you.max_strength = you.strength = cap_stat(sstr);
+ you.max_dex = you.dex = cap_stat(sdex);
+ you.max_intel = you.intel = cap_stat(sint);
+
+ you.redraw_strength = true;
+ you.redraw_dexterity = true;
+ you.redraw_intelligence = true;
+}
+
+#endif
diff --git a/crawl-ref/source/debug.h b/crawl-ref/source/debug.h
index cbc8161d3b..922d4c3a7d 100644
--- a/crawl-ref/source/debug.h
+++ b/crawl-ref/source/debug.h
@@ -3,6 +3,8 @@
* Summary: Debug and wizard related functions.
* Written by: Linley Henzell and Jesse Jones
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <4> 5/30/99 JDJ Added synch checks.
@@ -143,5 +145,9 @@ void stethoscope(int mwh);
void debug_item_scan( void );
void debug_get_religion( void );
void debug_change_species( void );
+void debug_fight_statistics( bool use_init_defaults );
+void debug_make_trap( void );
+void debug_make_shop( void );
+void debug_set_stats( void );
#endif
diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc
index 5f958b0512..8755413256 100644
--- a/crawl-ref/source/decks.cc
+++ b/crawl-ref/source/decks.cc
@@ -2,6 +2,8 @@
* File: decks.cc
* Summary: Functions with decks of cards.
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -224,7 +226,7 @@ void deck_of_cards(unsigned char which_deck)
unsigned char *card = deck_of_wonders;
unsigned char max_card = 0;
int i = 0;
- int brownie_points = 0; // for passing to done_good() {dlb}
+ int brownie_points = 0; // for passing to did_god_conduct() {dlb}
mpr("You draw a card...");
@@ -292,7 +294,7 @@ void deck_of_cards(unsigned char which_deck)
if (which_deck == DECK_OF_WONDERS || one_chance_in(3))
brownie_points++;
- done_good(GOOD_CARDS, brownie_points);
+ did_god_conduct(DID_CARDS, brownie_points);
}
return;
@@ -774,7 +776,7 @@ static void cards(unsigned char which_card)
case CARD_TORMENT:
mpr("You have drawn the Symbol of Torment.");
- torment( you.x_pos, you.y_pos );
+ torment( TORMENT_CARDS, you.x_pos, you.y_pos );
break;
// what about checking whether there are items there, too? {dlb}
@@ -800,36 +802,20 @@ static void cards(unsigned char which_card)
case CARD_ALTAR:
mpr("You have drawn the Altar.");
- if (you.religion == GOD_NO_GOD)
+ if (you.religion == GOD_NO_GOD ||
+ grd[you.x_pos][you.y_pos] != DNGN_FLOOR)
{
canned_msg(MSG_NOTHING_HAPPENS);
}
else
{
dvar1 = 179 + you.religion;
-
- if (grd[you.x_pos][you.y_pos] == DNGN_FLOOR)
- {
- strcpy(info, "An altar grows from the floor ");
- strcat(info,
- (you.species == SP_NAGA || you.species == SP_CENTAUR)
- ? "before you!" : "at your feet!");
- mpr(info);
- grd[you.x_pos][you.y_pos] = dvar1;
- }
- else
- {
- do
- {
- dvar[0] = 10 + random2(GXM - 20);
- dvar[1] = 10 + random2(GYM - 20);
- }
- while (grd[dvar[0]][dvar[1]] != DNGN_FLOOR);
-
- grd[dvar[0]][dvar[1]] = dvar1;
-
- mpr( "You sense divine power!" );
- }
+
+ snprintf( info, INFO_SIZE, "An altar grows from the floor %s!",
+ (you.species == SP_NAGA || you.species == SP_CENTAUR)
+ ? "before you" : "at your feet");
+ mpr(info);
+ grd[you.x_pos][you.y_pos] = dvar1;
}
break;
diff --git a/crawl-ref/source/decks.h b/crawl-ref/source/decks.h
index 1227ee19f1..43f41e0395 100644
--- a/crawl-ref/source/decks.h
+++ b/crawl-ref/source/decks.h
@@ -2,6 +2,8 @@
* File: decks.cc
* Summary: Functions with decks of cards.
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
diff --git a/crawl-ref/source/defines.h b/crawl-ref/source/defines.h
index dbb079a458..b36afc1ad3 100644
--- a/crawl-ref/source/defines.h
+++ b/crawl-ref/source/defines.h
@@ -10,6 +10,8 @@
*
* Copyright © 1999 Brian Robinson. // Me? How come?
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <4> 7/29/00 JDJ Renamed MNG NON_MONSTER, MNST MAX_MONSTERS, ITEMS MAX_ITEMS,
@@ -22,11 +24,12 @@
#ifndef DEFINES_H
#define DEFINES_H
+#define NUM_MONSTER_SPELL_SLOTS 6
+
#define ESCAPE '\x1b' // most ansi-friendly way I can think of defining this.
// there's got to be a better way...
-#ifdef _LIBUNIX_IMPLEMENTATION
-#elif macintosh
+#ifndef _LIBUNIX_IMPLEMENTATION
#else
#ifndef TRUE
#define TRUE 1
@@ -41,6 +44,9 @@
// max size of inventory array {dlb}:
#define ENDOFPACK 52
+// minimum value for strength required on armour and weapons
+#define STR_REQ_THRESHOLD 10
+
// max size of monter array {dlb}:
#define MAX_MONSTERS 200
// number of monster enchantments
@@ -48,6 +54,8 @@
// non-monster for mgrd[][] -- (MNST + 1) {dlb}:
#define NON_MONSTER 201
+#define MAX_SUBTYPES 50
+
// max size of item list {dlb}:
#define MAX_ITEMS 500
// non-item -- (ITEMS + 1) {dlb}
@@ -64,6 +72,55 @@
// max y-bound for level generation {dlb}
#define GYM 70
+// this is the size of the border around the playing area (see in_bounds())
+#define BOUNDARY_BORDER 1
+
+// Now some defines about the actual play area:
+// Note: these boundaries are exclusive for the zone the player can move/dig,
+// and are inclusive for the area that we display on the map.
+// Note: that the right (bottom) boundary is one smaller here.
+#define X_BOUND_1 BOUNDARY_BORDER
+#define X_BOUND_2 (GXM - BOUNDARY_BORDER)
+#define X_WIDTH (X_BOUND_2 - X_BOUND_1 + 1)
+
+#define Y_BOUND_1 BOUNDARY_BORDER
+#define Y_BOUND_2 (GYM - BOUNDARY_BORDER)
+#define Y_WIDTH (Y_BOUND_2 - Y_BOUND_1 + 1)
+
+// these mark the center zone where the player moves without shifting
+#define ABYSS_SHIFT_RADIUS 10
+
+#define X_ABYSS_1 (X_BOUND_1 + ABYSS_SHIFT_RADIUS)
+#define X_ABYSS_2 (GXM - X_ABYSS_1)
+#define X_ABYSS_WIDTH (X_ABYSS_2 - X_ABYSS_1 + 1)
+#define X_ABYSS_CENTER (X_ABYSS_1 + X_ABYSS_WIDTH / 2)
+
+#define Y_ABYSS_1 (Y_BOUND_1 + ABYSS_SHIFT_RADIUS)
+#define Y_ABYSS_2 (GYM - Y_ABYSS_1)
+#define Y_ABYSS_WIDTH (Y_ABYSS_2 - Y_ABYSS_1 + 1)
+#define Y_ABYSS_CENTER (Y_ABYSS_1 + Y_ABYSS_WIDTH / 2)
+
+#define LOS_SX 8
+#define LOS_EX 25
+#define LOS_SY 1
+#define LOS_EY 17
+
+#define VIEW_SX 1
+#define VIEW_EX 33
+#define VIEW_SY 1
+#define VIEW_EY 17
+
+#define VIEW_WIDTH (VIEW_EX - VIEW_SX + 1)
+#define VIEW_HEIGHT (VIEW_EY - VIEW_SY + 1)
+
+#define VIEW_Y_DIFF (((VIEW_EX - VIEW_SX + 1) - (VIEW_EY - VIEW_SY + 1)) / 2)
+
+// View centre must be the same as LOS centre.
+// VIEW_CX == 17
+#define VIEW_CX ((VIEW_SX + VIEW_EX) / 2)
+// VIEW_CY == 9
+#define VIEW_CY ((VIEW_SY + VIEW_EY) / 2)
+
// max traps per level
#define MAX_TRAPS 30
@@ -76,6 +133,69 @@
// lowest grid value which can be seen through
#define MINSEE 11
+// This value is used to make test_hit checks always succeed
+#define AUTOMATIC_HIT 1500
+
+// grids that monsters can see
+#define MONSTER_LOS_RANGE 8
+
+// Maximum charge level for rods
+#define MAX_ROD_CHARGE 17
+#define ROD_CHARGE_MULT 100
+
+// Should never exceed 255 - durations are saved as single bytes.
+#define GOURMAND_MAX 200
+#define GOURMAND_NUTRITION_BASE 20
+
+#define CHUNK_BASE_NUTRITION 1000
+
+// This value is used to mark immune levels of MR
+#define MAG_IMMUNE 5000
+
+// This is the damage amount used to signal insta-death
+#define INSTANT_DEATH -9999
+
+// grids that monsters can see
+#define MONSTER_LOS_RANGE 8
+
+// most items allowed in a shop
+#define MAX_SHOP_ITEMS 16
+
+// sound level standards
+// mininum is the base, we add mult * radius to it:
+#define SL_EXPLODE_MIN 10
+#define SL_EXPLODE_MULT 10
+
+// #define SL_BOW 3
+#define SL_TRAP_CLICK 3
+#define SL_HISS 6
+#define SL_BUZZ 6
+#define SL_GROWL 8
+#define SL_MOAN 8
+#define SL_SPLASH 8
+#define SL_CREAK 8
+#define SL_CROAK 8
+#define SL_BARK 10
+#define SL_YELL 10
+#define SL_TRAP_JAM 12
+#define SL_SHRIEK 12
+#define SL_ROAR 15
+#define SL_DIG 15
+#define SL_NOISY_WEAPON 20
+#define SL_HORN 25
+#define SL_NOISE_SCROLL 30
+#define SL_THUNDER 30
+#define SL_PROJECTED_NOISE 30
+#define SL_EARTHQUAKE 30
+#define SL_TRAP_ZOT 30
+
+// Maximum enchantment on weapons/armour/secondary armours
+// Note: use armour_max_enchant(item) to get the correct limit for item
+#define MAX_WPN_ENCHANT 5
+#define MAX_ARM_ENCHANT 5
+#define MAX_SEC_ENCHANT 2
+
+#define NUM_STAVE_ADJ 9
// some shortcuts:
#define menv env.mons
@@ -84,15 +204,6 @@
#define mgrd env.mgrid
#define igrd env.igrid
-#define ENVF_FLAGS 0xFF00U
-#define ENVF_DETECT_MONS 0x0100U
-#define ENVF_DETECT_ITEM 0x0200U
-
-// This square is known because of detect-creatures/detect-items
-#define ENVF_DETECTED 0x0800U
-
-#define ENVF_COLOR(x) (((x) >> 12) & 0xF)
-
// (MNG) -- for a reason! see usage {dlb}:
#define MHITNOT 201
// (MNG + 1) -- for a reason! see usage {dlb}:
@@ -139,6 +250,8 @@
#define COLFLAG_WILLSTAB 0x0400
#define COLFLAG_MAYSTAB 0x0800
+ #define COLFLAG_REVERSE 0x1000
+
enum CHAR_ATTRIBUTES
{
CHATTR_NORMAL, /* 0 */
@@ -157,12 +270,18 @@
//#endif
+#define PDESCS(colour) (colour)
+#define PDESCQ(qualifier, colour) (((qualifier) * PDC_NCOLOURS) + (colour))
+
+#define PCOLOUR(desc) ((desc) % PDC_NCOLOURS)
+#define PQUAL(desc) ((desc) / PDC_NCOLOURS)
+
#define MINIMUM( xxx, yyy ) (((xxx) < (yyy)) ? (xxx) : (yyy))
#define MAXIMUM( xxx, yyy ) (((xxx) > (yyy)) ? (xxx) : (yyy))
// Convert capital letters into mystic numbers representing
// CTRL sequences. This is a macro because a lot of the type
// it wants to be used in case labels.
-#define CONTROL( xxx ) (xxx - 'A' + 1)
+#define CONTROL( xxx ) ((xxx) - 'A' + 1)
#endif
diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc
index 0894207395..6998a3df50 100644
--- a/crawl-ref/source/delay.cc
+++ b/crawl-ref/source/delay.cc
@@ -2,6 +2,8 @@
* File: delay.cc
* Summary: Functions for handling multi-turn actions.
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> Sept 09, 2001 BWR Created
@@ -13,40 +15,111 @@
#include <stdio.h>
#include <string.h>
+#include "clua.h"
+#include "command.h"
#include "delay.h"
#include "enum.h"
#include "food.h"
+#include "invent.h"
#include "items.h"
#include "itemname.h"
+#include "itemprop.h"
#include "item_use.h"
#include "it_use2.h"
#include "message.h"
#include "misc.h"
#include "monstuff.h"
+#include "mstuff2.h"
#include "ouch.h"
#include "output.h"
#include "player.h"
#include "randart.h"
#include "spl-util.h"
#include "stuff.h"
+#include "travel.h"
+
+extern std::vector<SelItem> items_for_multidrop;
+
+static void armour_wear_effects(const int item_inv_slot);
+static void handle_run_delays(const delay_queue_item &delay);
+static void handle_macro_delay();
+
+// Returns true if this delay can act as a parent to other delays, i.e. if
+// other delays can be spawned while this delay is running. If is_parent_delay
+// returns true, new delays will be pushed immediately to the front of the
+// delay in question, rather than at the end of the queue.
+static bool is_parent_delay(int delay)
+{
+ // Interlevel travel can do upstairs/downstairs delays.
+ // Lua macros can in theory perform any of the other delays,
+ // including travel; in practise travel still assumes there can be
+ // no parent delay.
+ return (delay == DELAY_TRAVEL || delay == DELAY_MACRO);
+}
+
+static void push_delay(const delay_queue_item &delay)
+{
+ for (delay_queue_type::iterator i = you.delay_queue.begin();
+ i != you.delay_queue.end();
+ ++i)
+ {
+ if (is_parent_delay( i->type ))
+ {
+ you.delay_queue.insert(i, delay);
+ return;
+ }
+ }
+ you.delay_queue.push_back( delay );
+}
+
+static void pop_delay()
+{
+ if (!you.delay_queue.empty())
+ you.delay_queue.erase( you.delay_queue.begin() );
+}
+
+static void clear_pending_delays()
+{
+ while (you.delay_queue.size() > 1)
+ you.delay_queue.pop_back();
+}
void start_delay( int type, int turns, int parm1, int parm2 )
/***********************************************************/
{
- delay_queue_item delay;
+ delay_queue_item delay;
delay.type = type;
delay.duration = turns;
delay.parm1 = parm1;
delay.parm2 = parm2;
- you.delay_queue.push( delay );
+ switch ( delay.type ) {
+ case DELAY_ARMOUR_ON:
+ mpr("You start putting on your armour.", MSGCH_MULTITURN_ACTION);
+ break;
+ case DELAY_ARMOUR_OFF:
+ mpr("You start removing your armour.", MSGCH_MULTITURN_ACTION);
+ break;
+ case DELAY_MEMORISE:
+ mpr("You start memorising the spell.", MSGCH_MULTITURN_ACTION);
+ break;
+ case DELAY_PASSWALL:
+ mpr("You begin to meditate on the wall.", MSGCH_MULTITURN_ACTION);
+ break;
+ default:
+ break;
+ }
+ push_delay( delay );
}
void stop_delay( void )
/*********************/
{
- delay_queue_item delay = you.delay_queue.front();
+ if ( you.delay_queue.empty() )
+ return;
+
+ delay_queue_item delay = you.delay_queue.front();
// At the very least we can remove any queued delays, right
// now there is no problem with doing this... note that
@@ -54,42 +127,60 @@ void stop_delay( void )
// as the effect of a delay doesn't normally allow interaction
// until it is done... it merely chains up individual actions
// into a single action. -- bwr
- if (you.delay_queue.size() > 1)
- {
- while (you.delay_queue.size())
- you.delay_queue.pop();
-
- you.delay_queue.push( delay );
- }
+ clear_pending_delays();
switch (delay.type)
{
case DELAY_BUTCHER:
// Corpse keeps track of work in plus2 field, see handle_delay() -- bwr
mpr( "You stop butchering the corpse." );
- you.delay_queue.pop();
+ pop_delay();
break;
- case DELAY_MEMORIZE:
+ case DELAY_MEMORISE:
// Losing work here is okay... having to start from
// scratch is a reasonable behaviour. -- bwr
mpr( "Your memorization is interrupted." );
- you.delay_queue.pop();
+ pop_delay();
break;
case DELAY_PASSWALL:
// The lost work here is okay since this spell requires
- // the player to "attune to the rock". If changed, the
+ // the player to "attune to the rock". If changed, then
// the delay should be increased to reduce the power of
// this spell. -- bwr
mpr( "Your meditation is interrupted." );
- you.delay_queue.pop();
+ pop_delay();
+ break;
+
+ case DELAY_MULTIDROP:
+ // No work lost
+ mpr( "You stop dropping stuff." );
+ pop_delay();
+ break;
+
+ case DELAY_RUN:
+ case DELAY_REST:
+ case DELAY_TRAVEL:
+ case DELAY_MACRO:
+ // Always interruptible.
+ pop_delay();
+
+ // Keep things consistent, otherwise disturbing phenomena can occur.
+ // Note that runrest::stop() will turn around and call stop_delay()
+ // again, but that's okay because the delay is already popped off
+ // the queue.
+ if (is_run_delay(delay.type) && you.running)
+ stop_running();
+
+ // There's no special action needed for macros - if we don't call out
+ // to the Lua function, it can't do damage.
break;
- case DELAY_INTERUPTABLE:
- // always stopable by definition...
+ case DELAY_INTERRUPTIBLE:
+ // always stoppable by definition...
// try using a more specific type anyways. -- bwr
- you.delay_queue.pop();
+ pop_delay();
break;
case DELAY_EAT:
@@ -101,7 +192,7 @@ void stop_delay( void )
case DELAY_ARMOUR_ON:
case DELAY_ARMOUR_OFF:
- // These two have the default action of not being interuptable,
+ // These two have the default action of not being interruptible,
// although they will often be chained (remove cloak, remove
// armour, wear new armour, replace cloak), all of which can
// be stopped when complete. This is a fairly reasonable
@@ -117,7 +208,8 @@ void stop_delay( void )
case DELAY_DROP_ITEM: // one turn... only used for easy armour drops
case DELAY_ASCENDING_STAIRS: // short... and probably what people want
case DELAY_DESCENDING_STAIRS: // short... and probably what people want
- case DELAY_UNINTERUPTABLE: // never stopable
+ case DELAY_UNINTERRUPTIBLE: // never stoppable
+ case DELAY_JEWELLERY_ON: // one turn
default:
break;
}
@@ -136,414 +228,767 @@ int current_delay_action( void )
: DELAY_NOT_DELAYED);
}
+bool is_run_delay(int delay)
+{
+ return (delay == DELAY_RUN || delay == DELAY_REST
+ || delay == DELAY_TRAVEL);
+}
+
void handle_delay( void )
/***********************/
{
- int ego;
char str_pass[ ITEMNAME_SIZE ];
- if (you_are_delayed())
+ if (!you_are_delayed())
+ return;
+
+ delay_queue_item &delay = you.delay_queue.front();
+
+ // Run delays and Lua delays don't have a specific end time.
+ if (is_run_delay(delay.type))
{
- delay_queue_item &delay = you.delay_queue.front();
+ handle_run_delays(delay);
+ return;
+ }
- // First check cases where delay may no longer be valid:
- // XXX: need to handle passwall when monster digs -- bwr
- if (delay.type == DELAY_BUTCHER)
+ if (delay.type == DELAY_MACRO)
+ {
+ handle_macro_delay();
+ return;
+ }
+
+ // First check cases where delay may no longer be valid:
+ // XXX: need to handle passwall when monster digs -- bwr
+ if (delay.type == DELAY_BUTCHER)
+ {
+ // A monster may have raised the corpse you're chopping up! -- bwr
+ // Note that a monster could have raised the corpse and another
+ // monster could die and create a corpse with the same ID number...
+ // However, it would not be at the player's square like the
+ // original and that's why we do it this way. Note that
+ // we ignore the conversion to skeleton possibility just to
+ // be nice. -- bwr
+ if (is_valid_item( mitm[ delay.parm1 ] )
+ && mitm[ delay.parm1 ].base_type == OBJ_CORPSES
+ && mitm[ delay.parm1 ].x == you.x_pos
+ && mitm[ delay.parm1 ].y == you.y_pos )
{
- // A monster may have raised the corpse you're chopping up! -- bwr
- // Note that a monster could have raised the corpse and another
- // monster could die and create a corpse with the same ID number...
- // However, it would not be at the player's square like the
- // original and that's why we do it this way. Note that
- // we ignore the conversion to skeleton possiblity just to
- // be nice. -- bwr
- if (is_valid_item( mitm[ delay.parm1 ] )
- && mitm[ delay.parm1 ].base_type == OBJ_CORPSES
- && mitm[ delay.parm1 ].x == you.x_pos
- && mitm[ delay.parm1 ].y == you.y_pos)
- {
- // mark work done on the corpse in case we stop -- bwr
- mitm[ delay.parm1 ].plus2++;
- }
- else
- {
- // corpse is no longer valid!
- stop_delay();
- return;
+ // special < 100 is the rottenness check
+ if ( (mitm[delay.parm1].special < 100) &&
+ (delay.parm2 >= 100) ) {
+ mpr("The corpse rots.", MSGCH_ROTTEN_MEAT);
+ delay.parm2 = 99; // don't give the message twice
}
+
+ // mark work done on the corpse in case we stop -- bwr
+ mitm[ delay.parm1 ].plus2++;
+ }
+ else
+ {
+ // corpse is no longer valid!
+ stop_delay();
+ return;
}
+ }
+ if ( delay.type == DELAY_MULTIDROP )
+ {
+
+ // Throw away invalid items; items usually go invalid because
+ // of chunks rotting away.
+ while (!items_for_multidrop.empty()
+ // Don't look for gold in inventory
+ && items_for_multidrop[0].slot != PROMPT_GOT_SPECIAL
+ && !is_valid_item(you.inv[ items_for_multidrop[0].slot ]))
+ items_for_multidrop.erase( items_for_multidrop.begin() );
- // Handle delay:
- if (delay.duration > 0)
+ if ( items_for_multidrop.empty() )
{
+ // ran out of things to drop
+ pop_delay();
+ return;
+ }
+ }
+
+ // Handle delay:
+ if (delay.duration > 0)
+ {
#if DEBUG_DIAGNOSTICS
- snprintf( info, INFO_SIZE, "Delay type: %d duration: %d",
- delay.type, delay.duration );
+ snprintf( info, INFO_SIZE, "Delay type: %d (%s), duration: %d",
+ delay.type, delay_name(delay.type), delay.duration );
- mpr( info, MSGCH_DIAGNOSTICS );
+ mpr( info, MSGCH_DIAGNOSTICS );
#endif
- delay.duration--;
+ switch ( delay.type )
+ {
+ case DELAY_ARMOUR_ON:
+ in_name( delay.parm1, DESC_NOCAP_YOUR, str_pass );
+ snprintf( info, INFO_SIZE,
+ "You continue putting on %s.", str_pass );
+ mpr(info, MSGCH_MULTITURN_ACTION);
+ break;
+ case DELAY_ARMOUR_OFF:
+ in_name( delay.parm1, DESC_NOCAP_YOUR, str_pass );
+ snprintf( info, INFO_SIZE,
+ "You continue taking off %s.", str_pass );
+ mpr(info, MSGCH_MULTITURN_ACTION);
+ break;
+ case DELAY_BUTCHER:
+ mpr("You continue butchering the corpse.",
+ MSGCH_MULTITURN_ACTION);
+ break;
+ case DELAY_MEMORISE:
+ mpr("You continue memorising.", MSGCH_MULTITURN_ACTION);
+ break;
+ case DELAY_PASSWALL:
+ mpr("You continue meditating on the rock.",
+ MSGCH_MULTITURN_ACTION);
+ break;
+ case DELAY_MULTIDROP:
+ drop_item( items_for_multidrop[0].slot,
+ items_for_multidrop[0].quantity );
+ items_for_multidrop.erase( items_for_multidrop.begin() );
+ break;
+ default:
+ break;
}
- else
+ delay.duration--;
+ }
+ else
+ {
+ switch (delay.type)
{
- switch (delay.type)
- {
- case DELAY_AUTOPICKUP:
- break;
+ case DELAY_AUTOPICKUP:
+ break;
- case DELAY_WEAPON_SWAP:
- weapon_switch( delay.parm1 );
- break;
+ case DELAY_WEAPON_SWAP:
+ weapon_switch( delay.parm1 );
+ break;
- case DELAY_ARMOUR_ON:
- set_ident_flags( you.inv[ delay.parm1 ], ISFLAG_EQ_ARMOUR_MASK );
+ case DELAY_JEWELLERY_ON:
+ puton_ring( delay.parm1, false );
+ break;
- in_name( delay.parm1, DESC_NOCAP_YOUR, str_pass );
- snprintf( info, INFO_SIZE, "You finish putting on %s.", str_pass );
- mpr(info);
+ case DELAY_ARMOUR_ON:
+ armour_wear_effects( delay.parm1 );
+ break;
+
+ case DELAY_ARMOUR_OFF:
+ {
+ in_name( delay.parm1, DESC_NOCAP_YOUR, str_pass );
+ snprintf( info, INFO_SIZE, "You finish taking off %s.", str_pass );
+ mpr(info);
- if (you.inv[ delay.parm1 ].sub_type < ARM_SHIELD
- || you.inv[ delay.parm1 ].sub_type > ARM_LARGE_SHIELD)
+ const equipment_type slot =
+ get_armour_slot( you.inv[delay.parm1] );
+
+ if (slot == EQ_BODY_ARMOUR)
+ {
+ you.equip[EQ_BODY_ARMOUR] = -1;
+ }
+ else
+ {
+ switch (slot)
{
- you.equip[EQ_BODY_ARMOUR] = delay.parm1;
+ case EQ_SHIELD:
+ if (delay.parm1 == you.equip[EQ_SHIELD])
+ you.equip[EQ_SHIELD] = -1;
+ break;
- if (you.duration[DUR_ICY_ARMOUR] != 0)
- {
- mpr( "Your icy armour melts away.", MSGCH_DURATION );
- you.redraw_armour_class = 1;
- you.duration[DUR_ICY_ARMOUR] = 0;
- }
+ case EQ_CLOAK:
+ if (delay.parm1 == you.equip[EQ_CLOAK])
+ you.equip[EQ_CLOAK] = -1;
+ break;
+
+ case EQ_HELMET:
+ if (delay.parm1 == you.equip[EQ_HELMET])
+ you.equip[EQ_HELMET] = -1;
+ break;
+
+
+ case EQ_GLOVES:
+ if (delay.parm1 == you.equip[EQ_GLOVES])
+ you.equip[EQ_GLOVES] = -1;
+ break;
+
+ case EQ_BOOTS:
+ if (delay.parm1 == you.equip[EQ_BOOTS])
+ you.equip[EQ_BOOTS] = -1;
+ break;
+
+ default:
+ break;
}
- else
+ }
+
+ unwear_armour( delay.parm1 );
+
+ you.redraw_armour_class = 1;
+ you.redraw_evasion = 1;
+ break;
+ }
+ case DELAY_EAT:
+ mpr( "You finish eating." );
+ // For chunks, warn the player if they're not getting much
+ // nutrition.
+ if (delay.parm1)
+ chunk_nutrition_message(delay.parm1);
+ break;
+
+ case DELAY_MEMORISE:
+ mpr( "You finish memorising." );
+ add_spell_to_memory( delay.parm1 );
+ break;
+
+ case DELAY_PASSWALL:
+ {
+ mpr( "You finish merging with the rock." );
+ more(); // or the above message won't be seen
+
+ const int pass_x = delay.parm1;
+ const int pass_y = delay.parm2;
+
+ if (pass_x != 0 && pass_y != 0)
{
- switch (you.inv[ delay.parm1 ].sub_type)
+
+ switch (grd[ pass_x ][ pass_y ])
{
- case ARM_BUCKLER:
- case ARM_LARGE_SHIELD:
- case ARM_SHIELD:
- if (you.duration[DUR_CONDENSATION_SHIELD])
- {
- mpr( "Your icy shield evaporates.", MSGCH_DURATION );
- you.duration[DUR_CONDENSATION_SHIELD] = 0;
- }
- you.equip[EQ_SHIELD] = delay.parm1;
- break;
- case ARM_CLOAK:
- you.equip[EQ_CLOAK] = delay.parm1;
- break;
- case ARM_HELMET:
- you.equip[EQ_HELMET] = delay.parm1;
+ case DNGN_ROCK_WALL:
+ case DNGN_STONE_WALL:
+ case DNGN_METAL_WALL:
+ case DNGN_GREEN_CRYSTAL_WALL:
+ case DNGN_WAX_WALL:
+ case DNGN_SILVER_STATUE:
+ case DNGN_ORANGE_CRYSTAL_STATUE:
+ ouch(1 + you.hp, 0, KILLED_BY_PETRIFICATION);
break;
- case ARM_GLOVES:
- you.equip[EQ_GLOVES] = delay.parm1;
+
+ case DNGN_SECRET_DOOR: // oughtn't happen
+ case DNGN_CLOSED_DOOR: // open the door
+ grd[ pass_x ][ pass_y ] = DNGN_OPEN_DOOR;
break;
- case ARM_BOOTS:
- you.equip[EQ_BOOTS] = delay.parm1;
+
+ default:
break;
}
- }
- ego = get_armour_ego_type( you.inv[ delay.parm1 ] );
- if (ego != SPARM_NORMAL)
- {
- switch (ego)
+ // move any monsters out of the way:
+ int mon = mgrd[ pass_x ][ pass_y ];
+ if (mon != NON_MONSTER)
{
- case SPARM_RUNNING:
- strcpy(info, "You feel quick");
- strcat(info, (you.species == SP_NAGA
- || you.species == SP_CENTAUR) ? "." : " on your feet.");
- mpr(info);
- break;
+ // one square, a few squares, anywhere...
+ if (!shift_monster(&menv[mon])
+ && !monster_blink(&menv[mon]))
+ {
+ monster_teleport( &menv[mon], true, true );
+ }
+ }
- case SPARM_FIRE_RESISTANCE:
- mpr("You feel resistant to fire.");
- break;
+ move_player_to_grid(pass_x, pass_y, false, true, true);
+ redraw_screen();
+ }
+ }
+ break;
- case SPARM_COLD_RESISTANCE:
- mpr("You feel resistant to cold.");
- break;
+ case DELAY_BUTCHER:
+ strcpy( info, "You finish " );
+ strcat( info, (you.species == SP_TROLL
+ || you.species == SP_GHOUL) ? "ripping"
+ : "chopping" );
- case SPARM_POISON_RESISTANCE:
- mpr("You feel healthy.");
- break;
+ strcat( info, " the corpse into pieces." );
+ mpr( info );
- case SPARM_SEE_INVISIBLE:
- mpr("You feel perceptive.");
- break;
+ turn_corpse_into_chunks( mitm[ delay.parm1 ] );
- case SPARM_DARKNESS:
- if (!you.invis)
- mpr("You become transparent for a moment.");
- break;
+ if (you.berserker && you.berserk_penalty != NO_BERSERK_PENALTY)
+ {
+ mpr("You enjoyed that.");
+ you.berserk_penalty = 0;
+ }
+ break;
- case SPARM_STRENGTH:
- modify_stat(STAT_STRENGTH, 3, false);
- break;
+ case DELAY_DROP_ITEM:
+ // Note: checking if item is droppable is assumed to
+ // be done before setting up this delay... this includes
+ // quantity (delay.parm2). -- bwr
- case SPARM_DEXTERITY:
- modify_stat(STAT_DEXTERITY, 3, false);
- break;
+ // Make sure item still exists.
+ if (!is_valid_item( you.inv[ delay.parm1 ] ))
+ break;
- case SPARM_INTELLIGENCE:
- modify_stat(STAT_INTELLIGENCE, 3, false);
- break;
+ // Must handle unwield_item before we attempt to copy
+ // so that temporary brands and such are cleared. -- bwr
+ if (delay.parm1 == you.equip[EQ_WEAPON])
+ {
+ unwield_item( delay.parm1 );
+ you.equip[EQ_WEAPON] = -1;
+ canned_msg( MSG_EMPTY_HANDED );
+ }
- case SPARM_PONDEROUSNESS:
- mpr("You feel rather ponderous.");
- // you.speed += 2;
- you.redraw_evasion = 1;
- break;
+ if (!copy_item_to_grid( you.inv[ delay.parm1 ],
+ you.x_pos, you.y_pos, delay.parm2,
+ true ))
+ {
+ mpr("Too many items on this level, not dropping the item.");
+ }
+ else
+ {
+ quant_name( you.inv[ delay.parm1 ], delay.parm2,
+ DESC_NOCAP_A, str_pass );
- case SPARM_LEVITATION:
- mpr("You feel rather light.");
- break;
+ snprintf( info, INFO_SIZE, "You drop %s.", str_pass );
+ mpr(info);
- case SPARM_MAGIC_RESISTANCE:
- mpr("You feel resistant to magic.");
- break;
+ dec_inv_item_quantity( delay.parm1, delay.parm2 );
+ }
+ break;
+
+ case DELAY_ASCENDING_STAIRS:
+ up_stairs();
+ untag_followers();
+ break;
+
+ case DELAY_DESCENDING_STAIRS:
+ down_stairs( false, delay.parm1 );
+ untag_followers();
+ break;
+
+ case DELAY_INTERRUPTIBLE:
+ case DELAY_UNINTERRUPTIBLE:
+ // these are simple delays that have no effect when complete
+ break;
+
+ default:
+ mpr( "You finish doing something." );
+ break;
+ }
- case SPARM_PROTECTION:
- mpr("You feel protected.");
- break;
+ you.wield_change = true;
+ print_stats(); // force redraw of the stats
+ you.turn_is_over = true;
+ pop_delay();
+ }
+}
- case SPARM_STEALTH:
- mpr("You feel stealthy.");
- break;
+static void armour_wear_effects(const int item_slot)
+{
+ item_def &arm = you.inv[item_slot];
- case SPARM_RESISTANCE:
- mpr("You feel resistant to extremes of temperature.");
- break;
+ set_ident_flags(arm, ISFLAG_EQ_ARMOUR_MASK );
+ mprf("You finish putting on %s.", item_name(arm, DESC_NOCAP_YOUR));
- case SPARM_POSITIVE_ENERGY:
- mpr("Your life-force is being protected.");
- break;
+ const equipment_type eq_slot = get_armour_slot(arm);
- case SPARM_ARCHMAGI:
- if (!you.skills[SK_SPELLCASTING])
- mpr("You feel strangely numb.");
- else
- mpr("You feel extremely powerful.");
- break;
- }
- }
+ if (eq_slot == EQ_BODY_ARMOUR)
+ {
+ you.equip[EQ_BODY_ARMOUR] = item_slot;
- if (is_random_artefact( you.inv[ delay.parm1 ] ))
- use_randart( delay.parm1 );
+ if (you.duration[DUR_ICY_ARMOUR] != 0)
+ {
+ mpr( "Your icy armour melts away.", MSGCH_DURATION );
+ you.redraw_armour_class = 1;
+ you.duration[DUR_ICY_ARMOUR] = 0;
+ }
+ }
+ else
+ {
+ switch (eq_slot)
+ {
+ case EQ_SHIELD:
+ if (you.duration[DUR_CONDENSATION_SHIELD])
+ {
+ mpr( "Your icy shield evaporates.", MSGCH_DURATION );
+ you.duration[DUR_CONDENSATION_SHIELD] = 0;
+ }
+ you.equip[EQ_SHIELD] = item_slot;
+ break;
+ case EQ_CLOAK:
+ you.equip[EQ_CLOAK] = item_slot;
+ break;
+ case EQ_HELMET:
+ you.equip[EQ_HELMET] = item_slot;
+ break;
+ case EQ_GLOVES:
+ you.equip[EQ_GLOVES] = item_slot;
+ break;
+ case EQ_BOOTS:
+ you.equip[EQ_BOOTS] = item_slot;
+ break;
+ default:
+ break;
+ }
+ }
- if (item_cursed( you.inv[ delay.parm1 ] ))
- mpr( "Oops, that feels deathly cold." );
+ int ego = get_armour_ego_type( arm );
+ if (ego != SPARM_NORMAL)
+ {
+ switch (ego)
+ {
+ case SPARM_RUNNING:
+ mprf("You feel quick%s.",
+ (you.species == SP_NAGA || you.species == SP_CENTAUR)
+ ? "" : " on your feet");
+ break;
+
+ case SPARM_FIRE_RESISTANCE:
+ mpr("You feel resistant to fire.");
+ break;
+
+ case SPARM_COLD_RESISTANCE:
+ mpr("You feel resistant to cold.");
+ break;
+
+ case SPARM_POISON_RESISTANCE:
+ mpr("You feel healthy.");
+ break;
+
+ case SPARM_SEE_INVISIBLE:
+ mpr("You feel perceptive.");
+ break;
+
+ case SPARM_DARKNESS:
+ if (!you.invis)
+ mpr("You become transparent for a moment.");
+ break;
+
+ case SPARM_STRENGTH:
+ modify_stat(STAT_STRENGTH, 3, false);
+ break;
+
+ case SPARM_DEXTERITY:
+ modify_stat(STAT_DEXTERITY, 3, false);
+ break;
+
+ case SPARM_INTELLIGENCE:
+ modify_stat(STAT_INTELLIGENCE, 3, false);
+ break;
+
+ case SPARM_PONDEROUSNESS:
+ mpr("You feel rather ponderous.");
+ // you.speed += 2;
+ you.redraw_evasion = 1;
+ break;
+
+ case SPARM_LEVITATION:
+ mpr("You feel rather light.");
+ break;
+
+ case SPARM_MAGIC_RESISTANCE:
+ mpr("You feel resistant to magic.");
+ break;
+
+ case SPARM_PROTECTION:
+ mpr("You feel protected.");
+ break;
+
+ case SPARM_STEALTH:
+ mpr("You feel stealthy.");
+ break;
+
+ case SPARM_RESISTANCE:
+ mpr("You feel resistant to extremes of temperature.");
+ break;
+
+ case SPARM_POSITIVE_ENERGY:
+ mpr("Your life-force is being protected.");
+ break;
+
+ case SPARM_ARCHMAGI:
+ if (!you.skills[SK_SPELLCASTING])
+ mpr("You feel strangely numb.");
+ else
+ mpr("You feel extremely powerful.");
+ break;
+ }
+ }
- you.redraw_armour_class = 1;
- you.redraw_evasion = 1;
- break;
+ if (is_random_artefact( arm ))
+ use_randart( item_slot );
- case DELAY_ARMOUR_OFF:
- in_name( delay.parm1, DESC_NOCAP_YOUR, str_pass );
- snprintf( info, INFO_SIZE, "You finish taking off %s.", str_pass );
- mpr(info);
+ if (item_cursed( arm ))
+ mpr( "Oops, that feels deathly cold." );
- if (you.inv[ delay.parm1 ].sub_type < ARM_SHIELD
- || you.inv[ delay.parm1 ].sub_type > ARM_LARGE_SHIELD)
- {
- you.equip[EQ_BODY_ARMOUR] = -1;
- }
- else
- {
- switch (you.inv[ delay.parm1 ].sub_type)
- {
- case ARM_BUCKLER:
- case ARM_LARGE_SHIELD:
- case ARM_SHIELD:
- if (delay.parm1 == you.equip[EQ_SHIELD])
- you.equip[EQ_SHIELD] = -1;
- break;
+ warn_shield_penalties();
- case ARM_CLOAK:
- if (delay.parm1 == you.equip[EQ_CLOAK])
- you.equip[EQ_CLOAK] = -1;
- break;
+ you.redraw_armour_class = 1;
+ you.redraw_evasion = 1;
+}
- case ARM_HELMET:
- if (delay.parm1 == you.equip[EQ_HELMET])
- you.equip[EQ_HELMET] = -1;
- break;
+static command_type get_running_command() {
+ if ( kbhit() ) {
+ stop_running();
+ return CMD_NO_CMD;
+ }
+ if ( is_resting() ) {
+ you.running.rest();
+ return CMD_MOVE_NOWHERE;
+ }
+ return direction_to_command( you.running.x, you.running.y );
+}
+static void handle_run_delays(const delay_queue_item &delay)
+{
+ // Handle inconsistencies between the delay queue and you.running.
+ // We don't want to send the game into a deadlock.
+ if (!you.running)
+ {
+ pop_delay();
+ return;
+ }
- case ARM_GLOVES:
- if (delay.parm1 == you.equip[EQ_GLOVES])
- you.equip[EQ_GLOVES] = -1;
- break;
+ ASSERT( !you.turn_is_over );
- case ARM_BOOTS:
- if (delay.parm1 == you.equip[EQ_BOOTS])
- you.equip[EQ_BOOTS] = -1;
- break;
- }
- }
+ command_type cmd = CMD_NO_CMD;
+ switch (delay.type)
+ {
+ case DELAY_REST:
+ case DELAY_RUN:
+ cmd = get_running_command();
+ break;
+ case DELAY_TRAVEL:
+ cmd = travel();
+ break;
+ }
- unwear_armour( delay.parm1 );
+ if (cmd != CMD_NO_CMD)
+ {
+ mesclr();
+ process_command(cmd);
+ }
- you.redraw_armour_class = 1;
- you.redraw_evasion = 1;
- break;
+ // If you.running has gone to zero, and the run delay was not
+ // removed, remove it now. This is needed to clean up after
+ // find_travel_pos() function in travel.cc.
+ if (!you.running && is_run_delay(current_delay_action()))
+ pop_delay();
+}
- case DELAY_EAT:
- mpr( "You finish eating." );
- break;
+static void handle_macro_delay()
+{
+ run_macro();
+}
- case DELAY_MEMORIZE:
- mpr( "You finish memorising." );
- add_spell_to_memory( delay.parm1 );
- break;
+void run_macro(const char *macroname)
+{
+ const int currdelay = current_delay_action();
+ if (currdelay != DELAY_NOT_DELAYED && currdelay != DELAY_MACRO)
+ return;
- case DELAY_PASSWALL:
- {
- mpr( "You finish merging with the rock." );
- more(); // or the above message won't be seen
+#ifdef CLUA_BINDINGS
+ if (!clua)
+ {
+ mpr("Lua not initialized", MSGCH_DIAGNOSTICS);
+ stop_delay();
+ return;
+ }
- const int pass_x = delay.parm1;
- const int pass_y = delay.parm2;
+ if (!clua.callbooleanfn(false, "c_macro", "s", macroname))
+ {
+ if (clua.error.length())
+ mpr(clua.error.c_str());
- if (pass_x != 0 && pass_y != 0)
- {
+ stop_delay();
+ }
+ else
+ {
+ start_delay(DELAY_MACRO, 1);
+ }
+#else
+ stop_delay();
+#endif
+}
- switch (grd[ pass_x ][ pass_y ])
- {
- case DNGN_ROCK_WALL:
- case DNGN_STONE_WALL:
- case DNGN_METAL_WALL:
- case DNGN_GREEN_CRYSTAL_WALL:
- case DNGN_WAX_WALL:
- case DNGN_SILVER_STATUE:
- case DNGN_ORANGE_CRYSTAL_STATUE:
- ouch(1 + you.hp, 0, KILLED_BY_PETRIFICATION);
- break;
-
- case DNGN_SECRET_DOOR: // oughtn't happen
- case DNGN_CLOSED_DOOR: // open the door
- grd[ pass_x ][ pass_y ] = DNGN_OPEN_DOOR;
- break;
-
- default:
- break;
- }
+// Returns true if the delay should be interrupted, false if the user function
+// had no opinion on the matter, -1 if the delay should not be interrupted.
+static int userdef_interrupt_activity( const delay_queue_item &idelay,
+ activity_interrupt_type ai,
+ const activity_interrupt_data &at )
+{
+#ifdef CLUA_BINDINGS
+ const int delay = idelay.type;
+ lua_State *ls = clua.state();
+ if (!ls || ai == AI_FORCE_INTERRUPT)
+ return (true);
+
+ // Kludge: We have to continue to support ch_stop_run. :-(
+ if (is_run_delay(delay) && you.running && ai == AI_SEE_MONSTER)
+ {
+ bool stop_run = false;
+ if (clua.callfn("ch_stop_run", "M>b",
+ (const monsters *) at.data, &stop_run))
+ {
+ if (stop_run)
+ return (true);
- //jmf: hmm, what to do. kill the monster? (seems too powerful)
- // displace the monster? randomly teleport the monster?
- // This seems fair: try to move the monster, but if not
- // able to, then kill it.
- int mon = mgrd[ pass_x ][ pass_y ];
- if (mon != NON_MONSTER)
- {
- monster_blink( &menv[ mon ] );
+ // No further processing.
+ return (-1);
+ }
- // recheck square for monster
- mon = mgrd[ pass_x ][ pass_y ];
- if (mon != NON_MONSTER)
- monster_die( &menv[ mon ], KILL_YOU, 0 );
- }
+ // If we get here, ch_stop_run wasn't defined, fall through to the
+ // other handlers.
+ }
+
+ const char *interrupt_name = activity_interrupt_name(ai);
+ const char *act_name = delay_name(delay);
- you.x_pos = pass_x;
- you.y_pos = pass_y;
- redraw_screen();
+ bool ran = clua.callfn("c_interrupt_activity", "1:ssA",
+ act_name, interrupt_name, &at);
+ if (ran)
+ {
+ // If the function returned nil, we want to cease processing.
+ if (lua_isnil(ls, -1))
+ {
+ lua_pop(ls, 1);
+ return (-1);
+ }
- const unsigned char grid = grd[ you.x_pos ][ you.y_pos ];
- if ((grid == DNGN_LAVA || grid == DNGN_DEEP_WATER)
- && !player_is_levitating())
- {
- if (you.species == SP_MERFOLK && grid == DNGN_DEEP_WATER)
- {
- mpr("You fall into the water and return "
- "to your normal form.");
- merfolk_start_swimming();
- }
- else
- {
- fall_into_a_pool( true, grid );
- redraw_screen();
- }
- }
- }
- }
- break;
+ bool stopact = lua_toboolean(ls, -1);
+ lua_pop(ls, 1);
+ if (stopact)
+ return (true);
+ }
- case DELAY_BUTCHER:
- strcpy( info, "You finish " );
- strcat( info, (you.species == SP_TROLL
- || you.species == SP_GHOUL) ? "ripping"
- : "chopping" );
+ if (delay == DELAY_MACRO &&
+ clua.callbooleanfn(true, "c_interrupt_macro",
+ "sA", interrupt_name, &at))
+ return (true);
- strcat( info, " the corpse into pieces." );
- mpr( info );
+#endif
+ return (false);
+}
- turn_corpse_into_chunks( mitm[ delay.parm1 ] );
+// Returns true if the activity should be interrupted, false otherwise.
+static bool should_stop_activity(const delay_queue_item &item,
+ activity_interrupt_type ai,
+ const activity_interrupt_data &at)
+{
+ int userd = userdef_interrupt_activity(item, ai, at);
- if (you.berserker && you.berserk_penalty != NO_BERSERK_PENALTY)
- {
- mpr("You enjoyed that.");
- you.berserk_penalty = 0;
- }
- break;
+ // If the user script wanted to stop the activity or cease processing,
+ // do so.
+ if (userd)
+ return (userd == 1);
- case DELAY_DROP_ITEM:
- // Note: checking if item is dropable is assumed to
- // be done before setting up this delay... this includes
- // quantity (delay.parm2). -- bwr
+ return (ai == AI_FORCE_INTERRUPT ||
+ (Options.activity_interrupts[item.type][ai]));
+}
- // Make sure item still exists.
- if (!is_valid_item( you.inv[ delay.parm1 ] ))
- break;
+void interrupt_activity( activity_interrupt_type ai,
+ const activity_interrupt_data &at )
+{
+ const int delay = current_delay_action();
+ if (delay == DELAY_NOT_DELAYED)
+ return;
- // Must handle unwield_item before we attempt to copy
- // so that temporary brands and such are cleared. -- bwr
- if (delay.parm1 == you.equip[EQ_WEAPON])
- {
- unwield_item( delay.parm1 );
- you.equip[EQ_WEAPON] = -1;
- canned_msg( MSG_EMPTY_HANDED );
- }
+ // First try to stop the current delay.
+ const delay_queue_item &item = you.delay_queue.front();
+
+ if (should_stop_activity(item, ai, at))
+ {
+ stop_delay();
+ return;
+ }
- if (!copy_item_to_grid( you.inv[ delay.parm1 ],
- you.x_pos, you.y_pos, delay.parm2 ))
+ // Check the other queued delays; the first delay that is interruptible
+ // will kill itself and all subsequent delays. This is so that a travel
+ // delay stacked behind a delay such as stair/autopickup will be killed
+ // correctly by interrupts that the simple stair/autopickup delay ignores.
+ for (int i = 1, size = you.delay_queue.size(); i < size; ++i)
+ {
+ const delay_queue_item &it = you.delay_queue[i];
+ if (should_stop_activity(it, ai, at))
+ {
+ // Do we have a queued run delay? If we do, flush the delay queue
+ // so that stop running Lua notifications happen.
+ for (int j = i; j < size; ++j)
+ {
+ if (is_run_delay( you.delay_queue[j].type ))
{
- mpr("Too many items on this level, not dropping the item.");
+ stop_delay();
+ return;
}
- else
- {
- quant_name( you.inv[ delay.parm1 ], delay.parm2,
- DESC_NOCAP_A, str_pass );
+ }
- snprintf( info, INFO_SIZE, "You drop %s.", str_pass );
- mpr(info);
+ // Non-run queued delays can be discarded without any processing.
+ you.delay_queue.erase( you.delay_queue.begin() + i,
+ you.delay_queue.end() );
+ break;
+ }
+ }
+}
- dec_inv_item_quantity( delay.parm1, delay.parm2 );
- }
- break;
+static const char *activity_interrupt_names[] =
+{
+ "force", "keypress", "full_hp", "full_mp", "statue",
+ "hungry", "message", "hp_loss", "burden", "stat",
+ "monster", "monster_attack", "teleport"
+};
- case DELAY_ASCENDING_STAIRS:
- up_stairs();
- untag_followers();
- break;
+const char *activity_interrupt_name(activity_interrupt_type ai)
+{
+ ASSERT( sizeof(activity_interrupt_names)
+ / sizeof(*activity_interrupt_names) == NUM_AINTERRUPTS );
- case DELAY_DESCENDING_STAIRS:
- down_stairs( false, delay.parm1 );
- untag_followers();
- break;
+ if (ai == NUM_AINTERRUPTS)
+ return ("");
- case DELAY_INTERUPTABLE:
- case DELAY_UNINTERUPTABLE:
- // these are simple delays that have no effect when complete
- break;
+ return activity_interrupt_names[ai];
+}
- default:
- mpr( "You finish doing something." );
- break;
- }
+activity_interrupt_type get_activity_interrupt(const std::string &name)
+{
+ ASSERT( sizeof(activity_interrupt_names)
+ / sizeof(*activity_interrupt_names) == NUM_AINTERRUPTS );
- you.wield_change = true;
- print_stats(); // force redraw of the stats
- you.turn_is_over = 1;
- you.delay_queue.pop();
- }
+ for (int i = 0; i < NUM_AINTERRUPTS; ++i)
+ if (name == activity_interrupt_names[i])
+ return activity_interrupt_type(i);
+
+ return (NUM_AINTERRUPTS);
+}
+
+static const char *delay_names[] =
+{
+ "not_delayed", "eat", "armour_on", "armour_off", "jewellery_on",
+ "memorise", "butcher", "autopickup", "weapon_swap", "passwall",
+ "drop_item", "multidrop", "ascending_stairs", "descending_stairs", "run",
+ "rest", "travel", "macro", "interruptible", "uninterruptible",
+};
+
+// Gets a delay given its name.
+// name must be lowercased already!
+delay_type get_delay(const std::string &name)
+{
+ ASSERT( sizeof(delay_names) / sizeof(*delay_names) == NUM_DELAYS );
+
+ for (int i = 0; i < NUM_DELAYS; ++i)
+ {
+ if (name == delay_names[i])
+ return delay_type(i);
}
+
+ // Also check American spellings:
+ if (name == "armor_on")
+ return (DELAY_ARMOUR_ON);
+
+ if (name == "armor_off")
+ return (DELAY_ARMOUR_OFF);
+
+ if (name == "memorize")
+ return (DELAY_MEMORISE);
+
+ if (name == "jewelry_on")
+ return (DELAY_JEWELLERY_ON);
+
+ return (NUM_DELAYS);
+}
+
+const char *delay_name(int delay)
+{
+ ASSERT( sizeof(delay_names) / sizeof(*delay_names) == NUM_DELAYS );
+
+ if (delay < 0 || delay >= NUM_DELAYS)
+ return ("");
+
+ return delay_names[delay];
}
diff --git a/crawl-ref/source/delay.h b/crawl-ref/source/delay.h
index e171e355c8..778a14eeca 100644
--- a/crawl-ref/source/delay.h
+++ b/crawl-ref/source/delay.h
@@ -2,6 +2,8 @@
* File: delay.h
* Summary: Functions for handling multi-turn actions.
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> 09/09/01 BWR Created
@@ -10,10 +12,24 @@
#ifndef DELAY_H
#define DELAY_H
+#include "enum.h"
+
void start_delay( int type, int turns, int parm1 = 0, int parm2 = 0 );
void stop_delay( void );
bool you_are_delayed( void );
int current_delay_action( void );
void handle_delay( void );
+bool is_run_delay(int delay);
+const char *activity_interrupt_name(activity_interrupt_type ai);
+activity_interrupt_type get_activity_interrupt(const std::string &);
+
+const char *delay_name(int delay);
+delay_type get_delay(const std::string &);
+
+void perform_activity();
+void interrupt_activity( activity_interrupt_type ai,
+ const activity_interrupt_data &a
+ = activity_interrupt_data() );
+
#endif
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index 173e9b0ed4..f2608ed7ac 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -3,6 +3,8 @@
* Summary: Functions used to print information about various game objects.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <4> 10/14/99 BCR enummed describe_god()
@@ -33,6 +35,7 @@
#include "debug.h"
#include "fight.h"
#include "itemname.h"
+#include "itemprop.h"
#include "macro.h"
#include "mon-util.h"
#include "player.h"
@@ -41,7 +44,6 @@
#include "skills2.h"
#include "spl-book.h"
#include "stuff.h"
-#include "wpn-misc.h"
#include "spl-util.h"
@@ -112,7 +114,8 @@ static void print_description( const std::string &d )
if (nextLine >= currentPos && nextLine < currentPos + lineWidth)
{
- cprintf((d.substr(currentPos, nextLine - currentPos)).c_str());
+ cprintf("%s",
+ (d.substr(currentPos, nextLine - currentPos)).c_str());
currentPos = nextLine + 1;
continue;
}
@@ -331,6 +334,19 @@ static void randart_descpr( std::string &description, const item_def &item )
}
}
+static const char *trap_names[] =
+{
+ "dart", "arrow", "spear", "axe",
+ "teleport", "amnesia", "blade",
+ "bolt", "zot", "needle",
+};
+
+const char *trap_name(trap_type trap)
+{
+ if (trap >= TRAP_DART && trap < NUM_TRAPS)
+ return trap_names[ static_cast<int>( trap ) ];
+ return (NULL);
+}
//---------------------------------------------------------------
//
@@ -682,7 +698,7 @@ static std::string describe_demon(void)
// describe_weapon
//
//---------------------------------------------------------------
-static std::string describe_weapon( const item_def &item, char verbose)
+static std::string describe_weapon( const item_def &item, bool verbose)
{
std::string description;
@@ -785,7 +801,7 @@ static std::string describe_weapon( const item_def &item, char verbose)
}
else
{
- if (verbose == 1)
+ if (verbose)
{
switch (item.sub_type)
{
@@ -872,6 +888,12 @@ static std::string describe_weapon( const item_def &item, char verbose)
"and a skilled user can use it to great effect. ";
break;
+ case WPN_LONGBOW:
+ description += "A long, strong bow made of yew. "
+ "It does excellent damage in combat "
+ "and a skilled archer can use it to great effect. ";
+ break;
+
case WPN_BLOWGUN:
description += "A long, light tube, open at both ends. Doing "
"very little damage, its main use is to fire poisoned "
@@ -926,6 +948,17 @@ static std::string describe_weapon( const item_def &item, char verbose)
"single-edged blade. ";
break;
+ case WPN_LAJATANG:
+ description += "A very rare and extremely effective "
+ "imported weapon, featuring a pole with half-moon blades "
+ "at both ends. ";
+ break;
+
+ case WPN_LOCHABER_AXE:
+ description += "An enormous combination of a pike "
+ "and a battle axe.";
+ break;
+
case WPN_EXECUTIONERS_AXE:
description += "A huge axe. ";
break;
@@ -962,6 +995,10 @@ static std::string describe_weapon( const item_def &item, char verbose)
"A terrible weapon, forged in the fires of Hell. ";
break;
+ case WPN_BLESSED_BLADE:
+ description += "A blade blessed by the Shining One. ";
+ break;
+
case WPN_DEMON_WHIP:
description += "A terrible weapon, woven "
"in the depths of the inferno. ";
@@ -989,8 +1026,8 @@ static std::string describe_weapon( const item_def &item, char verbose)
description += "A large and heavy mace. ";
break;
- case WPN_GREAT_FLAIL:
- description += "A large and heavy flail. ";
+ case WPN_DIRE_FLAIL:
+ description += "A flail with spiked lumps on both ends.";
break;
case WPN_FALCHION:
@@ -1005,9 +1042,9 @@ static std::string describe_weapon( const item_def &item, char verbose)
}
}
- if (verbose == 1 && !launches_things( item.sub_type ))
+ if (verbose)
{
- description += "$Damage rating: ";
+ description += "$Damage rating: ";
append_value(description, property( item, PWPN_DAMAGE ), false);
description += "$Accuracy rating: ";
@@ -1015,7 +1052,7 @@ static std::string describe_weapon( const item_def &item, char verbose)
description += "$Base attack delay: ";
append_value(description, property( item, PWPN_SPEED ) * 10, false);
- description += "%%";
+ description += "%";
}
description += "$";
@@ -1023,7 +1060,7 @@ static std::string describe_weapon( const item_def &item, char verbose)
{
int spec_ench = get_weapon_brand( item );
- if (!is_random_artefact( item ) && verbose == 0)
+ if (!is_random_artefact( item ) && !verbose)
spec_ench = SPWPN_NORMAL;
// special weapon descrip
@@ -1061,7 +1098,7 @@ static std::string describe_weapon( const item_def &item, char verbose)
"all of orcish descent. ";
break;
case SPWPN_VENOM:
- if (launches_things( item.sub_type ))
+ if (is_range_weapon(item))
description += "It poisons the unbranded ammo it fires. ";
else
description += "It poisons the flesh of those it strikes. ";
@@ -1075,7 +1112,7 @@ static std::string describe_weapon( const item_def &item, char verbose)
"it drains the life of those it strikes. ";
break;
case SPWPN_SPEED:
- if (launches_things( item.sub_type ))
+ if (is_range_weapon(item))
{
description += "It allows its wielder to fire twice when "
"they would otherwise have fired only once. ";
@@ -1087,7 +1124,16 @@ static std::string describe_weapon( const item_def &item, char verbose)
}
break;
case SPWPN_VORPAL:
- description += "It inflicts extra damage upon your enemies. ";
+ if (is_range_weapon(item))
+ {
+ description += "Any ";
+ description += ammo_name( item );
+ description += " fired from it inflicts extra damage.";
+ }
+ else
+ {
+ description += "It inflicts extra damage upon your enemies. ";
+ }
break;
case SPWPN_FLAME:
description += "It turns projectiles fired from it into "
@@ -1147,7 +1193,7 @@ static std::string describe_weapon( const item_def &item, char verbose)
description += "$It has a curse placed upon it.";
}
- if (verbose == 1 && !launches_things( item.sub_type ))
+ if (verbose && !is_range_weapon(item))
{
#ifdef USE_NEW_COMBAT_STATS
const int str_weight = weapon_str_weight( item.base_type, item.sub_type );
@@ -1162,18 +1208,21 @@ static std::string describe_weapon( const item_def &item, char verbose)
description += "$This weapon is better for the dexterous.";
#endif
- switch (hands_reqd_for_weapon(item.base_type, item.sub_type))
+ switch (hands_reqd(item, player_size()))
{
- case HANDS_ONE_HANDED:
+ case HANDS_ONE:
description += "$It is a one handed weapon.";
break;
- case HANDS_ONE_OR_TWO_HANDED:
+ case HANDS_HALF:
description += "$It can be used with one hand, or more "
"effectively with two (i.e. when not using a shield).";
break;
- case HANDS_TWO_HANDED:
+ case HANDS_TWO:
description += "$It is a two handed weapon.";
break;
+ default:
+ description += "$It is a buggy weapon.";
+ break;
}
}
@@ -1186,7 +1235,7 @@ static std::string describe_weapon( const item_def &item, char verbose)
break;
}
- if (launches_things( item.sub_type ))
+ if (is_range_weapon(item))
{
switch (get_equip_race( item ))
{
@@ -1206,7 +1255,7 @@ static std::string describe_weapon( const item_def &item, char verbose)
}
}
- if (verbose == 1)
+ if (verbose)
{
description += "$It falls into the";
@@ -1216,6 +1265,7 @@ static std::string describe_weapon( const item_def &item, char verbose)
description += " 'slings' category. ";
break;
case WPN_BOW:
+ case WPN_LONGBOW:
description += " 'bows' category. ";
break;
case WPN_HAND_CROSSBOW:
@@ -1290,7 +1340,7 @@ static std::string describe_ammo( const item_def &item )
case MI_LARGE_ROCK:
description += "A rock, used by giants as a missile. ";
break;
- case MI_EGGPLANT:
+ case MI_NONE: // was eggplant
description += "A purple vegetable. "
"The presence of this object in the game "
"indicates a bug (or some kind of cheating on your part). ";
@@ -1330,7 +1380,7 @@ static std::string describe_ammo( const item_def &item )
// describe_armour
//
//---------------------------------------------------------------
-static std::string describe_armour( const item_def &item, char verbose )
+static std::string describe_armour( const item_def &item, bool verbose )
{
std::string description;
@@ -1345,7 +1395,7 @@ static std::string describe_armour( const item_def &item, char verbose )
}
else
{
- if (verbose == 1)
+ if (verbose)
{
switch (item.sub_type)
{
@@ -1403,16 +1453,21 @@ static std::string describe_armour( const item_def &item, char verbose )
case ARM_GLOVES:
description += "A pair of gloves. ";
break;
+
+ case ARM_CENTAUR_BARDING:
+ description += "An armour made for centaurs, "
+ "to wear over their equine half.";
+ break;
+
+ case ARM_NAGA_BARDING:
+ description += "A special armour made for nagas, "
+ "to wear over their tails.";
+ break;
+
case ARM_BOOTS:
- if (item.plus2 == TBOOT_NAGA_BARDING)
- description += "A special armour made for Nagas, "
- "to wear over their tails. ";
- else if (item.plus2 == TBOOT_CENTAUR_BARDING)
- description += "An armour made for centaurs, "
- "to wear over their equine half. ";
- else
- description += "A pair of sturdy boots. ";
+ description += "A pair of boots.";
break;
+
case ARM_BUCKLER:
description += "A small shield. ";
break;
@@ -1543,7 +1598,7 @@ static std::string describe_armour( const item_def &item, char verbose )
}
}
- if (verbose == 1
+ if (verbose
&& item.sub_type != ARM_SHIELD
&& item.sub_type != ARM_BUCKLER
&& item.sub_type != ARM_LARGE_SHIELD)
@@ -1557,7 +1612,8 @@ static std::string describe_armour( const item_def &item, char verbose )
// caps and wizard hats don't have a base AC
append_value(description, 0, false);
}
- else if (item.sub_type == ARM_BOOTS && item.plus2 != TBOOT_BOOTS)
+ else if (item.sub_type == ARM_NAGA_BARDING
+ || item.sub_type == ARM_CENTAUR_BARDING)
{
// Barding has AC value 4.
append_value(description, 4, false);
@@ -1575,7 +1631,7 @@ static std::string describe_armour( const item_def &item, char verbose )
int ego = get_armour_ego_type( item );
if (ego != SPARM_NORMAL
&& item_ident( item, ISFLAG_KNOW_TYPE )
- && verbose == 1)
+ && verbose)
{
description += "$";
@@ -1794,7 +1850,8 @@ static std::string describe_stick( const item_def &item )
case WAND_DISINTEGRATION:
description += "disrupts the physical structure of "
- "an object, especially a creature's body. ";
+ "anything but the hardest walls -- even rigid "
+ "statues, to say nothing of flesh. ";
break;
default:
@@ -2422,7 +2479,7 @@ static std::string describe_scroll( const item_def &item )
// describe_jewellery
//
//---------------------------------------------------------------
-static std::string describe_jewellery( const item_def &item, char verbose)
+static std::string describe_jewellery( const item_def &item, bool verbose)
{
std::string description;
@@ -2437,11 +2494,11 @@ static std::string describe_jewellery( const item_def &item, char verbose)
else if ((!is_random_artefact( item )
&& get_ident_type( OBJ_JEWELLERY, item.sub_type ) != ID_KNOWN_TYPE)
|| (is_random_artefact( item )
- && item_not_ident( item, ISFLAG_KNOW_TYPE )))
+ && !item_ident( item, ISFLAG_KNOW_TYPE )))
{
description += "A piece of jewellery.";
}
- else if (verbose == 1 || is_random_artefact( item ))
+ else if (verbose || is_random_artefact( item ))
{
switch (item.sub_type)
{
@@ -2623,22 +2680,28 @@ static std::string describe_jewellery( const item_def &item, char verbose)
case AMU_WARDING:
description +=
"This amulet repels some of the attacks of creatures "
- "which have been magically summoned. ";
+ "which have been magically summoned, and also "
+ "makes the wearer more resistant to draining attacks. ";
break;
case AMU_RESIST_CORROSION:
description +=
- "This amulet protects the armour and weaponry of its "
- "wearer from corrosion caused by acids, although not "
+ "This amulet protects the wearer and their equipment "
+ "from corrosion caused by acids, although not "
"infallibly so. ";
break;
case AMU_THE_GOURMAND:
description +=
+ "This amulet allows its wearer to digest raw meat "
+ "even when not hungry. Its effects on the wearer's digestion "
+ "and palate are cumulative over time, and are initially small.";
+ /*
"This amulet allows its wearer to consume meat in "
"various states of decay without suffering unduly as "
"a result. Poisonous or cursed flesh is still not "
"recommended. ";
+ */
break;
case AMU_CONSERVATION:
@@ -2676,7 +2739,7 @@ static std::string describe_jewellery( const item_def &item, char verbose)
description += "$";
}
- if ((verbose == 1 || is_random_artefact( item ))
+ if ((verbose || is_random_artefact( item ))
&& item_ident( item, ISFLAG_KNOW_PLUSES ))
{
// Explicit description of ring power (useful for randarts)
@@ -2845,11 +2908,12 @@ static std::string describe_staff( const item_def &item )
description +=
"allows its wielder to smite foes from afar. The wielder "
"must be at least level four to safely use this ability, "
- "which costs 4 magic points. ";
+ "which drains four charges. ";
break;
case STAFF_STRIKING:
- description += "allows its wielder to strike foes from afar. ";
+ description += "allows its wielder to strike foes from afar "
+ "with force bolts. ";
break;
case STAFF_SPELL_SUMMONING:
@@ -2893,13 +2957,16 @@ static std::string describe_staff( const item_def &item )
if (item_is_rod( item ))
{
- description +=
- "Casting a spell from it consumes no food, and will not fail.$";
+ if (item.sub_type != STAFF_STRIKING)
+ description +=
+ "$$It uses its own mana reservoir for casting spells, and "
+ "recharges automatically by channeling mana from its "
+ "wielder.";
}
else
{
description +=
- "$$Damage rating: 7 $Accuracy rating: +6 $Attack delay: 120%%";
+ "$$Damage rating: 7 $Accuracy rating: +6 $Attack delay: 120%";
description += "$$It falls into the 'staves' category. ";
}
@@ -3094,15 +3161,11 @@ static std::string describe_misc_item( const item_def &item )
return (description);
}
-#if MAC
-#pragma mark -
-#endif
-
// ========================================================================
// Public Functions
// ========================================================================
-bool is_dumpable_artifact( const item_def &item, char verbose)
+bool is_dumpable_artifact( const item_def &item, bool verbose)
{
bool ret = false;
@@ -3111,13 +3174,13 @@ bool is_dumpable_artifact( const item_def &item, char verbose)
ret = item_ident( item, ISFLAG_KNOW_PROPERTIES );
}
else if (item.base_type == OBJ_ARMOUR
- && (verbose == 1 && item_ident( item, ISFLAG_KNOW_TYPE )))
+ && (verbose && item_ident( item, ISFLAG_KNOW_TYPE )))
{
const int spec_ench = get_armour_ego_type( item );
ret = (spec_ench >= SPARM_RUNNING && spec_ench <= SPARM_PRESERVATION);
}
else if (item.base_type == OBJ_JEWELLERY
- && (verbose == 1
+ && (verbose
&& get_ident_type(OBJ_JEWELLERY, item.sub_type) == ID_KNOWN_TYPE))
{
ret = true;
@@ -3135,7 +3198,7 @@ bool is_dumpable_artifact( const item_def &item, char verbose)
// be interpreted as carriage returns.
//
//---------------------------------------------------------------
-std::string get_item_description( const item_def &item, char verbose, bool dump )
+std::string get_item_description( const item_def &item, bool verbose, bool dump )
{
std::string description;
description.reserve(500);
@@ -3236,22 +3299,22 @@ std::string get_item_description( const item_def &item, char verbose, bool dump
description += "This item should not exist. Mayday! Mayday! ";
}
- if (verbose == 1)
+ if (verbose)
{
description += "$It weighs around ";
- const int mass = mass_item( item );
+ const int mass = item_mass( item );
char item_mass[16];
itoa( mass / 10, item_mass, 10 );
for (int i = 0; i < 14; i++)
{
- if (item_mass[i] == '\0')
+ if (item_mass[i] == 0)
{
item_mass[i] = '.';
item_mass[i+1] = (mass % 10) + '0';
- item_mass[i+2] = '\0';
+ item_mass[i+2] = 0;
break;
}
}
@@ -3274,11 +3337,9 @@ std::string get_item_description( const item_def &item, char verbose, bool dump
void describe_item( const item_def &item )
{
#ifdef DOS_TERM
- char buffer[3400];
-
- gettext(25, 1, 80, 25, buffer);
-
- window(25, 1, 80, 25);
+ char buffer[4000];
+ gettext(1, 1, 80, 25, buffer);
+ // window(25, 1, 80, 25);
#endif
clrscr();
@@ -3306,8 +3367,7 @@ void describe_item( const item_def &item )
getch();
#ifdef DOS_TERM
- puttext(25, 1, 80, 25, buffer);
- window(1, 1, 80, 25);
+ puttext(1, 1, 80, 25, buffer);
#endif
} // end describe_item()
@@ -3326,10 +3386,9 @@ void describe_spell(int spelled)
description.reserve(500);
#ifdef DOS_TERM
- char buffer[3400];
-
- gettext(25, 1, 80, 25, buffer);
- window(25, 1, 80, 25);
+ char buffer[4000];
+ gettext(1, 1, 80, 25, buffer);
+ // window(25, 1, 80, 25);
#endif
clrscr();
@@ -4110,7 +4169,8 @@ void describe_spell(int spelled)
case SPELL_AIRSTRIKE: // jet planes in Crawl ??? {dlb}
description +=
"causes the air around a creature to twist itself into "
- "a whirling vortex of meteorological fury. ";
+ "a whirling vortex of meteorological fury. This spell "
+ "is especially effective against flying enemies.";
break;
case SPELL_SHADOW_CREATURES:
@@ -4325,14 +4385,6 @@ void describe_spell(int spelled)
"corporeal undead. ";
break;
- case SPELL_SHUGGOTH_SEED:
- description += "implants a shuggoth seed, the larval parasitic form "
- "of the fearsome shuggoth, in a living host. The "
- "shuggoth seed will draw life from its host and then "
- "hatch, whereupon a fully grown shuggoth will burst "
- "from the unfortunate host's chest. ";
- break;
-
case SPELL_MAXWELLS_SILVER_HAMMER:
description += "bestows a lethal but temporary gravitic field "
"to a crushing implement held by the caster. "
@@ -4371,6 +4423,11 @@ void describe_spell(int spelled)
"can be difficult to control. ";
break;
+ case SPELL_CHAIN_LIGHTNING:
+ description += "releases a massive electrical discharge that "
+ "arcs from target to target until it grounds out.";
+ break;
+
case SPELL_TWIST:
description += "causes a slight spatial distortion around a monster "
"in line of sight of the caster, causing injury. ";
@@ -4421,7 +4478,7 @@ void describe_spell(int spelled)
getch();
#ifdef DOS_TERM
- puttext(25, 1, 80, 25, buffer);
+ puttext(1, 1, 80, 25, buffer);
window(1, 1, 80, 25);
#endif
} // end describe_spell()
@@ -4441,14 +4498,14 @@ void describe_monsters(int class_described, unsigned char which_mons)
description.reserve(200);
#ifdef DOS_TERM
- char buffer[3400];
-
- gettext(25, 1, 80, 25, buffer);
- window(25, 1, 80, 25);
+ char buffer[4000];
+ gettext(1, 1, 80, 25, buffer);
+ // window(25, 1, 80, 25);
#endif
clrscr();
- description = std::string( ptr_monam( &(menv[ which_mons ]), DESC_CAP_A ) );
+
+ description = ptr_monam( &(menv[ which_mons ]), DESC_CAP_A );
description += "$$";
switch (class_described)
@@ -4835,6 +4892,10 @@ void describe_monsters(int class_described, unsigned char which_mons)
description += "It smells horrible.";
break;
+ case MONS_DEATH_DRAKE:
+ description += "A small dragon, radiating evil.";
+ break;
+
case MONS_FIREDRAKE:
description += "A small dragon, puffing clouds of smoke.";
break;
@@ -5806,6 +5867,44 @@ void describe_monsters(int class_described, unsigned char which_mons)
"A small and slimy eel, crackling with electrical discharge.";
break;
+ case MONS_DRACONIAN:
+ case MONS_RED_DRACONIAN:
+ case MONS_WHITE_DRACONIAN:
+ case MONS_GREEN_DRACONIAN:
+ case MONS_PALE_DRACONIAN:
+ case MONS_MOTTLED_DRACONIAN:
+ case MONS_BLACK_DRACONIAN:
+ case MONS_YELLOW_DRACONIAN:
+ case MONS_PURPLE_DRACONIAN:
+ case MONS_DRACONIAN_SHIFTER:
+ case MONS_DRACONIAN_SCORCHER:
+ case MONS_DRACONIAN_ZEALOT:
+ case MONS_DRACONIAN_ANNIHILATOR:
+ case MONS_DRACONIAN_CALLER:
+ case MONS_DRACONIAN_MONK:
+ case MONS_DRACONIAN_KNIGHT:
+ {
+ description += "A ";
+
+ const int subsp = draco_subspecies( &menv[which_mons] );
+ switch (subsp)
+ {
+ case MONS_DRACONIAN: description += "brown "; break;
+ case MONS_BLACK_DRACONIAN: description += "black "; break;
+ case MONS_MOTTLED_DRACONIAN: description += "mottled "; break;
+ case MONS_YELLOW_DRACONIAN: description += "yellow "; break;
+ case MONS_GREEN_DRACONIAN: description += "green "; break;
+ case MONS_PURPLE_DRACONIAN: description += "purple "; break;
+ case MONS_RED_DRACONIAN: description += "red "; break;
+ case MONS_WHITE_DRACONIAN: description += "white "; break;
+ case MONS_PALE_DRACONIAN: description += "pale "; break;
+ default:
+ break;
+ }
+
+ description += "scaled humanoid with wings.";
+ break;
+ }
case MONS_PLAYER_GHOST:
description += "The apparition of ";
description += ghost_description();
@@ -6050,6 +6149,16 @@ void describe_monsters(int class_described, unsigned char which_mons)
"covered in thick red scales and thorns.";
break;
+ case MONS_ORANGE_STATUE:
+ description += "An intricately carved statue of glittering orange "
+ "crystal. Its eyes fix on yours with a piercing gaze.";
+ break;
+
+ case MONS_SILVER_STATUE:
+ description += "A beautiful statue of silver. Its eyes "
+ "glow with an otherworldly radiance.";
+ break;
+
case MONS_PROGRAM_BUG:
default:
description += "If this monster is a \"program bug\", then it's "
@@ -6062,17 +6171,9 @@ void describe_monsters(int class_described, unsigned char which_mons)
#if DEBUG_DIAGNOSTICS
- if (mons_flag( menv[ which_mons ].type, M_SPELLCASTER ))
+ if (mons_class_flag( menv[ which_mons ].type, M_SPELLCASTER ))
{
- int hspell_pass[6] = { MS_NO_SPELL, MS_NO_SPELL, MS_NO_SPELL,
- MS_NO_SPELL, MS_NO_SPELL, MS_NO_SPELL };
-
- int msecc = ((class_described == MONS_HELLION) ? MST_BURNING_DEVIL :
- (class_described == MONS_PANDEMONIUM_DEMON) ? MST_GHOST
- : menv[ which_mons ].number);
-
- mons_spell_list(msecc, hspell_pass);
-
+ const monster_spells &hspell_pass = menv[which_mons].spells;
bool found_spell = false;
for (int i = 0; i < 6; i++)
@@ -6123,7 +6224,7 @@ void describe_monsters(int class_described, unsigned char which_mons)
getch();
#ifdef DOS_TERM
- puttext(25, 1, 80, 25, buffer);
+ puttext(1, 1, 80, 25, buffer);
window(1, 1, 80, 25);
#endif
} // end describe_monsters
@@ -6212,7 +6313,7 @@ static void print_god_abil_desc( int abil )
std::string str( abil_info.name );
str += std::string( 79 - str.length() - cost.length(), ' ' ) + cost + EOL;
- cprintf( str.c_str() );
+ cprintf( "%s", str.c_str() );
}
@@ -6257,7 +6358,7 @@ void describe_god( int which_god, bool give_title )
//mv: print god's name and title - if you can think up better titles
//I have nothing against
textcolor(colour);
- cprintf (god_name(which_god,true)); //print long god's name
+ cprintf( "%s", god_name(which_god,true)); //print long god's name
cprintf (EOL EOL);
//mv: print god's description
@@ -6268,17 +6369,19 @@ void describe_god( int which_god, bool give_title )
case GOD_ZIN:
description = "Zin is an ancient and revered God, dedicated to the establishment of order" EOL
"and the destruction of the forces of chaos and night. Valued worshippers " EOL
- "can gain a variety of powers useful in the fight against the evil, but must" EOL
- "abstain from the use of necromancy and other forms of unholy magic." EOL
- "Zin appreciates long-standing faith as well as sacrifices of valued objects." EOL;
+ "can gain blessings on their weapons and a variety of powers useful in the" EOL
+ "fight against the evil, but must abstain from the use of necromancy and other" EOL
+ "forms of unholy magic. Zin appreciates long-standing faith as well as " EOL
+ "sacrifices of valued objects.";
break;
case GOD_SHINING_ONE:
description = "The Shining One is a powerful crusading deity, allied with Zin in the fight" EOL
- "against evil. Followers may be granted with the ability to summarily dispense" EOL
- "the wrath of heaven, but must never use any form of evil magic and should" EOL
- "fight honourably. The Shining One appreciates long-standing persistence in " EOL
- "the endless crusade, as well as the dedicated destruction of unholy creatures.";
+ "against evil. Followers may be granted blessings on their weapons and the " EOL
+ "ability to summarily dispense the wrath of heaven, but must never use any " EOL
+ "form of evil magic and should fight honourably. The Shining One appreciates" EOL
+ "long-standing persistence in the endless crusade, as well as the dedicated " EOL
+ "destruction of unholy creatures.";
break;
case GOD_KIKUBAAQUDGHA:
@@ -6358,7 +6461,7 @@ void describe_god( int which_god, bool give_title )
"be reported to dev-team.";
}
- cprintf(description);
+ cprintf("%s", description);
//end of printing description
// title only shown for our own god
@@ -6372,17 +6475,17 @@ void describe_god( int which_god, bool give_title )
// based on your god
if (you.piety > 160)
{
- cprintf((which_god == GOD_SHINING_ONE) ? "Champion of Law" :
+ cprintf("%s", (which_god == GOD_SHINING_ONE) ? "Champion of Law" :
(which_god == GOD_ZIN) ? "Divine Warrior" :
(which_god == GOD_ELYVILON) ? "Champion of Light" :
- (which_god == GOD_OKAWARU) ? "Master of Thousand Battles" :
+ (which_god == GOD_OKAWARU) ? "Master of a Thousand Battles" :
(which_god == GOD_YREDELEMNUL) ? "Master of Eternal Death" :
(which_god == GOD_KIKUBAAQUDGHA) ? "Lord of Darkness" :
(which_god == GOD_MAKHLEB) ? "Champion of Chaos" :
(which_god == GOD_VEHUMET) ? "Lord of Destruction" :
(which_god == GOD_TROG) ? "Great Slayer" :
(which_god == GOD_NEMELEX_XOBEH) ? "Great Trickster" :
- (which_god == GOD_SIF_MUNA) ? "Master of Arcane" :
+ (which_god == GOD_SIF_MUNA) ? "Master of the Arcane" :
(which_god == GOD_XOM) ? "Teddy Bear" :
"Bogy the Lord of the Bugs"); // Xom and no god is handled before
}
@@ -6443,16 +6546,13 @@ void describe_god( int which_god, bool give_title )
if (you.religion != which_god)
{
textcolor (colour);
- snprintf( info, INFO_SIZE,
- (you.penance[which_god] >= 50) ? "%s's wrath is upon you!" :
+ cprintf( (you.penance[which_god] >= 50) ? "%s's wrath is upon you!" :
(you.penance[which_god] >= 20) ? "%s is annoyed with you." :
(you.penance[which_god] >= 5) ? "%s well remembers your sins." :
(you.penance[which_god] > 0) ? "%s is ready to forgive your sins." :
(you.worshipped[which_god]) ? "%s is ambivalent towards you."
: "%s is neutral towards you.",
god_name(which_god) );
-
- cprintf(info);
}
else
{
@@ -6470,32 +6570,23 @@ void describe_god( int which_god, bool give_title )
cprintf("You are ignored.");
else
{
- snprintf( info, INFO_SIZE,
-
- (you.piety > 130) ? "A prized avatar of %s.":
+ cprintf( (you.piety > 130) ? "A prized avatar of %s.":
(you.piety > 100) ? "A shining star in the eyes of %s." :
(you.piety > 70) ? "A rising star in the eyes of %s." :
(you.piety > 40) ? "%s is most pleased with you." :
(you.piety > 20) ? "%s has noted your presence." :
(you.piety > 5) ? "%s is noncommittal."
- : "You are beneath notice.",
-
- god_name(which_god)
- );
-
- cprintf(info);
+ : "You are beneath %s's notice.",
+ god_name(which_god));
}
}
//end of favour
//mv: following code shows abilities given from god (if any)
-
-
textcolor(LIGHTGRAY);
cprintf(EOL EOL "Granted powers : (Cost)" EOL);
textcolor(colour);
-
// mv: these gods protects you during your prayer (not mentioning XOM)
// chance for doing so is (random2(you.piety) >= 30)
// Note that it's not depending on penance.
@@ -6503,33 +6594,31 @@ void describe_god( int which_god, bool give_title )
// because god isn't really protecting player - he only sometimes
// saves his life (probably it shouldn't be displayed at all).
// What about this ?
+ bool penance_ability = false;
if ((which_god == GOD_ZIN
|| which_god == GOD_SHINING_ONE
|| which_god == GOD_ELYVILON
- || which_god == GOD_OKAWARU
|| which_god == GOD_YREDELEMNUL)
&& you.piety >= 30)
{
- snprintf( info, INFO_SIZE,
- "%s %s watches over you during prayer." EOL,
- god_name(which_god),
- (you.piety >= 150) ? "carefully": // > 4/5
- (you.piety >= 90) ? "often" : // > 2/3
- "sometimes" // less than 2:3
- );
-
- cprintf(info);
+ penance_ability = true; // suppress "none" later
+ cprintf( "%s %s watches over you during prayer." EOL,
+ god_name(which_god),
+ (you.piety >= 150) ? "carefully": // > 4/5
+ (you.piety >= 90) ? "often" : // > 2/3
+ "sometimes"); // less than 2:3
}
// mv: No abilities (except divine protection)
// under penance (fix me if I'm wrong)
if (player_under_penance())
- {
- cprintf( "None." EOL );
+ {
+ if ( !penance_ability )
+ cprintf( "None." EOL );
}
else
{
- switch (which_god) //mv: finaly let's print abilities
+ switch (which_god) //mv: finally let's print abilities
{
case GOD_ZIN:
if (you.piety >= 30)
@@ -6563,7 +6652,7 @@ void describe_god( int which_god, bool give_title )
print_god_abil_desc( ABIL_TSO_ANNIHILATE_UNDEAD );
if (you.piety >= 100)
- print_god_abil_desc( ABIL_TSO_THUNDERBOLT );
+ print_god_abil_desc( ABIL_TSO_CLEANSING_FLAME );
if (you.piety >= 120)
print_god_abil_desc( ABIL_TSO_SUMMON_DAEVA );
@@ -6619,9 +6708,6 @@ void describe_god( int which_god, bool give_title )
if (you.piety >= 75)
cprintf( "During prayer you have some protection from summoned creatures." EOL );
-
- if (you.piety >= 100)
- print_god_abil_desc( ABIL_VEHUMET_CHANNEL_ENERGY );
break;
@@ -6661,11 +6747,14 @@ void describe_god( int which_god, bool give_title )
break;
case GOD_SIF_MUNA:
- if (you.piety >= 50)
- print_god_abil_desc( ABIL_SIF_MUNA_FORGET_SPELL );
+ if (you.piety >= 30)
+ print_god_abil_desc( ABIL_SIF_MUNA_CHANNEL_ENERGY );
else
cprintf( "None." EOL );
+ if (you.piety >= 50)
+ print_god_abil_desc( ABIL_SIF_MUNA_FORGET_SPELL );
+
if (you.piety >= 100)
cprintf( "You are protected from some side-effects of spellcasting." EOL );
break;
diff --git a/crawl-ref/source/describe.h b/crawl-ref/source/describe.h
index 981f90ce01..9128c27555 100644
--- a/crawl-ref/source/describe.h
+++ b/crawl-ref/source/describe.h
@@ -4,6 +4,8 @@
* Summary: Functions used to print information about various game objects.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <2> 5/21/99 BWR Changed from is_artifact to is_dumpable_artifact
@@ -15,18 +17,19 @@
#include <string>
#include "externs.h"
+#include "enum.h"
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: chardump - spells4
* *********************************************************************** */
-bool is_dumpable_artifact( const item_def &item, char verbose );
+bool is_dumpable_artifact( const item_def &item, bool verbose );
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: chardump - describe
* *********************************************************************** */
-std::string get_item_description( const item_def &item, char verbose,
+std::string get_item_description( const item_def &item, bool verbose,
bool dump = false );
// last updated 12may2000 {dlb}
@@ -61,4 +64,6 @@ void describe_spell(int spelled);
* *********************************************************************** */
std::string ghost_description(bool concise = false);
+const char *trap_name(trap_type trap);
+
#endif
diff --git a/crawl-ref/source/direct.cc b/crawl-ref/source/direct.cc
index 911ccc8522..3e7b6fd845 100644
--- a/crawl-ref/source/direct.cc
+++ b/crawl-ref/source/direct.cc
@@ -3,6 +3,8 @@
* Summary: Functions used when picking squares.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <5> 01/08/01 GDL complete rewrite of direction()
@@ -76,7 +78,8 @@ static const char ycomp[9] = { 1, 1, 1, 0, 0, 0, -1, -1, -1 };
// [dshaligram] Removed . and 5 from dirchars so it's easier to
// special case them.
static const char dirchars[19] = { "b1j2n3h4bbl6y7k8u9" };
-static const char DOSidiocy[10] = { "OPQKSMGHI" };
+static const char DOSidiocy[10] = { "OPQKSMGHI" };
+static const char DOSunidiocy[10] = { "bjnh.lyku" };
static const char *aim_prompt = "Aim (move cursor or -/+/=, change mode with CTRL-F, select with . or >)";
static void describe_feature(int mx, int my, bool oos);
@@ -97,6 +100,12 @@ static bool is_mapped(int x, int y)
return (is_player_mapped(x, y));
}
+int dos_direction_unmunge(int doskey)
+{
+ const char *pos = strchr(DOSidiocy, doskey);
+ return (pos? DOSunidiocy[ pos - DOSidiocy ] : doskey);
+}
+
//---------------------------------------------------------------
//
// direction
@@ -127,7 +136,8 @@ static bool is_mapped(int x, int y)
//
// targetting mode is handled by look_around()
//---------------------------------------------------------------
-void direction( struct dist &moves, int restrict, int mode )
+
+void direction2( struct dist &moves, int restrict, int mode )
{
bool dirChosen = false;
bool targChosen = false;
@@ -143,7 +153,7 @@ void direction( struct dist &moves, int restrict, int mode )
// XXX. this is ALWAYS in relation to the player. But a bit of a hack
// nonetheless! --GDL
- gotoxy( 18, 9 );
+ gotoxy( VIEW_CX + 1, VIEW_CY );
int keyin = getchm(KC_TARGETING);
@@ -320,13 +330,43 @@ void direction( struct dist &moves, int restrict, int mode )
moves.ty = you.y_pos + moves.dy * my;
}
+/* safe version of direction */
+void direction( struct dist &moves, int restrict, int mode,
+ bool confirm_fizzle )
+{
+ while ( 1 )
+ {
+ direction2( moves, restrict, mode );
+ if ( moves.isMe && Options.confirm_self_target == true &&
+ mode != TARG_FRIEND )
+ {
+ if ( yesno("Really target yourself? ", false, 'n') )
+ return;
+ else
+ mpr("Choose a better target.", MSGCH_PROMPT);
+ }
+ else if ( confirm_fizzle && !moves.isValid && Options.fizzlecheck_on )
+ {
+ if ( yesno("Really fizzle? ", false, 'n') )
+ return;
+ else
+ mpr("Try again.", MSGCH_PROMPT);
+ }
+ else
+ {
+ return;
+ }
+ }
+}
+
+
// Attempts to describe a square that's not in line-of-sight. If
// there's a stash on the square, announces the top item and number
// of items, otherwise, if there's a stair that's in the travel
// cache and noted in the Dungeon (O)verview, names the stair.
static void describe_oos_square(int x, int y)
{
- if (!is_mapped(x, y))
+ if (!in_bounds(x, y) || !is_mapped(x, y))
return;
#ifdef STASH_TRACKING
@@ -365,8 +405,8 @@ void look_around(struct dist &moves, bool justLooking, int first_move, int mode)
bool dirChosen = false;
bool targChosen = false;
int dir = 0;
- int cx = 17;
- int cy = 9;
+ int cx = VIEW_CX;
+ int cy = VIEW_CY;
int newcx, newcy;
int mx, my; // actual map x,y (scratch)
int mid; // monster id (scratch)
@@ -414,6 +454,11 @@ void look_around(struct dist &moves, bool justLooking, int first_move, int mode)
if (!justLooking && keyin == ' ')
keyin = '\r';
+ // [dshaligram] Fudge: in targeting mode, '>' says shoot a missile
+ // that lands here.
+ if (!justLooking && keyin == '>')
+ keyin = 'X';
+
// DOS idiocy
if (keyin == 0)
{
@@ -441,6 +486,33 @@ void look_around(struct dist &moves, bool justLooking, int first_move, int mode)
// handle non-directional keys
switch (keyin)
{
+#ifdef WIZARD
+ case 'F':
+ targChosen = true;
+ mx = you.x_pos + cx - VIEW_CX;
+ my = you.y_pos + cy - VIEW_CY;
+ if (!in_bounds(mx, my))
+ break;
+ mid = mgrd[mx][my];
+
+ if (mid == NON_MONSTER)
+ break;
+
+ mprf("Changing attitude of %s\n",
+ ptr_monam(&menv[mid], DESC_PLAIN));
+ menv[mid].attitude =
+ menv[mid].attitude == ATT_HOSTILE?
+ ATT_FRIENDLY
+ : ATT_HOSTILE;
+
+ describe_monsters( menv[ mid ].type, mid );
+ redraw_screen();
+ mesclr( true );
+ // describe the cell again.
+ describe_cell(view2gridX(cx), view2gridY(cy));
+ break;
+#endif
+
case CONTROL('F'):
mode = (mode + 1) % TARG_NUM_MODES;
@@ -519,8 +591,10 @@ void look_around(struct dist &moves, bool justLooking, int first_move, int mode)
case '?':
targChosen = true;
- mx = you.x_pos + cx - 17;
- my = you.y_pos + cy - 9;
+ mx = you.x_pos + cx - VIEW_CX;
+ my = you.y_pos + cy - VIEW_CY;
+ if (!in_bounds(mx, my))
+ break;
mid = mgrd[mx][my];
if (mid == NON_MONSTER)
@@ -535,22 +609,23 @@ void look_around(struct dist &moves, bool justLooking, int first_move, int mode)
redraw_screen();
mesclr( true );
// describe the cell again.
- describe_cell(you.x_pos + cx - 17, you.y_pos + cy - 9);
+ describe_cell(view2gridX(cx), view2gridY(cy));
break;
case '\r':
case '\n':
case '.':
case '5':
+ case 'X':
// If we're in look-around mode, and the cursor is on
// the character and there's a valid travel target
// within the viewport, jump to that target.
- if (justLooking && cx == 17 && cy == 9)
+ if (justLooking && cx == VIEW_CX && cy == VIEW_CY)
{
if (you.travel_x > 0 && you.travel_y > 0)
{
- int nx = you.travel_x - you.x_pos + 17;
- int ny = you.travel_y - you.y_pos + 9;
+ int nx = grid2viewX(you.travel_x);
+ int ny = grid2viewY(you.travel_y);
if (in_viewport_bounds(nx, ny))
{
newcx = nx;
@@ -562,7 +637,7 @@ void look_around(struct dist &moves, bool justLooking, int first_move, int mode)
else
{
dirChosen = true;
- dir = 4;
+ dir = keyin == 'X'? -1 : 4;
}
break;
@@ -584,12 +659,12 @@ void look_around(struct dist &moves, bool justLooking, int first_move, int mode)
break;
// check for SELECTION
- if (dirChosen && dir == 4)
+ if (dirChosen && (dir == 4 || dir == -1))
{
// [dshaligram] We no longer vet the square coordinates if
// we're justLooking. By not vetting the coordinates, we make 'x'
// look_around() nicer for travel purposes.
- if (!justLooking)
+ if (!justLooking || !in_bounds(view2gridX(cx), view2gridY(cy)))
{
// RULE: cannot target what you cannot see
if (!in_vlos(cx, cy))
@@ -602,16 +677,17 @@ void look_around(struct dist &moves, bool justLooking, int first_move, int mode)
moves.isValid = true;
moves.isTarget = true;
- moves.tx = you.x_pos + cx - 17;
- moves.ty = you.y_pos + cy - 9;
+ moves.isEndpoint = (dir == -1);
+ moves.tx = you.x_pos + cx - VIEW_CX;
+ moves.ty = you.y_pos + cy - VIEW_CY;
if (moves.tx == you.x_pos && moves.ty == you.y_pos)
moves.isMe = true;
else
{
// try to set you.previous target
- mx = you.x_pos + cx - 17;
- my = you.y_pos + cy - 9;
+ mx = you.x_pos + cx - VIEW_CX;
+ my = you.y_pos + cy - VIEW_CY;
mid = mgrd[mx][my];
if (mid == NON_MONSTER)
@@ -633,10 +709,10 @@ void look_around(struct dist &moves, bool justLooking, int first_move, int mode)
}
// bounds check for newcx, newcy
- if (newcx < 1) newcx = 1;
- if (newcx > 33) newcx = 33;
- if (newcy < 1) newcy = 1;
- if (newcy > 17) newcy = 17;
+ if (newcx < VIEW_SX) newcx = VIEW_SX;
+ if (newcx > VIEW_EX) newcx = VIEW_EX;
+ if (newcy < VIEW_SY) newcy = VIEW_SY;
+ if (newcy > VIEW_EY) newcy = VIEW_EY;
// no-op if the cursor doesn't move.
if (newcx == cx && newcy == cy)
@@ -646,14 +722,19 @@ void look_around(struct dist &moves, bool justLooking, int first_move, int mode)
cx = newcx;
cy = newcy;
mesclr( true );
+
+ const int gridX = view2gridX(cx),
+ gridY = view2gridY(cy);
+
if (!in_vlos(cx, cy))
{
mpr("You can't see that place.");
- describe_oos_square(you.x_pos + cx - 17,
- you.y_pos + cy - 9);
+ describe_oos_square(gridX, gridY);
continue;
}
- describe_cell(you.x_pos + cx - 17, you.y_pos + cy - 9);
+
+ if (in_bounds(gridX, gridY))
+ describe_cell(gridX, gridY);
} // end WHILE
mesclr( true );
@@ -661,18 +742,19 @@ void look_around(struct dist &moves, bool justLooking, int first_move, int mode)
bool in_vlos(int x, int y)
{
- return in_los_bounds(x, y) && (env.show[x - 8][y] || (x == 17 && y == 9));
+ return in_los_bounds(x, y)
+ && (env.show[x - LOS_SX][y] || (x == VIEW_CX && y == VIEW_CY));
}
bool in_los(int x, int y)
{
- const int tx = x + 9 - you.x_pos,
- ty = y + 9 - you.y_pos;
+ const int tx = x + VIEW_CX - you.x_pos,
+ ty = y + VIEW_CY - you.y_pos;
- if (!in_los_bounds(tx + 8, ty))
+ if (!in_los_bounds(tx, ty))
return (false);
- return (x == you.x_pos && y == you.y_pos) || env.show[tx][ty];
+ return (x == you.x_pos && y == you.y_pos) || env.show[tx - LOS_SX][ty];
}
static bool find_monster( int x, int y, int mode )
@@ -688,7 +770,7 @@ static bool find_monster( int x, int y, int mode )
&& !mons_friendly( &menv[targ_mon] )
&&
(Options.target_zero_exp ||
- !mons_flag( menv[targ_mon].type, M_NO_EXP_GAIN )) )));
+ !mons_class_flag( menv[targ_mon].type, M_NO_EXP_GAIN )) )));
}
static bool find_feature( int x, int y, int mode )
@@ -760,12 +842,12 @@ static int next_los(int dir, int los, bool wrap)
bool in_viewport_bounds(int x, int y)
{
- return (x >= 1 && x <= 33 && y >= 1 && y <= 17);
+ return (x >= VIEW_SX && x <= VIEW_EX && y >= VIEW_SY && y <= VIEW_EY);
}
bool in_los_bounds(int x, int y)
{
- return !(x > 25 || x < 8 || y > 17 || y < 1);
+ return !(x > LOS_EX || x < LOS_SX || y > LOS_EY || y < LOS_SY);
}
//---------------------------------------------------------------
@@ -805,7 +887,8 @@ static char find_square( unsigned char xps, unsigned char yps,
{
// We've been told to flip between visible/hidden, so we
// need to find what we're currently on.
- bool vis = (env.show[xps - 8][yps] || (xps == 17 && yps == 9));
+ bool vis = (env.show[xps - 8][yps]
+ || (xps == VIEW_CX && yps == VIEW_CY));
if (wrap && (vis != (los == LOS_FLIPVH)) == (direction == 1))
{
@@ -828,9 +911,9 @@ static char find_square( unsigned char xps, unsigned char yps,
onlyVis = (los & LOS_VISIBLE);
onlyHidden = (los & LOS_HIDDEN);
- const int minx = 1, maxx = 33,
- miny = -7, maxy = 25,
- ctrx = 17, ctry = 9;
+ const int minx = VIEW_SX, maxx = VIEW_EX,
+ miny = VIEW_SY - VIEW_Y_DIFF, maxy = VIEW_EY + VIEW_Y_DIFF,
+ ctrx = VIEW_CX, ctry = VIEW_CY;
while (temp_xps >= minx - 1 && temp_xps <= maxx
&& temp_yps <= maxy && temp_yps >= miny - 1)
@@ -963,7 +1046,7 @@ static char find_square( unsigned char xps, unsigned char yps,
// continue;
if (temp_xps < minx - 1 || temp_xps > maxx
- || temp_yps < 1 || temp_yps > 17)
+ || temp_yps < VIEW_SY || temp_yps > VIEW_EY)
continue;
if (targ_x < 1 || targ_x >= GXM || targ_y < 1 || targ_y >= GYM)
@@ -986,61 +1069,12 @@ static char find_square( unsigned char xps, unsigned char yps,
next_los(direction, los, wrap)));
}
-static bool is_shopstair(int x, int y)
-{
- return (is_stair(grd[x][y]) || grd[x][y] == DNGN_ENTER_SHOP);
-}
-
-extern unsigned char (*mapch2) (unsigned char);
-static bool is_full_mapped(int x, int y)
-{
- unsigned grid = grd[x][y];
- int envch = env.map[x - 1][y - 1];
- return (envch && envch == mapch2(grid));
-}
-
-static int surround_nonshopstair_count(int x, int y)
-{
- int count = 0;
- for (int ix = -1; ix < 2; ++ix)
- {
- for (int iy = -1; iy < 2; ++iy)
- {
- int nx = x + ix, ny = y + iy;
- if (nx <= 0 || nx >= GXM || ny <= 0 || ny >= GYM)
- continue;
- if (is_full_mapped(nx, ny) && !is_shopstair(nx, ny))
- count++;
- }
- }
- return (count);
-}
-
-// For want of a better name...
-static bool clear_mapped(int x, int y)
-{
- if (!is_full_mapped(x, y))
- return (false);
-
- if (is_shopstair(x, y))
- return (surround_nonshopstair_count(x, y) > 0);
-
- return (true);
-}
-
static void describe_feature(int mx, int my, bool oos)
{
- if (oos && !clear_mapped(mx, my))
+ if (oos && !is_terrain_seen(mx, my))
return;
- unsigned oldfeat = grd[mx][my];
- if (oos && env.map[mx - 1][my - 1] == mapch2(DNGN_SECRET_DOOR))
- grd[mx][my] = DNGN_ROCK_WALL;
-
std::string desc = feature_description(mx, my);
-
- grd[mx][my] = oldfeat;
-
if (desc.length())
{
if (oos)
@@ -1049,10 +1083,29 @@ static void describe_feature(int mx, int my, bool oos)
}
}
-std::string feature_description(int mx, int my)
+// Returns a vector of features matching the given pattern.
+std::vector<dungeon_feature_type> features_by_desc(const text_pattern &pattern)
{
- int trf; // used for trap type??
- switch (grd[mx][my])
+ std::vector<dungeon_feature_type> features;
+
+ if (pattern.valid())
+ {
+ for (int i = 0; i < NUM_FEATURES; ++i)
+ {
+ std::string fdesc = feature_description(i);
+ if (fdesc.empty())
+ continue;
+
+ if (pattern.matches( fdesc ))
+ features.push_back( dungeon_feature_type(i) );
+ }
+ }
+ return (features);
+}
+
+std::string feature_description(int grid)
+{
+ switch (grid)
{
case DNGN_STONE_WALL:
return ("A stone wall.");
@@ -1105,57 +1158,14 @@ std::string feature_description(int mx, int my)
return ("A stone staircase leading up.");
case DNGN_ENTER_HELL:
return ("A gateway to hell.");
- case DNGN_BRANCH_STAIRS:
- return ("A staircase to a branch level.");
case DNGN_TRAP_MECHANICAL:
+ return ("A mechanical trap.");
case DNGN_TRAP_MAGICAL:
+ return ("A magical trap.");
case DNGN_TRAP_III:
- for (trf = 0; trf < MAX_TRAPS; trf++)
- {
- if (env.trap[trf].x == mx
- && env.trap[trf].y == my)
- {
- break;
- }
-
- if (trf == MAX_TRAPS - 1)
- {
- mpr("Error - couldn't find that trap.");
- error_message_to_player();
- break;
- }
- }
-
- switch (env.trap[trf].type)
- {
- case TRAP_DART:
- return ("A dart trap.");
- case TRAP_ARROW:
- return ("An arrow trap.");
- case TRAP_SPEAR:
- return ("A spear trap.");
- case TRAP_AXE:
- return ("An axe trap.");
- case TRAP_TELEPORT:
- return ("A teleportation trap.");
- case TRAP_AMNESIA:
- return ("An amnesia trap.");
- case TRAP_BLADE:
- return ("A blade trap.");
- case TRAP_BOLT:
- return ("A bolt trap.");
- case TRAP_ZOT:
- return ("A Zot trap.");
- case TRAP_NEEDLE:
- return ("A needle trap.");
- default:
- mpr("An undefined trap. Huh?");
- error_message_to_player();
- break;
- }
- break;
+ return ("A trap.");
case DNGN_ENTER_SHOP:
- return (shop_name(mx, my));
+ return ("A shop.");
case DNGN_ENTER_LABYRINTH:
return ("A labyrinth entrance.");
case DNGN_ENTER_DIS:
@@ -1258,8 +1268,72 @@ std::string feature_description(int mx, int my)
case DNGN_DRY_FOUNTAIN_VIII:
case DNGN_PERMADRY_FOUNTAIN:
return ("A dry fountain.");
+ default:
+ return ("");
+ }
+}
+
+std::string feature_description(int mx, int my)
+{
+ int trf; // used for trap type??
+
+ const int grid = grd[mx][my];
+ std::string desc = feature_description(grid);
+ switch (grid)
+ {
+ case DNGN_TRAP_MECHANICAL:
+ case DNGN_TRAP_MAGICAL:
+ case DNGN_TRAP_III:
+ for (trf = 0; trf < MAX_TRAPS; trf++)
+ {
+ if (env.trap[trf].x == mx
+ && env.trap[trf].y == my)
+ {
+ break;
+ }
+
+ if (trf == MAX_TRAPS - 1)
+ {
+ mpr("Error - couldn't find that trap.");
+ error_message_to_player();
+ break;
+ }
+ }
+
+ switch (env.trap[trf].type)
+ {
+ case TRAP_DART:
+ return ("A dart trap.");
+ case TRAP_ARROW:
+ return ("An arrow trap.");
+ case TRAP_SPEAR:
+ return ("A spear trap.");
+ case TRAP_AXE:
+ return ("An axe trap.");
+ case TRAP_TELEPORT:
+ return ("A teleportation trap.");
+ case TRAP_AMNESIA:
+ return ("An amnesia trap.");
+ case TRAP_BLADE:
+ return ("A blade trap.");
+ case TRAP_BOLT:
+ return ("A bolt trap.");
+ case TRAP_ZOT:
+ return ("A Zot trap.");
+ case TRAP_NEEDLE:
+ return ("A needle trap.");
+ default:
+ mpr("An undefined trap. Huh?");
+ error_message_to_player();
+ break;
+ }
+ break;
+ case DNGN_ENTER_SHOP:
+ return (shop_name(mx, my));
+ default:
+ break;
}
- return ("");
+ return (desc);
}
static void describe_cell(int mx, int my)
@@ -1343,7 +1417,8 @@ static void describe_cell(int mx, int my)
if (mons_is_mimic( menv[i].type ))
mimic_item = true;
- else if (!mons_flag(menv[i].type, M_NO_EXP_GAIN))
+ else if (!mons_class_flag(menv[i].type, M_NO_EXP_GAIN)
+ && !mons_is_statue(menv[i].type))
{
if (menv[i].behaviour == BEH_SLEEP)
{
@@ -1355,7 +1430,7 @@ static void describe_cell(int mx, int my)
else if (menv[i].behaviour == BEH_FLEE)
{
strcpy(info, mons_pronoun(menv[i].type, PRONOUN_CAP));
- strcat(info, " is fleeing in terror.");
+ strcat(info, " is retreating.");
mpr(info);
}
// hostile with target != you
@@ -1422,7 +1497,7 @@ static void describe_cell(int mx, int my)
strcat(info, " is covered in liquid flames.");
break;
default:
- info[0] = '\0';
+ info[0] = 0;
break;
} // end switch
if (info[0])
diff --git a/crawl-ref/source/direct.h b/crawl-ref/source/direct.h
index e591107578..cb31de043d 100644
--- a/crawl-ref/source/direct.h
+++ b/crawl-ref/source/direct.h
@@ -3,6 +3,8 @@
* Summary: Functions used when picking squares.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -28,7 +30,7 @@
#define DIR_DIR 2
void direction( struct dist &moves, int restricts = DIR_NONE,
- int mode = TARG_ANY );
+ int mode = TARG_ANY, bool confirm_fizzle = false );
// last updated 12may2000 {dlb}
/* ***********************************************************************
@@ -42,6 +44,31 @@ bool in_viewport_bounds(int x, int y);
bool in_los(int x, int y);
bool in_vlos(int x, int y);
+int dos_direction_unmunge(int doskey);
+
std::string feature_description(int mx, int my);
+std::string feature_description(int grid);
+
+std::vector<dungeon_feature_type> features_by_desc(const text_pattern &pattern);
+
+inline int view2gridX(int vx)
+{
+ return (you.x_pos + vx - VIEW_CX);
+}
+
+inline int view2gridY(int vy)
+{
+ return (you.y_pos + vy - VIEW_CY);
+}
+
+inline int grid2viewX(int gx)
+{
+ return (gx - you.x_pos + VIEW_CX);
+}
+
+inline int grid2viewY(int gy)
+{
+ return (gy - you.y_pos + VIEW_CY);
+}
#endif
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index a18ab7c726..011b46444b 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -34,18 +34,29 @@
#include "defines.h"
#include "enum.h"
#include "externs.h"
+#include "direct.h"
#include "dungeon.h"
#include "itemname.h"
+#include "itemprop.h"
#include "items.h"
+#include "mapdef.h"
#include "maps.h"
+#include "misc.h"
#include "mon-util.h"
#include "mon-pick.h"
#include "monplace.h"
+#include "notes.h"
#include "player.h"
#include "randart.h"
#include "spl-book.h"
#include "stuff.h"
-#include "wpn-misc.h"
+
+#define MAX_PIT_MONSTERS 10
+
+struct pit_mons_def {
+ int type;
+ int rare;
+};
struct spec_t {
bool created;
@@ -73,8 +84,6 @@ static void builder_items(int level_number, char level_type, int items_wanted);
static void builder_monsters(int level_number, char level_type, int mon_wanted);
static void place_specific_stair(unsigned char stair);
static void place_branch_entrances(int dlevel, char level_type);
-static bool place_specific_trap(unsigned char spec_x, unsigned char spec_y,
- unsigned char spec_type);
static void place_traps( int level_number );
static void prepare_swamp(void);
static void prepare_water( int level_number );
@@ -115,18 +124,15 @@ static void diamond_rooms(int level_number);
// ITEM & SHOP FUNCTIONS
static void place_shops(int level_number);
-static void place_spec_shop(int level_number, unsigned char shop_x,
- unsigned char shop_y, unsigned char force_s_type);
static unsigned char item_in_shop(unsigned char shop_type);
static bool treasure_area(int level_number, unsigned char ta1_x,
unsigned char ta2_x, unsigned char ta1_y,
unsigned char ta2_y);
-static char rare_weapon(unsigned char w_type);
static bool is_weapon_special(int the_weapon);
static void set_weapon_special(int the_weapon, int spwpn);
static void big_room(int level_number);
-static void chequerboard(spec_room &sr, unsigned char
- target, unsigned char floor1, unsigned char floor2);
+static void chequerboard(spec_room &sr, unsigned char target,
+ unsigned char floor1, unsigned char floor2);
static void roguey_level(int level_number, spec_room &sr);
static void morgue(spec_room &sr);
@@ -134,9 +140,10 @@ static void morgue(spec_room &sr);
static void special_room(int level_number, spec_room &sr);
static void specr_2(spec_room &sr);
static void beehive(spec_room &sr);
+static void jelly_pit(int level_number, spec_room &sr);
// VAULT FUNCTIONS
-static void build_vaults(int level_number, int force_vault);
+static void build_vaults(int level_number, int vault_number);
static void build_minivaults(int level_number, int force_vault);
static int vault_grid( int level_number, int vx, int vy, int altar_count,
FixedVector < char, 7 > &acq_item_class,
@@ -148,22 +155,84 @@ static int vault_grid( int level_number, int vx, int vy, int altar_count,
static int pick_an_altar(void);
static void place_altar(void);
+static std::string level_name(int subdepth)
+{
+ return place_name(
+ get_packed_place(
+ you.where_are_you, subdepth, you.level_type ) );
+}
+
+static bool got_curare_roll(const int item_level)
+{
+ return one_chance_in(item_level > 27? 6 :
+ item_level < 2 ? 15 :
+ (364 - 7 * item_level) / 25);
+}
-/*
- **************************************************
- * *
- * BEGIN PUBLIC FUNCTIONS *
- * *
- **************************************************
-*/
+static void place_altars()
+{
+ int altar_chances[][2] = {
+ // These are percentages
+ { BRANCH_MAIN_DUNGEON, 8 },
+ { BRANCH_DIS, 0 },
+ { BRANCH_GEHENNA, 0 },
+ { BRANCH_VESTIBULE_OF_HELL, 0 },
+ { BRANCH_COCYTUS, 0 },
+ { BRANCH_TARTARUS, 0 },
+ { BRANCH_INFERNO, 0 },
+ { BRANCH_THE_PIT, 0 },
+ { BRANCH_ORCISH_MINES, 20 },
+ { BRANCH_HIVE, 0 },
+ { BRANCH_LAIR, 5 },
+ { BRANCH_SLIME_PITS, 5 },
+ { BRANCH_VAULTS, 5 },
+ { BRANCH_CRYPT, 5 },
+ { BRANCH_HALL_OF_BLADES, 0 },
+ { BRANCH_HALL_OF_ZOT, 1 },
+ { BRANCH_ECUMENICAL_TEMPLE, 0 },
+ { BRANCH_SNAKE_PIT, 10 },
+ { BRANCH_ELVEN_HALLS, 8 },
+ { BRANCH_TOMB, 0 },
+ { BRANCH_SWAMP, 0 },
+ { BRANCH_CAVERNS, 0 },
+ { -1, -1 }
+ };
+
+ // No altars before level 5.
+ if (you.your_level < 4)
+ return;
+
+ for (int i = 0; altar_chances[i][0] != -1; ++i)
+ {
+ if (player_in_branch( altar_chances[i][0] ))
+ {
+ int prob = altar_chances[i][1];
+ while (prob)
+ {
+ if (random2(100) >= prob)
+ break;
+
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Placing an altar");
+#endif
+ place_altar();
+ // Reduce the chance and try to place another.
+ prob /= 5;
+ }
+ break;
+ }
+ }
+}
+
+/**********************************************************************
+ * builder() - kickoff for the dungeon generator.
+ *********************************************************************/
void builder(int level_number, char level_type)
{
int i; // generic loop variable
int x,y; // generic map loop variables
- // srandom(time(NULL));
-
// blank level with DNGN_ROCK_WALL
make_box(0,0,GXM-1,GYM-1,DNGN_ROCK_WALL,DNGN_ROCK_WALL);
@@ -225,7 +294,7 @@ void builder(int level_number, char level_type)
}
}
- // hook up the special room (if there is one, and it hasn't
+ // hook up the special room (if there is one, and it hasn't
// been hooked up already in roguey_level()
if (sr.created && !sr.hooked_up)
specr_2(sr);
@@ -274,7 +343,7 @@ void builder(int level_number, char level_type)
if (level_number > 5 && one_chance_in(500 - 5 * level_number))
items_wanted = 10 + random2avg( 90, 2 ); // rich level!
- // change pre-rock (105) to rock, and pre-floor (106) to floor
+ // change pre-rock (105) to rock, and pre-floor (106) to floor
replace_area( 0,0,GXM-1,GYM-1, DNGN_BUILDER_SPECIAL_WALL, DNGN_ROCK_WALL );
replace_area( 0,0,GXM-1,GYM-1, DNGN_BUILDER_SPECIAL_FLOOR, DNGN_FLOOR );
@@ -284,7 +353,7 @@ void builder(int level_number, char level_type)
// place monsters
builder_monsters(level_number, level_type, mon_wanted);
- // place shops, if appropriate
+ // place shops, if appropriate
if (player_in_branch( BRANCH_MAIN_DUNGEON )
|| player_in_branch( BRANCH_ORCISH_MINES )
|| player_in_branch( BRANCH_ELVEN_HALLS )
@@ -385,8 +454,7 @@ void builder(int level_number, char level_type)
mons_place( MONS_CURSE_SKULL, BEH_SLEEP, MHITNOT, false, 0, 0 );
}
- if (player_in_branch( BRANCH_ORCISH_MINES ) && one_chance_in(5))
- place_altar();
+ place_altars();
// hall of blades (1 level deal) - no down staircases, thanks!
if (player_in_branch( BRANCH_HALL_OF_BLADES ))
@@ -441,19 +509,6 @@ int items( int allow_uniques, // not just true-false,
if (p == NON_ITEM)
return (NON_ITEM);
- // clear all properties except mitm.base_type <used in switch below> {dlb}:
- mitm[p].sub_type = 0;
- mitm[p].flags = 0;
- mitm[p].special = 0;
- mitm[p].plus = 0;
- mitm[p].plus2 = 0;
- mitm[p].x = 0;
- mitm[p].y = 0;
- mitm[p].link = NON_ITEM;
- mitm[p].slot = 0;
- mitm[p].orig_monnum = 0;
- mitm[p].orig_place = 0;
-
// cap item_level unless an acquirement-level item {dlb}:
if (item_level > 50 && item_level != MAKE_GOOD_ITEM)
item_level = 50;
@@ -528,9 +583,10 @@ int items( int allow_uniques, // not just true-false,
// this replaced the infinite loop (wasteful) -- may need
// to make into its own function to allow ease of tweaking
// distribution {dlb}:
- temp_rand = random2(9);
+ temp_rand = random2(10);
- mitm[p].sub_type = ((temp_rand == 8) ? WPN_DEMON_BLADE :
+ mitm[p].sub_type = ((temp_rand == 9) ? WPN_LAJATANG :
+ (temp_rand == 8) ? WPN_DEMON_BLADE :
(temp_rand == 7) ? WPN_DEMON_TRIDENT :
(temp_rand == 6) ? WPN_DEMON_WHIP :
(temp_rand == 5) ? WPN_DOUBLE_SWORD :
@@ -547,7 +603,7 @@ int items( int allow_uniques, // not just true-false,
{
temp_value = (unsigned char) random2(NUM_WEAPONS);
- if (rare_weapon(temp_value) >= random2(10) + 1)
+ if (weapon_rarity(temp_value) >= random2(10) + 1)
{
mitm[p].sub_type = temp_value;
break;
@@ -614,8 +670,14 @@ int items( int allow_uniques, // not just true-false,
if (item_level > 6
&& random2(3000) <= 30 + (item_level * 3) && one_chance_in(12))
{
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Making fixed artifact.");
+#endif
if (make_item_fixed_artefact( mitm[p], (item_level == 51) ))
+ {
+ quant = 1;
break;
+ }
}
}
@@ -647,7 +709,7 @@ int items( int allow_uniques, // not just true-false,
case WPN_FLAIL:
case WPN_SPIKED_FLAIL:
case WPN_GREAT_MACE:
- case WPN_GREAT_FLAIL:
+ case WPN_DIRE_FLAIL:
if (one_chance_in(6))
set_equip_race( mitm[p], ISFLAG_ELVEN );
if (one_chance_in(4))
@@ -729,6 +791,7 @@ int items( int allow_uniques, // not just true-false,
case WPN_HALBERD:
case WPN_GLAIVE:
case WPN_EXECUTIONERS_AXE:
+ case WPN_LOCHABER_AXE:
if (one_chance_in(5))
set_equip_race( mitm[p], ISFLAG_ORCISH );
break;
@@ -739,6 +802,7 @@ int items( int allow_uniques, // not just true-false,
break;
case WPN_KATANA:
+ case WPN_LAJATANG:
case WPN_KNIFE:
case WPN_SLING:
set_equip_race( mitm[p], ISFLAG_NO_RACE );
@@ -752,6 +816,11 @@ int items( int allow_uniques, // not just true-false,
set_equip_race( mitm[p], ISFLAG_ELVEN );
break;
+ case WPN_LONGBOW:
+ set_equip_race( mitm[p], one_chance_in(3) ? ISFLAG_ELVEN
+ : ISFLAG_NO_RACE );
+ break;
+
case WPN_CROSSBOW:
if (one_chance_in(4))
set_equip_race( mitm[p], ISFLAG_ORCISH );
@@ -793,7 +862,7 @@ int items( int allow_uniques, // not just true-false,
// there's a good chance that we'll just strip them of
// their ego type at the bottom of this function. -- bwr
if (item_level == MAKE_GOOD_ITEM
- && cmp_equip_race( mitm[p], ISFLAG_ORCISH ))
+ && get_equip_race( mitm[p] ) == ISFLAG_ORCISH)
{
set_equip_race( mitm[p], ISFLAG_NO_RACE );
}
@@ -824,7 +893,7 @@ int items( int allow_uniques, // not just true-false,
if ((random2(200) <= 50 + item_level
|| item_level == MAKE_GOOD_ITEM
- || is_demonic(mitm[p].sub_type))
+ || is_demonic(mitm[p]))
// nobody would bother enchanting a club
&& mitm[p].sub_type != WPN_CLUB
&& mitm[p].sub_type != WPN_GIANT_CLUB
@@ -836,7 +905,7 @@ int items( int allow_uniques, // not just true-false,
{
if (random2(300) <= 100 + item_level
|| item_level == MAKE_GOOD_ITEM
- || is_demonic( mitm[p].sub_type ))
+ || is_demonic( mitm[p] ))
{
// note: this doesn't guarantee special enchantment
switch (mitm[p].sub_type)
@@ -869,7 +938,7 @@ int items( int allow_uniques, // not just true-false,
// **** intentional fall through here ****
case WPN_FLAIL:
case WPN_SPIKED_FLAIL:
- case WPN_GREAT_FLAIL:
+ case WPN_DIRE_FLAIL:
case WPN_HAMMER:
if (one_chance_in(25))
set_weapon_special(p, SPWPN_PAIN);
@@ -1054,14 +1123,15 @@ int items( int allow_uniques, // not just true-false,
case WPN_HALBERD:
case WPN_GLAIVE:
+ case WPN_SCYTHE:
+ case WPN_TRIDENT:
+ case WPN_LOCHABER_AXE:
if (one_chance_in(30))
set_weapon_special(p, SPWPN_HOLY_WRATH);
if (one_chance_in(4))
set_weapon_special(p, SPWPN_PROTECTION);
// **** intentional fall through here ****
- case WPN_SCYTHE:
- case WPN_TRIDENT:
if (one_chance_in(5))
set_weapon_special(p, SPWPN_SPEED);
// **** intentional fall through here ****
@@ -1102,18 +1172,18 @@ int items( int allow_uniques, // not just true-false,
break;
// **** possible intentional fall through here ****
case WPN_BOW:
+ case WPN_LONGBOW:
case WPN_CROSSBOW:
- if (one_chance_in(30))
- set_weapon_special( p, SPWPN_SPEED );
-
- if (one_chance_in(5))
- set_weapon_special( p, SPWPN_PROTECTION );
+ {
+ const int tmp = random2(1000);
- if (coinflip())
- set_weapon_special(p, (coinflip() ? SPWPN_FLAME
- : SPWPN_FROST));
+ set_weapon_special( p, (tmp < 375) ? SPWPN_FLAME :
+ (tmp < 750) ? SPWPN_FROST :
+ (tmp < 920) ? SPWPN_PROTECTION :
+ (tmp < 980) ? SPWPN_VORPAL
+ : SPWPN_SPEED );
break;
-
+ }
case WPN_BLOWGUN:
if (one_chance_in(7))
set_weapon_special(p, SPWPN_VENOM);
@@ -1173,6 +1243,10 @@ int items( int allow_uniques, // not just true-false,
set_weapon_special(p, SPWPN_VENOM);
break;
+ case WPN_BLESSED_BLADE: // special gift of TSO
+ set_weapon_special( p, SPWPN_HOLY_WRATH );
+ break;
+
// unlisted weapons have no associated, standard ego-types {dlb}
default:
break;
@@ -1227,7 +1301,7 @@ int items( int allow_uniques, // not just true-false,
}
// value was "0" comment said "orc" so I went with comment {dlb}
- if (cmp_equip_race( mitm[p], ISFLAG_ORCISH ))
+ if (get_equip_race(mitm[p]) == ISFLAG_ORCISH)
{
// no holy wrath or slay orc and 1/2 the time no-ego
const int brand = get_weapon_brand( mitm[p] );
@@ -1253,8 +1327,8 @@ int items( int allow_uniques, // not just true-false,
&& mitm[p].sub_type != WPN_CLUB
&& mitm[p].sub_type != WPN_GIANT_CLUB
&& mitm[p].sub_type != WPN_GIANT_SPIKED_CLUB
- && cmp_equip_desc( mitm[p], 0 )
- && cmp_equip_race( mitm[p], 0 ))
+ && get_equip_desc(mitm[p]) == 0
+ && get_equip_race(mitm[p]) == 0)
{
set_equip_desc( mitm[p], (coinflip() ? ISFLAG_GLOWING
: ISFLAG_RUNED) );
@@ -1346,7 +1420,10 @@ int items( int allow_uniques, // not just true-false,
if (mitm[p].sub_type == MI_NEEDLE
&& (item_level == MAKE_GOOD_ITEM || !one_chance_in(5)))
{
- set_item_ego_type( mitm[p], OBJ_MISSILES, SPMSL_POISONED_II );
+ const int pois =
+ got_curare_roll(item_level)
+ ? SPMSL_CURARE : SPMSL_POISONED_II;
+ set_item_ego_type( mitm[p], OBJ_MISSILES, pois );
}
else
{
@@ -1365,7 +1442,7 @@ int items( int allow_uniques, // not just true-false,
// orcish ammo gets poisoned a lot more often -- in the original
// code it was poisoned every time!?
- if (cmp_equip_race( mitm[p], ISFLAG_ORCISH ) && one_chance_in(3))
+ if (get_equip_race(mitm[p]) == ISFLAG_ORCISH && one_chance_in(3))
set_item_ego_type( mitm[p], OBJ_MISSILES, SPMSL_POISONED_II );
// reduced quantity if special
@@ -1378,9 +1455,9 @@ int items( int allow_uniques, // not just true-false,
mitm[p].plus += random2(5);
// elven arrows and dwarven bolts are quality items
- if ((cmp_equip_race( mitm[p], ISFLAG_ELVEN )
+ if ((get_equip_race(mitm[p]) == ISFLAG_ELVEN
&& mitm[p].sub_type == MI_ARROW)
- || (cmp_equip_race( mitm[p], ISFLAG_DWARVEN )
+ || (get_equip_race(mitm[p]) == ISFLAG_DWARVEN
&& mitm[p].sub_type == MI_BOLT))
{
mitm[p].plus += random2(3);
@@ -1466,17 +1543,18 @@ int items( int allow_uniques, // not just true-false,
}
}
- hide2armour( &(mitm[p].sub_type) );
+ hide2armour(mitm[p]);
// mitm[p].special = SPARM_RANDART_II + random2(4);
make_item_randart( mitm[p] );
mitm[p].plus = 0;
- if (mitm[p].sub_type == ARM_BOOTS)
+ if (mitm[p].sub_type == ARM_BOOTS
+ && one_chance_in(10))
{
- mitm[p].plus2 = TBOOT_BOOTS;
- if (one_chance_in(10))
- mitm[p].plus2 = random2( NUM_BOOT_TYPES );
+ mitm[p].sub_type =
+ coinflip()? ARM_NAGA_BARDING
+ : ARM_CENTAUR_BARDING;
}
mitm[p].plus += random2(4);
@@ -1530,17 +1608,22 @@ int items( int allow_uniques, // not just true-false,
set_equip_race( mitm[p], ISFLAG_ELVEN );
break;
+ case ARM_NAGA_BARDING:
+ case ARM_CENTAUR_BARDING:
case ARM_BOOTS:
- if (one_chance_in(4))
+ if (mitm[p].sub_type == ARM_BOOTS)
{
- mitm[p].plus2 = TBOOT_NAGA_BARDING;
- break;
- }
+ if (one_chance_in(4))
+ {
+ mitm[p].sub_type = ARM_NAGA_BARDING;
+ break;
+ }
- if (one_chance_in(4))
- {
- mitm[p].plus2 = TBOOT_CENTAUR_BARDING;
- break;
+ if (one_chance_in(4))
+ {
+ mitm[p].sub_type = ARM_CENTAUR_BARDING;
+ break;
+ }
}
if (one_chance_in(4))
@@ -1552,8 +1635,8 @@ int items( int allow_uniques, // not just true-false,
break;
case ARM_HELMET:
- if (cmp_helmet_type( mitm[p], THELM_CAP )
- || cmp_helmet_type( mitm[p], THELM_WIZARD_HAT ))
+ if (get_helmet_type(mitm[p]) == THELM_CAP
+ || get_helmet_type(mitm[p]) == THELM_WIZARD_HAT)
{
if (one_chance_in(6))
set_equip_race( mitm[p], ISFLAG_ELVEN );
@@ -1612,7 +1695,7 @@ int items( int allow_uniques, // not just true-false,
if (50 + item_level >= random2(250)
|| item_level == MAKE_GOOD_ITEM
|| (mitm[p].sub_type == ARM_HELMET
- && cmp_helmet_type( mitm[p], THELM_WIZARD_HAT )))
+ && get_helmet_type(mitm[p]) == THELM_WIZARD_HAT))
{
mitm[p].plus += random2(3);
@@ -1621,7 +1704,7 @@ int items( int allow_uniques, // not just true-false,
if (30 + item_level >= random2(350)
&& (item_level == MAKE_GOOD_ITEM
- || (!cmp_equip_race( mitm[p], ISFLAG_ORCISH )
+ || (!get_equip_race(mitm[p]) == ISFLAG_ORCISH
|| (mitm[p].sub_type <= ARM_PLATE_MAIL && coinflip()))))
{
switch (mitm[p].sub_type)
@@ -1629,12 +1712,21 @@ int items( int allow_uniques, // not just true-false,
case ARM_SHIELD: // shield - must do special things for this!
case ARM_LARGE_SHIELD:
case ARM_BUCKLER:
- set_item_ego_type( mitm[p], OBJ_ARMOUR, SPARM_PROTECTION );
+ {
+ const int tmp = random2(1000);
+
+ set_item_ego_type( mitm[p], OBJ_ARMOUR,
+ (tmp < 40) ? SPARM_RESISTANCE :
+ (tmp < 160) ? SPARM_FIRE_RESISTANCE :
+ (tmp < 280) ? SPARM_COLD_RESISTANCE :
+ (tmp < 400) ? SPARM_POISON_RESISTANCE :
+ (tmp < 520) ? SPARM_POSITIVE_ENERGY
+ : SPARM_PROTECTION );
break; // prot
//break;
-
+ }
case ARM_CLOAK:
- if (cmp_equip_race( mitm[p], ISFLAG_DWARVEN ))
+ if (get_equip_race(mitm[p]) == ISFLAG_DWARVEN)
break;
switch (random2(4))
@@ -1660,7 +1752,7 @@ int items( int allow_uniques, // not just true-false,
break;
case ARM_HELMET:
- if (cmp_helmet_type(mitm[p],THELM_WIZARD_HAT) && coinflip())
+ if (get_helmet_type(mitm[p]) == THELM_WIZARD_HAT && coinflip())
{
if (one_chance_in(3))
{
@@ -1688,20 +1780,20 @@ int items( int allow_uniques, // not just true-false,
break;
case ARM_BOOTS:
- switch (random2(3))
- {
- case 0:
- if (mitm[p].plus2 == TBOOT_BOOTS)
- set_item_ego_type(mitm[p], OBJ_ARMOUR, SPARM_RUNNING);
- break;
- case 1:
- set_item_ego_type(mitm[p], OBJ_ARMOUR, SPARM_LEVITATION);
- break;
- case 2:
- set_item_ego_type(mitm[p], OBJ_ARMOUR, SPARM_STEALTH);
- break;
- }
+ case ARM_NAGA_BARDING:
+ case ARM_CENTAUR_BARDING:
+ {
+ const int tmp = random2(600)
+ + 200 * (mitm[p].sub_type != ARM_BOOTS);
+
+ set_item_ego_type( mitm[p], OBJ_ARMOUR,
+ (tmp < 200) ? SPARM_RUNNING :
+ (tmp < 400) ? SPARM_LEVITATION :
+ (tmp < 600) ? SPARM_STEALTH :
+ (tmp < 700) ? SPARM_COLD_RESISTANCE
+ : SPARM_FIRE_RESISTANCE );
break;
+ }
case ARM_ROBE:
switch (random2(4))
@@ -1782,8 +1874,8 @@ int items( int allow_uniques, // not just true-false,
}
// if not given a racial type, and special, give shiny/runed/etc desc.
- if (cmp_equip_race( mitm[p], 0 )
- && cmp_equip_desc( mitm[p], 0 )
+ if (get_equip_race(mitm[p]) == 0
+ && get_equip_desc(mitm[p]) == 0
&& (((is_random_artefact(mitm[p])
|| get_armour_ego_type( mitm[p] ) != SPARM_NORMAL)
&& !one_chance_in(10))
@@ -1810,7 +1902,7 @@ int items( int allow_uniques, // not just true-false,
// would be an enchanted item which somehow didn't get converted
// into armour).
if (item_level == MAKE_GOOD_ITEM)
- hide2armour( &(mitm[p].sub_type) ); // what of animal hides? {dlb}
+ hide2armour(mitm[p]); // what of animal hides? {dlb}
// skin armours + Crystal PM don't get special enchantments
// or species, but can be randarts
@@ -1903,7 +1995,7 @@ int items( int allow_uniques, // not just true-false,
for (count = 0; count < 1000; count++)
{
temp_rand = random2( NUM_MONSTERS ); // random monster
- temp_rand = mons_charclass( temp_rand ); // corpse base type
+ temp_rand = mons_species( temp_rand ); // corpse base type
if (mons_weight( temp_rand ) > 0) // drops a corpse
break;
@@ -2339,7 +2431,13 @@ int items( int allow_uniques, // not just true-false,
}
}
- mitm[p].special = random2(9);
+ mitm[p].special = random2(NUM_STAVE_ADJ);
+
+ if (item_is_rod( mitm[p] ))
+ {
+ mitm[p].plus2 = random_range(9, 14) * ROD_CHARGE_MULT;
+ mitm[p].plus = mitm[p].plus2;
+ }
quant = 1;
break;
@@ -2486,6 +2584,20 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
if (thing_created == NON_ITEM)
return;
+ // don't give top-tier wands before 5 HD
+ if ( menv[mid].hit_dice < 5 )
+ {
+ // technically these wands will be undercharged, but it
+ // doesn't really matter
+ if ( mitm[thing_created].sub_type == WAND_FIRE )
+ mitm[thing_created].sub_type = WAND_FLAME;
+ if ( mitm[thing_created].sub_type == WAND_COLD )
+ mitm[thing_created].sub_type = WAND_FROST;
+ if ( mitm[thing_created].sub_type == WAND_LIGHTNING )
+ mitm[thing_created].sub_type = (coinflip() ?
+ WAND_FLAME : WAND_FROST);
+ }
+
mitm[thing_created].flags = 0;
menv[mid].inv[MSLOT_WAND] = thing_created;
}
@@ -2508,13 +2620,6 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
if (bp == NON_ITEM)
return;
- mitm[bp].quantity = 0; // set below if force_item, else we toss this item!
- mitm[bp].plus = 0;
- mitm[bp].plus2 = 0;
- mitm[bp].special = 0;
- mitm[bp].orig_place = 0;
- mitm[bp].orig_monnum = 0;
-
// this flags things to "goto give_armour" below ... {dlb}
mitm[bp].base_type = 101;
@@ -2533,7 +2638,7 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
{
case MONS_KOBOLD:
// a few of the smarter kobolds have blowguns.
- if (one_chance_in(15) && level_number > 1)
+ if (one_chance_in(10) && level_number > 1)
{
mitm[bp].base_type = OBJ_WEAPONS;
mitm[bp].sub_type = WPN_BLOWGUN;
@@ -2647,8 +2752,11 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
// deliberate fall through {gdl}
case MONS_ORC_PRIEST:
item_race = MAKE_ITEM_ORCISH;
- // deliberate fall through {dlb}
+ // deliberate fall through {gdl}
+
case MONS_TERENCE:
+ case MONS_DRACONIAN:
+ case MONS_DRACONIAN_ZEALOT:
if (!one_chance_in(5))
{
mitm[bp].base_type = OBJ_WEAPONS;
@@ -2681,13 +2789,14 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
item_race = MAKE_ITEM_ELVEN;
mitm[bp].base_type = OBJ_WEAPONS;
- temp_rand = random2(8);
- mitm[bp].sub_type = ((temp_rand > 5) ? WPN_LONG_SWORD : // 2 in 8
- (temp_rand > 3) ? WPN_SHORT_SWORD : // 2 in 8
- (temp_rand > 2) ? WPN_SCIMITAR : // 1 in 8
- (temp_rand > 1) ? WPN_MACE : // 1 in 8
- (temp_rand > 0) ? WPN_BOW // 1 in 8
- : WPN_HAND_CROSSBOW); // 1 in 8
+ temp_rand = random2(100);
+ mitm[bp].sub_type = ((temp_rand > 79) ? WPN_LONG_SWORD : // 20%
+ (temp_rand > 59) ? WPN_SHORT_SWORD : // 20%
+ (temp_rand > 45) ? WPN_SCIMITAR : // 14%
+ (temp_rand > 31) ? WPN_MACE : // 14%
+ (temp_rand > 18) ? WPN_BOW : // 13%
+ (temp_rand > 5) ? WPN_HAND_CROSSBOW // 13%
+ : WPN_LONGBOW); // 6%
break;
case MONS_DEEP_ELF_ANNIHILATOR:
@@ -2697,6 +2806,10 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
case MONS_DEEP_ELF_MAGE:
case MONS_DEEP_ELF_SORCERER:
case MONS_DEEP_ELF_SUMMONER:
+ case MONS_DRACONIAN_SHIFTER:
+ case MONS_DRACONIAN_SCORCHER:
+ case MONS_DRACONIAN_ANNIHILATOR:
+ case MONS_DRACONIAN_CALLER:
item_race = MAKE_ITEM_ELVEN;
mitm[bp].base_type = OBJ_WEAPONS;
@@ -2725,6 +2838,14 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
case MONS_RUPERT:
case MONS_SKELETAL_WARRIOR:
case MONS_WAYNE:
+ case MONS_PALE_DRACONIAN:
+ case MONS_RED_DRACONIAN:
+ case MONS_WHITE_DRACONIAN:
+ case MONS_GREEN_DRACONIAN:
+ case MONS_MOTTLED_DRACONIAN:
+ case MONS_BLACK_DRACONIAN:
+ case MONS_YELLOW_DRACONIAN:
+ case MONS_PURPLE_DRACONIAN:
mitm[bp].base_type = OBJ_WEAPONS;
temp_rand = random2(120);
@@ -2757,18 +2878,20 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
case MONS_URUG:
case MONS_VAULT_GUARD:
case MONS_VAMPIRE_KNIGHT:
+ case MONS_DRACONIAN_KNIGHT:
mitm[bp].base_type = OBJ_WEAPONS;
- temp_rand = random2(24);
- mitm[bp].sub_type = ((temp_rand > 19) ? WPN_GREAT_SWORD :// 16.67%
- (temp_rand > 15) ? WPN_LONG_SWORD : // 16.67%
- (temp_rand > 11) ? WPN_BATTLEAXE : // 16.67%
- (temp_rand > 7) ? WPN_WAR_AXE : // 16.67%
- (temp_rand > 5) ? WPN_GREAT_MACE : // 8.33%
- (temp_rand > 3) ? WPN_GREAT_FLAIL :// 8.33%
- (temp_rand > 1) ? WPN_GLAIVE : // 8.33%
- (temp_rand > 0) ? WPN_BROAD_AXE // 4.17%
- : WPN_HALBERD); // 4.17%
+ temp_rand = random2(25);
+ mitm[bp].sub_type = ((temp_rand > 20) ? WPN_GREAT_SWORD : // 16%
+ (temp_rand > 16) ? WPN_LONG_SWORD : // 16%
+ (temp_rand > 12) ? WPN_BATTLEAXE : // 16%
+ (temp_rand > 8) ? WPN_WAR_AXE : // 16%
+ (temp_rand > 5) ? WPN_GREAT_MACE : // 12%
+ (temp_rand > 3) ? WPN_DIRE_FLAIL : // 8%
+ (temp_rand > 2) ? WPN_LOCHABER_AXE : // 4%
+ (temp_rand > 1) ? WPN_GLAIVE : // 4%
+ (temp_rand > 0) ? WPN_BROAD_AXE // 4%
+ : WPN_HALBERD); // 4%
if (one_chance_in(4))
mitm[bp].plus += 1 + random2(3);
@@ -2795,7 +2918,7 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
if (one_chance_in(10) || menv[mid].type == MONS_ETTIN)
{
- mitm[bp].sub_type = ((one_chance_in(10)) ? WPN_GREAT_FLAIL
+ mitm[bp].sub_type = ((one_chance_in(10)) ? WPN_DIRE_FLAIL
: WPN_GREAT_MACE);
}
break;
@@ -2837,7 +2960,7 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
if (one_chance_in(10))
{
- mitm[bp].sub_type = (one_chance_in(10) ? WPN_GREAT_FLAIL
+ mitm[bp].sub_type = (one_chance_in(10) ? WPN_DIRE_FLAIL
: WPN_GREAT_MACE);
}
break;
@@ -2847,6 +2970,9 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
item_race = MAKE_ITEM_NO_RACE;
mitm[bp].base_type = OBJ_WEAPONS;
mitm[bp].sub_type = WPN_BOW;
+ if (menv[mid].type == MONS_CENTAUR_WARRIOR
+ && one_chance_in(3))
+ mitm[bp].sub_type = WPN_LONGBOW;
break;
case MONS_YAKTAUR:
@@ -2893,7 +3019,7 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
mitm[bp].base_type = OBJ_WEAPONS;
mitm[bp].colour = WHITE; // forced by force_item above {dlb}
- mitm[bp].sub_type = (one_chance_in(4) ? WPN_GREAT_SWORD
+ mitm[bp].sub_type = (one_chance_in(4) ? WPN_BLESSED_BLADE
: WPN_LONG_SWORD);
set_equip_desc( mitm[bp], ISFLAG_GLOWING );
@@ -3039,7 +3165,7 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
(temp_rand == 1) ? WPN_BOW
: WPN_HALBERD);
- if (mitm[bp].sub_type == WPN_BOW)
+ if (is_range_weapon(mitm[bp]))
set_item_ego_type( mitm[bp], OBJ_WEAPONS, SPWPN_FLAME );
else
set_item_ego_type( mitm[bp], OBJ_WEAPONS, SPWPN_FLAMING );
@@ -3115,10 +3241,10 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
// mv: gives ammunition
// note that item_race is not reset for this section
if (menv[mid].inv[MSLOT_WEAPON] != NON_ITEM
- && launches_things( mitm[menv[mid].inv[MSLOT_WEAPON]].sub_type ))
+ && is_range_weapon( mitm[menv[mid].inv[MSLOT_WEAPON]] ))
{
xitc = OBJ_MISSILES;
- xitt = launched_by(mitm[menv[mid].inv[MSLOT_WEAPON]].sub_type);
+ xitt = fires_ammo_type(mitm[menv[mid].inv[MSLOT_WEAPON]]);
thing_created = items( 0, xitc, xitt, true, give_level, item_race );
if (thing_created == NON_ITEM)
@@ -3127,7 +3253,10 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
// monsters will always have poisoned needles -- otherwise
// they are just going to behave badly --GDL
if (xitt == MI_NEEDLE)
- set_item_ego_type(mitm[thing_created], OBJ_MISSILES, SPMSL_POISONED);
+ set_item_ego_type(mitm[thing_created], OBJ_MISSILES,
+ got_curare_roll(give_level)?
+ SPMSL_CURARE
+ : SPMSL_POISONED);
mitm[thing_created].x = 0;
mitm[thing_created].y = 0;
@@ -3141,12 +3270,6 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
if (bp == NON_ITEM)
return;
- mitm[bp].x = 0;
- mitm[bp].y = 0;
- mitm[bp].link = NON_ITEM;
- mitm[bp].orig_place = 0;
- mitm[bp].orig_monnum = 0;
-
item_race = MAKE_ITEM_RANDOM_RACE;
give_level = 1 + (level_number / 2);
@@ -3265,6 +3388,22 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
case MONS_JESSICA:
case MONS_KOBOLD_DEMONOLOGIST:
case MONS_OGRE_MAGE:
+ case MONS_DRACONIAN:
+ case MONS_RED_DRACONIAN:
+ case MONS_WHITE_DRACONIAN:
+ case MONS_GREEN_DRACONIAN:
+ case MONS_PALE_DRACONIAN:
+ case MONS_MOTTLED_DRACONIAN:
+ case MONS_BLACK_DRACONIAN:
+ case MONS_YELLOW_DRACONIAN:
+ case MONS_PURPLE_DRACONIAN:
+ case MONS_DRACONIAN_SHIFTER:
+ case MONS_DRACONIAN_SCORCHER:
+ case MONS_DRACONIAN_ANNIHILATOR:
+ case MONS_DRACONIAN_CALLER:
+ case MONS_DRACONIAN_MONK:
+ case MONS_DRACONIAN_ZEALOT:
+ case MONS_DRACONIAN_KNIGHT:
case MONS_ORC_WIZARD:
case MONS_WIZARD:
item_race = MAKE_ITEM_NO_RACE;
@@ -3365,16 +3504,16 @@ static void check_doors(void)
solid_count = 0;
// first half of each conditional represents bounds checking {dlb}:
- if (grd[x - 1][y] < DNGN_LAST_SOLID_TILE)
+ if (grid_is_solid( grd[x - 1][y] ))
solid_count++;
- if (grd[x + 1][y] < DNGN_LAST_SOLID_TILE)
+ if (grid_is_solid( grd[x + 1][y] ))
solid_count++;
- if (grd[x][y - 1] < DNGN_LAST_SOLID_TILE)
+ if (grid_is_solid( grd[x][y - 1] ))
solid_count++;
- if (grd[x][y + 1] < DNGN_LAST_SOLID_TILE)
+ if (grid_is_solid( grd[x][y + 1] ))
solid_count++;
grd[x][y] = ((solid_count < 2) ? DNGN_FLOOR : DNGN_CLOSED_DOOR);
@@ -3421,9 +3560,11 @@ static void prepare_swamp(void)
int i, j; // loop variables
int temp_rand; // probability determination {dlb}
- for (i = 10; i < (GXM - 10); i++)
+ const int margin = 10;
+
+ for (i = margin; i < (GXM - margin); i++)
{
- for (j = 10; j < (GYM - 10); j++)
+ for (j = margin; j < (GYM - margin); j++)
{
// doors -> floors {dlb}
if (grd[i][j] == DNGN_CLOSED_DOOR || grd[i][j] == DNGN_SECRET_DOOR)
@@ -3507,7 +3648,7 @@ static bool find_in_area(int sx, int sy, int ex, int ey, unsigned char feature)
return (false);
}
-// stamp a box. can avoid a possible type, and walls and floors can
+// stamp a box. can avoid a possible type, and walls and floors can
// be different (or not stamped at all)
// Note that the box boundaries are INclusive.
static bool make_box(int room_x1, int room_y1, int room_x2, int room_y2,
@@ -3547,7 +3688,7 @@ static bool make_box(int room_x1, int room_y1, int room_x2, int room_y2,
// take care of labyrinth, abyss, pandemonium
// returns 1 if we should skip further generation,
-// -1 if we should immediately quit, and 0 otherwise.
+// -1 if we should immediately quit, and 0 otherwise.
static int builder_by_type(int level_number, char level_type)
{
if (level_type == LEVEL_LABYRINTH)
@@ -3586,13 +3727,35 @@ static int builder_by_type(int level_number, char level_type)
if (which_demon >= 0)
{
+ const char *pandemon_level_names[] = {
+ "mnoleg", "lom_lobon", "cerebov", "gloorx_vloq"
+ };
you.unique_creatures[40 + which_demon] = 1;
- build_vaults(level_number, which_demon + 60);
+
+ const int vault =
+ random_map_for_tag(pandemon_level_names[(int) which_demon]);
+
+ ASSERT(vault != -1);
+ if (vault == -1)
+ {
+ fprintf(stderr, "Failed to find Pandemonium level %s!\n",
+ pandemon_level_names[(int) which_demon]);
+ exit(1);
+ }
+
+ build_vaults(level_number, vault);
}
else
{
plan_main(level_number, 0);
- build_minivaults(level_number, 300 + random2(9));
+ int vault = random_map_for_tag("pan");
+ ASSERT( vault != -1 );
+ if (vault == -1)
+ {
+ fprintf(stderr, "Failed to build Pandemonium minivault!\n");
+ exit(1);
+ }
+ build_minivaults(level_number, vault);
}
return 1;
@@ -3603,110 +3766,38 @@ static int builder_by_type(int level_number, char level_type)
}
// returns 1 if we should skip further generation,
-// -1 if we should immediately quit, and 0 otherwise.
+// -1 if we should immediately quit, and 0 otherwise.
static int builder_by_branch(int level_number)
{
+ int subdepth = subdungeon_depth(you.where_are_you, level_number);
+ const std::string name = level_name(subdepth);
+ std::string altname;
+
+ if (subdepth == branch_depth( branch_stair(you.where_are_you) ))
+ altname = level_name(0);
+
+ int vault = random_map_for_place(name);
+ if (vault == -1)
+ vault = random_map_for_place(altname);
+
+ if (vault != -1)
+ {
+ build_vaults(level_number, vault);
+ // [dshaligram] XXX: Is link_items() needed for all vaults?
+ link_items();
+ return 1;
+ }
+
switch (you.where_are_you)
{
case BRANCH_HIVE:
- if (level_number == you.branch_stairs[STAIRS_HIVE]
- + branch_depth(STAIRS_HIVE))
- build_vaults(level_number, 80);
- else
- spotty_level(false, 100 + random2(500), false);
+ spotty_level(false, 100 + random2(500), false);
return 1;
case BRANCH_SLIME_PITS:
- if (level_number == you.branch_stairs[STAIRS_SLIME_PITS]
- + branch_depth(STAIRS_SLIME_PITS))
- {
- build_vaults(level_number, 81);
- }
- else
- spotty_level(false, 100 + random2(500), false);
+ spotty_level(false, 100 + random2(500), false);
return 1;
- case BRANCH_VAULTS:
- if (level_number == you.branch_stairs[STAIRS_VAULTS]
- + branch_depth(STAIRS_VAULTS))
- {
- build_vaults(level_number, 82);
- return 1;
- }
- break;
-
- case BRANCH_HALL_OF_BLADES:
- if (level_number == you.branch_stairs[STAIRS_HALL_OF_BLADES]
- + branch_depth(STAIRS_HALL_OF_BLADES))
- {
- build_vaults(level_number, 83);
- return 1;
- }
- break;
-
- case BRANCH_HALL_OF_ZOT:
- if (level_number == you.branch_stairs[STAIRS_HALL_OF_ZOT]
- + branch_depth(STAIRS_HALL_OF_ZOT))
- {
- build_vaults(level_number, 84);
- return 1;
- }
- break;
-
- case BRANCH_ECUMENICAL_TEMPLE:
- if (level_number == you.branch_stairs[STAIRS_ECUMENICAL_TEMPLE]
- + branch_depth(STAIRS_ECUMENICAL_TEMPLE))
- {
- build_vaults(level_number, 85);
- return 1;
- }
- break;
-
- case BRANCH_SNAKE_PIT:
- if (level_number == you.branch_stairs[STAIRS_SNAKE_PIT]
- + branch_depth(STAIRS_SNAKE_PIT))
- {
- build_vaults(level_number, 86);
- return 1;
- }
- break;
-
- case BRANCH_ELVEN_HALLS:
- if (level_number == you.branch_stairs[STAIRS_ELVEN_HALLS]
- + branch_depth(STAIRS_ELVEN_HALLS))
- {
- build_vaults(level_number, 87);
- return 1;
- }
- break;
-
- case BRANCH_TOMB:
- if (level_number == you.branch_stairs[STAIRS_TOMB] + 1)
- {
- build_vaults(level_number, 88);
- return 1;
- }
- else if (level_number == you.branch_stairs[STAIRS_TOMB] + 2)
- {
- build_vaults(level_number, 89);
- return 1;
- }
- else if (level_number == you.branch_stairs[STAIRS_TOMB] + 3)
- {
- build_vaults(level_number, 90);
- return 1;
- }
- break;
-
- case BRANCH_SWAMP:
- if (level_number == you.branch_stairs[STAIRS_SWAMP]
- + branch_depth(STAIRS_SWAMP))
- {
- build_vaults(level_number, 91);
- return 1;
- }
- break;
-
case BRANCH_ORCISH_MINES:
spotty_level(false, 100 + random2(500), false);
return 1;
@@ -3719,43 +3810,6 @@ static int builder_by_branch(int level_number)
}
break;
- case BRANCH_VESTIBULE_OF_HELL:
- build_vaults( level_number, 50 );
- link_items();
- return -1;
-
- case BRANCH_DIS:
- if (level_number == 33)
- {
- build_vaults(level_number, 51);
- return 1;
- }
- break;
-
- case BRANCH_GEHENNA:
- if (level_number == 33)
- {
- build_vaults(level_number, 52);
- return 1;
- }
- break;
-
- case BRANCH_COCYTUS:
- if (level_number == 33)
- {
- build_vaults(level_number, 53);
- return 1;
- }
- break;
-
- case BRANCH_TARTARUS:
- if (level_number == 33)
- {
- build_vaults(level_number, 54);
- return 1;
- }
- break;
-
default:
break;
}
@@ -3773,17 +3827,25 @@ static int builder_normal(int level_number, char level_type, spec_room &sr)
bool skipped = false;
bool done_city = false;
- if (player_in_branch( BRANCH_DIS ))
+ int vault = random_map_for_place(
+ level_name(
+ subdungeon_depth(you.where_are_you, level_number)));
+
+ if (vault == -1
+ && player_in_branch( BRANCH_MAIN_DUNGEON )
+ && level_number > 10 && level_number < 26 && one_chance_in(9))
+ vault = random_map_for_depth(level_number);
+
+ if (vault != -1)
{
- city_level(level_number);
+ // Can't have vaults on you.where_are_you != BRANCH_MAIN_DUNGEON levels
+ build_vaults(level_number, vault);
return 1;
}
- if (player_in_branch( BRANCH_MAIN_DUNGEON )
- && level_number > 10 && level_number < 23 && one_chance_in(9))
+ if (player_in_branch( BRANCH_DIS ))
{
- // Can't have vaults on you.where_are_you != BRANCH_MAIN_DUNGEON levels
- build_vaults(level_number, 100);
+ city_level(level_number);
return 1;
}
@@ -3816,7 +3878,11 @@ static int builder_normal(int level_number, char level_type, spec_room &sr)
plan_main(level_number, 0);
if (one_chance_in(3) && level_number > 6)
- build_minivaults(level_number, 200);
+ {
+ int mvault = random_map_for_depth(level_number, true);
+ if (mvault != -1)
+ build_minivaults(level_number, mvault);
+ }
return 1;
}
@@ -3834,8 +3900,12 @@ static int builder_normal(int level_number, char level_type, spec_room &sr)
&& player_in_branch( BRANCH_MAIN_DUNGEON )
&& one_chance_in(4))
{
- build_minivaults(level_number, 200);
- return 1;
+ int mvault = random_map_for_depth(level_number, true);
+ if (mvault != -1)
+ {
+ build_minivaults(level_number, mvault);
+ return 1;
+ }
}
}
else
@@ -3850,7 +3920,7 @@ static int builder_normal(int level_number, char level_type, spec_room &sr)
}
}
- // maybe create a special room, if roguey_level hasn't done it
+ // maybe create a special room, if roguey_level hasn't done it
// already.
if (!sr.created && level_number > 5 && !done_city && one_chance_in(5))
special_room(level_number, sr);
@@ -3858,7 +3928,7 @@ static int builder_normal(int level_number, char level_type, spec_room &sr)
return 0;
}
-// returns 1 if we should skip extras(), otherwise 0
+// returns 1 if we should skip extras(), otherwise 0
static int builder_basic(int level_number)
{
int temp_rand;
@@ -3967,8 +4037,12 @@ static void builder_extras( int level_number, int level_type )
&& player_in_branch( BRANCH_MAIN_DUNGEON )
&& one_chance_in(3))
{
- build_minivaults(level_number, 200);
- return;
+ int mvault = random_map_for_depth(level_number, true);
+ if (mvault != -1)
+ {
+ build_minivaults(level_number, mvault);
+ return;
+ }
}
if (level_number > 5 && one_chance_in(10))
@@ -4037,31 +4111,38 @@ static void place_traps(int level_number)
}
while (grd[env.trap[i].x][env.trap[i].y] != DNGN_FLOOR);
- env.trap[i].type = TRAP_DART;
+ unsigned char &trap_type = env.trap[i].type;
+ trap_type = TRAP_DART;
if ((random2(1 + level_number) > 1) && one_chance_in(4))
- env.trap[i].type = TRAP_NEEDLE;
- if (random2(1 + level_number) > 2)
- env.trap[i].type = TRAP_ARROW;
+ trap_type = TRAP_NEEDLE;
if (random2(1 + level_number) > 3)
- env.trap[i].type = TRAP_SPEAR;
+ trap_type = TRAP_SPEAR;
if (random2(1 + level_number) > 5)
- env.trap[i].type = TRAP_AXE;
+ trap_type = TRAP_AXE;
+
+ // Note we're boosting arrow trap numbers by moving it
+ // down the list, and making spear and axe traps rarer.
+ if (trap_type == TRAP_DART?
+ random2(1 + level_number) > 2
+ : one_chance_in(7))
+ trap_type = TRAP_ARROW;
+
if (random2(1 + level_number) > 7)
- env.trap[i].type = TRAP_BOLT;
+ trap_type = TRAP_BOLT;
if (random2(1 + level_number) > 11)
- env.trap[i].type = TRAP_BLADE;
+ trap_type = TRAP_BLADE;
if ((random2(1 + level_number) > 14 && one_chance_in(3))
|| (player_in_branch( BRANCH_HALL_OF_ZOT ) && coinflip()))
{
- env.trap[i].type = TRAP_ZOT;
+ trap_type = TRAP_ZOT;
}
if (one_chance_in(20))
- env.trap[i].type = TRAP_TELEPORT;
+ trap_type = TRAP_TELEPORT;
if (one_chance_in(40))
- env.trap[i].type = TRAP_AMNESIA;
+ trap_type = TRAP_AMNESIA;
grd[env.trap[i].x][env.trap[i].y] = DNGN_UNDISCOVERED_TRAP;
} // end "for i"
@@ -4174,6 +4255,10 @@ static void place_branch_entrances(int dlevel, char level_type)
stair = branch + DNGN_ENTER_ORCISH_MINES;
place_specific_stair(stair);
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Placing stair: %s",
+ feature_description(stair).c_str());
+#endif
} // end loop - possible branch entrances
}
@@ -4334,7 +4419,7 @@ static void make_trail(int xs, int xr, int ys, int yr, int corrlength,
static int good_door_spot(int x, int y)
{
- if ((grd[x][y] > DNGN_WATER_X && grd[x][y] < DNGN_ENTER_PANDEMONIUM)
+ if ((!grid_is_solid(grd[x][y]) && grd[x][y] < DNGN_ENTER_PANDEMONIUM)
|| grd[x][y] == DNGN_CLOSED_DOOR)
{
return 1;
@@ -4395,8 +4480,8 @@ static bool make_room(int sx,int sy,int ex,int ey,int max_doors, int doorlevel)
{
// left side
if (grd[sx-1][ry] == DNGN_FLOOR
- && grd[sx-1][ry-1] < DNGN_LAST_SOLID_TILE
- && grd[sx-1][ry+1] < DNGN_LAST_SOLID_TILE)
+ && grid_is_solid(grd[sx-1][ry-1])
+ && grid_is_solid(grd[sx-1][ry+1]))
{
if (random2(10) < doorlevel)
grd[sx-1][ry] = DNGN_CLOSED_DOOR;
@@ -4404,8 +4489,8 @@ static bool make_room(int sx,int sy,int ex,int ey,int max_doors, int doorlevel)
// right side
if (grd[ex+1][ry] == DNGN_FLOOR
- && grd[ex+1][ry-1] < DNGN_LAST_SOLID_TILE
- && grd[ex+1][ry+1] < DNGN_LAST_SOLID_TILE)
+ && grid_is_solid(grd[ex+1][ry-1])
+ && grid_is_solid(grd[ex+1][ry+1]))
{
if (random2(10) < doorlevel)
grd[ex+1][ry] = DNGN_CLOSED_DOOR;
@@ -4417,8 +4502,8 @@ static bool make_room(int sx,int sy,int ex,int ey,int max_doors, int doorlevel)
{
// top
if (grd[rx][sy-1] == DNGN_FLOOR
- && grd[rx-1][sy-1] < DNGN_LAST_SOLID_TILE
- && grd[rx+1][sy-1] < DNGN_LAST_SOLID_TILE)
+ && grid_is_solid(grd[rx-1][sy-1])
+ && grid_is_solid(grd[rx+1][sy-1]))
{
if (random2(10) < doorlevel)
grd[rx][sy-1] = DNGN_CLOSED_DOOR;
@@ -4426,8 +4511,8 @@ static bool make_room(int sx,int sy,int ex,int ey,int max_doors, int doorlevel)
// bottom
if (grd[rx][ey+1] == DNGN_FLOOR
- && grd[rx-1][ey+1] < DNGN_LAST_SOLID_TILE
- && grd[rx+1][ey+1] < DNGN_LAST_SOLID_TILE)
+ && grid_is_solid(grd[rx-1][ey+1])
+ && grid_is_solid(grd[rx+1][ey+1]))
{
if (random2(10) < doorlevel)
grd[rx][ey+1] = DNGN_CLOSED_DOOR;
@@ -4477,7 +4562,7 @@ static void builder_monsters(int level_number, char level_type, int mon_wanted)
while(which_unique < 0 || you.unique_creatures[which_unique])
{
- // sometimes, we just quit if a unique is already placed.
+ // sometimes, we just quit if a unique is already placed.
if (which_unique >= 0 && !one_chance_in(3))
{
which_unique = -1;
@@ -4656,7 +4741,7 @@ static void builder_items(int level_number, char level_type, int items_wanted)
// the entire intent of this function is to find a
// hallway from a special room to a floor space somewhere,
// changing the special room wall (DNGN_BUILDER_SPECIAL_WALL)
-// to a closed door, and normal rock wall to pre-floor.
+// to a closed door, and normal rock wall to pre-floor.
// Anything that might otherwise block the hallway is changed
// to pre-floor.
static void specr_2(spec_room &sr)
@@ -4759,6 +4844,79 @@ static void specr_2(spec_room &sr)
sr.hooked_up = true;
} // end specr_2()
+// Fill special room sr with monsters from the pit_list at density%...
+// then place a "lord of the pit" of lord_type at (lordx, lordy).
+static void fill_monster_pit( spec_room &sr,
+ FixedVector<pit_mons_def, MAX_PIT_MONSTERS> &pit_list,
+ int density, int lord_type, int lordx, int lordy )
+{
+ int i, x, y;
+
+ // make distribution cumulative
+ for (i = 1; i < MAX_PIT_MONSTERS; i++)
+ {
+ // assuming that the first zero rarity is the end of the list:
+ if (!pit_list[i].rare)
+ break;
+
+ pit_list[i].rare = pit_list[i].rare + pit_list[i - 1].rare;
+ }
+
+ const int num_types = i;
+ const int rare_sum = pit_list[num_types - 1].rare;
+
+ // calculate die_size, factoring in the density% of the pit
+ const int die_size = (rare_sum * 100) / density;
+
+#if DEBUG_DIAGNOSTICS
+ for (i = 0; i < num_types; i++)
+ {
+ char buff[ ITEMNAME_SIZE ];
+
+ const int delta = ((i > 0) ? pit_list[i].rare - pit_list[i - 1].rare
+ : pit_list[i].rare);
+
+ const float perc = (static_cast<float>( delta ) * 100.0)
+ / static_cast<float>( rare_sum );
+
+ mprf( MSGCH_DIAGNOSTICS, "%6.2f%%: %s", perc,
+ moname( pit_list[i].type, true, DESC_PLAIN, buff ) );
+ }
+#endif
+
+ // put the boss monster down
+ if (lord_type != MONS_PROGRAM_BUG)
+ mons_place( lord_type, BEH_SLEEP, MHITNOT, true, lordx, lordy );
+
+ // place monsters and give them items {dlb}:
+ for (x = sr.x1; x <= sr.x2; x++)
+ {
+ for (y = sr.y1; y <= sr.y2; y++)
+ {
+ // avoid the boss (or anyone else we may have dropped already)
+ if (mgrd[x][y] != NON_MONSTER)
+ continue;
+
+ const int roll = random2( die_size );
+
+ // density skip (no need to iterate)
+ if (roll >= rare_sum)
+ continue;
+
+ // run throught the cumulative chances and place a monster
+ for (i = 0; i < num_types; i++)
+ {
+ if (roll < pit_list[i].rare)
+ {
+ mons_place( pit_list[i].type, BEH_SLEEP, MHITNOT,
+ true, x, y );
+ break;
+ }
+ }
+ }
+ }
+}
+
static void special_room(int level_number, spec_room &sr)
{
char spec_room_type = SROOM_LAIR_KOBOLD;
@@ -4804,6 +4962,7 @@ static void special_room(int level_number, spec_room &sr)
if ((level_number > 13 && spec_room_type == SROOM_LAIR_KOBOLD)
|| (level_number < 16 && spec_room_type == SROOM_MORGUE)
+ || (level_number < 14 && spec_room_type == SROOM_JELLY_PIT)
|| (level_number < 17 && one_chance_in(4)))
{
spec_room_type = SROOM_LAIR_ORC;
@@ -4811,8 +4970,13 @@ static void special_room(int level_number, spec_room &sr)
if (level_number > 19 && coinflip())
spec_room_type = SROOM_MORGUE;
- }
+ if (level_number > 13 &&
+ one_chance_in(6 - (level_number > 23) - (level_number > 18)))
+ {
+ spec_room_type = SROOM_JELLY_PIT;
+ }
+ }
switch (spec_room_type)
{
@@ -4959,6 +5123,10 @@ static void special_room(int level_number, spec_room &sr)
case SROOM_MORGUE:
morgue(sr);
break;
+
+ case SROOM_JELLY_PIT:
+ jelly_pit(level_number, sr);
+ break;
}
} // end special_room()
@@ -5007,7 +5175,7 @@ static void beehive(spec_room &sr)
mons_place( one_chance_in(7) ? MONS_KILLER_BEE_LARVA
: MONS_KILLER_BEE,
- BEH_SLEEP, MHITNOT, true, x, y );
+ BEH_SLEEP, MHITNOT, true, x, y );
}
}
@@ -5039,29 +5207,29 @@ static void build_minivaults(int level_number, int force_vault)
RANDOM_MONSTER,
RANDOM_MONSTER);
- char vgrid[81][81];
-
- if (force_vault == 200)
- {
- force_vault = 200 + random2(37);
- }
-
- vault_main(vgrid, mons_array, force_vault, level_number);
+ map_type vgrid;
+ vault_placement place;
+ vault_main(vgrid, mons_array, place, force_vault, level_number);
int vx, vy;
int v1x, v1y;
+ // [ds] The margin around the edges of the map where the minivault won't be
+ // placed. Purely arbitrary as far as I can see.
+ const int margin = 12;
+
/* find a target area which can be safely overwritten: */
while(1)
{
- //if ( one_chance_in(1000) ) return;
- v1x = 12 + random2(45);
- v1y = 12 + random2(35);
+ v1x = random_range( margin, GXM - margin - place.width );
+ v1y = random_range( margin, GYM - margin - place.height );
- for (vx = v1x; vx < v1x + 12; vx++)
+ for (vx = v1x; vx < v1x + place.width; vx++)
{
- for (vy = v1y; vy < v1y + 12; vy++)
+ for (vy = v1y; vy < v1y + place.height; vy++)
{
+ // [ds] An escape hatch to keep from hanging forever looking
+ // for a good place.
if (one_chance_in(2000))
return;
@@ -5078,12 +5246,11 @@ static void build_minivaults(int level_number, int force_vault)
}
/* must not be completely isolated: */
- for (vx = v1x; vx < v1x + 12; vx++)
+ for (vx = v1x; vx < v1x + place.width; vx++)
{
// if (vx != v1x && vx != v1x + 12) continue;
- for (vy = v1y; vy < v1y + 12; vy++)
+ for (vy = v1y; vy < v1y + place.height; vy++)
{
- // if (vy != v1y && vy != v1y + 12) continue;
if (grd[vx][vy] == DNGN_FLOOR
|| grd[vx][vy] == DNGN_CLOSED_DOOR
|| grd[vx][vy] == DNGN_SECRET_DOOR)
@@ -5098,11 +5265,13 @@ static void build_minivaults(int level_number, int force_vault)
break;
}
- for (vx = v1x; vx < v1x + 12; vx++)
+ for (vx = v1x; vx < v1x + place.width; vx++)
{
- for (vy = v1y; vy < v1y + 12; vy++)
+ for (vy = v1y; vy < v1y + place.height; vy++)
{
- grd[vx][vy] = vgrid[vx - v1x][vy - v1y];
+ // [dshaligram] vault_main always populates vgrid[y][x] instead of
+ // vgrid[x][y] now.
+ grd[vx][vy] = vgrid[vy - v1y][vx - v1x];
}
}
@@ -5111,9 +5280,9 @@ static void build_minivaults(int level_number, int force_vault)
int num_runes = 0;
// paint the minivault onto the grid
- for (vx = v1x; vx < v1x + 12; vx++)
+ for (vx = v1x; vx < v1x + place.width; vx++)
{
- for (vy = v1y; vy < v1y + 12; vy++)
+ for (vy = v1y; vy < v1y + place.height; vy++)
{
altar_count = vault_grid( level_number, vx, vy, altar_count,
acq_item_class, mons_array,
@@ -5159,9 +5328,11 @@ static void build_vaults(int level_number, int force_vault)
//bool exclusive2 = coinflip(); // usage commented out below {dlb}
- char vgrid[81][81];
+ map_type vgrid;
+ vault_placement place;
- char gluggy = vault_main(vgrid, mons_array, force_vault, level_number);
+ int gluggy =
+ vault_main(vgrid, mons_array, place, force_vault, level_number);
int vx, vy;
int v1x = 0, v1y = 0, v2x = 0, v2y = 0;
@@ -5187,67 +5358,48 @@ static void build_vaults(int level_number, int force_vault)
}
}
- switch (gluggy)
- {
- case MAP_NORTH:
- v1x = 1;
- v2x = GXM;
- v1y = 1;
- v2y = 35;
- initial_y++;
- dig_dir_x = 0;
- dig_dir_y = 1;
- break;
+ // If the map takes the whole screen, our work is done.
+ if (gluggy == MAP_ENCOMPASS)
+ return;
- case MAP_NORTHWEST:
- v1x = 1;
- v2x = 40;
- v1y = 1;
- v2y = 35;
- initial_y++;
- dig_dir_x = 1;
- dig_dir_y = 0;
- break;
+ // Figure out which way we need to go to dig our way out of the vault.
+ const bool x_edge =
+ initial_x == place.x || initial_x == place.x + place.width - 1;
+ const bool y_edge =
+ initial_y == place.y || initial_y == place.y + place.height - 1;
- case MAP_NORTHEAST:
- v1x = 40;
- v2x = GXM;
- v1y = 1;
- v2y = 35;
- initial_y++;
- dig_dir_x = -1;
- dig_dir_y = 0;
- break;
+ if (x_edge)
+ {
+ dig_dir_x = place.x == 0? 1 : -1;
+ initial_x += dig_dir_x;
+ }
- case MAP_SOUTHWEST:
- v1x = 1;
- v2x = 40;
- v1y = 35;
- v2y = GYM;
- initial_y--;
- dig_dir_x = 0;
- dig_dir_y = -1;
- break;
+ if (y_edge)
+ {
+ dig_dir_y = place.y == 0? 1 : -1;
+ initial_y += dig_dir_y;
+ }
- case MAP_SOUTHEAST:
- v1x = 40;
- v2x = GXM;
- v1y = 35;
- v2y = GYM;
- initial_y--;
- dig_dir_x = 0;
- dig_dir_y = -1;
- break;
+ // Does this level require Dis treatment (metal wallification)?
+ // XXX: Change this so the level definition can explicitly state what
+ // kind of wallification it wants.
+ const bool dis_wallify = place.map->has_tag("dis");
- case MAP_ENCOMPASS:
- return;
+ v1x = place.x + 1;
+ v1y = place.y + 1;
+ v2x = place.x + place.width;
+ v2y = place.y + place.height;
- case MAP_NORTH_DIS:
- v1x = 1;
- v2x = GXM;
- v1y = 1;
- v2y = 35;
- plan_4(1, 1, 80, 35, DNGN_METAL_WALL);
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS,
+ "Vault: (%d,%d)-(%d,%d), exit (%d,%d), dir (%d,%d); Dis: %s",
+ v1x, v1y, v2x, v2y, initial_x, initial_y, dig_dir_x, dig_dir_y,
+ dis_wallify? "yes" : "no");
+#endif
+
+ if (dis_wallify)
+ {
+ plan_4(v1x, v1y, v2x, v2y, DNGN_METAL_WALL);
goto vstair;
}
@@ -5323,7 +5475,7 @@ static void build_vaults(int level_number, int force_vault)
dig_place_x = initial_x;
dig_place_y = initial_y;
- if (gluggy != MAP_NORTH_DIS)
+ if (!dis_wallify)
{
for (i = 0; i < 40; i++)
{
@@ -5402,7 +5554,8 @@ static int vault_grid( int level_number, int vx, int vy, int altar_count,
int not_used;
// first, set base tile for grids {dlb}:
- grd[vx][vy] = ((vgrid == 'x') ? DNGN_ROCK_WALL :
+ const int grid =
+ grd[vx][vy] = ((vgrid == 'x') ? DNGN_ROCK_WALL :
(vgrid == 'X') ? DNGN_PERMAROCK_WALL :
(vgrid == 'c') ? DNGN_STONE_WALL :
(vgrid == 'v') ? DNGN_METAL_WALL :
@@ -5539,6 +5692,19 @@ static int vault_grid( int level_number, int vx, int vy, int altar_count,
break;
}
+ if (grid == DNGN_ORANGE_CRYSTAL_STATUE
+ || grid == DNGN_SILVER_STATUE)
+ {
+ const int mtype =
+ grid == DNGN_ORANGE_CRYSTAL_STATUE? MONS_ORANGE_STATUE
+ : MONS_SILVER_STATUE;
+
+ grd[vx][vy] = DNGN_FLOOR;
+
+ place_monster( not_used, mtype, 30, BEH_HOSTILE,
+ MHITNOT, true, vx, vy, false);
+ }
+
// finally, handle grids that place monsters {dlb}:
if (vgrid >= '0' && vgrid <= '9')
{
@@ -5786,9 +5952,9 @@ void item_colour( item_def &item )
break;
}
- if (is_demonic( item.sub_type ))
+ if (is_demonic( item ))
item.colour = random_colour();
- else if (launches_things( item.sub_type ))
+ else if (is_range_weapon( item ))
item.colour = BROWN;
else
{
@@ -5810,7 +5976,7 @@ void item_colour( item_def &item )
break;
default:
item.colour = LIGHTCYAN;
- if (cmp_equip_race( item, ISFLAG_DWARVEN ))
+ if (get_equip_race(item) == ISFLAG_DWARVEN)
item.colour = CYAN;
break;
}
@@ -5834,7 +6000,7 @@ void item_colour( item_def &item )
break;
default:
item.colour = LIGHTCYAN;
- if (cmp_equip_race( item, ISFLAG_DWARVEN ))
+ if (get_equip_race(item) == ISFLAG_DWARVEN)
item.colour = CYAN;
break;
}
@@ -5848,13 +6014,16 @@ void item_colour( item_def &item )
{
case ARM_CLOAK:
case ARM_ROBE:
+ case ARM_NAGA_BARDING:
+ case ARM_CENTAUR_BARDING:
+ case ARM_CAP:
item.colour = random_colour();
break;
case ARM_HELMET:
//caps and wizard's hats are random coloured
- if (cmp_helmet_type( item, THELM_CAP )
- || cmp_helmet_type( item, THELM_WIZARD_HAT ))
+ if (get_helmet_type(item) == THELM_CAP
+ || get_helmet_type(item) == THELM_WIZARD_HAT)
{
item.colour = random_colour();
}
@@ -5869,45 +6038,45 @@ void item_colour( item_def &item )
break;
case ARM_DRAGON_HIDE:
case ARM_DRAGON_ARMOUR:
- item.colour = mons_colour( MONS_DRAGON );
+ item.colour = mons_class_colour( MONS_DRAGON );
break;
case ARM_TROLL_HIDE:
case ARM_TROLL_LEATHER_ARMOUR:
- item.colour = mons_colour( MONS_TROLL );
+ item.colour = mons_class_colour( MONS_TROLL );
break;
case ARM_CRYSTAL_PLATE_MAIL:
item.colour = LIGHTGREY;
break;
case ARM_ICE_DRAGON_HIDE:
case ARM_ICE_DRAGON_ARMOUR:
- item.colour = mons_colour( MONS_ICE_DRAGON );
+ item.colour = mons_class_colour( MONS_ICE_DRAGON );
break;
case ARM_STEAM_DRAGON_HIDE:
case ARM_STEAM_DRAGON_ARMOUR:
- item.colour = mons_colour( MONS_STEAM_DRAGON );
+ item.colour = mons_class_colour( MONS_STEAM_DRAGON );
break;
case ARM_MOTTLED_DRAGON_HIDE:
case ARM_MOTTLED_DRAGON_ARMOUR:
- item.colour = mons_colour( MONS_MOTTLED_DRAGON );
+ item.colour = mons_class_colour( MONS_MOTTLED_DRAGON );
break;
case ARM_STORM_DRAGON_HIDE:
case ARM_STORM_DRAGON_ARMOUR:
- item.colour = mons_colour( MONS_STORM_DRAGON );
+ item.colour = mons_class_colour( MONS_STORM_DRAGON );
break;
case ARM_GOLD_DRAGON_HIDE:
case ARM_GOLD_DRAGON_ARMOUR:
- item.colour = mons_colour( MONS_GOLDEN_DRAGON );
+ item.colour = mons_class_colour( MONS_GOLDEN_DRAGON );
break;
case ARM_ANIMAL_SKIN:
item.colour = BROWN;
break;
case ARM_SWAMP_DRAGON_HIDE:
case ARM_SWAMP_DRAGON_ARMOUR:
- item.colour = mons_colour( MONS_SWAMP_DRAGON );
+ item.colour = mons_class_colour( MONS_SWAMP_DRAGON );
break;
default:
item.colour = LIGHTCYAN;
- if (cmp_equip_race( item, ISFLAG_DWARVEN ))
+ if (get_equip_race(item) == ISFLAG_DWARVEN)
item.colour = CYAN;
break;
}
@@ -6045,7 +6214,7 @@ void item_colour( item_def &item )
break;
case FOOD_CHUNK:
// set the appropriate colour of the meat:
- temp_value = mons_colour( item.plus );
+ temp_value = mons_class_colour( item.plus );
item.colour = (temp_value == BLACK) ? LIGHTRED : temp_value;
break;
default:
@@ -6284,7 +6453,7 @@ void item_colour( item_def &item )
case OBJ_CORPSES:
// set the appropriate colour of the body:
- temp_value = mons_colour( item.plus );
+ temp_value = mons_class_colour( item.plus );
item.colour = (temp_value == BLACK) ? LIGHTRED : temp_value;
break;
@@ -6294,77 +6463,6 @@ void item_colour( item_def &item )
}
} // end item_colour()
-// Checks how rare a weapon is. Many of these have special routines for
-// placement, especially those with a rarity of zero. Chance is out of 10.
-static char rare_weapon(unsigned char w_type)
-{
-
- // zero value weapons must be placed specially -- see items() {dlb}
- if (is_demonic(w_type))
- return 0;
-
- switch (w_type)
- {
- case WPN_CLUB:
- case WPN_DAGGER:
- return 10;
- case WPN_HAND_AXE:
- case WPN_FALCHION:
- case WPN_MACE:
- case WPN_QUARTERSTAFF:
- return 9;
- case WPN_BOW:
- case WPN_FLAIL:
- case WPN_HAMMER:
- case WPN_SABRE:
- case WPN_SHORT_SWORD:
- case WPN_SLING:
- case WPN_SPEAR:
- return 8;
- case WPN_LONG_SWORD:
- case WPN_MORNINGSTAR:
- case WPN_WAR_AXE:
- return 7;
- case WPN_BATTLEAXE:
- case WPN_CROSSBOW:
- case WPN_GREAT_SWORD:
- case WPN_SCIMITAR:
- case WPN_TRIDENT:
- return 6;
- case WPN_GLAIVE:
- case WPN_HALBERD:
- case WPN_BLOWGUN:
- return 5;
- case WPN_BROAD_AXE:
- case WPN_HAND_CROSSBOW:
- case WPN_SPIKED_FLAIL:
- case WPN_WHIP:
- return 4;
- case WPN_GREAT_MACE:
- return 3;
- case WPN_ANCUS:
- case WPN_GREAT_FLAIL:
- case WPN_SCYTHE:
- return 2;
- case WPN_GIANT_CLUB:
- case WPN_GIANT_SPIKED_CLUB:
- return 1;
- // zero value weapons must be placed specially -- see items() {dlb}
- case WPN_DOUBLE_SWORD:
- case WPN_EVENINGSTAR:
- case WPN_EXECUTIONERS_AXE:
- case WPN_KATANA:
- case WPN_KNIFE:
- case WPN_QUICK_BLADE:
- case WPN_TRIPLE_SWORD:
- return 0;
-
- default:
- // should not happen now that calls are bounded by NUM_WEAPONS {dlb}
- return -1;
- }
-} // end rare_weapon()
-
//jmf: generate altar based on where you are, or possibly randomly
static int pick_an_altar(void)
{
@@ -6549,15 +6647,18 @@ static void place_shops(int level_number)
}
} // end place_shops()
-static void place_spec_shop( int level_number,
- unsigned char shop_x, unsigned char shop_y,
- unsigned char force_s_type )
+void place_spec_shop( int level_number,
+ unsigned char shop_x, unsigned char shop_y,
+ unsigned char force_s_type, bool representative )
{
int orb = 0;
int i = 0;
int j = 0; // loop variable
int item_level;
+ bool note_status = notes_are_active();
+ activate_notes(false);
+
for (i = 0; i < MAX_SHOPS; i++)
{
if (env.shop[i].type == SHOP_UNASSIGNED)
@@ -6593,6 +6694,8 @@ static void place_spec_shop( int level_number,
}
int plojy = 5 + random2avg(12, 3);
+ if (representative)
+ plojy = env.shop[i].type == SHOP_WAND? NUM_WANDS : 16;
for (j = 0; j < plojy; j++)
{
@@ -6614,7 +6717,8 @@ static void place_spec_shop( int level_number,
// General Stores (see item_in_shop() below) (GDL)
while(true)
{
- orb = items( 1, item_in_shop(env.shop[i].type), OBJ_RANDOM, true,
+ const int subtype = representative? j : OBJ_RANDOM;
+ orb = items( 1, item_in_shop(env.shop[i].type), subtype, true,
item_level, 250 );
if (orb != NON_ITEM
@@ -6637,6 +6741,9 @@ static void place_spec_shop( int level_number,
if (orb == NON_ITEM)
break;
+ if (representative && mitm[orb].base_type == OBJ_WANDS)
+ mitm[orb].plus = 7;
+
// set object 'position' (gah!) & ID status
mitm[orb].x = 0;
mitm[orb].y = 5 + i;
@@ -6653,6 +6760,8 @@ static void place_spec_shop( int level_number,
env.shop[i].y = shop_y;
grd[shop_x][shop_y] = DNGN_ENTER_SHOP;
+
+ activate_notes(note_status);
} // end place_spec_shop()
static unsigned char item_in_shop(unsigned char shop_type)
@@ -7270,11 +7379,8 @@ static bool octa_room(spec_room &sr, int oblique_max, unsigned char type_floor)
if (grd[x][y] == DNGN_FLOOR && type_floor == DNGN_SHALLOW_WATER)
grd[x][y] = DNGN_SHALLOW_WATER;
- if (type_floor >= DNGN_LAST_SOLID_TILE
- && grd[x][y] == DNGN_CLOSED_DOOR)
- {
+ if (grd[x][y] == DNGN_CLOSED_DOOR && !grid_is_solid(type_floor))
grd[x][y] = DNGN_FLOOR; // ick
- }
}
if (oblique > 0)
@@ -7289,8 +7395,6 @@ static bool octa_room(spec_room &sr, int oblique_max, unsigned char type_floor)
static void labyrinth_level(int level_number)
{
- int temp_rand; // probability determination {dlb}
-
int keep_lx = 0, keep_ly = 0;
int keep_lx2 = 0, keep_ly2 = 0;
char start_point_x = 10;
@@ -7421,14 +7525,12 @@ static void labyrinth_level(int level_number)
finishing:
start_point_x = 10 + random2(GXM - 20);
- int treasure_item = 0;
-
- unsigned char glopop = OBJ_RANDOM; // used in calling items() {dlb}
+ int glopop = OBJ_RANDOM; // used in calling items() {dlb}
int num_items = 8 + random2avg(9, 2);
for (int i = 0; i < num_items; i++)
{
- temp_rand = random2(11);
+ int temp_rand = random2(11);
glopop = ((temp_rand == 0 || temp_rand == 9) ? OBJ_WEAPONS :
(temp_rand == 1 || temp_rand == 10) ? OBJ_ARMOUR :
@@ -7440,8 +7542,8 @@ static void labyrinth_level(int level_number)
(temp_rand == 7) ? OBJ_BOOKS
/* (temp_rand == 8) */ : OBJ_STAVES);
- treasure_item = items( 1, glopop, OBJ_RANDOM, true,
- level_number * 3, 250 );
+ const int treasure_item = items( 1, glopop, OBJ_RANDOM, true,
+ level_number * 3, 250 );
if (treasure_item != NON_ITEM)
{
@@ -7457,10 +7559,8 @@ static void labyrinth_level(int level_number)
link_items();
// turn rock walls into undiggable stone or metal:
- temp_rand = random2(50);
-
- unsigned char wall_xform = ((temp_rand > 10) ? DNGN_STONE_WALL // 78.0%
- : DNGN_METAL_WALL); // 22.0%
+ unsigned char wall_xform = ((random2(50) > 10) ? DNGN_STONE_WALL // 78.0%
+ : DNGN_METAL_WALL); // 22.0%
replace_area(0,0,GXM-1,GYM-1,DNGN_ROCK_WALL,wall_xform);
@@ -7511,7 +7611,7 @@ static int box_room_door_spot(int x, int y)
static int box_room_doors( int bx1, int bx2, int by1, int by2, int new_doors)
{
- int good_doors[200]; // 1 == good spot, 2 == door placed!
+ int good_doors[200]; // 1 == good spot, 2 == door placed!
int spot;
int i,j;
int doors_placed = new_doors;
@@ -7520,7 +7620,7 @@ static int box_room_doors( int bx1, int bx2, int by1, int by2, int new_doors)
if ( 2 * ( (bx2 - bx1) + (by2-by1) ) > 200)
return 0;
- // go through, building list of good door spots, and replacing wall
+ // go through, building list of good door spots, and replacing wall
// with door if we're about to block off another door.
int spot_count = 0;
@@ -7907,7 +8007,7 @@ static void big_room(int level_number)
// helper function for chequerboard rooms
// note that box boundaries are INclusive
-static void chequerboard( spec_room &sr, unsigned char target,
+static void chequerboard( spec_room &sr, unsigned char target,
unsigned char floor1, unsigned char floor2 )
{
int i, j;
@@ -8129,8 +8229,50 @@ static void morgue(spec_room &sr)
}
} // end morgue()
-static bool place_specific_trap(unsigned char spec_x, unsigned char spec_y,
- unsigned char spec_type)
+static void jelly_pit(int level_number, spec_room &sr)
+{
+ FixedVector< pit_mons_def, MAX_PIT_MONSTERS > pit_list;
+ const int lordx = sr.x1 + random2(sr.x2 - sr.x1);
+ const int lordy = sr.y1 + random2(sr.y2 - sr.y1);
+
+ for (int i = 0; i < MAX_PIT_MONSTERS; i++)
+ {
+ pit_list[i].type = MONS_PROGRAM_BUG;
+ pit_list[i].rare = 0;
+ }
+
+#if DEBUG_DIAGNOSTICS
+ mprf( MSGCH_DIAGNOSTICS, "Build: Jelly Pit" );
+#endif
+ pit_list[0].type = MONS_OOZE;
+ pit_list[0].rare = 27 - level_number / 5;
+
+ pit_list[1].type = MONS_JELLY;
+ pit_list[1].rare = 20;
+
+ pit_list[2].type = MONS_BROWN_OOZE;
+ pit_list[2].rare = 3 + level_number;
+
+ pit_list[3].type = MONS_DEATH_OOZE;
+ pit_list[3].rare = 2 + (2 * level_number) / 3;
+
+ if (level_number >= 12)
+ {
+ pit_list[4].type = MONS_AZURE_JELLY;
+ pit_list[4].rare = 1 + (level_number - 12) / 3;
+ }
+
+ if (level_number >= 15)
+ {
+ pit_list[5].type = MONS_ACID_BLOB;
+ pit_list[5].rare = 1 + (level_number - 15) / 4;
+ }
+
+ fill_monster_pit( sr, pit_list, 90, MONS_PROGRAM_BUG, lordx, lordy );
+}
+
+bool place_specific_trap(unsigned char spec_x, unsigned char spec_y,
+ unsigned char spec_type)
{
if (spec_type == TRAP_RANDOM)
spec_type = random2(NUM_TRAPS);
@@ -8202,12 +8344,12 @@ void define_zombie( int mid, int ztype, int cs, int power )
{
// this limit can be updated if mons->number goes >8 bits..
test = random2(182); // not guaranteed to be valid, so..
- cls = mons_charclass(test);
+ cls = mons_species(test);
if (cls == MONS_PROGRAM_BUG)
continue;
- // on certain branches, zombie creation will fail if we use
- // the mons_rarity() functions, because (for example) there
+ // on certain branches, zombie creation will fail if we use
+ // the mons_rarity() functions, because (for example) there
// are NO zombifiable "native" abyss creatures. Other branches
// where this is a problem are hell levels and the crypt.
// we have to watch for summoned zombies on other levels, too,
@@ -8266,8 +8408,8 @@ void define_zombie( int mid, int ztype, int cs, int power )
break;
}
- // every so often, we'll relax the OOD restrictions. Avoids
- // infinite loops (if we don't do this, things like creating
+ // every so often, we'll relax the OOD restrictions. Avoids
+ // infinite loops (if we don't do this, things like creating
// a large skeleton on level 1 may hang the game!
if (one_chance_in(5))
relax++;
@@ -8279,7 +8421,7 @@ void define_zombie( int mid, int ztype, int cs, int power )
}
else
{
- menv[mid].number = mons_charclass(ztype);
+ menv[mid].number = mons_species(ztype);
mons_sec2 = menv[mid].number;
}
@@ -8348,6 +8490,7 @@ void define_zombie( int mid, int ztype, int cs, int power )
}
menv[mid].number = mons_sec2;
+ menv[mid].colour = mons_class_colour(cs);
} // end define_zombie()
#ifdef USE_RIVERS
diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h
index dedd41ae68..7db4d30569 100644
--- a/crawl-ref/source/dungeon.h
+++ b/crawl-ref/source/dungeon.h
@@ -3,6 +3,8 @@
* Summary: Functions used when building new levels.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -17,6 +19,14 @@
#define MAKE_GOOD_ITEM 351
+// Should be the larger of GXM/GYM
+#define MAP_SIDE GXM
+
+// This may sometimes be used as map_type[x][y] (for minivaults) and as
+// map_type[y][x] for large-scale vaults. Keep an eye out for the associated
+// brain-damage. [dshaligram]
+typedef char map_type[MAP_SIDE + 1][MAP_SIDE + 1];
+
void item_colour( item_def &item );
// last updated 12may2000 {dlb}
@@ -46,4 +56,13 @@ void give_item(int mid, int level_number);
* *********************************************************************** */
void define_zombie(int mid, int ztype, int cs, int power);
+bool is_wall(int feature);
+
+bool place_specific_trap(unsigned char spec_x, unsigned char spec_y,
+ unsigned char spec_type);
+
+void place_spec_shop(int level_number, unsigned char shop_x,
+ unsigned char shop_y, unsigned char force_s_type,
+ bool representative = false );
+
#endif
diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc
index 16517cba40..f3116be7f2 100644
--- a/crawl-ref/source/effects.cc
+++ b/crawl-ref/source/effects.cc
@@ -3,6 +3,8 @@
* Summary: Misc stuff.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -20,6 +22,7 @@
#include "direct.h"
#include "dungeon.h"
#include "itemname.h"
+#include "itemprop.h"
#include "items.h"
#include "misc.h"
#include "monplace.h"
@@ -37,27 +40,63 @@
#include "spl-util.h"
#include "stuff.h"
#include "view.h"
-#include "wpn-misc.h"
// torment_monsters is called with power 0 because torment is
// UNRESISTABLE except for being undead or having torment
-// resistance! Even if we used maximum power of 1000, high
+// resistance! Even if we used maximum power of 1000, high
// level monsters and characters would save too often. (GDL)
-static int torment_monsters(int x, int y, int pow, int garbage)
+int torment_monsters(int x, int y, int pow, int caster)
{
UNUSED( pow );
- UNUSED( garbage );
// is player?
if (x == you.x_pos && y == you.y_pos)
{
- if (you.is_undead || you.mutation[MUT_TORMENT_RESISTANCE])
+ // [dshaligram] Switched to using ouch() instead of dec_hp so that
+ // notes can also track torment and activities can be interrupted
+ // correctly.
+ int hploss = 0;
+ if (!player_res_torment())
+ {
+ // negative energy resistance can alleviate torment
+ hploss = you.hp * (50 - player_prot_life() * 5) / 100 - 1;
+ if (hploss >= you.hp)
+ hploss = you.hp - 1;
+ if (hploss < 0)
+ hploss = 0;
+ }
+
+ if (!hploss)
mpr("You feel a surge of unholy energy.");
else
{
mpr("Your body is wracked with pain!");
- dec_hp((you.hp / 2) - 1, false);
+
+ const char *aux = "torment";
+ if (caster < 0)
+ {
+ switch (caster)
+ {
+ case TORMENT_CARDS:
+ case TORMENT_SPELL:
+ aux = "Symbol of Torment";
+ break;
+ case TORMENT_SPWLD:
+ // FIXME: If we ever make any other weapon / randart
+ // eligible to torment, this will be incorrect.
+ aux = "Sceptre of Torment";
+ break;
+ case TORMENT_SCROLL:
+ aux = "scroll of torment";
+ break;
+ }
+ caster = TORMENT_GENERIC;
+ }
+ ouch(hploss, caster,
+ caster != TORMENT_GENERIC? KILLED_BY_MONSTER
+ : KILLED_BY_SOMETHING,
+ aux);
}
return 1;
@@ -83,9 +122,9 @@ static int torment_monsters(int x, int y, int pow, int garbage)
return 1;
}
-void torment(int tx, int ty)
+void torment(int caster, int tx, int ty)
{
- apply_area_within_radius(torment_monsters, tx, ty, 0, 8, 0);
+ apply_area_within_radius(torment_monsters, tx, ty, 0, 8, caster);
} // end torment()
void banished(unsigned char gate_type)
@@ -215,15 +254,16 @@ void direct_effect(struct bolt &pbolt)
{
case DMNBM_HELLFIRE:
mpr( "You are engulfed in a burst of hellfire!" );
- strcpy( pbolt.beam_name, "hellfire" );
+ pbolt.name = "hellfire";
pbolt.ex_size = 1;
- pbolt.flavour = BEAM_EXPLOSION;
+ pbolt.flavour = BEAM_HELLFIRE;
+ pbolt.is_explosion = true;
pbolt.type = SYM_ZAP;
pbolt.colour = RED;
pbolt.thrower = KILL_MON_MISSILE;
- pbolt.aux_source = NULL;
- pbolt.isBeam = false;
- pbolt.isTracer = false;
+ pbolt.aux_source.clear();
+ pbolt.is_beam = false;
+ pbolt.is_tracer = false;
pbolt.hit = 20;
pbolt.damage = dice_def( 3, 20 );
pbolt.aux_source = "burst of hellfire";
@@ -232,7 +272,7 @@ void direct_effect(struct bolt &pbolt)
case DMNBM_SMITING:
mpr( "Something smites you!" );
- strcpy( pbolt.beam_name, "smiting" ); // for ouch
+ pbolt.name = "smiting";
pbolt.aux_source = "by divine providence";
damage_taken = 7 + random2avg(11, 2);
break;
@@ -256,7 +296,8 @@ void direct_effect(struct bolt &pbolt)
// apply damage and handle death, where appropriate {dlb}
if (damage_taken > 0)
- ouch(damage_taken, pbolt.beam_source, KILLED_BY_BEAM, pbolt.aux_source);
+ ouch(damage_taken, pbolt.beam_source, KILLED_BY_BEAM,
+ pbolt.aux_source.c_str());
return;
} // end direct_effect()
@@ -276,7 +317,7 @@ void mons_direct_effect(struct bolt &pbolt, int i)
{
case DMNBM_HELLFIRE:
simple_monster_message(monster, " is engulfed in hellfire.");
- strcpy(pbolt.beam_name, "hellfire");
+ pbolt.name = "hellfire";
pbolt.flavour = BEAM_LAVA;
damage_taken = 5 + random2(10) + random2(5);
@@ -285,7 +326,7 @@ void mons_direct_effect(struct bolt &pbolt, int i)
case DMNBM_SMITING:
simple_monster_message(monster, " is smitten.");
- strcpy(pbolt.beam_name, "smiting");
+ pbolt.name = "smiting";
pbolt.flavour = BEAM_MISSILE;
damage_taken += 7 + random2avg(11, 2);
@@ -295,7 +336,7 @@ void mons_direct_effect(struct bolt &pbolt, int i)
break;
case DMNBM_MUTATION:
- if (mons_holiness( monster->type ) != MH_NATURAL)
+ if (mons_holiness(monster) != MH_NATURAL)
simple_monster_message(monster, " is unaffected.");
else if (check_mons_resist_magic( monster, pbolt.ench_power ))
simple_monster_message(monster, " resists.");
@@ -471,23 +512,23 @@ bool acquirement(unsigned char force_class, int agent)
//mpr("[r|R] - Just give me something good.");
mpr("What kind of item would you like to acquire? ", MSGCH_PROMPT);
- keyin = get_ch();
+ keyin = tolower( get_ch() );
- if (keyin == 'a' || keyin == 'A')
+ if (keyin == 'a')
class_wanted = OBJ_WEAPONS;
- else if (keyin == 'b' || keyin == 'B')
+ else if (keyin == 'b')
class_wanted = OBJ_ARMOUR;
- else if (keyin == 'c' || keyin == 'C')
+ else if (keyin == 'c')
class_wanted = OBJ_JEWELLERY;
- else if (keyin == 'd' || keyin == 'D')
+ else if (keyin == 'd')
class_wanted = OBJ_BOOKS;
- else if (keyin == 'e' || keyin == 'E')
+ else if (keyin == 'e')
class_wanted = OBJ_STAVES;
- else if (keyin == 'f' || keyin == 'F')
+ else if (keyin == 'f')
class_wanted = OBJ_FOOD;
- else if (keyin == 'g' || keyin == 'G')
+ else if (keyin == 'g')
class_wanted = OBJ_MISCELLANY;
- else if (keyin == 'h' || keyin == 'H')
+ else if (keyin == 'h')
class_wanted = OBJ_GOLD;
}
else
@@ -505,7 +546,7 @@ bool acquirement(unsigned char force_class, int agent)
if (class_wanted == OBJ_FOOD)
{
- // food is a little less predicatable now -- bwr
+ // food is a little less predictable now -- bwr
if (you.species == SP_GHOUL)
{
@@ -514,7 +555,7 @@ bool acquirement(unsigned char force_class, int agent)
}
else
{
- // Meat is better than bread (except for herbivors), and
+ // Meat is better than bread (except for herbivores), and
// by choosing it as the default we don't have to worry
// about special cases for carnivorous races (ie kobold)
type_wanted = FOOD_MEAT_RATION;
@@ -523,7 +564,7 @@ bool acquirement(unsigned char force_class, int agent)
type_wanted = FOOD_BREAD_RATION;
// If we have some regular rations, then we're probably be more
- // interested in faster foods (escpecially royal jelly)...
+ // interested in faster foods (especially royal jelly)...
// otherwise the regular rations should be a good enough offer.
if (already_has[FOOD_MEAT_RATION]
+ already_has[FOOD_BREAD_RATION] >= 2 || coinflip())
@@ -550,17 +591,26 @@ bool acquirement(unsigned char force_class, int agent)
int skill = SK_FIGHTING;
// Can't do much with launchers, so we'll avoid them for now -- bwr
- for (int i = SK_SHORT_BLADES; i <= SK_STAVES; i++)
+ for (int i = SK_SHORT_BLADES; i < SK_DARTS; i++)
{
if (i == SK_UNUSED_1)
continue;
// Adding a small constant allows for the occasional
- // weapon in an untrained skill.
- count += (you.skills[i] + 1);
+ // weapon in an untrained skill. Since the game
+ // doesn't allow for much in the way of good launchers,
+ // we'll lower their weight.
+
+ int weight = 0;
+
+ weight = you.skills[i] + 1;
+ if (weight)
+ {
+ count += weight;
- if (random2(count) < you.skills[i] + 1)
- skill = i;
+ if (random2(count) < weight)
+ skill = i;
+ }
}
if (skill == SK_STAVES)
@@ -572,21 +622,25 @@ bool acquirement(unsigned char force_class, int agent)
// skipping clubs, knives, blowguns
for (int i = WPN_MACE; i < NUM_WEAPONS; i++)
{
- // skipping launchers
- if (i == WPN_SLING)
- i = WPN_GLAIVE;
-
+ // FIXME: Add a flag to itemprop.cc to do these exclusions
// skipping giant clubs
- if (i == WPN_GIANT_CLUB)
- i = WPN_EVENINGSTAR;
+ if (i == WPN_GIANT_CLUB || i == WPN_GIANT_SPIKED_CLUB)
+ continue;
// skipping knife and blowgun
- if (i == WPN_KNIFE)
- i = WPN_FALCHION;
+ if (i == WPN_KNIFE || i == WPN_BLOWGUN)
+ continue;
+
+ // blessed blades can only be created by the player, never found
+ if (i == WPN_BLESSED_BLADE)
+ continue;
// "rare" weapons are only considered some of the time...
// still, the chance is higher than actual random creation
- if (weapon_skill( OBJ_WEAPONS, i ) == skill
+ int wskill = range_skill(OBJ_WEAPONS, i);
+ if (wskill == SK_RANGED_COMBAT)
+ wskill = weapon_skill(OBJ_WEAPONS, i);
+ if (wskill == skill
&& (i < WPN_EVENINGSTAR || i > WPN_BROAD_AXE
|| (i >= WPN_HAMMER && i <= WPN_SABRE)
|| one_chance_in(4)))
@@ -598,6 +652,72 @@ bool acquirement(unsigned char force_class, int agent)
}
}
}
+ else if (class_wanted == OBJ_MISSILES)
+ {
+ int count = 0;
+ int skill = SK_RANGED_COMBAT;
+
+ for (int i = SK_SLINGS; i <= SK_DARTS; i++)
+ {
+ if (you.skills[i])
+ {
+ count += you.skills[i];
+ if (random2(count) < you.skills[i])
+ skill = i;
+ }
+ }
+
+ switch (skill)
+ {
+ case SK_SLINGS:
+ type_wanted = MI_STONE;
+ break;
+
+ case SK_BOWS:
+ type_wanted = MI_ARROW;
+ break;
+
+ case SK_CROSSBOWS:
+ type_wanted = MI_DART;
+ for (int i = 0; i < ENDOFPACK; i++)
+ {
+ // Assuming that crossbow in inventory means that they
+ // want bolts for it (not darts for a hand crossbow)...
+ // perhaps we should check for both and compare ammo
+ // amounts on hand?
+ if (is_valid_item( you.inv[i] )
+ && you.inv[i].base_type == OBJ_WEAPONS
+ && you.inv[i].sub_type == WPN_CROSSBOW)
+ {
+ type_wanted = MI_BOLT;
+ break;
+ }
+ }
+ break;
+
+ case SK_DARTS:
+ type_wanted = MI_DART;
+ for (int i = 0; i < ENDOFPACK; i++)
+ {
+ if (is_valid_item( you.inv[i] )
+ && you.inv[i].base_type == OBJ_WEAPONS
+ && you.inv[i].sub_type == WPN_BLOWGUN)
+ {
+ // Assuming that blowgun in inventory means that they
+ // may want needles for it (but darts might also be
+ // wanted). Maybe expand this... see above comment.
+ if (coinflip())
+ type_wanted = MI_NEEDLE;
+ break;
+ }
+ }
+ break;
+
+ default:
+ type_wanted = MI_DART;
+ break;
+ }
+ }
else if (class_wanted == OBJ_ARMOUR)
{
// Increasing the representation of the non-body armour
@@ -631,11 +751,11 @@ bool acquirement(unsigned char force_class, int agent)
case SP_PALE_DRACONIAN:
case SP_UNK0_DRACONIAN:
case SP_UNK1_DRACONIAN:
- case SP_UNK2_DRACONIAN:
+ case SP_BASE_DRACONIAN:
case SP_SPRIGGAN:
if (type_wanted == ARM_GLOVES || type_wanted == ARM_BOOTS)
{
- type_wanted = OBJ_RANDOM;
+ type_wanted = ARM_ROBE; // no heavy armour
}
else if (type_wanted == ARM_SHIELD)
{
@@ -819,7 +939,7 @@ bool acquirement(unsigned char force_class, int agent)
if (best_any >= SK_FIGHTING
&& best_any <= SK_STAVES)
{
- // Fighter mage's get the fighting enchantment books
+ // Fighter mages get the fighting enchantment books
if (!you.had_book[BOOK_WAR_CHANTS])
type_wanted = BOOK_WAR_CHANTS;
else if (!you.had_book[BOOK_TUKIMA])
@@ -1050,10 +1170,11 @@ bool acquirement(unsigned char force_class, int agent)
while (already_has[type_wanted] && !one_chance_in(200));
}
- if (grd[you.x_pos][you.y_pos] == DNGN_LAVA
- || grd[you.x_pos][you.y_pos] == DNGN_DEEP_WATER)
+ if (grid_destroys_items(grd[you.x_pos][you.y_pos]))
{
- mpr("You hear a splash."); // how sad (and stupid)
+ // how sad (and stupid)
+ mprf(MSGCH_SOUND,
+ grid_item_destruction_message(grd[you.x_pos][you.y_pos]));
}
else
{
@@ -1067,39 +1188,46 @@ bool acquirement(unsigned char force_class, int agent)
return (false);
}
+ // easier to read this way
+ item_def& thing(mitm[thing_created]);
+
+ // give some more gold
+ if ( class_wanted == OBJ_GOLD )
+ thing.quantity += 150;
+
// remove curse flag from item
- do_uncurse_item( mitm[thing_created] );
+ do_uncurse_item( thing );
- if (mitm[thing_created].base_type == OBJ_BOOKS)
+ if (thing.base_type == OBJ_BOOKS)
{
- if (mitm[thing_created].base_type == BOOK_MINOR_MAGIC_I
- || mitm[thing_created].base_type == BOOK_MINOR_MAGIC_II
- || mitm[thing_created].base_type == BOOK_MINOR_MAGIC_III)
+ if (thing.base_type == BOOK_MINOR_MAGIC_I
+ || thing.base_type == BOOK_MINOR_MAGIC_II
+ || thing.base_type == BOOK_MINOR_MAGIC_III)
{
you.had_book[ BOOK_MINOR_MAGIC_I ] = 1;
you.had_book[ BOOK_MINOR_MAGIC_II ] = 1;
you.had_book[ BOOK_MINOR_MAGIC_III ] = 1;
}
- else if (mitm[thing_created].base_type == BOOK_CONJURATIONS_I
- || mitm[thing_created].base_type == BOOK_CONJURATIONS_II)
+ else if (thing.base_type == BOOK_CONJURATIONS_I
+ || thing.base_type == BOOK_CONJURATIONS_II)
{
you.had_book[ BOOK_CONJURATIONS_I ] = 1;
you.had_book[ BOOK_CONJURATIONS_II ] = 1;
}
else
{
- you.had_book[ mitm[thing_created].sub_type ] = 1;
+ you.had_book[ thing.sub_type ] = 1;
}
}
- else if (mitm[thing_created].base_type == OBJ_JEWELLERY)
+ else if (thing.base_type == OBJ_JEWELLERY)
{
- switch (mitm[thing_created].sub_type)
+ switch (thing.sub_type)
{
case RING_SLAYING:
// make sure plus to damage is >= 1
- mitm[thing_created].plus2 = abs( mitm[thing_created].plus2 );
- if (mitm[thing_created].plus2 == 0)
- mitm[thing_created].plus2 = 1;
+ thing.plus2 = abs( thing.plus2 );
+ if (thing.plus2 == 0)
+ thing.plus2 = 1;
// fall through...
case RING_PROTECTION:
@@ -1108,24 +1236,24 @@ bool acquirement(unsigned char force_class, int agent)
case RING_DEXTERITY:
case RING_EVASION:
// make sure plus is >= 1
- mitm[thing_created].plus = abs( mitm[thing_created].plus );
- if (mitm[thing_created].plus == 0)
- mitm[thing_created].plus = 1;
+ thing.plus = abs( thing.plus );
+ if (thing.plus == 0)
+ thing.plus = 1;
break;
case RING_HUNGER:
case AMU_INACCURACY:
// these are the only truly bad pieces of jewellery
if (!one_chance_in(9))
- make_item_randart( mitm[thing_created] );
+ make_item_randart( thing );
break;
default:
break;
}
}
- else if (mitm[thing_created].base_type == OBJ_WEAPONS
- && !is_fixed_artefact( mitm[thing_created] ))
+ else if (thing.base_type == OBJ_WEAPONS
+ && !is_fixed_artefact( thing ))
{
// HACK: make unwieldable weapons wieldable
// Note: messing with fixed artefacts is probably very bad.
@@ -1135,23 +1263,23 @@ bool acquirement(unsigned char force_class, int agent)
case SP_MUMMY:
case SP_GHOUL:
{
- int brand = get_weapon_brand( mitm[thing_created] );
+ int brand = get_weapon_brand( thing );
if (brand == SPWPN_HOLY_WRATH
|| brand == SPWPN_DISRUPTION)
{
- if (!is_random_artefact( mitm[thing_created] ))
+ if (!is_random_artefact( thing ))
{
- set_item_ego_type( mitm[thing_created],
+ set_item_ego_type( thing,
OBJ_WEAPONS, SPWPN_VORPAL );
}
else
{
- // keep reseting seed until it's good:
+ // keep resetting seed until it's good:
for (; brand == SPWPN_HOLY_WRATH
|| brand == SPWPN_DISRUPTION;
- brand = get_weapon_brand(mitm[thing_created]))
+ brand = get_weapon_brand(thing))
{
- make_item_randart( mitm[thing_created] );
+ make_item_randart( thing );
}
}
}
@@ -1162,30 +1290,35 @@ bool acquirement(unsigned char force_class, int agent)
case SP_GNOME:
case SP_KOBOLD:
case SP_SPRIGGAN:
- switch (mitm[thing_created].sub_type)
+ switch (thing.sub_type)
{
+ case WPN_LONGBOW:
+ thing.sub_type = WPN_BOW;
+ break;
+
case WPN_GREAT_SWORD:
case WPN_TRIPLE_SWORD:
- mitm[thing_created].sub_type =
+ thing.sub_type =
(coinflip() ? WPN_FALCHION : WPN_LONG_SWORD);
break;
case WPN_GREAT_MACE:
- case WPN_GREAT_FLAIL:
- mitm[thing_created].sub_type =
+ case WPN_DIRE_FLAIL:
+ thing.sub_type =
(coinflip() ? WPN_MACE : WPN_FLAIL);
break;
case WPN_BATTLEAXE:
case WPN_EXECUTIONERS_AXE:
- mitm[thing_created].sub_type =
+ thing.sub_type =
(coinflip() ? WPN_HAND_AXE : WPN_WAR_AXE);
break;
case WPN_HALBERD:
case WPN_GLAIVE:
case WPN_SCYTHE:
- mitm[thing_created].sub_type =
+ case WPN_LOCHABER_AXE:
+ thing.sub_type =
(coinflip() ? WPN_SPEAR : WPN_TRIDENT);
break;
}
@@ -1195,16 +1328,16 @@ bool acquirement(unsigned char force_class, int agent)
break;
}
}
- else if (mitm[thing_created].base_type == OBJ_ARMOUR
- && !is_fixed_artefact( mitm[thing_created] ))
+ else if (thing.base_type == OBJ_ARMOUR
+ && !is_fixed_artefact( thing ))
{
// HACK: make unwearable hats and boots wearable
// Note: messing with fixed artefacts is probably very bad.
- switch (mitm[thing_created].sub_type)
+ switch (thing.sub_type)
{
case ARM_HELMET:
- if ((cmp_helmet_type( mitm[thing_created], THELM_HELM )
- || cmp_helmet_type( mitm[thing_created], THELM_HELMET ))
+ if ((get_helmet_type(thing) == THELM_HELM
+ || get_helmet_type(thing) == THELM_HELMET)
&& ((you.species >= SP_OGRE && you.species <= SP_OGRE_MAGE)
|| player_genus(GENPC_DRACONIAN)
|| you.species == SP_MINOTAUR
@@ -1213,26 +1346,40 @@ bool acquirement(unsigned char force_class, int agent)
|| you.mutation[MUT_HORNS]))
{
// turn it into a cap or wizard hat
- set_helmet_type( mitm[thing_created],
- coinflip() ? THELM_CAP : THELM_WIZARD_HAT );
+ set_helmet_type(thing,
+ coinflip() ? THELM_CAP : THELM_WIZARD_HAT);
- mitm[thing_created].colour = random_colour();
+ thing.colour = random_colour();
}
break;
case ARM_BOOTS:
if (you.species == SP_NAGA)
- mitm[thing_created].plus2 = TBOOT_NAGA_BARDING;
+ thing.sub_type = ARM_NAGA_BARDING;
else if (you.species == SP_CENTAUR)
- mitm[thing_created].plus2 = TBOOT_CENTAUR_BARDING;
- else
- mitm[thing_created].plus2 = TBOOT_BOOTS;
+ thing.sub_type = ARM_CENTAUR_BARDING;
// fix illegal barding ego types caused by above hack
- if (mitm[thing_created].plus2 != TBOOT_BOOTS
- && get_armour_ego_type( mitm[thing_created] ) == SPARM_RUNNING)
+ if (thing.sub_type != ARM_BOOTS &&
+ get_armour_ego_type(thing) == SPARM_RUNNING)
{
- set_item_ego_type( mitm[thing_created], OBJ_ARMOUR, SPARM_NORMAL );
+ set_item_ego_type( thing, OBJ_ARMOUR, SPARM_NORMAL );
+ }
+ break;
+
+ case ARM_NAGA_BARDING:
+ case ARM_CENTAUR_BARDING:
+ // make barding appropriate
+ if (you.species == SP_NAGA )
+ thing.sub_type = ARM_NAGA_BARDING;
+ else if ( you.species == SP_CENTAUR )
+ thing.sub_type = ARM_CENTAUR_BARDING;
+ else {
+ thing.sub_type = ARM_BOOTS;
+ // Fix illegal ego types
+ if (get_armour_ego_type(thing) == SPARM_COLD_RESISTANCE ||
+ get_armour_ego_type(thing) == SPARM_FIRE_RESISTANCE)
+ set_item_ego_type(thing, OBJ_ARMOUR, SPARM_NORMAL);
}
break;
@@ -1260,48 +1407,91 @@ bool acquirement(unsigned char force_class, int agent)
bool recharge_wand(void)
{
- if (you.equip[EQ_WEAPON] == -1
- || you.inv[you.equip[EQ_WEAPON]].base_type != OBJ_WANDS)
- {
+ if (you.equip[EQ_WEAPON] == -1)
return (false);
- }
- unsigned char charge_gain = 0;
+ item_def &wand = you.inv[ you.equip[EQ_WEAPON] ];
- switch (you.inv[you.equip[EQ_WEAPON]].sub_type)
+ if (wand.base_type != OBJ_WANDS && !item_is_rod(wand))
+ return (false);
+
+ int charge_gain = 0;
+ if (wand.base_type == OBJ_WANDS)
{
- case WAND_INVISIBILITY:
- case WAND_FIREBALL:
- case WAND_HEALING:
- charge_gain = 3;
- break;
+ // remove "empty" autoinscription
+ const char* empty_inscription = "[empty]";
+ size_t p = wand.inscription.find(empty_inscription);
+ if ( p != std::string::npos ) {
+ // found it, delete it
+ size_t prespace = 0;
+ if ( p != 0 && wand.inscription[p-1] == ' ' )
+ prespace = 1;
+ wand.inscription =
+ wand.inscription.substr(0, p - prespace) +
+ wand.inscription.substr(p + strlen(empty_inscription),
+ std::string::npos);
+ }
+ switch (wand.sub_type)
+ {
+ case WAND_INVISIBILITY:
+ case WAND_FIREBALL:
+ case WAND_HEALING:
+ case WAND_HASTING:
+ charge_gain = 3;
+ break;
- case WAND_LIGHTNING:
- case WAND_DRAINING:
- charge_gain = 4;
- break;
+ case WAND_LIGHTNING:
+ case WAND_DRAINING:
+ charge_gain = 4;
+ break;
- case WAND_FIRE:
- case WAND_COLD:
- charge_gain = 5;
- break;
+ case WAND_FIRE:
+ case WAND_COLD:
+ charge_gain = 5;
+ break;
- default:
- charge_gain = 8;
- break;
+ default:
+ charge_gain = 8;
+ break;
+ }
+
+ char str_pass[ ITEMNAME_SIZE ];
+ item_name(wand, DESC_CAP_YOUR, str_pass);
+ mprf("%s glows for a moment.", str_pass);
+
+ wand.plus += 1 + random2avg( ((charge_gain - 1) * 3) + 1, 3 );
+
+ if (wand.plus > charge_gain * 3)
+ wand.plus = charge_gain * 3;
}
+ else
+ {
+ // This is a rod.
+ bool work = false;
- char str_pass[ ITEMNAME_SIZE ];
- in_name(you.equip[EQ_WEAPON], DESC_CAP_YOUR, str_pass);
- strcpy(info, str_pass);
- strcat(info, " glows for a moment.");
- mpr(info);
+ if (wand.plus2 <= MAX_ROD_CHARGE * ROD_CHARGE_MULT)
+ {
+ wand.plus2 += ROD_CHARGE_MULT;
+
+ if (wand.plus2 > MAX_ROD_CHARGE * ROD_CHARGE_MULT)
+ wand.plus2 = MAX_ROD_CHARGE * ROD_CHARGE_MULT;
+
+ work = true;
+ }
- you.inv[you.equip[EQ_WEAPON]].plus +=
- 1 + random2avg( ((charge_gain - 1) * 3) + 1, 3 );
+ if (wand.plus < wand.plus2)
+ {
+ wand.plus = wand.plus2;
+ work = true;
+ }
- if (you.inv[you.equip[EQ_WEAPON]].plus > charge_gain * 3)
- you.inv[you.equip[EQ_WEAPON]].plus = charge_gain * 3;
+ if (!work)
+ return (false);
+
+ char str_pass[ITEMNAME_SIZE];
+ item_name( wand, DESC_CAP_YOUR, str_pass );
+ mprf("%s glows for a moment.", str_pass);
+ }
you.wield_change = true;
return (true);
@@ -1346,8 +1536,8 @@ void yell(void)
switch (keyn)
{
case '!':
- mpr("You yell for attention!");
- you.turn_is_over = 1;
+ mpr("You yell for attention!", MSGCH_SOUND);
+ you.turn_is_over = true;
noisy( 12, you.x_pos, you.y_pos );
return;
diff --git a/crawl-ref/source/effects.h b/crawl-ref/source/effects.h
index b7442a493e..44d1ba56a5 100644
--- a/crawl-ref/source/effects.h
+++ b/crawl-ref/source/effects.h
@@ -3,6 +3,8 @@
* Summary: Misc stuff.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -86,7 +88,8 @@ void yell(void);
* called from: ability - decks - fight - it_use3 - item_use - mstuff2 -
* spell
* *********************************************************************** */
-void torment( int tx, int ty );
+void torment( int caster, int tx, int ty );
+int torment_monsters(int x, int y, int pow, int caster);
#endif
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index 55d24085e1..4bf996d51f 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -3,6 +3,8 @@
* Summary: Global (ick) enums.
* Written by: Daniel Ligon
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <11> 7 Aug 01 MV Changed MSLOT_UNASSIGNED_I to MSLOT_MISCELLANY
@@ -30,7 +32,7 @@
#ifndef ENUM_H
#define ENUM_H
-enum ABILITIES
+enum ability_type
{
ABIL_NON_ABILITY = -1,
ABIL_SPIT_POISON = 1, // 1
@@ -49,7 +51,7 @@ enum ABILITIES
ABIL_BREATHE_STEAM,
ABIL_FLY, // 15
ABIL_SUMMON_MINOR_DEMON,
- ABIL_SUMMON_DEMON,
+ ABIL_SUMMON_DEMONS,
ABIL_HELLFIRE,
ABIL_TORMENT,
ABIL_RAISE_DEAD, // 20
@@ -79,7 +81,7 @@ enum ABILITIES
ABIL_TSO_REPEL_UNDEAD = 120, // 120
ABIL_TSO_SMITING,
ABIL_TSO_ANNIHILATE_UNDEAD,
- ABIL_TSO_THUNDERBOLT,
+ ABIL_TSO_CLEANSING_FLAME,
ABIL_TSO_SUMMON_DAEVA, // 124
ABIL_KIKU_RECALL_UNDEAD_SLAVES = 130, // 130
ABIL_KIKU_ENSLAVE_UNDEAD = 132, // 132
@@ -89,7 +91,7 @@ enum ABILITIES
ABIL_YRED_ANIMATE_DEAD,
ABIL_YRED_DRAIN_LIFE,
ABIL_YRED_CONTROL_UNDEAD, // 144
- ABIL_VEHUMET_CHANNEL_ENERGY = 160, // 160
+ // 160 - reserved for Vehumet
ABIL_OKAWARU_MIGHT = 170, // 170
ABIL_OKAWARU_HEALING,
ABIL_OKAWARU_HASTE, // 172
@@ -97,7 +99,8 @@ enum ABILITIES
ABIL_MAKHLEB_LESSER_SERVANT_OF_MAKHLEB,
ABIL_MAKHLEB_MAJOR_DESTRUCTION,
ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB, // 183
- ABIL_SIF_MUNA_FORGET_SPELL = 190, // 190
+ ABIL_SIF_MUNA_CHANNEL_ENERGY = 190, // 190
+ ABIL_SIF_MUNA_FORGET_SPELL,
ABIL_TROG_BERSERK = 200, // 200
ABIL_TROG_MIGHT,
ABIL_TROG_HASTE_SELF, // 202
@@ -110,11 +113,15 @@ enum ABILITIES
ABIL_TRAN_SERPENT_OF_HELL,
ABIL_ROTTING,
ABIL_TORMENT_II,
- ABIL_SHUGGOTH_SEED,
+ ABIL_PAIN,
+ ABIL_ENSLAVE_UNDEAD,
+ ABIL_BOLT_OF_FIRE,
+ ABIL_BOLT_OF_COLD,
+ ABIL_HELLFROST,
ABIL_RENOUNCE_RELIGION = 250 // 250
};
-enum ABILITY_FLAGS
+enum ability_flag_type
{
ABFLAG_NONE = 0x00000000,
ABFLAG_BREATH = 0x00000001, // ability uses DUR_BREATH_WEAPON
@@ -126,34 +133,28 @@ enum ABILITY_FLAGS
ABFLAG_PERMANENT_MP = 0x00000040 // costs permanent MPs
};
-enum ACTIVITY
+enum activity_interrupt_type
{
- ACT_NONE = 0,
- ACT_MULTIDROP,
- ACT_RUNNING,
- ACT_TRAVELING,
- ACT_MACRO,
-
- ACT_ACTIVITY_COUNT
-};
+ AI_FORCE_INTERRUPT = 0, // Forcibly kills any activity that can be
+ // interrupted.
+ AI_KEYPRESS,
+ AI_FULL_HP, // Player is fully healed
+ AI_FULL_MP, // Player has recovered all mp
+ AI_STATUE, // Bad statue has come into view
+ AI_HUNGRY, // Hunger increased
+ AI_MESSAGE, // Message was displayed
+ AI_HP_LOSS,
+ AI_BURDEN_CHANGE,
+ AI_STAT_CHANGE,
+ AI_SEE_MONSTER,
+ AI_MONSTER_ATTACKS,
+ AI_TELEPORT,
-enum ACT_INTERRUPT
-{
- AI_FORCE_INTERRUPT = 0, // Forcibly kills any activity
- AI_KEYPRESS = 0x01,
- AI_FULL_HP = 0x02, // Player is fully healed
- AI_FULL_MP = 0x04, // Player has recovered all mp
- AI_STATUE = 0x08, // Bad statue has come into view
- AI_HUNGRY = 0x10, // Hunger increased
- AI_MESSAGE = 0x20, // Message was displayed
- AI_HP_LOSS = 0x40,
- AI_BURDEN_CHANGE = 0x80,
- AI_STAT_CHANGE = 0x100,
- AI_SEE_MONSTER = 0x200,
- AI_TELEPORT = 0x400
+ // Always the last.
+ NUM_AINTERRUPTS
};
-enum AI_PAYLOAD
+enum activity_interrupt_payload_type
{
AIP_NONE,
AIP_INT,
@@ -162,7 +163,7 @@ enum AI_PAYLOAD
AIP_HP_LOSS
};
-enum AMMUNITION_DESCRIPTIONS
+enum ammunition_description_type
{
DAMMO_ORCISH = 3, // 3
DAMMO_ELVEN,
@@ -170,7 +171,7 @@ enum AMMUNITION_DESCRIPTIONS
};
// Various ways to get the acquirement effect.
-enum AQ_AGENTS
+enum acquirement_agent_type
{
AQ_SCROLL = 0,
@@ -184,7 +185,7 @@ enum AQ_AGENTS
AQ_WIZMODE = 200
};
-enum ARMOUR
+enum armour_type
{
ARM_ROBE, // 0
ARM_LEATHER_ARMOUR,
@@ -219,10 +220,16 @@ enum ARMOUR
ARM_ANIMAL_SKIN, // 30
ARM_SWAMP_DRAGON_HIDE,
ARM_SWAMP_DRAGON_ARMOUR,
+ ARM_STUDDED_LEATHER_ARMOUR,
+ ARM_CAP,
+ ARM_CENTAUR_BARDING, // 35
+ ARM_NAGA_BARDING,
+
NUM_ARMOURS
};
-enum ARMOUR_DESCRIPTIONS
+// these are for the old system (still used for reading old files)
+enum armour_description_type
{
DARM_PLAIN, // added for the heck of it, 15 Apr 2000 {dlb}
DARM_EMBROIDERED_SHINY = 1, // which it is dependent upon armour subtype {dlb}
@@ -233,19 +240,18 @@ enum ARMOUR_DESCRIPTIONS
DARM_ORCISH
};
-enum ARMOUR_PROPERTIES
+enum armour_property_type
{
PARM_AC, // 0
PARM_EVASION
};
-// Note: currently the size of the attr array is hard coded at 30! ick! -- bwr
-enum ATTRIBUTES
+enum attribute_type
{
ATTR_DIVINE_LIGHTNING_PROTECTION, // 0
// ATTR_SPEC_AIR, // don't use this!
// ATTR_SPEC_EARTH,
- ATTR_CONTROL_TELEPORT = 3,
+ ATTR_CONTROL_TELEPORT = 3, // obsolete
ATTR_WALK_SLOWLY,
ATTR_TRANSFORMATION, // 5
ATTR_CARD_COUNTDOWN,
@@ -258,10 +264,15 @@ enum ATTRIBUTES
ATTR_WALLS,
ATTR_LAST_WALLS,
ATTR_DELAYED_FIREBALL, // bwr: reserve fireballs
- NUM_ATTRIBUTES // must always remain last member {dlb}
+ ATTR_DEMONIC_POWER_1,
+ ATTR_DEMONIC_POWER_2,
+ ATTR_DEMONIC_POWER_3,
+ ATTR_DEMONIC_POWER_4,
+ ATTR_DEMONIC_POWER_5, // 19
+ NUM_ATTRIBUTES = 30 // must be at least 30
};
-enum BANDS
+enum band_type
{
BAND_NO_BAND = 0,
BAND_KOBOLDS = 1,
@@ -306,10 +317,11 @@ enum BANDS
BAND_BOGGARTS,
BAND_BLINK_FROGS,
BAND_SKELETAL_WARRIORS, // 44
+ BAND_DRACONIAN, // 45
NUM_BANDS // always last
};
-enum BEAMS // beam[].flavour
+enum beam_type // beam[].flavour
{
BEAM_MISSILE, // 0
BEAM_MMISSILE, // 1 - and similarly unresistable things
@@ -319,13 +331,17 @@ enum BEAMS // beam[].flavour
BEAM_ELECTRICITY, // 5
BEAM_POISON,
BEAM_NEG,
- BEAM_ACID, // 8
- BEAM_EXPLOSION = 10, // 10
- BEAM_SPORE, // 11
- BEAM_POISON_ARROW, // 12
- BEAM_HELLFIRE, // 13 - found 11jan2000 {dlb}
- BEAM_ENERGY = 17,
- BEAM_HOLY = 18, // 18 - aka beam of cleansing, golden flame
+ BEAM_ACID,
+ BEAM_MIASMA,
+ // BEAM_EXPLOSION, // 10 - use is_explosion, and BEAM of flavour
+ BEAM_SPORE = 11,
+ BEAM_POISON_ARROW,
+ BEAM_HELLFIRE,
+ BEAM_NAPALM,
+ BEAM_STEAM, // 15
+ BEAM_HELLFROST,
+ BEAM_ENERGY,
+ BEAM_HOLY, // 18 - aka beam of cleansing, golden flame
BEAM_FRAG,
BEAM_LAVA, // 20
BEAM_BACKLIGHT,
@@ -352,6 +368,8 @@ enum BEAMS // beam[].flavour
BEAM_DISPEL_UNDEAD, // YELLOW
BEAM_DISINTEGRATION, // WHITE
BEAM_ENSLAVE_DEMON, // colour "16"
+ BEAM_BLINK,
+ BEAM_PETRIFY,
// new beams for evaporate
BEAM_POTION_STINKING_CLOUD,
@@ -363,10 +381,12 @@ enum BEAMS // beam[].flavour
BEAM_POTION_BLACK_SMOKE,
BEAM_POTION_BLUE_SMOKE,
BEAM_POTION_PURP_SMOKE,
- BEAM_POTION_RANDOM
+ BEAM_POTION_RANDOM,
+
+ BEAM_LINE_OF_SIGHT // only used for checking monster LOS
};
-enum BOOKS
+enum book_type
{
BOOK_MINOR_MAGIC_I, // 0
BOOK_MINOR_MAGIC_II,
@@ -419,7 +439,7 @@ enum BOOKS
NUM_BOOKS
};
-enum BRANCHES // you.where_are_you
+enum branch_type // you.where_are_you
{
BRANCH_MAIN_DUNGEON, // 0
BRANCH_DIS,
@@ -441,10 +461,11 @@ enum BRANCHES // you.where_are_you
BRANCH_SNAKE_PIT,
BRANCH_ELVEN_HALLS, // 20
BRANCH_TOMB,
- BRANCH_SWAMP
+ BRANCH_SWAMP,
+ BRANCH_CAVERNS
};
-enum BRANCH_STAIRS // you.branch_stairs[] - 10 less than BRANCHES {dlb}
+enum branch_stair_type // you.branch_stairs[] - 10 less than BRANCHES {dlb}
{
STAIRS_ORCISH_MINES, // 0
STAIRS_HIVE,
@@ -458,17 +479,18 @@ enum BRANCH_STAIRS // you.branch_stairs[] - 10 less than BRANCHES {dlb}
STAIRS_SNAKE_PIT,
STAIRS_ELVEN_HALLS, // 10
STAIRS_TOMB,
- STAIRS_SWAMP
+ STAIRS_SWAMP,
+ STAIRS_CAVERNS
};
-enum BURDEN_STATES // you.burden_state
+enum burden_state_type // you.burden_state
{
BS_UNENCUMBERED, // 0
BS_ENCUMBERED = 2, // 2
BS_OVERLOADED = 5 // 5
};
-enum CANNED_MESSAGES // canned_msg() - unsigned char
+enum canned_message_type // canned_msg() - unsigned char
{
MSG_SOMETHING_APPEARS, // 0
MSG_NOTHING_HAPPENS,
@@ -480,10 +502,22 @@ enum CANNED_MESSAGES // canned_msg() - unsigned char
MSG_UNTHINKING_ACT,
MSG_SPELL_FIZZLES,
MSG_HUH,
- MSG_EMPTY_HANDED
+ MSG_EMPTY_HANDED,
+ MSG_NOT_IN_PRESENT_FORM,
+ MSG_TOO_CONFUSED,
+ MSG_DISORIENTED,
+ MSG_CANT_REACH
};
-enum CLOUD_TYPES // cloud_type[], place_cloud(), big_cloud()
+enum char_set_type
+{
+ CSET_ASCII, // flat 7-bit ASCII
+ CSET_IBM, // 8-bit ANSI/Code Page 437
+ CSET_DEC, // 8-bit DEC, 0xE0-0xFF shifted for line drawing chars
+ NUM_CSET
+};
+
+enum cloud_type
{
CLOUD_NONE, // 0
CLOUD_FIRE, // 1
@@ -496,6 +530,7 @@ enum CLOUD_TYPES // cloud_type[], place_cloud(), big_cloud()
CLOUD_STEAM, // 8
CLOUD_MIASMA = 9, // 9: found 11jan2000 {dlb}
CLOUD_BLACK_SMOKE = 10, //was: CLOUD_STICKY_FLAME and wrong 19jan2000 {dlb}
+ CLOUD_RANDOM = 98,
CLOUD_DEBUGGING = 99, // 99: used once as 'nonexistent cloud' {dlb}
// if env.cloud_type > 100, it is a monster's cloud {dlb}
CLOUD_FIRE_MON = 101, // 101: found 11jan2000 {dlb}
@@ -510,7 +545,7 @@ enum CLOUD_TYPES // cloud_type[], place_cloud(), big_cloud()
CLOUD_BLACK_SMOKE_MON = 110 // 110: added 19jan2000 {dlb}
};
-enum COMMANDS
+enum command_type
{
CMD_NO_CMD = 1000, // 1000
CMD_MOVE_NOWHERE,
@@ -589,14 +624,12 @@ enum COMMANDS
CMD_REPLAY_MESSAGES,
CMD_REDRAW_SCREEN,
CMD_MACRO_ADD,
- CMD_MACRO_SAVE,
CMD_SAVE_GAME,
CMD_SAVE_GAME_NOW,
- CMD_SUSPEND_GAME, // 1000 + 80
- CMD_QUIT,
+ CMD_SUSPEND_GAME,
+ CMD_QUIT, // 1000 + 80
CMD_WIZARD,
CMD_DESTROY_ITEM,
- CMD_OBSOLETE_INVOKE,
CMD_MARK_STASH,
CMD_FORGET_STASH,
@@ -605,17 +638,133 @@ enum COMMANDS
CMD_INTERLEVEL_TRAVEL,
CMD_FIX_WAYPOINT,
- CMD_CLEAR_MAP
-};
-
-enum CONFIRM_LEVEL
+ CMD_CLEAR_MAP,
+ CMD_INSCRIBE_ITEM,
+ CMD_TOGGLE_NOFIZZLE,
+ CMD_TOGGLE_AUTOPRAYER,
+ CMD_MAKE_NOTE,
+ CMD_RESISTS_SCREEN,
+
+ /* overmap commands */
+ CMD_MAP_CLEAR_MAP,
+ CMD_MAP_ADD_WAYPOINT,
+ CMD_MAP_EXCLUDE_AREA,
+ CMD_MAP_CLEAR_EXCLUDES,
+
+ CMD_MAP_MOVE_LEFT,
+ CMD_MAP_MOVE_DOWN,
+ CMD_MAP_MOVE_UP,
+ CMD_MAP_MOVE_RIGHT,
+ CMD_MAP_MOVE_UP_LEFT,
+ CMD_MAP_MOVE_DOWN_LEFT,
+ CMD_MAP_MOVE_UP_RIGHT,
+ CMD_MAP_MOVE_DOWN_RIGHT,
+
+ CMD_MAP_JUMP_LEFT,
+ CMD_MAP_JUMP_DOWN,
+ CMD_MAP_JUMP_UP,
+ CMD_MAP_JUMP_RIGHT,
+ CMD_MAP_JUMP_UP_LEFT,
+ CMD_MAP_JUMP_DOWN_LEFT,
+ CMD_MAP_JUMP_UP_RIGHT,
+ CMD_MAP_JUMP_DOWN_RIGHT,
+
+ CMD_MAP_SCROLL_DOWN,
+ CMD_MAP_SCROLL_UP,
+
+ CMD_MAP_FIND_UPSTAIR,
+ CMD_MAP_FIND_DOWNSTAIR,
+ CMD_MAP_FIND_YOU,
+ CMD_MAP_FIND_PORTAL,
+ CMD_MAP_FIND_TRAP,
+ CMD_MAP_FIND_ALTAR,
+ CMD_MAP_FIND_EXCLUDED,
+ CMD_MAP_FIND_F,
+ CMD_MAP_FIND_WAYPOINT,
+ CMD_MAP_FIND_STASH,
+
+ CMD_MAP_GOTO_TARGET,
+
+ CMD_MAP_EXIT_MAP,
+
+ /* targeting commands */
+ CMD_TARGET_DOWN_LEFT,
+ CMD_TARGET_DOWN,
+ CMD_TARGET_DOWN_RIGHT,
+ CMD_TARGET_LEFT,
+ CMD_TARGET_RIGHT,
+ CMD_TARGET_UP_LEFT,
+ CMD_TARGET_UP,
+ CMD_TARGET_UP_RIGHT,
+ CMD_TARGET_CYCLE_TARGET_MODE,
+ CMD_TARGET_PREV_TARGET,
+ CMD_TARGET_SELECT,
+ CMD_TARGET_OBJ_CYCLE_BACK,
+ CMD_TARGET_OBJ_CYCLE_FORWARD,
+ CMD_TARGET_CYCLE_FORWARD,
+ CMD_TARGET_CYCLE_BACK,
+ CMD_TARGET_CENTER,
+ CMD_TARGET_CANCEL,
+ CMD_TARGET_OLD_SPACE,
+ CMD_TARGET_FIND_TRAP,
+ CMD_TARGET_FIND_PORTAL,
+ CMD_TARGET_FIND_ALTAR,
+ CMD_TARGET_FIND_UPSTAIR,
+ CMD_TARGET_FIND_DOWNSTAIR,
+ CMD_TARGET_FIND_YOU,
+ CMD_TARGET_DESCRIBE,
+
+ // [ds] Silently ignored, requests another round of input.
+ CMD_NEXT_CMD
+
+};
+
+enum confirm_level_type
{
CONFIRM_NONE_EASY,
CONFIRM_SAFE_EASY,
CONFIRM_ALL_EASY
};
-enum CORPSE_EFFECTS
+enum conduct_type
+{
+ DID_NECROMANCY = 1, // vamp/drain/pain wpns, Zong/Curses
+ DID_UNHOLY, // demon wpns, demon spells
+ DID_ATTACK_HOLY,
+ DID_ATTACK_FRIEND,
+ DID_FRIEND_DIES,
+ DID_STABBING,
+ DID_POISON,
+ DID_DEDICATED_BUTCHERY,
+ DID_DEDICATED_KILL_LIVING,
+ DID_DEDICATED_KILL_UNDEAD,
+ DID_DEDICATED_KILL_DEMON,
+ DID_DEDICATED_KILL_NATURAL_EVIL, // unused
+ DID_DEDICATED_KILL_WIZARD,
+ DID_DEDICATED_KILL_PRIEST, // unused
+
+ // [dshaligram] No distinction between killing Angels during prayer or
+ // otherwise, borrowed from bwr 4.1.
+ DID_KILL_ANGEL,
+ DID_LIVING_KILLED_BY_UNDEAD_SLAVE,
+ DID_LIVING_KILLED_BY_SERVANT,
+ DID_UNDEAD_KILLED_BY_SERVANT,
+ DID_DEMON_KILLED_BY_SERVANT,
+ DID_NATURAL_EVIL_KILLED_BY_SERVANT, // unused
+ DID_ANGEL_KILLED_BY_SERVANT,
+ DID_SPELL_MEMORISE,
+ DID_SPELL_CASTING,
+ DID_SPELL_PRACTISE,
+ DID_SPELL_NONUTILITY, // unused
+ DID_CARDS,
+ DID_STIMULANTS, // unused
+ DID_EAT_MEAT, // unused
+ DID_CREATED_LIFE, // unused
+
+ NUM_CONDUCTS
+};
+
+enum corpse_effect_type
{
CE_NOCORPSE, // 0
CE_CLEAN, // 1
@@ -629,13 +778,13 @@ enum CORPSE_EFFECTS
CE_ROTTEN = 50 // 50 - must remain at 50 for now {dlb}
};
-enum CORPSES
+enum corpse_type
{
CORPSE_BODY, // 0
CORPSE_SKELETON
};
-enum DEATH_KNIGHT_CHOICES
+enum death_knight_type
{
DK_NO_SELECTION,
DK_NECROMANCY,
@@ -643,7 +792,16 @@ enum DEATH_KNIGHT_CHOICES
DK_RANDOM
};
-enum DECKS
+enum startup_book_type
+{
+ SBT_NO_SELECTION = 0,
+ SBT_FIRE,
+ SBT_COLD,
+ SBT_SUMM,
+ SBT_RANDOM
+};
+
+enum deck_type
{
DECK_OF_WONDERS, // 0
DECK_OF_SUMMONING,
@@ -652,25 +810,40 @@ enum DECKS
DECK_OF_PUNISHMENT
};
-enum DELAY
+// When adding new delays, update their names in delay.cc, or bad things will
+// happen.
+enum delay_type
{
DELAY_NOT_DELAYED,
DELAY_EAT,
DELAY_ARMOUR_ON,
DELAY_ARMOUR_OFF,
- DELAY_MEMORIZE,
+ DELAY_JEWELLERY_ON,
+ DELAY_MEMORISE,
DELAY_BUTCHER,
DELAY_AUTOPICKUP,
DELAY_WEAPON_SWAP, // for easy_butcher
DELAY_PASSWALL,
DELAY_DROP_ITEM,
+ DELAY_MULTIDROP,
DELAY_ASCENDING_STAIRS,
DELAY_DESCENDING_STAIRS,
- DELAY_INTERUPTABLE = 100, // simple interuptable delay
- DELAY_UNINTERUPTABLE // simple uninteruptable delay
+
+ // [dshaligram] Shift-running, resting, travel and macros are now
+ // also handled as delays.
+ DELAY_RUN,
+ DELAY_REST,
+ DELAY_TRAVEL,
+
+ DELAY_MACRO,
+
+ DELAY_INTERRUPTIBLE, // simple interruptible delay
+ DELAY_UNINTERRUPTIBLE, // simple uninterruptible delay
+
+ NUM_DELAYS
};
-enum DEMON_BEAMS
+enum demon_beam_type
{
DMNBM_HELLFIRE, // 0
DMNBM_SMITING,
@@ -678,14 +851,15 @@ enum DEMON_BEAMS
DMNBM_MUTATION
};
-enum DEMON_CLASSES // summon_any_demon()
+enum demon_class_type
{
DEMON_LESSER, // 0: Class V
DEMON_COMMON, // 1: Class II-IV
- DEMON_GREATER // 2: Class I
+ DEMON_GREATER, // 2: Class I
+ DEMON_RANDOM // any of the above
};
-enum DESCRIPTION_LEVEL
+enum description_level_type
{
DESC_CAP_THE, // 0
DESC_NOCAP_THE, // 1
@@ -699,19 +873,71 @@ enum DESCRIPTION_LEVEL
DESC_INVENTORY // 8
};
-enum DIRECTION // (unsigned char) you.char_direction
+enum dragon_class_type
+{
+ DRAGON_LIZARD,
+ DRAGON_DRACONIAN,
+ DRAGON_DRAGON
+};
+
+enum game_direction_type
{
DIR_DESCENDING = 0, // 0 - change and lose savefile compatibility (!!!)
DIR_ASCENDING = 1 // 1 - change and lose savefile compatibility (!!!)
};
-enum DROP_MODE
+// NOTE: The order of these is very important to their usage!
+// [dshaligram] If adding/removing from this list, also update view.cc!
+enum dungeon_char_type
+{
+ DCHAR_WALL, // 0
+ DCHAR_WALL_MAGIC,
+ DCHAR_FLOOR,
+ DCHAR_FLOOR_MAGIC,
+ DCHAR_DOOR_OPEN,
+ DCHAR_DOOR_CLOSED, // 5
+ DCHAR_TRAP,
+ DCHAR_STAIRS_DOWN,
+ DCHAR_STAIRS_UP,
+ DCHAR_ALTAR,
+ DCHAR_ARCH, // 10
+ DCHAR_FOUNTAIN,
+ DCHAR_WAVY,
+ DCHAR_STATUE,
+ DCHAR_INVIS_EXPOSED,
+ DCHAR_ITEM_DETECTED, // 15
+ DCHAR_ITEM_ORB,
+ DCHAR_ITEM_WEAPON,
+ DCHAR_ITEM_ARMOUR,
+ DCHAR_ITEM_WAND,
+ DCHAR_ITEM_FOOD, // 20
+ DCHAR_ITEM_SCROLL,
+ DCHAR_ITEM_RING,
+ DCHAR_ITEM_POTION,
+ DCHAR_ITEM_MISSILE,
+ DCHAR_ITEM_BOOK, // 25
+ DCHAR_ITEM_STAVE,
+ DCHAR_ITEM_MISCELLANY,
+ DCHAR_ITEM_CORPSE,
+ DCHAR_ITEM_GOLD,
+ DCHAR_ITEM_AMULET, // 30
+ DCHAR_CLOUD, // 31
+ NUM_DCHAR_TYPES
+};
+
+enum drop_mode_type
{
DM_SINGLE,
DM_MULTI
};
-enum DUNGEON_FEATURES // (unsigned char) grd[][]
+// lowest grid value which can be occupied (walk, swim, fly)
+#define MINMOVE 31
+
+// lowest grid value which can be seen through
+#define MINSEE 11
+
+enum dungeon_feature_type
{
DNGN_UNSEEN, // 0
DNGN_ROCK_WALL,
@@ -723,14 +949,12 @@ enum DUNGEON_FEATURES // (unsigned char) grd[][]
DNGN_ORCISH_IDOL,
DNGN_WAX_WALL, // 8
DNGN_PERMAROCK_WALL, // 9 - for undiggable walls
- DNGN_LAST_SOLID_TILE = 10, // 10 - just here temporarily {dlb}
- DNGN_LAVA_X = 11, // 11
- DNGN_WATER_X, // 12
DNGN_SILVER_STATUE = 21, // 21
DNGN_GRANITE_STATUE,
DNGN_ORANGE_CRYSTAL_STATUE, // 23
- DNGN_STATUE_39 = 39, // 39
+ DNGN_STATUE_RESERVED_1,
+ DNGN_STATUE_RESERVED_2, // 25
DNGN_LAVA = 61, // 61
DNGN_DEEP_WATER, // 62
@@ -738,9 +962,10 @@ enum DUNGEON_FEATURES // (unsigned char) grd[][]
DNGN_WATER_STUCK,
DNGN_FLOOR, // 67
- DNGN_ENTER_HELL = 69, // 69
+ DNGN_EXIT_HELL, // 68
+ DNGN_ENTER_HELL, // 69
DNGN_OPEN_DOOR, // 70
- DNGN_BRANCH_STAIRS, // 71
+ // DNGN_BRANCH_STAIRS, // 71
DNGN_TRAP_MECHANICAL = 75, // 75
DNGN_TRAP_MAGICAL,
DNGN_TRAP_III,
@@ -786,6 +1011,10 @@ enum DUNGEON_FEATURES // (unsigned char) grd[][]
DNGN_ENTER_ELVEN_HALLS, // 120
DNGN_ENTER_TOMB,
DNGN_ENTER_SWAMP, // 122
+ DNGN_ENTER_RESERVED_1,
+ DNGN_ENTER_RESERVED_2,
+ DNGN_ENTER_RESERVED_3,
+ DNGN_ENTER_RESERVED_4, // 126
DNGN_RETURN_FROM_ORCISH_MINES = 130, // 130
DNGN_RETURN_FROM_HIVE,
@@ -800,6 +1029,10 @@ enum DUNGEON_FEATURES // (unsigned char) grd[][]
DNGN_RETURN_FROM_ELVEN_HALLS, // 140
DNGN_RETURN_FROM_TOMB,
DNGN_RETURN_FROM_SWAMP, // 142
+ DNGN_RETURN_RESERVED_1,
+ DNGN_RETURN_RESERVED_2,
+ DNGN_RETURN_RESERVED_3,
+ DNGN_RETURN_RESERVED_4, // 146
DNGN_ALTAR_ZIN = 180, // 180
DNGN_ALTAR_SHINING_ONE,
@@ -824,10 +1057,41 @@ enum DUNGEON_FEATURES // (unsigned char) grd[][]
DNGN_DRY_FOUNTAIN_VI,
DNGN_DRY_FOUNTAIN_VII,
DNGN_DRY_FOUNTAIN_VIII,
- DNGN_PERMADRY_FOUNTAIN = 210 // added (from dungeon.cc/maps.cc) 22jan2000 {dlb}
-};
-
-enum DURATIONS // you.duration[]
+ DNGN_PERMADRY_FOUNTAIN = 210, // added (from dungeon.cc/maps.cc) 22jan2000 {dlb}
+
+ // Real terrain must all occur before 256 to guarantee it fits
+ // into the unsigned char used for the grid!
+
+ // There aren't really terrain, but they're passed in and used
+ // to get their appearance character so I'm putting them here for now.
+ DNGN_ITEM_ORB = 256,
+ DNGN_INVIS_EXPOSED = 257,
+ DNGN_ITEM_WEAPON = 258,
+ DNGN_ITEM_ARMOUR = 259,
+ DNGN_ITEM_WAND = 260,
+ DNGN_ITEM_FOOD = 261,
+ DNGN_ITEM_UNUSED_1 = 262,
+ DNGN_ITEM_SCROLL = 263,
+ DNGN_ITEM_RING = 264,
+ DNGN_ITEM_POTION = 265,
+ DNGN_ITEM_MISSILE = 266,
+ DNGN_ITEM_BOOK = 267,
+ DNGN_ITEM_UNUSED_2 = 268,
+ DNGN_ITEM_STAVE = 269,
+ DNGN_ITEM_MISCELLANY = 270,
+ DNGN_ITEM_CORPSE = 271,
+ DNGN_ITEM_GOLD = 272,
+ DNGN_ITEM_AMULET = 273,
+ DNGN_ITEM_DETECTED = 274,
+
+ DNGN_CLOUD = 280,
+ NUM_FEATURES, // for use in lookup table in view.cc
+
+ DNGN_RANDOM,
+ DNGN_START_OF_MONSTERS = 297 // don't go past here! see view.cc
+};
+
+enum duration_type
{
DUR_LIQUID_FLAMES, // 0
DUR_ICY_ARMOUR,
@@ -850,18 +1114,54 @@ enum DURATIONS // you.duration[]
DUR_SEE_INVISIBLE,
DUR_WEAPON_BRAND, // general "branding" spell counter
DUR_SILENCE,
- DUR_GLAMOUR, // 20
- DUR_SHUGGOTH_SEED_RELOAD,
- DUR_INFECTED_SHUGGOTH_SEED,
- DUR_CONDENSATION_SHIELD, // 23
+ DUR_GLAMOUR, // 20
+ DUR_CONDENSATION_SHIELD = 23, // 23
DUR_STONESKIN,
- DUR_REPEL_UNDEAD, // 25
- DUR_LAST_DUR, //jmf: for asserts
- NUM_DURATIONS = 30
- // set at 30 to prevent savefile incompatibilities 12mar2000{dlb}
-};
-
-enum ENCHANTMENT // menv[].enchantment[]
+ DUR_REPEL_UNDEAD, // 25
+ DUR_STUN,
+ DUR_CUT, // 27
+ DUR_GOURMAND, // 28
+ NUM_DURATIONS = 30 // must be at least 30
+};
+
+// various elemental colour schemes... used for abstracting random short lists
+// MUST match the order in initfile.cc or breakage results.
+enum element_type
+{
+ EC_FIRE = 32, // fiery colours (must be first and > higest colour)
+ EC_ICE, // icy colours
+ EC_EARTH, // earthy colours
+ EC_ELECTRICITY, // electrical side of air
+ EC_AIR, // non-electric and general air magic
+ EC_POISON, // used only for venom mage and stalker stuff
+ EC_WATER, // used only for the elemental
+ EC_MAGIC, // general magical effect
+ EC_MUTAGENIC, // transmute, poly, radiation effects
+ EC_WARP, // teleportation and anything similar
+ EC_ENCHANT, // magical enhancements
+ EC_HEAL, // holy healing (not necromantic stuff)
+ EC_HOLY, // general "good" god effects
+ EC_DARK, // darkness
+ EC_DEATH, // currently only assassin (and equal to EC_NECRO)
+ EC_NECRO, // necromancy stuff
+ EC_UNHOLY, // demonology stuff
+ EC_VEHUMET, // vehumet's odd-ball colours
+ EC_CRYSTAL, // colours of crystal
+ EC_BLOOD, // colours of blood
+ EC_SMOKE, // colours of smoke
+ EC_SLIME, // colours of slime
+ EC_JEWEL, // colourful
+ EC_ELVEN, // used for colouring elf fabric items
+ EC_DWARVEN, // used for colouring dwarf fabric items
+ EC_ORCISH, // used for colouring orc fabric items
+ EC_GILA, // gila monster colours
+ EC_FLOOR, // colour of the area's floor
+ EC_ROCK, // colour of the area's rock
+ EC_STONE, // colour of the area's stone
+ EC_RANDOM // any colour (except BLACK)
+};
+
+enum enchant_type
{
ENCH_NONE = 0, // 0
ENCH_SLOW,
@@ -924,14 +1224,23 @@ enum ENCHANTMENT // menv[].enchantment[]
NUM_ENCHANTMENTS
};
-enum ENCHANT_STATS
+enum enchant_retval
+{
+ ERV_FAIL,
+ ERV_NEW,
+ ERV_INCREASED
+};
+
+enum enchant_stat_type
{
ENCHANT_TO_HIT,
ENCHANT_TO_DAM
};
-enum EQUIPMENT
+enum equipment_type
{
+ EQ_NONE = -1,
+
EQ_WEAPON, // 0
EQ_CLOAK,
EQ_HELMET,
@@ -952,7 +1261,7 @@ enum EQUIPMENT
EQ_ALL_ARMOUR // check all armour types
};
-enum FIRE_TYPES
+enum fire_type
{
FIRE_NONE,
FIRE_LAUNCHER,
@@ -962,19 +1271,24 @@ enum FIRE_TYPES
FIRE_SPEAR,
FIRE_HAND_AXE,
FIRE_CLUB,
+ FIRE_ROCK,
NUM_FIRE_TYPES
};
-enum FLUSH_REASONS
+enum flush_reason_type
{
FLUSH_ON_FAILURE, // spell/ability failed to cast
FLUSH_BEFORE_COMMAND, // flush before getting a command
FLUSH_ON_MESSAGE, // flush when printing a message
- FLUSH_LUA, // flush when Lua wants us to
+ FLUSH_ON_WARNING_MESSAGE, // flush on MSGCH_WARN messages
+ FLUSH_ON_DANGER_MESSAGE, // flush on MSGCH_DANGER messages
+ FLUSH_ON_PROMPT, // flush on MSGCH_PROMPT messages
+ FLUSH_ON_UNSAFE_YES_OR_NO_PROMPT, // flush when !safe set to yesno()
+ FLUSH_LUA, // flush when Lua wants to flush
NUM_FLUSH_REASONS
};
-enum FOODS // mitm[].sub_type[]
+enum food_type
{
FOOD_MEAT_RATION, // 0
FOOD_BREAD_RATION,
@@ -1001,21 +1315,21 @@ enum FOODS // mitm[].sub_type[]
NUM_FOODS
};
-enum GENUS_PLAYER // see player::player_genus()
+enum genus_type
{
GENPC_DRACONIAN, // 0
GENPC_ELVEN, // 1
GENPC_DWARVEN // 2
};
-enum GENDER
+enum gender_type
{
GENDER_NEUTER,
GENDER_MALE,
GENDER_FEMALE
};
-enum GHOST_VALUES
+enum ghost_value_type
{
GVAL_MAX_HP, // 0
GVAL_EV,
@@ -1047,9 +1361,9 @@ enum GHOST_VALUES
GVAL_DEMONLORD_CYCLE_COLOUR // 13
};
-enum GODS // you.religion
+enum god_type
{
- GOD_NO_GOD, // 0
+ GOD_NO_GOD, // 0 -- must be zero
GOD_ZIN,
GOD_SHINING_ONE,
GOD_KIKUBAAQUDGHA,
@@ -1067,35 +1381,16 @@ enum GODS // you.religion
GOD_RANDOM = 100
};
-enum GOOD_THINGS
+enum hands_reqd_type
{
- GOOD_KILLED_LIVING = 1, // 1 - killed a living monster in god's name
- GOOD_KILLED_UNDEAD, // 2 - killed an undead in god's name
- GOOD_KILLED_DEMON, // 3 - killed a demon in god's name
- GOOD_KILLED_ANGEL_I, // 4 - killed an angel (any time)
- GOOD_KILLED_ANGEL_II, // 5 - killed an angel in god's name
- // (all above pass HD of monster as pgain)
- GOOD_HACKED_CORPSE, // 6 - hacked up a corpse in god's name
- GOOD_OFFER_STUFF, // 7 - offered inanimate stuff at an altar
- GOOD_OFFER_CORPSE, // as above,including at least one corpse
- GOOD_SLAVES_KILL_LIVING,// 9 - undead slaves killed a living thing
- GOOD_SERVANTS_KILL, // 10 - any servants kill anything
- GOOD_CARDS, // 11 - cards (Nemelex)
- GOOD_KILLED_WIZARD,
- GOOD_KILLED_PRIEST,
- GOOD_POISON,
- GOOD_ATTACKED_FRIEND,
- NUM_GOOD_THINGS
-};
+ HANDS_ONE,
+ HANDS_HALF,
+ HANDS_TWO,
-enum HANDS_REQUIRED
-{
- HANDS_ONE_HANDED = 1, // 1
- HANDS_TWO_HANDED,
- HANDS_ONE_OR_TWO_HANDED
+ HANDS_DOUBLE // not a level, marks double ended weapons (== half)
};
-enum HELMET_TYPES // used in pluses2
+enum helmet_type
{
THELM_HELMET = 0x0000,
THELM_HELM = 0x0001,
@@ -1106,7 +1401,6 @@ enum HELMET_TYPES // used in pluses2
THELM_SPECIAL = 0x0004, // type used only for artefacts (mask, hat)
THELM_TYPE_MASK = 0x00ff,
-
THELM_DESC_PLAIN = 0x0000,
THELM_DESC_WINGED = 0x0100,
THELM_DESC_HORNED = 0x0200,
@@ -1119,30 +1413,8 @@ enum HELMET_TYPES // used in pluses2
THELM_DESC_MASK = 0xff00
};
-#if 0
-enum HELMET_DESCRIPTIONS
-{
- DHELM_WINGED = 1, // 1
- DHELM_HORNED,
- DHELM_CRESTED,
- DHELM_PLUMED,
- DHELM_SPIKED, // 5
- DHELM_VISORED,
- DHELM_JEWELLED
-};
-
-enum HELMET_TYPES // used in pluses2
-{
- THELM_HELMET = 0,
- THELM_HELM,
- THELM_CAP,
- THELM_WIZARD_HAT,
- NUM_HELMET_TYPES,
- THELM_SPECIAL // type used only for artefacts (mask, hat)
-};
-#endif
-enum BOOT_TYPES // used in pluses2
+enum boot_type // used in pluses2
{
TBOOT_BOOTS = 0,
TBOOT_NAGA_BARDING,
@@ -1151,7 +1423,7 @@ enum BOOT_TYPES // used in pluses2
};
-enum HUNGER_STATES // you.hunger_state
+enum hunger_state // you.hunger_state
{
HS_RAVENOUS, // 0: not used within code, really
HS_STARVING,
@@ -1161,7 +1433,7 @@ enum HUNGER_STATES // you.hunger_state
HS_ENGORGED // 5
};
-enum ITEM_STATUS_FLAGS // per item flags: ie. ident status, cursed status
+enum item_status_flag_type // per item flags: ie. ident status, cursed status
{
ISFLAG_KNOW_CURSE = 0x00000001, // curse status
ISFLAG_KNOW_TYPE = 0x00000002, // artefact name, sub/special types
@@ -1175,9 +1447,9 @@ enum ITEM_STATUS_FLAGS // per item flags: ie. ident status, cursed status
ISFLAG_EQ_JEWELLERY_MASK = 0x0000000F, // mask of flags for known jewellery
ISFLAG_CURSED = 0x00000100, // cursed
- ISFLAG_RESERVED_1 = 0x00000200, // reserved (re-curses on wield?)
- ISFLAG_RESERVED_2 = 0x00000400, // reserved (heavy cursed?)
- ISFLAG_RESERVED_3 = 0x00000800, // reserved (perma-cursed?)
+ ISFLAG_RESERVED_1 = 0x00000200, // reserved
+ ISFLAG_RESERVED_2 = 0x00000400, // reserved
+ ISFLAG_RESERVED_3 = 0x00000800, // reserved
ISFLAG_CURSE_MASK = 0x00000F00, // mask of all curse related flags
ISFLAG_RANDART = 0x00001000, // special value is seed
@@ -1186,6 +1458,7 @@ enum ITEM_STATUS_FLAGS // per item flags: ie. ident status, cursed status
ISFLAG_DROPPED = 0x00004000, // dropped item (no autopickup)
ISFLAG_THROWN = 0x00008000, // thrown missile weapon
+ // these don't have to remain as flags
ISFLAG_NO_DESC = 0x00000000, // used for clearing these flags
ISFLAG_GLOWING = 0x00010000, // weapons or armour
ISFLAG_RUNED = 0x00020000, // weapons or armour
@@ -1201,16 +1474,17 @@ enum ITEM_STATUS_FLAGS // per item flags: ie. ident status, cursed status
ISFLAG_DEBUG_MARK = 0x80000000 // used for testing item structure
};
-enum ITEM_DESCRIPTIONS
+enum item_description_type
{
IDESC_WANDS,
IDESC_POTIONS,
IDESC_SCROLLS, // special field (like the others)
IDESC_RINGS,
- IDESC_SCROLLS_II // pluses field
+ IDESC_SCROLLS_II,
+ NUM_IDESC
};
-enum ITEM_MAKE_SPECIES // used only for race during creation
+enum item_make_species_type
{
MAKE_ITEM_ELVEN = 1,
MAKE_ITEM_DWARVEN = 2,
@@ -1220,7 +1494,7 @@ enum ITEM_MAKE_SPECIES // used only for race during creation
MAKE_ITEM_RANDOM_RACE = 250
};
-enum ITEM_ORIGIN_DUMP_SELECT
+enum item_origin_dump_selector
{
IODS_PRICE = 0, // Extra info is provided based on price
IODS_ARTIFACTS = 1, // Extra information on artifacts
@@ -1234,22 +1508,23 @@ enum ITEM_ORIGIN_DUMP_SELECT
IODS_EVERYTHING = 0xFF
};
-enum ITEM_TYPE_ID // used for first index of id[4][50]
+enum item_type_id_type
{
IDTYPE_WANDS = 0,
IDTYPE_SCROLLS,
IDTYPE_JEWELLERY,
- IDTYPE_POTIONS
+ IDTYPE_POTIONS,
+ NUM_IDTYPE
};
-enum ITEM_TYPE_ID_STATE // used for values in id[4][50]
+enum item_type_id_state_type // used for values in id[4][50]
{
ID_UNKNOWN_TYPE = 0,
ID_KNOWN_TYPE,
ID_TRIED_TYPE
};
-enum JEWELLERY
+enum jewellery_type
{
RING_REGENERATION, // 0
RING_PROTECTION,
@@ -1288,7 +1563,7 @@ enum JEWELLERY
NUM_JEWELLERY
};
-enum JOB
+enum job_type
{
JOB_FIGHTER, // 0
JOB_WIZARD,
@@ -1324,7 +1599,7 @@ enum JOB
JOB_UNKNOWN = 100
};
-enum KILLBY
+enum kill_method_type
{
KILLED_BY_MONSTER, // 0
KILLED_BY_POISON,
@@ -1352,14 +1627,17 @@ enum KILLBY
KILLED_BY_SPORE,
KILLED_BY_TSO_SMITING,
KILLED_BY_PETRIFICATION, // 25
- KILLED_BY_SHUGGOTH,
- KILLED_BY_SOMETHING,
+ KILLED_BY_SOMETHING = 27,
KILLED_BY_FALLING_DOWN_STAIRS,
KILLED_BY_ACID,
+ KILLED_BY_CURARE,
+ KILLED_BY_MELTING,
+ KILLED_BY_BLEEDING,
+
NUM_KILLBY
};
-enum KillCategory
+enum kill_category
{
KC_YOU,
KC_FRIENDLY,
@@ -1367,20 +1645,28 @@ enum KillCategory
KC_NCATEGORIES
};
-enum KILLER // monster_die(), thing_thrown
+enum killer_type // monster_die(), thing_thrown
{
KILL_YOU = 1, // 1
KILL_MON,
KILL_YOU_MISSILE,
KILL_MON_MISSILE,
KILL_MISC, // 5
- KILL_RESET // abjuration, etc.
+ KILL_RESET, // abjuration, etc.
+ KILL_DISMISSED // only on new game startup
};
#define YOU_KILL(x) ((x) == KILL_YOU || (x) == KILL_YOU_MISSILE)
#define MON_KILL(x) ((x) == KILL_MON || (x) == KILL_MON_MISSILE)
-enum LEVEL_TYPES // you.level_type
+enum launch_retval
+{
+ LRET_FUMBLED = 0, // must be left as 0
+ LRET_LAUNCHED,
+ LRET_THROWN
+};
+
+enum level_area_type // you.level_type
{
LEVEL_DUNGEON, // 0
LEVEL_LABYRINTH,
@@ -1388,48 +1674,67 @@ enum LEVEL_TYPES // you.level_type
LEVEL_PANDEMONIUM
};
-enum LOAD_MODE
+enum load_mode_type
{
LOAD_START_GAME,
LOAD_RESTART_GAME,
LOAD_ENTER_LEVEL
};
-enum MAP_SECTIONS // see maps.cc and dungeon.cc {dlb}
+// [dshaligram] Maps can be mirrored; for every orientation, there must be
+// a suitable mirror.
+enum map_section_type // see maps.cc and dungeon.cc {dlb}
{
+ MAP_NONE = -1,
MAP_NORTH = 1, // 1
- MAP_NORTHWEST,
+ MAP_SOUTH,
+ MAP_EAST,
+ MAP_WEST,
+ MAP_NORTHWEST, // 5
MAP_NORTHEAST,
MAP_SOUTHWEST,
- MAP_SOUTHEAST, // 5
- MAP_ENCOMPASS,
- MAP_NORTH_DIS
+ MAP_SOUTHEAST,
+ MAP_ENCOMPASS
+};
+
+enum menu_type
+{
+ MT_INVSELECT, // General - select single item
+ MT_INVLIST, // List inventory
+ MT_DROP
};
// if you mess with this list, you'll need to make changes in initfile.cc
-enum MESSAGE_CHANNEL
+// to message_channel_names, and probably also to message.cc to colour
+// everything properly
+enum msg_channel_type
{
MSGCH_PLAIN, // regular text
MSGCH_PROMPT, // various prompts
MSGCH_GOD, // god/religion (param is god)
+ MSGCH_PRAY, // praying messages (param is god)
MSGCH_DURATION, // effect down/warnings
MSGCH_DANGER, // serious life threats (ie very large HP attacks)
MSGCH_WARN, // much less serious threats
MSGCH_FOOD, // hunger notices
MSGCH_RECOVERY, // recovery from disease/stat/poison condition
+ MSGCH_SOUND, // messages about things the player hears
MSGCH_TALK, // monster talk (param is monster type)
MSGCH_INTRINSIC_GAIN, // player level/stat/species-power gains
MSGCH_MUTATION, // player gain/lose mutations
MSGCH_MONSTER_SPELL, // monsters casting spells
MSGCH_MONSTER_ENCHANT,// monsters enchantments up and down
MSGCH_MONSTER_DAMAGE, // monster damage reports (param is level)
+ MSGCH_MONSTER_TARGET, // message marking the monster as a target
MSGCH_ROTTEN_MEAT, // messages about chunks/corpses becoming rotten
MSGCH_EQUIPMENT, // equipment listing messages
- MSGCH_DIAGNOSTICS, // various diagnostic messages
+ MSGCH_FLOOR_ITEMS, // like equipment, but lists of floor items
+ MSGCH_MULTITURN_ACTION, // delayed action messages
+ MSGCH_DIAGNOSTICS, // various diagnostic messages
NUM_MESSAGE_CHANNELS // always last
};
-enum MESSAGE_COLOURS
+enum msg_colour_type
{
MSGCOL_BLACK = 0, // the order of these colours is important
MSGCOL_BLUE,
@@ -1452,7 +1757,7 @@ enum MESSAGE_COLOURS
MSGCOL_PLAIN // same as plain channel
};
-enum MISCELLANY // mitm[].sub_type
+enum misc_item_type
{
MISC_BOTTLED_EFREET, // 0
MISC_CRYSTAL_BALL_OF_SEEING,
@@ -1475,7 +1780,7 @@ enum MISCELLANY // mitm[].sub_type
NUM_MISCELLANY // mv: used for random generation
};
-enum MISSILES // (unsigned char)
+enum missile_type
{
MI_STONE, // 0
MI_ARROW,
@@ -1484,10 +1789,83 @@ enum MISSILES // (unsigned char)
MI_NEEDLE,
MI_LARGE_ROCK, //jmf: it'd be nice to move MI_LARGE_ROCK to DEBRIS_ROCK
NUM_MISSILES,
- MI_EGGPLANT
+ MI_NONE // was MI_EGGPLANT... used for launch type detection
+};
+
+// properties of the monster class (other than resists/vulnerabilities)
+enum mons_class_flags
+{
+ M_NO_FLAGS = 0,
+
+ M_SPELLCASTER = (1<< 0), // any non-physical-attack powers,
+ M_ACTUAL_SPELLS = (1<< 1), // monster is a wizard,
+ M_PRIEST = (1<< 2), // monster is a priest
+ M_FIGHTER = (1<< 3), // monster is skilled fighter
+
+ M_FLIES = (1<< 4), // will crash to ground if paralysed?
+ M_LEVITATE = (1<< 5), // ... but not if this is set
+ M_INVIS = (1<< 6), // is created invis
+ M_SEE_INVIS = (1<< 7), // can see invis
+ M_SPEAKS = (1<< 8), // uses talking code
+ M_CONFUSED = (1<< 9), // monster is perma-confused,
+ M_BATTY = (1<<10), // monster is batty
+ M_SPLITS = (1<<11), // monster can split
+ M_AMPHIBIOUS = (1<<12), // monster can swim in water,
+ M_THICK_SKIN = (1<<13), // monster has more effective AC,
+ M_HUMANOID = (1<<14), // for Glamour
+ M_COLD_BLOOD = (1<<15), // susceptible to cold
+ M_WARM_BLOOD = (1<<16), // no effect currently
+ M_REGEN = (1<<17), // regenerates quickly
+ M_BURROWS = (1<<18), // monster digs through rock
+ M_EVIL = (1<<19), // monster vulnerable to holy spells
+
+ M_UNIQUE = (1<<20), // monster is a unique
+ M_FROZEN = (1<<21), // XXX: Potentially ditchable
+
+
+ M_SPECIAL_ABILITY = (1<<26), // XXX: eventually make these spells?
+ M_COLOUR_SHIFT = (1<<27), // flag for element colour shifters
+ M_DCHAR_SYMBOL = (1<<28), // monster looks like a DCHAR terrain
+
+ M_NO_SKELETON = (1<<29), // boneless corpses
+ M_NO_WOUNDS = (1<<30), // doesn't show would level
+ M_NO_EXP_GAIN = (1<<31) // worth 0 xp
+};
+
+enum mon_resist_flags
+{
+ MR_NO_FLAGS = 0,
+
+ // resistances
+ // Notes:
+ // - negative energy is mostly handled via mons_has_life_force()
+ // - acid is handled mostly by genus (jellies) plus non-living
+ // - asphyx-resistance replaces hellfrost resistance.
+ MR_RES_ELEC = (1<< 0),
+ MR_RES_POISON = (1<< 1),
+ MR_RES_FIRE = (1<< 2),
+ MR_RES_HELLFIRE = (1<< 3),
+ MR_RES_COLD = (1<< 4),
+ MR_RES_ASPHYX = (1<< 5),
+
+ // vulnerabilities
+ MR_VUL_ELEC = (1<< 6),
+ MR_VUL_POISON = (1<< 7),
+ MR_VUL_FIRE = (1<< 8),
+ MR_VUL_COLD = (1<< 9),
+
+ // melee armour resists/vulnerabilities
+ // XXX: how to do combos (bludgeon/slice, bludgeon/pierce)
+ MR_RES_PIERCE = (1<<10),
+ MR_RES_SLICE = (1<<11),
+ MR_RES_BLUDGEON = (1<<12),
+
+ MR_VUL_PIERCE = (1<<13),
+ MR_VUL_SLICE = (1<<14),
+ MR_VUL_BLUDGEON = (1<<15)
};
-enum MON_TARG_MODE
+enum targ_mode_type
{
TARG_ANY,
TARG_ENEMY,
@@ -1495,7 +1873,8 @@ enum MON_TARG_MODE
TARG_NUM_MODES
};
-enum MONSTERS // (int) menv[].type
+// note this order is very sensitive... look at mons_is_unique()
+enum monster_type // (int) menv[].type
{
MONS_GIANT_ANT, // 0
MONS_GIANT_BAT,
@@ -1662,6 +2041,7 @@ enum MONSTERS // (int) menv[].type
MONS_RED_WASP, // 170
MONS_SWAMP_DRAGON,
MONS_SWAMP_DRAKE,
+ MONS_DEATH_DRAKE,
MONS_SOLDIER_ANT,
MONS_HILL_GIANT,
MONS_QUEEN_ANT, // 175
@@ -1775,6 +2155,23 @@ enum MONSTERS // (int) menv[].type
MONS_BORIS, // 310
// BCR - end second batch of uniques.
+ MONS_DRACONIAN,
+ MONS_BLACK_DRACONIAN,
+ MONS_MOTTLED_DRACONIAN,
+ MONS_YELLOW_DRACONIAN,
+ MONS_GREEN_DRACONIAN, // 315
+ MONS_PURPLE_DRACONIAN,
+ MONS_RED_DRACONIAN,
+ MONS_WHITE_DRACONIAN,
+ MONS_PALE_DRACONIAN,
+ MONS_DRACONIAN_CALLER, // 320
+ MONS_DRACONIAN_MONK,
+ MONS_DRACONIAN_ZEALOT,
+ MONS_DRACONIAN_SHIFTER,
+ MONS_DRACONIAN_ANNIHILATOR,
+ MONS_DRACONIAN_KNIGHT, // 325
+ MONS_DRACONIAN_SCORCHER,
+
// The Lords of Hell:
MONS_GERYON = 340, // 340
MONS_DISPATER,
@@ -1848,57 +2245,62 @@ enum MONSTERS // (int) menv[].type
MONS_WATER_ELEMENTAL,
MONS_SWAMP_WORM, // 435
+ // Statuary
+ MONS_ORANGE_STATUE,
+ MONS_SILVER_STATUE,
+
NUM_MONSTERS, // used for polymorph
RANDOM_MONSTER = 1000, // used to distinguish between a random monster and using program bugs for error trapping {dlb}
WANDERING_MONSTER = 2500 // only used in monster placement routines - forced limit checks {dlb}
};
-enum MONSTER_BEHAVIOUR // create_monster()
+enum beh_type
{
BEH_SLEEP, // 0
BEH_WANDER,
BEH_SEEK,
BEH_FLEE,
BEH_CORNERED,
+ BEH_PANIC, // like flee but without running away
+ BEH_INVESTIGATE, // investigating an ME_DISTURB
NUM_BEHAVIOURS, // max # of legal states
BEH_CHARMED, // hostile-but-charmed; create only
BEH_FRIENDLY, // used during creation only
BEH_HOSTILE, // creation only
- BEH_GOD_GIFT // creation only
+ BEH_GOD_GIFT, // creation only
+ BEH_GUARD // creation only - monster is guard
};
-enum MONSTER_ATTITUDES
+enum mon_attitude_type
{
ATT_HOSTILE, // 0, default in most cases
ATT_FRIENDLY, // created friendly (or tamed?)
ATT_NEUTRAL
};
-enum MONSTER_EVENTS
+enum mon_event_type
{
ME_EVAL, // 0, evaluate monster AI state
ME_DISTURB, // noisy
ME_ANNOY, // annoy at range
ME_ALERT, // alert to presence
ME_WHACK, // physical attack
+ ME_SHOT, // attack at range
ME_SCARE, // frighten monster
ME_CORNERED // cannot flee
};
-#if 0
-// Obsolete... use mons_charclass()
-enum MONSTER_CATEGORIES
+enum mon_flight_type
{
- MC_MIMIC, // 0
- NUM_MC,
- MC_UNSPECIFIED = 255 // keep at end !!! mind the upper limit of 255 {dlb}
+ FLY_NOT,
+ FLY_POWERED, // wings, etc... paralysis == fall
+ FLY_LEVITATION // doesn't require physical effort
};
-#endif
// Note: These are currently stored in chars!!!
// Need to fix struct monsters and the savefile if you want more.
-enum MONSTER_FLAGS
+enum monster_flag_type
{
MF_CREATED_FRIENDLY = 0x01, // no benefit from killing
MF_GOD_GIFT = 0x02, // player not penalized by its death
@@ -1906,12 +2308,12 @@ enum MONSTER_FLAGS
MF_JUST_SUMMONED = 0x08, // monster skips next available action
MF_TAKING_STAIRS = 0x10, // is following player through stairs
- MF_UNUSED_I = 0x20,
- MF_UNUSED_II = 0x40,
- MF_UNUSED_III = 0x80
+ MF_INTERESTING = 0x20, // Player finds monster interesting
+ MF_SEEN = 0x40, // Player already seen monster
+ MF_UNUSED_I = 0x80
};
-enum MONSTER_DAMAGE
+enum mon_dam_level_type
{
MDAM_OKAY,
MDAM_LIGHTLY_DAMAGED,
@@ -1922,14 +2324,14 @@ enum MONSTER_DAMAGE
MDAM_DEAD
};
-enum MONSTER_DESCRIPTORS // things that cross categorical lines {dlb}
+enum mon_desc_type // things that cross categorical lines {dlb}
{
MDSC_LEAVES_HIDE, // 0
MDSC_REGENERATES,
MDSC_NOMSG_WOUNDS
};
-enum MONSTER_HOLINESS // matches (char) H_foo in mon-util.h, see: monster_holiness()
+enum mon_holy_type // matches (char) H_foo in mon-util.h, see: monster_holiness()
{
MH_HOLY, // 0 - was -1
MH_NATURAL, // 1 - was 0
@@ -1939,7 +2341,7 @@ enum MONSTER_HOLINESS // matches (char) H_foo in mon-util.h, see: monster_holine
MH_PLANT // plants
};
-enum MONSTER_INVENTORY_SLOTS // (int) menv[].inv[]
+enum mon_inv_type // (int) menv[].inv[]
{
MSLOT_WEAPON,
MSLOT_MISSILE, // although it is a second weapon for MONS_TWO_HEADED_OGRE - how to reconcile cleanly? {dlb}
@@ -1952,16 +2354,20 @@ enum MONSTER_INVENTORY_SLOTS // (int) menv[].inv[]
NUM_MONSTER_SLOTS = 8 // value must remain 8 for savefile compatibility {dlb}
};
-enum MONSTER_ITEM_USE
+// order of these is important:
+enum mon_itemuse_type
{
MONUSE_NOTHING,
MONUSE_EATS_ITEMS,
MONUSE_OPEN_DOORS,
MONUSE_STARTING_EQUIPMENT,
- MONUSE_WEAPONS_ARMOUR
+ MONUSE_WEAPONS_ARMOUR,
+ MONUSE_MAGIC_ITEMS
};
-enum MONSTER_SPELLS // mons_cast(), mspell_list[], mons_spells()
+// XXX: someday merge these into SPELL_
+// If changing this list, keep mon-util.cc spell names in sync.
+enum mon_spell_type
{
MS_MMISSILE, // 0
MS_FLAME,
@@ -2016,12 +2422,25 @@ enum MONSTER_SPELLS // mons_cast(), mspell_list[], mons_spells()
MS_METAL_SPLINTERS, // 50
MS_SUMMON_DEMON_GREATER, // [foo]_1 was confusing - renamed 13jan2000 {dlb}
MS_BANISHMENT,
+ MS_CONTROLLED_BLINK,
+ MS_CONTROL_UNDEAD,
+ MS_MIASMA, // 55
+ MS_SUMMON_LIZARDS,
+ MS_BLINK_OTHER,
+ MS_DISPEL_UNDEAD,
+ MS_HELLFROST,
+ MS_POISON_ARROW, // 60
+ MS_SUMMON_SMALL_MAMMALS,
+ MS_SUMMON_MUSHROOMS,
+ // XXX: before adding more monster versions of player spells we should
+ // consider merging the two lists into one and just having monsters
+ // fail to implement the ones that are impractical.
NUM_MONSTER_SPELLS,
MS_NO_SPELL = 100
};
// XXX: These still need to be applied in mon-data.h
-enum MONSTER_SPELL_TEMPLATES
+enum mon_spellbook_type
{
MST_ORC_WIZARD_I = 0,
MST_ORC_WIZARD_II,
@@ -2036,7 +2455,8 @@ enum MONSTER_SPELL_TEMPLATES
MST_VAMPIRE_KNIGHT,
MST_VAMPIRE_MAGE,
MST_EFREET = 50,
- MST_BRAIN_WORM = 52,
+ MST_KILLER_KLOWN,
+ MST_BRAIN_WORM,
MST_GIANT_ORANGE_BRAIN,
MST_RAKSHASA,
MST_GREAT_ORB_OF_EYES, // 55
@@ -2109,13 +2529,19 @@ enum MONSTER_SPELL_TEMPLATES
MST_BOGGART,
MST_EYE_OF_DEVASTATION, // 125
MST_QUICKSILVER_DRAGON,
- MST_IRON_DRAGON, // 127
+ MST_IRON_DRAGON,
MST_SKELETAL_WARRIOR,
+ MST_MYSTIC,
+ MST_DEATH_DRAKE, // 130
+ MST_DRAC_SCORCHER, // As Bioster would say.. pig*s
+ MST_DRAC_CALLER,
+ MST_DRAC_SHIFTER,
+ MST_CURSE_TOE,
NUM_MSTYPES,
MST_NO_SPELLS = 250
};
-enum MUTATIONS
+enum mutation_type
{
MUT_TOUGH_SKIN, // 0
MUT_STRONG,
@@ -2201,25 +2627,7 @@ enum MUTATIONS
NUM_MUTATIONS
};
-enum NAUGHTY_THINGS
-{
- NAUGHTY_NECROMANCY = 1, // 1 - using necromancy (spell or device)
- NAUGHTY_UNHOLY, // 2 - using unholy stuff (call imp, summon things)
- NAUGHTY_KILLING, // 3 - killing in the name of a peaceful deity
- NAUGHTY_ATTACK_HOLY, // 4 - attacking holy things
- NAUGHTY_ATTACK_FRIEND, // 5 - attacking friendly things
- NAUGHTY_FRIEND_DIES, // 6 - allowing friendly things to die
- NAUGHTY_BUTCHER, // 7 - butchering in the name of a peaceful deity
- NAUGHTY_STABBING, // 8 - stabbing
- NAUGHTY_SPELLCASTING, // 9 - spellcasting
- NAUGHTY_POISON, // 10 - poisoning
- NAUGHTY_STIMULANTS, //jmf: next three new, some not yet used
- NAUGHTY_ATE_MEAT,
- NAUGHTY_CREATED_LIFE,
- NUM_NAUGHTY_THINGS
-};
-
-enum OBJECT_CLASSES // (unsigned char) mitm[].base_type
+enum object_class_type // (unsigned char) mitm[].base_type
{
OBJ_WEAPONS, // 0
OBJ_MISSILES,
@@ -2244,18 +2652,86 @@ enum OBJECT_CLASSES // (unsigned char) mitm[].base_type
// for blanket random sub_type .. see dungeon::items()
};
-enum OBJECT_SELECTORS
+enum object_selector
{
OSEL_ANY = -1,
OSEL_WIELD = -2
};
-enum ORBS
+enum operation_types
+{
+ OPER_WIELD = 'w',
+ OPER_QUAFF = 'q',
+ OPER_DROP = 'd',
+ OPER_EAT = 'e',
+ OPER_TAKEOFF = 'T',
+ OPER_WEAR = 'W',
+ OPER_PUTON = 'P',
+ OPER_REMOVE = 'R',
+ OPER_READ = 'r',
+ OPER_MEMORISE = 'M',
+ OPER_ZAP = 'z',
+ OPER_THROW = 't',
+ OPER_EXAMINE = 'v',
+ OPER_ANY = 0
+};
+
+enum orb_type
{
ORB_ZOT // 0
};
-enum POTIONS
+enum player_size_type
+{
+ PSIZE_BODY, // entire body size -- used for EV/size of target
+ PSIZE_TORSO, // torso only (hybrids -- size of parts that use equip)
+ PSIZE_PROFILE // profile only (for stealth checks)
+};
+
+// [dshaligram] If you edit potion colours/descriptions, also update
+// itemname.cc.
+enum potion_description_colour_type
+{
+ PDC_CLEAR,
+ PDC_BLUE,
+ PDC_BLACK,
+ PDC_SILVERY,
+ PDC_CYAN,
+ PDC_PURPLE,
+ PDC_ORANGE,
+ PDC_INKY,
+ PDC_RED,
+ PDC_YELLOW,
+ PDC_GREEN,
+ PDC_BROWN,
+ PDC_PINK,
+ PDC_WHITE,
+ PDC_NCOLOURS
+};
+
+// [dshaligram] If you edit potion colours/descriptions, also update
+// itemname.cc.
+enum potion_description_qualifier_type
+{
+ PDQ_NONE,
+ PDQ_BUBBLING,
+ PDQ_FUMING,
+ PDQ_FIZZY,
+ PDQ_VISCOUS,
+ PDQ_LUMPY,
+ PDQ_SMOKY,
+ PDQ_GLOWING,
+ PDQ_SEDIMENTED,
+ PDQ_METALLIC,
+ PDQ_MURKY,
+ PDQ_GLUGGY,
+ PDQ_OILY,
+ PDQ_SLIMY,
+ PDQ_EMULSIFIED,
+ PDQ_NQUALS
+};
+
+enum potion_type
{
POT_HEALING, // 0
POT_HEAL_WOUNDS,
@@ -2284,7 +2760,7 @@ enum POTIONS
NUM_POTIONS
};
-enum PRONOUN_TYPE
+enum pronoun_type
{
PRONOUN_CAP, // 0
PRONOUN_NOCAP, // 1
@@ -2293,7 +2769,7 @@ enum PRONOUN_TYPE
PRONOUN_REFLEXIVE // 4 (reflexive is always lowercase)
};
-enum PROXIMITY // proximity to player to create monster
+enum proximity_type // proximity to player to create monster
{
PROX_ANYWHERE,
PROX_CLOSE_TO_PLAYER,
@@ -2301,7 +2777,7 @@ enum PROXIMITY // proximity to player to create monster
PROX_NEAR_STAIRS
};
-enum RANDART_PROP
+enum randart_prop_type
{
RAP_BRAND, // 0
RAP_AC,
@@ -2332,17 +2808,25 @@ enum RANDART_PROP
RAP_ACCURACY,
RAP_DAMAGE,
RAP_CURSED,
- RAP_STEALTH
+ RAP_STEALTH,
+ RAP_NUM_PROPERTIES
};
-enum READ_BOOK_ACTION
+enum read_book_action_type
{
RBOOK_USE_STAFF,
- RBOOK_MEMORIZE,
+ RBOOK_MEMORISE,
RBOOK_READ_SPELL
};
-enum RUN_DIR
+enum run_check_type
+{
+ RCHECK_LEFT,
+ RCHECK_FRONT,
+ RCHECK_RIGHT
+};
+
+enum run_dir_type
{
RDIR_UP = 0,
RDIR_UP_RIGHT,
@@ -2355,7 +2839,18 @@ enum RUN_DIR
RDIR_REST
};
-enum RUNE_TYPES
+enum run_mode_type
+{
+ RMODE_INTERLEVEL = -3, // Interlevel travel (Ctrl+G)
+ RMODE_EXPLORE = -2, // Exploring (Ctrl+O)
+ RMODE_TRAVEL = -1, // Classic or Plain Old travel
+ RMODE_NOT_RUNNING = 0, // must remain equal to 0
+ RMODE_CONTINUE,
+ RMODE_START,
+ RMODE_REST_DURATION = 100
+};
+
+enum rune_type
{
// Note: that runes DIS-SWAMP have the same numberic value as the branch
RUNE_DIS = 1,
@@ -2379,17 +2874,18 @@ enum RUNE_TYPES
RUNE_LOM_LOBON,
RUNE_CEREBOV,
RUNE_GLOORX_VLOQ,
- NUM_RUNE_TYPES // should always be last
+ NUM_RUNE_TYPES, // should always be last
+ RUNE_NONE
};
-enum SCORE_FORMAT
+enum score_format_type
{
SCORE_TERSE, // one line
SCORE_REGULAR, // two lines (name, cause, blank)
SCORE_VERBOSE // everything (dates, times, god, etc)
};
-enum SCROLLS
+enum scroll_type
{
SCR_IDENTIFY, // 0
SCR_TELEPORTATION,
@@ -2417,7 +2913,7 @@ enum SCROLLS
NUM_SCROLLS
};
-enum SHOPS // (unsigned char) env.sh_type[], item_in_shop(), in_a_shop()
+enum shop_type // (unsigned char) env.sh_type[], item_in_shop(), in_a_shop()
{
SHOP_WEAPON, // 0
SHOP_ARMOUR,
@@ -2436,7 +2932,47 @@ enum SHOPS // (unsigned char) env.sh_type[], item_in_shop(), in_a_shop()
SHOP_RANDOM = 255 // keep set at 255 for now {dlb}
};
-enum SKILLS
+enum shout_type
+{
+ S_SILENT, // silent
+ S_SHOUT, // shout
+ S_BARK, // bark
+ S_SHOUT2, // shout twice
+ S_ROAR, // roar
+ S_SCREAM, // scream
+ S_BELLOW, // bellow (?)
+ S_SCREECH, // screech
+ S_BUZZ, // buzz
+ S_MOAN, // moan
+ S_WHINE, // irritating whine (mosquito)
+ S_CROAK, // frog croak
+ S_GROWL, // for bears
+ S_HISS, // for snakes and lizards
+ NUM_SHOUTS,
+ S_RANDOM
+};
+
+// These are often addressed relative to each other (esp. delta SIZE_MEDIUM)
+enum size_type
+{
+ SIZE_TINY, // rat/bat
+ SIZE_LITTLE, // spriggan
+ SIZE_SMALL, // halfling/kobold/gnome
+ SIZE_MEDIUM, // human/elf/dwarf
+ SIZE_LARGE, // troll/ogre
+ SIZE_BIG, // centaur/naga/large quadrupeds
+ SIZE_GIANT, // giant
+ SIZE_HUGE, // dragon
+ NUM_SIZE_LEVELS,
+ SIZE_CHARACTER // transformations that don't change size
+};
+
+// [dshaligram] If you add a new skill, update skills2.cc, specifically
+// the skills[] array and skill_display_order[]. New skills must go at the
+// end of the list or in the unused skill numbers. NEVER rearrange this enum or
+// move existing skills to new numbers; save file compatibility depends on this
+// order.
+enum skill_type
{
SK_FIGHTING, // 0
SK_SHORT_BLADES,
@@ -2450,7 +2986,7 @@ enum SKILLS
SK_BOWS,
SK_CROSSBOWS, // 10
SK_DARTS,
- SK_THROWING,
+ SK_RANGED_COMBAT,
SK_ARMOUR,
SK_DODGING,
SK_STEALTH, // 15
@@ -2473,10 +3009,14 @@ enum SKILLS
SK_POISON_MAGIC,
SK_INVOCATIONS,
SK_EVOCATIONS,
- NUM_SKILLS // must remain last member {dlb}
+ NUM_SKILLS, // must remain last regular member
+
+ SK_BLANK_LINE, // used for skill output
+ SK_COLUMN_BREAK, // used for skill output
+ SK_NONE
};
-enum SPECIAL_ARMOR
+enum special_armour_type
{
SPARM_NORMAL, // 0
SPARM_RUNNING,
@@ -2504,32 +3044,42 @@ enum SPECIAL_ARMOR
SPARM_RANDART_V = 29 // 29 - highest value found thus far {dlb}
};
-enum SPECIAL_MISSILES // to separate from weapons in general {dlb}
+enum special_missile_type // to separate from weapons in general {dlb}
{
SPMSL_NORMAL, // 0
SPMSL_FLAME, // 1
SPMSL_ICE, // 2
SPMSL_POISONED, // 3 - from poison_ammo() enchantment {dlb}
- SPMSL_POISONED_II // 4
+ SPMSL_POISONED_II, // 4
+ SPMSL_CURARE // 5
};
-enum SPECIAL_ROOMS
+enum special_room_type
{
SROOM_LAIR_ORC, // 0
SROOM_LAIR_KOBOLD,
SROOM_TREASURY,
SROOM_BEEHIVE,
+ SROOM_JELLY_PIT,
SROOM_MORGUE,
NUM_SPECIAL_ROOMS // 5 - must remain final member {dlb}
};
-enum SPECIAL_RINGS // jewellery mitm[].special values
+enum special_ring_type // jewellery mitm[].special values
{
SPRING_RANDART = 200,
SPRING_UNRANDART = 201
};
-enum SPECIAL_WEAPONS // equivalent to (you.inv[].special or mitm[].special) % 30
+// order is important on these (see player_speed())
+enum speed_type
+{
+ SPEED_SLOWED,
+ SPEED_NORMAL,
+ SPEED_HASTED
+};
+
+enum brand_type // equivalent to (you.inv[].special or mitm[].special) % 30
{
SPWPN_NORMAL, // 0
SPWPN_FLAMING,
@@ -2579,7 +3129,7 @@ enum SPECIAL_WEAPONS // equivalent to (you.inv[].special or mitm[].special) % 30
SPWPN_STAFF_OF_WUCAD_MU // 195
};
-enum SPECIAL_WIELD // you.special_wield
+enum special_wield_type // you.special_wield
{
SPWLD_NONE, // 0
SPWLD_SING,
@@ -2599,7 +3149,7 @@ enum SPECIAL_WIELD // you.special_wield
SPWLD_SHOUT // 54 - see it_use3::special_wielded() {dlb}
};
-enum SPECIES
+enum species_type
{
SP_HUMAN = 1, // 1
SP_ELF,
@@ -2629,7 +3179,7 @@ enum SPECIES
SP_PALE_DRACONIAN,
SP_UNK0_DRACONIAN,
SP_UNK1_DRACONIAN,
- SP_UNK2_DRACONIAN,
+ SP_BASE_DRACONIAN,
SP_CENTAUR, // 30
SP_DEMIGOD,
SP_SPRIGGAN,
@@ -2643,7 +3193,7 @@ enum SPECIES
SP_UNKNOWN = 100
};
-enum SPELLS
+enum spell_type
{
SPELL_IDENTIFY, // 0
SPELL_TELEPORT_SELF,
@@ -2827,18 +3377,38 @@ enum SPELLS
SPELL_AIR_WALK, // "dematerialize" (air/transmigration)
SPELL_SANDBLAST, // mini-frag; can use stones for material comp 195
SPELL_ROTTING, // evil god power or necromantic transmigration
- SPELL_SHUGGOTH_SEED, // evil god power or necromantic summoning
SPELL_MAXWELLS_SILVER_HAMMER, // vorpal-brand maces etc.
SPELL_CONDENSATION_SHIELD, // "shield" of icy vapour
- SPELL_SEMI_CONTROLLED_BLINK, //jmf: to test effect 200
- SPELL_STONESKIN,
+ SPELL_SEMI_CONTROLLED_BLINK, //jmf: to test effect
+ SPELL_STONESKIN, // 200
SPELL_SIMULACRUM,
- SPELL_CONJURE_BALL_LIGHTNING, // 203 (be wary of 210, see below)
+ SPELL_CONJURE_BALL_LIGHTNING,
+ SPELL_CHAIN_LIGHTNING, // 203 (be wary of 209/210, see below)
NUM_SPELLS,
SPELL_NO_SPELL = 210 // 210 - added 22jan2000 {dlb}
};
-enum SPELL_TYPES //jmf: 24jul2000: changed from integer-list to bitfield
+enum spflag_type
+{
+ SPFLAG_NONE = 0x0000,
+ SPFLAG_DIR_OR_TARGET = 0x0001, // use DIR_NONE targeting
+ SPFLAG_TARGET = 0x0002, // use DIR_TARGET targeting
+ SPFLAG_GRID = 0x0004, // use DIR_GRID targeting
+ SPFLAG_DIR = 0x0008, // use DIR_DIR targeting
+ SPFLAG_TARGETING_MASK = 0x000f, // used to test for targeting
+ SPFLAG_HELPFUL = 0x0010, // TARG_FRIENDS used
+ SPFLAG_NOT_SELF = 0x0020, // aborts on isMe
+ SPFLAG_UNHOLY = 0x0040 // counts at "unholy"
+};
+
+enum spret_type
+{
+ SPRET_ABORT = 0, // should be left as 0
+ SPRET_FAIL,
+ SPRET_SUCCESS
+};
+
+enum spschool_flag_type
{
SPTYP_NONE = 0, // "0" is reserved for no type at all {dlb}
SPTYP_CONJURATION = 1, // was 11, but only for old typematch routine {dlb}
@@ -2859,13 +3429,13 @@ enum SPELL_TYPES //jmf: 24jul2000: changed from integer-list to bitfield
SPTYP_RANDOM = 1<<14
};
-enum SLOT_SELECT_MODES
+enum slot_select_mode
{
SS_FORWARD = 0,
SS_BACKWARD = 1
};
-enum STATS
+enum stat_type
{
STAT_STRENGTH, // 0
STAT_DEXTERITY,
@@ -2875,14 +3445,14 @@ enum STATS
STAT_RANDOM = 255 // leave at 255, added for increase_stats() handling {dlb}
};
-enum STATUE_TYPES
+enum statue_type
{
STATUE_SILVER,
STATUE_ORANGE_CRYSTAL,
NUM_STATUE_TYPES
};
-enum STATUS_REDRAW_FLAGS
+enum status_redraw_flag_type
{
REDRAW_HUNGER = 0x00000001,
REDRAW_BURDEN = 0x00000002,
@@ -2908,7 +3478,7 @@ enum STATUS_REDRAW_FLAGS
REDRAW_LINE_3_MASK = 0x007f0000
};
-enum STAVES
+enum stave_type
{
STAFF_WIZARDRY, // 0
STAFF_POWER,
@@ -2936,7 +3506,8 @@ enum STAVES
NUM_STAVES // must remain last member {dlb}
};
-enum SYMBOLS // beam[].type - note that this (and its variants) also accepts values from other enums - confusing {dlb}
+// beam[].type - note that this (and its variants) also accepts values from other enums - confusing {dlb}
+enum zap_symbol_type
{
SYM_SPACE = ' ', // 32
SYM_FLASK = '!', // 33
@@ -2951,10 +3522,11 @@ enum SYMBOLS // beam[].type - note that this (and its variants) also accepts val
SYM_SCROLL = '?', // 63
SYM_DEBUG = 'X', // 88
SYM_ARMOUR = '[', // 91
- SYM_MISSILE = '`' // 96
+ SYM_MISSILE = '`', // 96
+ SYM_EXPLOSION = '#'
};
-enum TAGS // used during save/load process to identify data blocks
+enum tag_type // used during save/load process to identify data blocks
{
TAG_VERSION = 0, // should NEVER be read in!
TAG_YOU = 1, // 'you' structure
@@ -2968,15 +3540,25 @@ enum TAGS // used during save/load process to identify data blocks
NUM_TAGS
};
-enum TAGTYPES // file types supported by tag system
+enum tag_file_type // file types supported by tag system
{
TAGTYPE_PLAYER=0, // Foo.sav
TAGTYPE_LEVEL, // Foo.00a, .01a, etc.
- TAGTYPE_GHOST // bones.xxx
+ TAGTYPE_GHOST, // bones.xxx
+
+ TAGTYPE_PLAYER_NAME // Used only to read the player name
};
+enum torment_source_type
+{
+ TORMENT_GENERIC = -1,
+ TORMENT_CARDS = -2, // Symbol of torment
+ TORMENT_SPWLD = -3, // Special wield torment
+ TORMENT_SCROLL = -4,
+ TORMENT_SPELL = -5 // SPELL_SYMBOL_OF_TORMENT
+};
-enum TRANSFORMATIONS
+enum transformation_type
{
TRAN_NONE, // 0
TRAN_SPIDER,
@@ -2990,7 +3572,7 @@ enum TRANSFORMATIONS
NUM_TRANSFORMATIONS // must remain last member {dlb}
};
-enum TRAPS // env.trap_type[]
+enum trap_type // env.trap_type[]
{
TRAP_DART, // 0
TRAP_ARROW,
@@ -3004,10 +3586,11 @@ enum TRAPS // env.trap_type[]
TRAP_NEEDLE,
NUM_TRAPS, // must remain last 'regular' member {dlb}
TRAP_UNASSIGNED = 100, // keep set at 100 for now {dlb}
+ TRAP_NONTELEPORT = 254,
TRAP_RANDOM = 255 // set at 255 to avoid potential conflicts {dlb}
};
-enum UNARMED_ATTACKS
+enum unarmed_attack_type
{
UNAT_NO_ATTACK, // 0
UNAT_KICK,
@@ -3016,31 +3599,150 @@ enum UNARMED_ATTACKS
UNAT_PUNCH
};
-enum UNDEAD_STATES // you.is_undead
+enum undead_state_type // you.is_undead
{
US_ALIVE, // 0
US_HUNGRY_DEAD,
US_UNDEAD
};
-enum UNIQUE_ITEM_STATUS
+enum unique_item_status_type
{
UNIQ_NOT_EXISTS = 0,
UNIQ_EXISTS = 1,
UNIQ_LOST_IN_ABYSS = 2
};
-enum VORPAL_DESCRIPTIONS
-{
- DVORP_CRUSHING, // 0
- DVORP_SLICING,
- DVORP_PIERCING,
- DVORP_CHOPPING
+// NOTE: THE ORDER AND VALUE OF THESE IS CURRENTLY VERY IMPORTANT!
+enum vault_type
+{
+ VAULT_VAULT_1 = 0,
+ VAULT_VAULT_2 = 1,
+ VAULT_VAULT_3 = 2,
+ VAULT_VAULT_4 = 3,
+ VAULT_VAULT_5 = 4,
+ VAULT_VAULT_6 = 5,
+ VAULT_VAULT_7 = 6,
+ VAULT_VAULT_8 = 7,
+ VAULT_VAULT_9 = 8,
+ VAULT_VAULT_10 = 9,
+ VAULT_ORC_TEMPLE = 10,
+ VAULT_FARM_AND_COUNTRY = 11,
+ VAULT_FORT_YAKTAUR = 12,
+ VAULT_BOX_LEVEL = 13,
+ VAULT_MY_MAP = 14,
+
+ VAULT_VESTIBULE_MAP = 50,
+ VAULT_CASTLE_DIS = 51,
+ VAULT_ASMODEUS = 52,
+ VAULT_ANTAEUS = 53,
+ VAULT_ERESHKIGAL = 54,
+
+ VAULT_MNOLEG = 60,
+ VAULT_LOM_LOBON = 61,
+ VAULT_CEREBOV = 62,
+ VAULT_GLOORX_VLOQ = 63,
+ // VAULT_MOLLUSC = 64,
+
+ VAULT_BEEHIVE = 80,
+ VAULT_SLIME_PIT = 81,
+ VAULT_BOTTOM_OF_VAULTS = 82,
+ VAULT_HALL_OF_BLADES = 83,
+ VAULT_HALL_OF_ZOT = 84,
+ VAULT_TEMPLE = 85,
+ VAULT_SNAKE_PIT = 86,
+ VAULT_ELF_HALL = 87,
+ VAULT_TOMB_1 = 88,
+ VAULT_TOMB_2 = 89,
+ VAULT_TOMB_3 = 90,
+ VAULT_SWAMP = 91,
+
+ VAULT_RANDOM = 100,
+
+ VAULT_MINIVAULT_1 = 200,
+ VAULT_MINIVAULT_2 = 201,
+ VAULT_MINIVAULT_3 = 202,
+ VAULT_MINIVAULT_4 = 203,
+ VAULT_MINIVAULT_5 = 204,
+ VAULT_MINIVAULT_6 = 205,
+ VAULT_MINIVAULT_7 = 206,
+ VAULT_MINIVAULT_8 = 207,
+ VAULT_MINIVAULT_9 = 208,
+ VAULT_MINIVAULT_10 = 209,
+ VAULT_MINIVAULT_11 = 210,
+ VAULT_MINIVAULT_12 = 211,
+ VAULT_MINIVAULT_13 = 212,
+ VAULT_MINIVAULT_14 = 213,
+ VAULT_MINIVAULT_15 = 214,
+ VAULT_MINIVAULT_16 = 215,
+ VAULT_MINIVAULT_17 = 216,
+ VAULT_MINIVAULT_18 = 217,
+ VAULT_MINIVAULT_19 = 218,
+ VAULT_MINIVAULT_20 = 219,
+ VAULT_MINIVAULT_21 = 220,
+ VAULT_MINIVAULT_22 = 221,
+ VAULT_MINIVAULT_23 = 222,
+ VAULT_MINIVAULT_24 = 223,
+ VAULT_MINIVAULT_25 = 224,
+ VAULT_MINIVAULT_26 = 225,
+ VAULT_MINIVAULT_27 = 226,
+ VAULT_MINIVAULT_28 = 227,
+ VAULT_MINIVAULT_29 = 228,
+ VAULT_MINIVAULT_30 = 229,
+ VAULT_MINIVAULT_31 = 230,
+ VAULT_MINIVAULT_32 = 231,
+ VAULT_MINIVAULT_33 = 232,
+ VAULT_MINIVAULT_34 = 233,
+ VAULT_MINIVAULT_35 = 234,
+
+ VAULT_RAND_DEMON_1 = 300,
+ VAULT_RAND_DEMON_2 = 301,
+ VAULT_RAND_DEMON_3 = 302,
+ VAULT_RAND_DEMON_4 = 303,
+ VAULT_RAND_DEMON_5 = 304,
+ VAULT_RAND_DEMON_6 = 305,
+ VAULT_RAND_DEMON_7 = 306,
+ VAULT_RAND_DEMON_8 = 307,
+ VAULT_RAND_DEMON_9 = 308
+};
+
+enum vorpal_damage_type
+{
+ // Types of damage a weapon can do... currently assuming that anything
+ // with BLUDGEON always does "AND" with any other specified types,
+ // and and sets not including BLUDGEON are "OR".
+ DAM_BASH = 0x0000, // non-melee weapon blugeoning
+ DAM_BLUDGEON = 0x0001, // crushing
+ DAM_SLICE = 0x0002, // slicing/chopping
+ DAM_PIERCE = 0x0004, // stabbing/piercing
+ DAM_WHIP = 0x0008, // whip slashing (no butcher)
+
+ // These are used for vorpal weapon desc (don't set more than one)
+ DVORP_NONE = 0x0000, // used for non-melee weapons
+ DVORP_CRUSHING = 0x1000,
+ DVORP_SLICING = 0x2000,
+ DVORP_PIERCING = 0x3000,
+ DVORP_CHOPPING = 0x4000, // used for axes
+ DVORP_SLASHING = 0x5000, // used for whips
+ DVORP_STABBING = 0x6000, // used for knives/daggers
+
+ // These are shortcuts to tie vorpal/damage types for easy setting...
+ // as above, setting more than one vorpal type is trouble.
+ DAMV_NON_MELEE = DVORP_NONE | DAM_BASH, // launchers
+ DAMV_CRUSHING = DVORP_CRUSHING | DAM_BLUDGEON,
+ DAMV_SLICING = DVORP_SLICING | DAM_SLICE,
+ DAMV_PIERCING = DVORP_PIERCING | DAM_PIERCE,
+ DAMV_CHOPPING = DVORP_CHOPPING | DAM_SLICE,
+ DAMV_SLASHING = DVORP_SLASHING | DAM_WHIP,
+ DAMV_STABBING = DVORP_STABBING | DAM_PIERCE,
+
+ DAM_MASK = 0x0fff, // strips vorpal specification
+ DAMV_MASK = 0xf000 // strips non-vorpal specification
};
// NOTE: This order is very special! Its basically the same as ZAP_*,
// and there are bits of the code that still use that fact.. see zap_wand().
-enum WANDS // mitm[].subtype
+enum wand_type // mitm[].subtype
{
WAND_FLAME, // 0
WAND_FROST,
@@ -3065,7 +3767,7 @@ enum WANDS // mitm[].subtype
NUM_WANDS // must remain last member {dlb}
};
-enum WEAPONS
+enum weapon_type
{
// Base weapons
WPN_CLUB, // 0
@@ -3111,18 +3813,24 @@ enum WEAPONS
WPN_TRIDENT,
WPN_SPIKED_FLAIL,
WPN_GREAT_MACE,
- WPN_GREAT_FLAIL, // 40
+ WPN_DIRE_FLAIL, // 40
WPN_KNIFE,
WPN_BLOWGUN,
WPN_FALCHION,
- NUM_WEAPONS, // 44 - must remain last regular member {dlb}
+ WPN_BLESSED_BLADE, // 44
+ WPN_LONGBOW,
+ WPN_LAJATANG,
+ WPN_LOCHABER_AXE,
+
+ NUM_WEAPONS, // 48 - must be last regular member {dlb}
+
// special cases
WPN_UNARMED = 500, // 500
WPN_UNKNOWN = 1000, // 1000
WPN_RANDOM
};
-enum WEAPON_DESCRIPTIONS
+enum weapon_description_type
{
DWPN_PLAIN = 0, // 0 - added to round out enum {dlb}
DWPN_RUNED = 1, // 1
@@ -3132,7 +3840,7 @@ enum WEAPON_DESCRIPTIONS
DWPN_DWARVEN // 5
};
-enum WEAPON_PROPERTIES
+enum weapon_property_type
{
PWPN_DAMAGE, // 0
PWPN_HIT,
@@ -3141,7 +3849,7 @@ enum WEAPON_PROPERTIES
#ifdef WIZARD
-enum WIZARD_OPTIONS
+enum wizard_option_type
{
WIZ_NEVER, // protect player from accidental wiz
WIZ_NO, // don't start character in wiz mode
@@ -3150,7 +3858,7 @@ enum WIZARD_OPTIONS
#endif
-enum ZAPS // zapping(), zappy()
+enum zap_type
{
ZAP_FLAME, // 0
ZAP_FROST,
@@ -3199,7 +3907,7 @@ enum ZAPS // zapping(), zappy()
ZAP_AGONY,
ZAP_DISRUPTION, // 45
ZAP_DISINTEGRATION, // 46
- ZAP_ISKS_CROSS, // 47: Isk's Cross -- commented out, deprecated {dlb}
+ // ZAP_ISKS_CROSS, // 47: Isk's Cross -- commented out, deprecated {dlb}
ZAP_BREATHE_STEAM = 48, // 48
ZAP_CONTROL_DEMON,
ZAP_ORB_OF_FRAGMENTATION, // 50
@@ -3212,8 +3920,18 @@ enum ZAPS // zapping(), zappy()
ZAP_SMALL_SANDBLAST,
ZAP_MAGMA,
ZAP_POISON_ARROW,
+ ZAP_BREATHE_STICKY_FLAME,
+ ZAP_BREATHE_LIGHTNING,
+ ZAP_PETRIFY,
+ ZAP_HELLFROST,
NUM_ZAPS // must remain last member {dlb}
};
+enum zombie_size_type
+{
+ Z_NOZOMBIE,
+ Z_SMALL,
+ Z_BIG
+};
#endif // ENUM_H
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 0a3a423b7c..51288baa43 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -16,7 +16,6 @@
#ifndef EXTERNS_H
#define EXTERNS_H
-#include <queue>
#include <vector>
#include <list>
#include <string>
@@ -45,26 +44,14 @@ extern unsigned char show_green; // defined in view.cc {dlb}
// defined in mon-util.cc -- w/o this screen redraws *really* slow {dlb}
extern FixedVector<unsigned short, 1000> mcolour;
+const int kNameLen = 30;
#ifdef SHORT_FILE_NAMES
- const int kNameLen = 30;
const int kFileNameLen = 6;
- const int kFileNameSize = 5 + kFileNameLen;
-
#else
- #ifdef SAVE_DIR_PATH
- // file name length has to be able to cover full paths -- bwross
- const int kNameLen = 30;
- const int kFileNameLen = 250;
- const int kFileNameSize = 5 + kFileNameLen;
- #else
- const int kNameLen = 30;
- const int kFileNameLen = 28;
- const int kFileNameSize = 5 + kFileNameLen;
- #endif
+ const int kFileNameLen = 250;
#endif
-
-// Length of Path + File Name
+// Used only to bound the init file name length
const int kPathLen = 256;
// This value is used to mark that the current berserk is free from
@@ -74,36 +61,36 @@ const int kPathLen = 256;
struct monsters;
struct ait_hp_loss;
-struct activity_interrupt_t
+struct activity_interrupt_data
{
- AI_PAYLOAD apt;
+ activity_interrupt_payload_type apt;
const void *data;
- activity_interrupt_t()
+ activity_interrupt_data()
: apt(AIP_NONE), data(NULL)
{
}
- activity_interrupt_t(const int *i)
+ activity_interrupt_data(const int *i)
: apt(AIP_INT), data(i)
{
}
- activity_interrupt_t(const char *s)
+ activity_interrupt_data(const char *s)
: apt(AIP_STRING), data(s)
{
}
- activity_interrupt_t(const std::string &s)
+ activity_interrupt_data(const std::string &s)
: apt(AIP_STRING), data(s.c_str())
{
}
- activity_interrupt_t(const monsters *m)
+ activity_interrupt_data(const monsters *m)
: apt(AIP_MONSTER), data(m)
{
}
- activity_interrupt_t(const ait_hp_loss *ahl)
+ activity_interrupt_data(const ait_hp_loss *ahl)
: apt(AIP_HP_LOSS), data(ahl)
{
}
- activity_interrupt_t(const activity_interrupt_t &a)
+ activity_interrupt_data(const activity_interrupt_data &a)
: apt(a.apt), data(a.data)
{
}
@@ -147,6 +134,7 @@ struct dist
bool isTarget; // target (true), or direction (false)?
bool isMe; // selected self (convenience: tx == you.x_pos,
// ty == you.y_pos)
+ bool isEndpoint; // Does the player want the attack to stop at (tx,ty)?
bool isCancel; // user cancelled (usually <ESC> key)
int tx,ty; // target x,y or logical extension of beam to map edge
int dx,dy; // delta x and y if direction - always -1,0,1
@@ -171,26 +159,59 @@ struct bolt
char thrower; // what kind of thing threw this?
char ex_size; // explosion radius (0==none)
int beam_source; // NON_MONSTER or monster index #
- char beam_name[40];
- bool isBeam; // beams? (can hits multiple targets?)
- const char *aux_source; // source of KILL_MISC beams
+ std::string name;
+ bool is_beam; // beams? (can hits multiple targets?)
+ bool is_explosion;
+ bool is_big_cloud; // expands into big_cloud at endpoint
+ bool is_enchant; // no block/dodge, but mag resist
+ bool is_energy; // mostly energy/non-physical attack
+ bool is_launched; // was fired from launcher?
+ bool is_thrown; // was thrown from hand?
+ bool target_first; // targeting by direction
+ bool aimed_at_spot; // aimed at (x,y), should not cross
+ std::string aux_source; // source of KILL_MISC beams
// OUTPUT parameters (tracing, ID)
- bool obviousEffect; // did an 'obvious' effect happen?
+ bool obvious_effect; // did an 'obvious' effect happen?
int fr_count, foe_count; // # of times a friend/foe is "hit"
int fr_power, foe_power; // total levels/hit dice affected
// INTERNAL use - should not usually be set outside of beam.cc
- bool isTracer; // is this a tracer?
- bool aimedAtFeet; // this was aimed at self!
- bool msgGenerated; // an appropriate msg was already mpr'd
- bool isExplosion; // explosion phase (as opposed to beam phase)
- bool smartMonster; // tracer firer can guess at other mons. resists?
- bool canSeeInvis; // tracer firer can see invisible?
- bool isFriendly; // tracer firer is enslaved or pet
- int foeRatio; // 100* foe ratio (see mons_should_fire())
+ bool is_tracer; // is this a tracer?
+ bool aimed_at_feet; // this was aimed at self!
+ bool msg_generated; // an appropriate msg was already mpr'd
+ bool in_explosion_phase; // explosion phase (as opposed to beam phase)
+ bool smart_monster; // tracer firer can guess at other mons. resists?
+ bool can_see_invis; // tracer firer can see invisible?
+ bool is_friendly; // tracer firer is enslaved or pet
+ int foe_ratio; // 100* foe ratio (see mons_should_fire())
+
+public:
+ // A constructor to try and fix some of the bugs that occur because
+ // this struct never seems to be properly initialized. Definition
+ // is over in beam.cc.
+ bolt();
+
+ void set_target(const dist &);
};
+struct ray_def
+{
+ double accx;
+ double accy;
+ double slope;
+ // Quadrant 1: down-right
+ // Quadrant 2: down-left
+ // Quadrant 3: up-left
+ // Quadrant 4: up-right
+ int quadrant;
+
+ int x() const { return (int)(accx); }
+ int y() const { return (int)(accy); }
+ int advance(); // returns the direction taken (0,1,2)
+ void advance_and_bounce();
+ void regress();
+};
struct run_check_dir
{
@@ -217,7 +238,7 @@ struct item_def
short plus2; // +to dam, sub-sub type for boots and helms
long special; // special stuff
unsigned char colour; // item colour
- unsigned long flags; // item statuc flags
+ unsigned long flags; // item status flags
short quantity; // number of items
short x; // x-location; for inventory items = -1
@@ -227,12 +248,20 @@ struct item_def
unsigned short orig_place;
short orig_monnum;
+
+ std::string inscription;
- item_def() : base_type(0), sub_type(0), plus(0), plus2(0),
+ item_def() : base_type(OBJ_UNASSIGNED), sub_type(0), plus(0), plus2(0),
special(0L), colour(0), flags(0L), quantity(0),
- x(0), y(0), link(0), slot(0), orig_place(0),
+ x(0), y(0), link(NON_ITEM), slot(0), orig_place(0),
orig_monnum(0)
{
+ inscription.clear();
+ }
+
+ void clear()
+ {
+ *this = item_def();
}
};
@@ -256,25 +285,67 @@ private:
size_t maxsize;
};
+class runrest
+{
+public:
+ int runmode;
+ int mp;
+ int hp;
+ int x, y;
+
+ FixedVector<run_check_dir,3> run_check; // array of grids to check
+
+public:
+ runrest();
+ void initialise(int rdir, int mode);
+
+ operator int () const;
+ const runrest &operator = (int newrunmode);
+
+ // Returns true if we're currently resting.
+ bool is_rest() const;
+
+ // Clears run state.
+ void clear();
+
+ // Stops running.
+ void stop();
+
+ // Take one off the rest counter.
+ void rest();
+
+ // Decrements the run counter. Identical to rest.
+ void rundown();
+
+ // Checks if shift-run should be aborted and aborts the run if necessary.
+ // Returns true if you were running and are now no longer running.
+ bool check_stop_running();
+
+ // Check if we've reached the HP/MP stop-rest condition
+ void check_hp();
+ void check_mp();
+
+private:
+ void set_run_check(int index, int compass_dir);
+ bool run_grids_changed() const;
+};
+
+typedef std::vector<delay_queue_item> delay_queue_type;
+
struct player
{
- ACTIVITY activity; // The current multiturn activity, usually set to ACT_NONE
- char turn_is_over; // flag signaling that player has performed a timed action
+ bool turn_is_over; // flag signaling that player has performed a timed action
unsigned char prev_targ;
char your_name[kNameLen];
unsigned char species;
- char run_x;
- char run_y;
-
// Coordinates of last travel target; note that this is never used by
// travel itself, only by the level-map to remember the last travel target.
short travel_x, travel_y;
- FixedVector< run_check_dir, 3 > run_check; // array of grids to check
- signed char running; // Nonzero if running/traveling.
+ runrest running; // Nonzero if running/traveling.
char special_wield;
char deaths_door;
@@ -316,6 +387,13 @@ struct player
bool wield_change; // redraw weapon
unsigned long redraw_status_flags;
+
+ // PC's symbol (usually @) and colour.
+ int symbol;
+ int colour;
+
+ FixedVector< char, NUM_STATUE_TYPES > visible_statue;
+
char redraw_hit_points;
char redraw_magic_points;
char redraw_strength;
@@ -327,6 +405,8 @@ struct player
char redraw_gold;
char redraw_evasion;
+ unsigned char flash_colour;
+
unsigned char hit_points_regeneration;
unsigned char magic_points_regeneration;
@@ -376,7 +456,7 @@ struct player
char is_undead; // see UNDEAD_STATES in enum.h
- std::queue< delay_queue_item > delay_queue; // pending actions
+ delay_queue_type delay_queue; // pending actions
FixedVector<unsigned char, 50> skills;
FixedVector<unsigned char, 50> practise_skill;
@@ -403,6 +483,7 @@ struct player
unsigned char gift_timeout;
FixedVector<unsigned char, MAX_NUM_GODS> penance;
FixedVector<unsigned char, MAX_NUM_GODS> worshipped;
+ FixedVector<short, MAX_NUM_GODS> num_gifts;
FixedVector<unsigned char, 100> mutation;
@@ -440,10 +521,29 @@ struct player
// table contains soft links.
FixedVector<int, 52> spell_letter_table; // ref to spell by slot
FixedVector<int, 52> ability_letter_table; // ref to ability by enum
+
+public:
+ player();
+ void init();
+
+ bool is_valid() const;
+ std::string short_desc() const;
+
+ // For sorting
+ bool operator < (const player &p) const;
};
extern struct player you;
+class monster_spells : public FixedVector<int, NUM_MONSTER_SPELL_SLOTS>
+{
+public:
+ monster_spells()
+ : FixedVector<int, NUM_MONSTER_SPELL_SLOTS>(MS_NO_SPELL)
+ { }
+ void clear() { init(MS_NO_SPELL); }
+};
+
struct monsters
{
int type;
@@ -459,12 +559,16 @@ struct monsters
unsigned char target_x;
unsigned char target_y;
FixedVector<int, 8> inv;
+ monster_spells spells;
unsigned char attitude; // from MONS_ATTITUDE
unsigned int behaviour;
unsigned int foe;
FixedVector<unsigned int, NUM_MON_ENCHANTS> enchantment;
unsigned char flags; // bitfield of boolean flags
+
unsigned int number; // #heads (hydra), etc.
+ int colour;
+
int foe_memory; // how long to 'remember' foe x,y
// once they go out of sight
};
@@ -536,10 +640,6 @@ struct ghost_struct
extern struct ghost_struct ghost;
-
-extern void (*viewwindow) (char, bool);
-
-
struct system_environment
{
char *crawl_name;
@@ -548,6 +648,8 @@ struct system_environment
char *crawl_dir;
char *home; // only used by MULTIUSER systems
bool board_with_nail; // Easter Egg silliness
+
+ std::string crawl_executable_path; // path to crawl from argv[0]
};
extern system_environment SysEnv;
@@ -585,62 +687,26 @@ struct colour_mapping
int colour;
};
-class formatted_string
+class InitLineInput;
+struct game_options
{
public:
- formatted_string() : ops() { }
- formatted_string(const std::string &s);
-
- operator std::string() const;
- void display(int start = 0, int end = -1) const;
- std::string tostring(int start = 0, int end = -1) const;
+ game_options();
+ void reset_startup_options();
+ void reset_options();
- void cprintf(const char *s, ...);
- void cprintf(const std::string &s);
- void gotoxy(int x, int y);
- void textcolor(int color);
+ void read_option_line(const std::string &s, bool runscripts = false);
+ void read_options(InitLineInput &, bool runscripts);
-private:
- enum fs_op_type
- {
- FSOP_COLOUR,
- FSOP_CURSOR,
- FSOP_TEXT
- };
+public:
+ std::string save_dir; // Directory where saves and bones go.
- struct fs_op
- {
- fs_op_type type;
- int x, y;
- std::string text;
-
- fs_op(int color)
- : type(FSOP_COLOUR), x(color), y(-1), text()
- {
- }
-
- fs_op(int cx, int cy)
- : type(FSOP_CURSOR), x(cx), y(cy), text()
- {
- }
-
- fs_op(const std::string &s)
- : type(FSOP_TEXT), x(-1), y(-1), text(s)
- {
- }
-
- operator fs_op_type () const
- {
- return type;
- }
- void display() const;
- };
+ std::string player_name;
- std::vector<fs_op> ops;
-};
+ bool autopickup_on;
+ bool autoprayer_on;
+ bool fizzlecheck_on;
-struct game_options
-{
long autopickups; // items to autopickup
bool verbose_dump; // make character dumps contain more detail
bool detailed_stat_dump; // add detailed stat and resist dump
@@ -649,14 +715,23 @@ struct game_options
bool show_uncursed; // label known uncursed items as "uncursed"
bool always_greet; // display greeting message when reloading
bool easy_open; // open doors with movement
- bool easy_armour; // allow auto-removing of armour
+ bool easy_unequip; // allow auto-removing of armour / jewelry
bool easy_butcher; // open doors with movement
+ bool increasing_skill_progress; // skills go from 0-10 or 10-0
+ bool confirm_self_target; // require confirmation before selftarget
+ bool safe_autopickup; // don't autopickup when monsters visible
+ bool note_skill_max; // take note when skills reach new max
+ bool note_all_spells; // take note when learning any spell
+ bool use_notes; // take (and dump) notes
+ int note_hp_percent; // percentage hp for notetaking
+ int ood_interesting; // how many levels OOD is noteworthy?
int easy_confirm; // make yesno() confirming easier
int easy_quit_item_prompts; // make item prompts quitable on space
int colour[16]; // macro fg colours to other colours
int background; // select default background colour
int channels[NUM_MESSAGE_CHANNELS]; // msg channel colouring
int weapon; // auto-choose weapon for character
+ int book; // auto-choose book for character
int chaos_knight; // choice of god for Chaos Knights (Xom/Makleb)
int death_knight; // choice of god/necromancy for Death Knights
int priest; // choice of god for priests (Zin/Yred)
@@ -680,6 +755,9 @@ struct game_options
bool flush_input[NUM_FLUSH_REASONS]; // when to flush input buff
bool lowercase_invocations; // prefer lowercase invocations
+ char_set_type char_set;
+ FixedVector<unsigned char, NUM_DCHAR_TYPES> char_table;
+
int num_colours; // used for setting up curses colour table (8 or 16)
#ifdef WIZARD
@@ -690,16 +768,31 @@ struct game_options
int sc_entries; // # of score entries
int sc_format; // Format for score entries
+
+ std::string map_file_name; // name of mapping file to use
std::vector<text_pattern> banned_objects; // Objects we'll never pick up
+ std::vector<text_pattern> note_monsters; // Interesting monsters
+ std::vector<text_pattern> note_messages; // Interesting messages
+ std::vector<std::pair<text_pattern, std::string> > autoinscriptions;
+ std::vector<text_pattern> note_items; // Objects to note
+ std::vector<int> note_skill_levels; // Skill levels to note
+
bool pickup_thrown; // Pickup thrown missiles
bool pickup_dropped; // Pickup dropped objects
int travel_delay; // How long to pause between travel moves
- std::vector<message_filter> stop_travel; // Messages that stop travel
+ // Messages that stop travel
+ std::vector<message_filter> travel_stop_message;
int stash_tracking; // How stashes are tracked
bool travel_colour; // Colour levelmap using travel information?
+ int tc_reachable; // Colour for squares that are reachable
+ int tc_excluded; // Colour for excluded squares.
+ int tc_exclude_circle; // Colour for squares in the exclusion radius
+ int tc_dangerous; // Colour for trapped squares, deep water, lava.
+ int tc_disconnected;// Areas that are completely disconnected.
+
int travel_stair_cost;
int travel_exclude_radius2; // Square of the travel exclude radius
@@ -709,8 +802,6 @@ struct game_options
unsigned detected_monster_colour; // Colour of detected monsters
unsigned detected_item_colour; // Colour of detected items
- unsigned remembered_monster_colour; // Colour for monsters remembered
- // on the map.
unsigned heap_brand; // Highlight heaps of items in the playing area
unsigned stab_brand; // Highlight monsters that are stabbable
@@ -722,12 +813,18 @@ struct game_options
std::vector<sound_mapping> sound_mappings;
std::vector<colour_mapping> menu_colour_mappings;
+ bool sort_menus;
+
int dump_kill_places; // How to dump place information for kills.
int dump_message_count; // How many old messages to dump
int dump_item_origins; // Show where items came from?
int dump_item_origin_price;
+ // Order of sections in the character dump.
+ std::vector<std::string> dump_order;
+
+ bool safe_zero_exp; // If true, you feel safe around 0xp monsters
bool target_zero_exp; // If true, targeting targets zero-exp
// monsters.
bool target_wrap; // Wrap around from last to first target
@@ -745,7 +842,7 @@ struct game_options
std::vector<text_pattern> drop_filter;
- FixedVector< unsigned, ACT_ACTIVITY_COUNT > activity_interrupts;
+ FixedArray<bool, NUM_DELAYS, NUM_AINTERRUPTS> activity_interrupts;
// Previous startup options
bool remember_name; // Remember and reprompt with last name
@@ -757,6 +854,15 @@ struct game_options
// If the player prefers to merge kill records, this option can do that.
int kill_map[KC_NCATEGORIES];
+
+#ifdef WIZARD
+ // Parameters for fight simulations.
+ long fsim_rounds;
+ int fsim_str, fsim_int, fsim_dex;
+ int fsim_xl;
+ std::string fsim_mons;
+ std::vector<std::string> fsim_kit;
+#endif // WIZARD
typedef std::map<std::string, std::string> opt_map;
opt_map named_options; // All options not caught above are
@@ -771,7 +877,30 @@ struct game_options
char prev_cls;
int prev_ck, prev_dk, prev_pr;
int prev_weapon;
+ int prev_book;
bool prev_randpick;
+
+public:
+ // Convenience accessors for the second-class options in named_options.
+ int o_int(const char *name, int def = 0) const;
+ long o_long(const char *name, long def = 0L) const;
+ bool o_bool(const char *name, bool def = false) const;
+ std::string o_str(const char *name, const char *def = NULL) const;
+ int o_colour(const char *name, int def = LIGHTGREY) const;
+
+private:
+ void set_default_activity_interrupts();
+ void clear_activity_interrupts(FixedVector<bool, NUM_AINTERRUPTS> &eints);
+ void set_activity_interrupt(
+ FixedVector<bool, NUM_AINTERRUPTS> &eints,
+ const std::string &interrupt);
+ void set_activity_interrupt(const std::string &activity_name,
+ const std::string &interrupt_names,
+ bool append_interrupts);
+ void add_dump_fields(const std::string &text);
+ void do_kill_map(const std::string &from, const std::string &to);
+
+ static const std::string interrupt_prefix;
};
extern game_options Options;
@@ -784,6 +913,7 @@ struct tagHeader
struct scorefile_entry
{
+public:
char version;
char release;
long points;
@@ -820,6 +950,46 @@ struct scorefile_entry
long num_turns; // number of turns taken
int num_diff_runes; // number of rune types in inventory
int num_runes; // total number of runes in inventory
+
+public:
+ scorefile_entry();
+ scorefile_entry(int damage, int death_source, int death_type,
+ const char *aux, bool death_cause_only = false);
+
+ void init_death_cause(int damage, int death_source, int death_type,
+ const char *aux);
+ void init();
+ void reset();
+
+ enum death_desc_verbosity {
+ DDV_TERSE,
+ DDV_ONELINE,
+ DDV_NORMAL,
+ DDV_VERBOSE
+ };
+
+ std::string hiscore_line(death_desc_verbosity verbosity) const;
+
+ std::string character_description(death_desc_verbosity) const;
+ // Full description of death: Killed by an xyz wielding foo
+ std::string death_description(death_desc_verbosity) const;
+
+ std::string death_place(death_desc_verbosity) const;
+
+ std::string game_time(death_desc_verbosity) const;
+
+private:
+ std::string single_cdesc() const;
+ std::string strip_article_a(const std::string &s) const;
+ std::string terse_missile_cause() const;
+ std::string terse_beam_cause() const;
+ std::string terse_wild_magic() const;
+ std::string terse_trap() const;
+ const char *damage_verb() const;
+ const char *death_source_desc() const;
+ std::string damage_string(bool terse = false) const;
};
+extern const struct coord_def Compass[8];
+
#endif // EXTERNS_H
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 6a93de441e..48444db55e 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -3,6 +3,8 @@
* Summary: Functions used during combat.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <11> 07-jul-2000 JDJ Fixed some of the code in you_attack so it doesn't
@@ -48,6 +50,7 @@
#include "it_use2.h"
#include "items.h"
#include "itemname.h"
+#include "itemprop.h"
#include "macro.h"
#include "misc.h"
#include "monplace.h"
@@ -67,7 +70,6 @@
#include "spl-cast.h"
#include "stuff.h"
#include "view.h"
-#include "wpn-misc.h"
#define HIT_WEAK 7
#define HIT_MED 18
@@ -126,70 +128,207 @@ int effective_stat_bonus( int wepType )
#endif
}
-void you_attack(int monster_attacked, bool unarmed_attacks)
-{
- struct monsters *defender = &menv[monster_attacked];
+// returns random2(x) is random_factor is true, otherwise
+// the mean.
+static int maybe_random2( int x, bool random_factor ) {
+ if ( random_factor )
+ return random2(x);
+ else
+ return x / 2;
+}
+
+// Returns the to-hit for your extra unarmed.attacks.
+// DOES NOT do the final roll (i.e., random2(your_to_hit)).
+static int calc_your_to_hit_unarmed() {
int your_to_hit;
- int damage_done = 0;
- bool hit = false;
- unsigned char stab_bonus = 0; // this is never negative {dlb}
- int temp_rand; // for probability determination {dlb}
+
+ your_to_hit = 13 + you.dex / 2 + you.skills[SK_UNARMED_COMBAT] / 2
+ + you.skills[SK_FIGHTING] / 5;
+
+ if (wearing_amulet(AMU_INACCURACY))
+ your_to_hit -= 5;
+
+ if (you.hunger_state == HS_STARVING)
+ your_to_hit -= 3;
+
+ your_to_hit += slaying_bonus(PWPN_HIT);
+
+ return your_to_hit;
+}
+
+// Calculates your to-hit roll. If random_factor is true, be
+// stochastic; if false, determinstic (e.g. for chardumps.)
+int calc_your_to_hit( int heavy_armour,
+ bool hand_and_a_half_bonus,
+ bool water_attack,
+ bool random_factor ) {
const int weapon = you.equip[EQ_WEAPON];
const bool ur_armed = (weapon != -1); // compacts code a bit {dlb}
- const bool bearing_shield = (you.equip[EQ_SHIELD] != -1);
- const int melee_brand = player_damage_brand();
+ int wpn_skill = SK_UNARMED_COMBAT;
- bool water_attack = false;
+ if (weapon != -1) {
+ wpn_skill = weapon_skill( you.inv[weapon].base_type,
+ you.inv[weapon].sub_type );
+ }
- char damage_noise[80], damage_noise2[80];
+ int your_to_hit;
- int heavy_armour = 0;
- char str_pass[ ITEMNAME_SIZE ];
+ // preliminary to_hit modifications:
+ your_to_hit = 15 + (calc_stat_to_hit_base() / 2);
-#if DEBUG_DIAGNOSTICS
- char st_prn[ 20 ];
-#endif
+ if (water_attack)
+ your_to_hit += 5;
- FixedVector< char, RA_PROPERTIES > art_proprt;
+ if (wearing_amulet(AMU_INACCURACY))
+ your_to_hit -= 5;
- if (ur_armed && you.inv[weapon].base_type == OBJ_WEAPONS
- && is_random_artefact( you.inv[weapon] ))
- {
- randart_wpn_properties( you.inv[weapon], art_proprt );
+ // if you can't see yourself, you're a little less acurate.
+ if (you.invis && !player_see_invis())
+ your_to_hit -= 5;
+
+ // fighting contribution
+ your_to_hit += maybe_random2(1 + you.skills[SK_FIGHTING], random_factor);
+
+ // weapon skill contribution
+ if (ur_armed) {
+ if (wpn_skill != SK_FIGHTING) {
+ your_to_hit += maybe_random2(you.skills[wpn_skill] + 1,
+ random_factor);
+ }
}
- else
+ else { // ...you must be unarmed
+ your_to_hit +=
+ (you.species == SP_TROLL || you.species == SP_GHOUL) ? 4 : 2;
+
+ your_to_hit += maybe_random2(1 + you.skills[SK_UNARMED_COMBAT],
+ random_factor);
+ }
+
+ // weapon bonus contribution
+ if (ur_armed)
{
- // Probably over protective, but in this code we're going
- // to play it safe. -- bwr
- for (int i = 0; i < RA_PROPERTIES; i++)
- art_proprt[i] = 0;
+ if (you.inv[ weapon ].base_type == OBJ_WEAPONS)
+ {
+ your_to_hit += you.inv[ weapon ].plus;
+ your_to_hit += property( you.inv[ weapon ], PWPN_HIT );
+
+ if (get_equip_race(you.inv[ weapon ]) == ISFLAG_ELVEN
+ && player_genus(GENPC_ELVEN))
+ {
+ your_to_hit += (random_factor && coinflip() ? 2 : 1);
+ }
+ }
+ else if (item_is_staff( you.inv[ weapon ] ))
+ {
+ // magical staff
+ your_to_hit += property( you.inv[ weapon ], PWPN_HIT );
+ }
+ }
+
+ // slaying bonus
+ your_to_hit += slaying_bonus(PWPN_HIT);
+
+ // hunger penalty
+ if (you.hunger_state == HS_STARVING)
+ your_to_hit -= 3;
+
+ // armour penalty
+ your_to_hit -= heavy_armour;
+
+#if DEBUG_DIAGNOSTICS
+ int roll_hit = your_to_hit;
+#endif
+
+ // hit roll
+ your_to_hit = maybe_random2(your_to_hit, random_factor);
+
+#if DEBUG_DIAGNOSTICS
+ snprintf( info, INFO_SIZE, "to hit die: %d; rolled value: %d",
+ roll_hit, your_to_hit );
+
+ mpr( info, MSGCH_DIAGNOSTICS );
+#endif
+
+ if (hand_and_a_half_bonus)
+ your_to_hit += maybe_random2(3, random_factor);
+
+ if (ur_armed && wpn_skill == SK_SHORT_BLADES && you.sure_blade)
+ your_to_hit += 5 +
+ (random_factor ? random2limit( you.sure_blade, 10 ) :
+ you.sure_blade / 2);
+
+ // other stuff
+ if (!ur_armed) {
+ if ( you.confusing_touch )
+ // just trying to touch is easier that trying to damage
+ your_to_hit += maybe_random2(you.dex, random_factor);
+
+ switch ( you.attribute[ATTR_TRANSFORMATION] ) {
+ case TRAN_NONE:
+ break;
+ case TRAN_SPIDER:
+ your_to_hit += maybe_random2(10, random_factor);
+ break;
+ case TRAN_ICE_BEAST:
+ your_to_hit += maybe_random2(10, random_factor);
+ break;
+ case TRAN_BLADE_HANDS:
+ your_to_hit += maybe_random2(12, random_factor);
+ break;
+ case TRAN_STATUE:
+ your_to_hit += maybe_random2(9, random_factor);
+ break;
+ case TRAN_SERPENT_OF_HELL:
+ case TRAN_DRAGON:
+ your_to_hit += maybe_random2(10, random_factor);
+ break;
+ case TRAN_LICH:
+ your_to_hit += maybe_random2(10, random_factor);
+ break;
+ case TRAN_AIR:
+ your_to_hit = 0;
+ break;
+ default:
+ break;
+ }
}
+ return your_to_hit;
+}
+
+// Calculates your heavy armour penalty. If random_factor is true,
+// be stochastic; if false, deterministic (e.g. for chardumps.)
+int calc_heavy_armour_penalty( bool random_factor ) {
+
+ const bool ur_armed = (you.equip[EQ_WEAPON] != -1);
+ int heavy_armour = 0;
+
// heavy armour modifiers for shield borne
- if (bearing_shield)
+ if (you.equip[EQ_SHIELD] != -1)
{
switch (you.inv[you.equip[EQ_SHIELD]].sub_type)
{
case ARM_SHIELD:
- if (you.skills[SK_SHIELDS] < random2(7))
+ if (you.skills[SK_SHIELDS] < maybe_random2(7, random_factor))
heavy_armour++;
break;
case ARM_LARGE_SHIELD:
if ((you.species >= SP_OGRE && you.species <= SP_OGRE_MAGE)
|| player_genus(GENPC_DRACONIAN))
{
- if (you.skills[SK_SHIELDS] < random2(13))
+ if (you.skills[SK_SHIELDS] < maybe_random2(13, random_factor))
heavy_armour++; // was potentially "+= 3" {dlb}
}
else
{
for (int i = 0; i < 3; i++)
{
- if (you.skills[SK_SHIELDS] < random2(13))
- heavy_armour += random2(3);
+ if (you.skills[SK_SHIELDS] < maybe_random2(13,
+ random_factor))
+ heavy_armour += maybe_random2(3, random_factor);
}
}
break;
@@ -204,14 +343,69 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
const int ev_pen = property( you.inv[you.equip[EQ_BODY_ARMOUR]],
PARM_EVASION );
- if (ev_pen < 0 && random2(you.skills[SK_ARMOUR]) < abs( ev_pen ))
- heavy_armour += random2( abs(ev_pen) );
+ if (ev_pen < 0 &&
+ maybe_random2(you.skills[SK_ARMOUR], random_factor) < abs(ev_pen))
+ heavy_armour += maybe_random2( abs(ev_pen), random_factor );
}
// ??? what is the reasoning behind this ??? {dlb}
// My guess is that its supposed to encourage monk-style play -- bwr
- if (!ur_armed)
- heavy_armour *= (coinflip() ? 3 : 2);
+ if (!ur_armed) {
+ if ( random_factor ) {
+ heavy_armour *= (coinflip() ? 3 : 2);
+ }
+ // (2+3)/2
+ else {
+ heavy_armour *= 5;
+ heavy_armour /= 2;
+ }
+ }
+ return heavy_armour;
+}
+
+// Returns true if you hit the monster.
+bool you_attack(int monster_attacked, bool unarmed_attacks)
+{
+ struct monsters *defender = &menv[monster_attacked];
+
+ int your_to_hit;
+ int damage_done = 0;
+ bool hit = false;
+ unsigned char stab_bonus = 0; // this is never negative {dlb}
+ int temp_rand; // for probability determination {dlb}
+
+ const int weapon = you.equip[EQ_WEAPON];
+ const bool ur_armed = (weapon != -1); // compacts code a bit {dlb}
+ const bool bearing_shield = (you.equip[EQ_SHIELD] != -1);
+
+ const int melee_brand = player_damage_brand();
+
+ bool water_attack = false;
+
+ char damage_noise[80], damage_noise2[80];
+
+ char str_pass[ ITEMNAME_SIZE ];
+
+#if DEBUG_DIAGNOSTICS
+ char st_prn[ 20 ];
+#endif
+
+ FixedVector< char, RA_PROPERTIES > art_proprt;
+
+ if (ur_armed && you.inv[weapon].base_type == OBJ_WEAPONS
+ && is_random_artefact( you.inv[weapon] ))
+ {
+ randart_wpn_properties( you.inv[weapon], art_proprt );
+ }
+ else
+ {
+ // Probably over protective, but in this code we're going
+ // to play it safe. -- bwr
+ for (int i = 0; i < RA_PROPERTIES; i++)
+ art_proprt[i] = 0;
+ }
+
+ const int heavy_armour = calc_heavy_armour_penalty(true);
// Calculate the following two flags in advance
// to know what player does this combat turn:
@@ -229,24 +423,23 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
bool use_hand_and_a_half_bonus = false;
int wpn_skill = SK_UNARMED_COMBAT;
- int hands_reqd = HANDS_ONE_HANDED;
+ int hands = HANDS_ONE;
if (weapon != -1)
{
wpn_skill = weapon_skill( you.inv[weapon].base_type,
you.inv[weapon].sub_type );
- hands_reqd = hands_reqd_for_weapon( you.inv[weapon].base_type,
- you.inv[weapon].sub_type );
+ hands = hands_reqd( you.inv[weapon], player_size() );
}
if (unarmed_attacks
&& !can_do_unarmed_combat
&& !bearing_shield && ur_armed
- && item_uncursed( you.inv[ weapon ] )
- && hands_reqd == HANDS_ONE_OR_TWO_HANDED)
+ && !item_cursed( you.inv[ weapon ] )
+ && hands == HANDS_HALF)
{
- // currently: +1 dam, +1 hit, -1 spd (loosly)
+ // currently: +1 dam, +1 hit, -1 spd (loosely)
use_hand_and_a_half_bonus = true;
}
@@ -258,10 +451,11 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
* *
**************************************************************************
*/
- bool helpless = mons_flag(defender->type, M_NO_EXP_GAIN);
+ bool helpless = mons_class_flag(defender->type, M_NO_EXP_GAIN)
+ || mons_is_statue(defender->type);
if (mons_friendly(defender))
- naughty(NAUGHTY_ATTACK_FRIEND, 5);
+ did_god_conduct(DID_ATTACK_FRIEND, 5);
if (you.pet_target == MHITNOT)
you.pet_target = monster_attacked;
@@ -272,66 +466,36 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
if (random2(you.dex) < 4 || one_chance_in(5))
{
mpr("Unstable footing causes you to fumble your attack.");
- return;
+ return (false);
}
}
// wet merfolk
if (player_is_swimming()
- // monster not a water creature
- && monster_habitat( defender->type ) != DNGN_DEEP_WATER
- && !mons_flag( defender->type, M_AMPHIBIOUS )
- // monster in water
- && (grd[defender->x][defender->y] == DNGN_SHALLOW_WATER
- || grd[defender->x][defender->y] == DNGN_DEEP_WATER)
- // monster not flying
- && !mons_flies( defender ))
+ // monster not a water creature, but is in water
+ && monster_floundering(defender))
{
water_attack = true;
}
- // preliminary to_hit modifications:
- your_to_hit = 15 + (calc_stat_to_hit_base() / 2);
-
- if (water_attack)
- your_to_hit += 5;
-
- if (wearing_amulet(AMU_INACCURACY))
- your_to_hit -= 5;
-
- // if you can't see yourself, you're a little less acurate.
- if (you.invis && !player_see_invis())
- your_to_hit -= 5;
-
- your_to_hit += random2(1 + you.skills[SK_FIGHTING]);
+ // new unified to-hit calculation
+ your_to_hit = calc_your_to_hit( heavy_armour, use_hand_and_a_half_bonus,
+ water_attack, true );
- if (ur_armed)
- {
- if (wpn_skill)
- your_to_hit += random2(you.skills[wpn_skill] + 1);
- }
- else // ...you must be unarmed
- {
- your_to_hit += (you.species == SP_TROLL
- || you.species == SP_GHOUL) ? 4 : 2;
-
- your_to_hit += random2(1 + you.skills[SK_UNARMED_COMBAT]);
- }
+ //jmf: check for backlight enchantment
+ if (mons_has_ench(defender, ENCH_BACKLIGHT_I, ENCH_BACKLIGHT_IV))
+ your_to_hit += 2 + random2(8);
// energy expenditure in terms of food:
make_hungry(3, true);
- if (ur_armed
- && you.inv[ weapon ].base_type == OBJ_WEAPONS
- && is_random_artefact( you.inv[ weapon ] ))
+ if (ur_armed &&
+ you.inv[ weapon ].base_type == OBJ_WEAPONS &&
+ is_random_artefact( you.inv[ weapon ] ) &&
+ art_proprt[RAP_ANGRY] >= 1 &&
+ random2(1 + art_proprt[RAP_ANGRY]))
{
- if (art_proprt[RAP_ANGRY] >= 1)
- {
- if (random2(1 + art_proprt[RAP_ANGRY]))
- {
- go_berserk(false);
- }
- }
+ go_berserk(false);
}
switch (you.special_wield)
@@ -352,63 +516,11 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
break;
}
- if (you.mutation[MUT_BERSERK])
- {
- if (random2(100) < (you.mutation[MUT_BERSERK] * 10) - 5)
- go_berserk(false);
- }
-
- if (ur_armed)
- {
- if (you.inv[ weapon ].base_type == OBJ_WEAPONS)
- {
- // there was some stupid conditional here that applied this
- // "if (plus >= 0)" and "else" that .. which is all
- // cases (d'oh!) {dlb}
- your_to_hit += you.inv[ weapon ].plus;
- your_to_hit += property( you.inv[ weapon ], PWPN_HIT );
-
- if (cmp_equip_race( you.inv[ weapon ], ISFLAG_ELVEN )
- && player_genus(GENPC_ELVEN))
- {
- your_to_hit += (coinflip() ? 2 : 1);
- }
- }
- else if (item_is_staff( you.inv[ weapon ] ))
- {
- /* magical staff */
- your_to_hit += property( you.inv[ weapon ], PWPN_HIT );
- }
- }
-
- your_to_hit += slaying_bonus(PWPN_HIT); // see: player.cc
-
- if (you.hunger_state == HS_STARVING)
- your_to_hit -= 3;
-
- your_to_hit -= heavy_armour;
-
-#if DEBUG_DIAGNOSTICS
- int roll_hit = your_to_hit;
-#endif
-
- // why does this come here and not later? {dlb}
- // apparently to give the following pluses more significance -- bwr
- your_to_hit = random2(your_to_hit);
-
-#if DEBUG_DIAGNOSTICS
- snprintf( info, INFO_SIZE, "to hit die: %d; rolled value: %d",
- roll_hit, your_to_hit );
-
- mpr( info, MSGCH_DIAGNOSTICS );
-#endif
-
- if (use_hand_and_a_half_bonus)
- your_to_hit += random2(3);
-
- if (ur_armed && wpn_skill == SK_SHORT_BLADES && you.sure_blade)
- your_to_hit += 5 + random2limit( you.sure_blade, 10 );
+ if (you.mutation[MUT_BERSERK] &&
+ (random2(100) < (you.mutation[MUT_BERSERK] * 10) - 5))
+ go_berserk(false);
+ // calculate damage
int damage = 1;
if (!ur_armed) // empty-handed
@@ -417,9 +529,6 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
if (you.confusing_touch)
{
- // just trying to touch is easier that trying to damage
- // special_brand = SPWPN_CONFUSE;
- your_to_hit += random2(you.dex);
// no base hand damage while using this spell
damage = 0;
}
@@ -434,34 +543,27 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
case TRAN_SPIDER:
damage = 5;
// special_brand = SPWPN_VENOM;
- your_to_hit += random2(10);
break;
case TRAN_ICE_BEAST:
damage = 12;
// special_brand = SPWPN_FREEZING;
- your_to_hit += random2(10);
break;
case TRAN_BLADE_HANDS:
damage = 12 + (you.strength / 4) + (you.dex / 4);
- your_to_hit += random2(12);
break;
case TRAN_STATUE:
damage = 12 + you.strength;
- your_to_hit += random2(9);
break;
case TRAN_SERPENT_OF_HELL:
case TRAN_DRAGON:
damage = 20 + you.strength;
- your_to_hit += random2(10);
break;
case TRAN_LICH:
damage = 5;
// special_brand = SPWPN_DRAINING;
- your_to_hit += random2(10);
break;
case TRAN_AIR:
- damage = 0;
- your_to_hit = 0;
+ damage = 0;
break;
}
}
@@ -491,10 +593,6 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
const int base_damage = damage;
#endif
- //jmf: check for backlight enchantment
- if (mons_has_ench(defender, ENCH_BACKLIGHT_I, ENCH_BACKLIGHT_IV))
- your_to_hit += 2 + random2(8);
-
int weapon_speed2 = 10;
int min_speed = 3;
@@ -513,7 +611,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
min_speed = 5;
// Using both hands can get a weapon up to speed 7
- if ((hands_reqd == HANDS_TWO_HANDED || use_hand_and_a_half_bonus)
+ if ((hands == HANDS_TWO || use_hand_and_a_half_bonus)
&& min_speed > 7)
{
min_speed = 7;
@@ -545,10 +643,11 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
if (you.burden_state == BS_UNENCUMBERED
&& one_chance_in(heavy_armour + 1))
{
- weapon_speed2 = 10 - you.skills[SK_UNARMED_COMBAT] / 3;
-
- if (weapon_speed2 < 4)
- weapon_speed2 = 4;
+ weapon_speed2 = 10 - you.skills[SK_UNARMED_COMBAT] / 5;
+
+ /* this shouldn't happen anyway...sanity */
+ if (weapon_speed2 < 5)
+ weapon_speed2 = 5;
}
}
@@ -556,11 +655,14 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
{
switch (you.inv[you.equip[EQ_SHIELD]].sub_type)
{
- case ARM_SHIELD:
- weapon_speed2++;
- break;
case ARM_LARGE_SHIELD:
- weapon_speed2 += 2;
+ if (you.skills[SK_SHIELDS] <= 10 + random2(17))
+ weapon_speed2++;
+ // [dshaligram] Fall-through
+
+ case ARM_SHIELD:
+ if (you.skills[SK_SHIELDS] <= 3 + random2(17))
+ weapon_speed2++;
break;
}
}
@@ -599,7 +701,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
// confused (but not perma-confused)
if (mons_has_ench(defender, ENCH_CONFUSION)
- && !mons_flag(defender->type, M_CONFUSED))
+ && !mons_class_flag(defender->type, M_CONFUSED))
{
stabAttempt = true;
stab_bonus = 2;
@@ -642,10 +744,9 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
mpr( info, MSGCH_DIAGNOSTICS );
#endif
- if ((your_to_hit >= defender->evasion || one_chance_in(30))
- || ((defender->speed_increment <= 60
- || defender->behaviour == BEH_SLEEP)
- && !one_chance_in(10 + you.skills[SK_STABBING])))
+ if ((your_to_hit >= defender->evasion || one_chance_in(30)) ||
+ ((mons_is_paralysed(defender) || defender->behaviour == BEH_SLEEP)
+ && !one_chance_in(10 + you.skills[SK_STABBING])))
{
hit = true;
int dammod = 78;
@@ -742,13 +843,13 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
if (use_hand_and_a_half_bonus)
damage_done += random2(3);
- if (cmp_equip_race( you.inv[ weapon ], ISFLAG_DWARVEN )
+ if (get_equip_race(you.inv[ weapon ]) == ISFLAG_DWARVEN
&& player_genus(GENPC_DWARVEN))
{
damage_done += random2(3);
}
- if (cmp_equip_race( you.inv[ weapon ], ISFLAG_ORCISH )
+ if (get_equip_race(you.inv[ weapon ]) == ISFLAG_ORCISH
&& you.species == SP_HILL_ORC && coinflip())
{
damage_done++;
@@ -758,8 +859,8 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
bonus_damage = damage_done;
#endif
- if (!launches_things( you.inv[ weapon ].sub_type )
- && item_not_ident( you.inv[ weapon ], ISFLAG_KNOW_PLUSES )
+ if (!is_range_weapon( you.inv[weapon] )
+ && !item_ident( you.inv[ weapon ], ISFLAG_KNOW_PLUSES )
&& random2(100) < you.skills[ wpn_skill ])
{
set_ident_flags( you.inv[ weapon ], ISFLAG_KNOW_PLUSES );
@@ -781,10 +882,10 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
exercise(SK_STABBING, 1 + random2avg(5, 4));
- if (mons_holiness(defender->type) == MH_NATURAL
- || mons_holiness(defender->type) == MH_HOLY)
+ if (mons_holiness(defender) == MH_NATURAL
+ || mons_holiness(defender) == MH_HOLY)
{
- naughty(NAUGHTY_STABBING, 4);
+ did_god_conduct(DID_STABBING, 4);
}
}
else
@@ -917,7 +1018,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
#endif
if (ur_armed && melee_brand == SPWPN_VAMPIRICISM)
{
- if (mons_holiness(defender->type) == MH_NATURAL
+ if (mons_holiness(defender) == MH_NATURAL
&& damage_done > 0 && you.hp < you.hp_max
&& !one_chance_in(5))
{
@@ -929,7 +1030,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
if (you.hunger_state != HS_ENGORGED)
lessen_hunger(30 + random2avg(59, 2), true);
- naughty(NAUGHTY_NECROMANCY, 2);
+ did_god_conduct(DID_NECROMANCY, 2);
}
}
@@ -945,17 +1046,19 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
snprintf( info, INFO_SIZE, "You %s the ball lightning.", damage_noise);
mpr(info);
}
- return;
+ return (true);
}
if (damage_done < 1 && player_monster_visible( defender ))
{
hit = true;
- snprintf( info, INFO_SIZE, "You %s ", damage_noise);
- strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
- strcat(info, ", but do no damage.");
- mpr(info);
+ if ( !ur_armed || melee_brand != SPWPN_VORPAL )
+ {
+ snprintf(info, INFO_SIZE, "You %s %s, but do no damage.",
+ damage_noise, ptr_monam(defender, DESC_NOCAP_THE));
+ mpr(info);
+ }
}
}
else
@@ -1002,44 +1105,44 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
mpr(info);
- if (mons_holiness(defender->type) == MH_HOLY)
- done_good(GOOD_KILLED_ANGEL_I, 1);
+ if (mons_holiness(defender) == MH_HOLY)
+ did_god_conduct(DID_KILL_ANGEL, 1);
if (you.special_wield == SPWLD_TORMENT)
{
- torment(you.x_pos, you.y_pos);
- naughty(NAUGHTY_UNHOLY, 5);
+ torment(TORMENT_SPWLD, you.x_pos, you.y_pos);
+ did_god_conduct(DID_UNHOLY, 5);
}
if (you.special_wield == SPWLD_ZONGULDROK
|| you.special_wield == SPWLD_CURSE)
{
- naughty(NAUGHTY_NECROMANCY, 3);
+ did_god_conduct(DID_NECROMANCY, 3);
}
}
- if (defender->type == MONS_JELLY
- || defender->type == MONS_BROWN_OOZE
- || defender->type == MONS_ACID_BLOB
- || defender->type == MONS_ROYAL_JELLY)
- {
- weapon_acid(5);
- }
-
/* remember, damage_done is still useful! */
if (hit)
{
+ if (defender->type == MONS_JELLY
+ || defender->type == MONS_BROWN_OOZE
+ || defender->type == MONS_ACID_BLOB
+ || defender->type == MONS_ROYAL_JELLY)
+ {
+ weapon_acid(5);
+ }
+
int specdam = 0;
if (ur_armed
&& you.inv[ weapon ].base_type == OBJ_WEAPONS
- && is_demonic( you.inv[ weapon ].sub_type ))
+ && is_demonic( you.inv[ weapon ] ))
{
- naughty(NAUGHTY_UNHOLY, 1);
+ did_god_conduct(DID_UNHOLY, 1);
}
- if (mons_holiness(defender->type) == MH_HOLY)
- naughty(NAUGHTY_ATTACK_HOLY, defender->hit_dice);
+ if (mons_holiness(defender) == MH_HOLY)
+ did_god_conduct(DID_ATTACK_HOLY, defender->hit_dice);
if (defender->type == MONS_HYDRA)
{
@@ -1204,7 +1307,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
ptr_monam(defender, DESC_CAP_THE) );
mpr(info);
- naughty(NAUGHTY_NECROMANCY, 4);
+ did_god_conduct(DID_NECROMANCY, 4);
}
}
break;
@@ -1228,7 +1331,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
{
dec_mp(STAFF_COST);
- if (item_not_ident( you.inv[weapon], ISFLAG_KNOW_TYPE ))
+ if (!item_ident( you.inv[weapon], ISFLAG_KNOW_TYPE ))
{
set_ident_flags( you.inv[weapon], ISFLAG_KNOW_TYPE );
strcpy(info, "You are wielding ");
@@ -1316,7 +1419,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
// there should be a case in here for holy monsters,
// see elsewhere in fight.cc {dlb}
specdam = 0;
- switch (mons_holiness(defender->type))
+ switch (mons_holiness(defender))
{
case MH_UNDEAD:
specdam = 1 + random2(damage_done);
@@ -1325,6 +1428,9 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
case MH_DEMONIC:
specdam = 1 + (random2(damage_done * 15) / 10);
break;
+
+ default:
+ break;
}
break;
@@ -1344,7 +1450,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
break;
case SPWPN_ORC_SLAYING:
- if (mons_charclass(defender->type) == MONS_ORC)
+ if (mons_species(defender->type) == MONS_ORC)
hurt_monster(defender, 1 + random2(damage_done));
break;
@@ -1375,19 +1481,22 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
defender->hit_points = 0;
specdam = 1 + (random2(damage_done) / 2);
- naughty( NAUGHTY_NECROMANCY, 2 );
+ did_god_conduct( DID_NECROMANCY, 2 );
break;
/* 9 = speed - done before */
case SPWPN_VORPAL:
specdam = 1 + random2(damage_done) / 2;
+ if (damage_done < 1)
+ mprf(MSGCH_PLAIN, "You strike %s.",
+ ptr_monam(defender, DESC_NOCAP_THE));
break;
case SPWPN_VAMPIRICISM:
specdam = 0; // NB: does no extra damage
- if (mons_holiness(defender->type) != MH_NATURAL)
+ if (mons_holiness(defender) != MH_NATURAL)
break;
else if (mons_res_negative_energy(defender) > 0)
break;
@@ -1411,12 +1520,12 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
if (you.hunger_state != HS_ENGORGED)
lessen_hunger(random2avg(59, 2), true);
- naughty( NAUGHTY_NECROMANCY, 2 );
+ did_god_conduct( DID_NECROMANCY, 2 );
break;
case SPWPN_DISRUPTION:
specdam = 0;
- if (mons_holiness(defender->type) == MH_UNDEAD && !one_chance_in(3))
+ if (mons_holiness(defender) == MH_UNDEAD && !one_chance_in(3))
{
simple_monster_message(defender, " shudders.");
specdam += random2avg((1 + (damage_done * 3)), 3);
@@ -1431,7 +1540,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
simple_monster_message(defender, " convulses in agony.");
specdam += random2( 1 + you.skills[SK_NECROMANCY] );
}
- naughty(NAUGHTY_NECROMANCY, 4);
+ did_god_conduct(DID_NECROMANCY, 4);
break;
case SPWPN_DISTORTION:
@@ -1484,7 +1593,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
if (coinflip())
{
monster_die(defender, KILL_RESET, 0);
- return;
+ return (true);
}
break;
@@ -1519,7 +1628,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
if (defender->hit_points < 1)
{
monster_die(defender, KILL_YOU, 0);
- return;
+ return (hit);
}
if (unarmed_attacks)
@@ -1608,13 +1717,13 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
sc_dam += 5;
if (you.equip[EQ_HELMET] != -1
- && (cmp_helmet_type( you.inv[you.equip[EQ_HELMET]], THELM_HELMET )
- || cmp_helmet_type( you.inv[you.equip[EQ_HELMET]], THELM_HELM )))
+ && (get_helmet_type(you.inv[you.equip[EQ_HELMET]]) == THELM_HELMET
+ || get_helmet_type(you.inv[you.equip[EQ_HELMET]]) == THELM_HELM))
{
sc_dam += 2;
- if (cmp_helmet_desc( you.inv[you.equip[EQ_HELMET]], THELM_DESC_SPIKED )
- || cmp_helmet_desc( you.inv[you.equip[EQ_HELMET]], THELM_DESC_HORNED ))
+ if (get_helmet_desc(you.inv[you.equip[EQ_HELMET]]) == THELM_DESC_SPIKED
+ || get_helmet_desc(you.inv[you.equip[EQ_HELMET]]) == THELM_DESC_HORNED)
{
sc_dam += 3;
}
@@ -1676,7 +1785,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
/* no punching with a shield or 2-handed wpn, except staves */
if (bearing_shield || coinflip()
- || (ur_armed && hands_reqd == HANDS_TWO_HANDED
+ || (ur_armed && hands == HANDS_TWO
&& you.inv[weapon].base_type != OBJ_STAVES
&& you.inv[weapon].sub_type != WPN_QUARTERSTAFF) )
{
@@ -1701,19 +1810,11 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
}
- your_to_hit = 13 + you.dex / 2 + you.skills[SK_UNARMED_COMBAT] / 2
- + you.skills[SK_FIGHTING] / 5;
-
- if (wearing_amulet(AMU_INACCURACY))
- your_to_hit -= 5;
+ // unified to-hit calculation
+ your_to_hit = calc_your_to_hit_unarmed();
+ your_to_hit = random2(your_to_hit);
- make_hungry(2, true);
-
- if (you.hunger_state == HS_STARVING)
- your_to_hit -= 3;
-
- your_to_hit += slaying_bonus(PWPN_HIT);
- your_to_hit = random2(your_to_hit);
+ make_hungry(2, true);
damage = sc_dam; //4 + you.experience_level / 3;
@@ -1721,7 +1822,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
if (your_to_hit >= defender->evasion || one_chance_in(30))
{
- bool hit = true;
+ hit = true;
int dammod = 10;
const int dam_stat_val = calc_stat_to_dam_base();
@@ -1793,8 +1894,8 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
if (brand == SPWPN_VENOM && coinflip())
poison_monster( defender, true );
- if (mons_holiness(defender->type) == MH_HOLY)
- done_good(GOOD_KILLED_ANGEL_I, 1);
+ if (mons_holiness(defender) == MH_HOLY)
+ did_god_conduct(DID_KILL_ANGEL, 1);
hit = true;
}
@@ -1833,7 +1934,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
strcat(info, "the ball lightning.");
mpr(info);
}
- return;
+ return (true);
}
}
else
@@ -1851,7 +1952,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
if (hit)
print_wounds(defender);
- return;
+ return (hit);
} // end you_attack()
void monster_attack(int monster_attacking)
@@ -1888,8 +1989,7 @@ void monster_attack(int monster_attacking)
// This should happen after the mons_friendly check so we're
// only disturbed by hostiles. -- bwr
- if (you_are_delayed())
- stop_delay();
+ interrupt_activity( AI_MONSTER_ATTACKS, attacker );
if (attacker->type == MONS_GIANT_SPORE
|| attacker->type == MONS_BALL_LIGHTNING)
@@ -1898,7 +1998,7 @@ void monster_attack(int monster_attacking)
return;
}
- // if a friend wants to help, they can attack <monster_attacking>
+ // if a friend wants to help, they can attack <monster_attacking>
if (you.pet_target == MHITNOT)
you.pet_target = monster_attacking;
@@ -1906,7 +2006,7 @@ void monster_attack(int monster_attacking)
return;
if (you.duration[DUR_REPEL_UNDEAD]
- && mons_holiness( attacker->type ) == MH_UNDEAD
+ && mons_holiness( attacker ) == MH_UNDEAD
&& !check_mons_resist_magic( attacker, you.piety ))
{
simple_monster_message(attacker,
@@ -1932,7 +2032,7 @@ void monster_attack(int monster_attacking)
if (grd[attacker->x][attacker->y] == DNGN_SHALLOW_WATER
&& !mons_flies( attacker )
- && !mons_flag( attacker->type, M_AMPHIBIOUS )
+ && !mons_class_flag( attacker->type, M_AMPHIBIOUS )
&& monster_habitat( attacker->type ) == DNGN_FLOOR
&& one_chance_in(4))
{
@@ -2015,16 +2115,25 @@ void monster_attack(int monster_attacking)
}
// Factors against blocking
- const int con_block = 15 + attacker->hit_dice
- + (10 * you.shield_blocks * you.shield_blocks);
-
- // Factors for blocking
- const int pro_block = player_shield_class() + (random2(you.dex) / 5);
+ // [dshaligram] Scaled back HD effect to 50% of previous, reduced
+ // shield_blocks multiplier to 5.
+ const int con_block =
+ random2(15 + attacker->hit_dice / 2
+ + (5 * you.shield_blocks * you.shield_blocks));
+
+ // Factors for blocking:
+ // [dshaligram] Added weighting for shields skill, increased dex bonus
+ // from .2 to .25
+ const int pro_block =
+ random2(player_shield_class())
+ + (random2(you.dex) / 4)
+ + (random2(skill_bump(SK_SHIELDS)) / 4)
+ - 1;
if (!you.paralysis && !you_are_delayed() && !you.conf
&& player_monster_visible( attacker )
&& player_shield_class() > 0
- && random2(con_block) <= random2(pro_block))
+ && con_block <= pro_block)
{
you.shield_blocks++;
@@ -2066,8 +2175,8 @@ void monster_attack(int monster_attacking)
damage_taken = random2(damage_size);
- if (cmp_equip_race(mitm[attacker->inv[hand_used]],ISFLAG_ORCISH)
- && mons_charclass(attacker->type) == MONS_ORC
+ if (get_equip_race(mitm[attacker->inv[hand_used]]) == ISFLAG_ORCISH
+ && mons_species(attacker->type) == MONS_ORC
&& coinflip())
{
damage_taken++;
@@ -2155,7 +2264,7 @@ void monster_attack(int monster_attacking)
if (attacker->type != MONS_DANCING_WEAPON && mmov_x != NON_ITEM
&& mitm[mmov_x].base_type == OBJ_WEAPONS
- && !launches_things( mitm[mmov_x].sub_type ))
+ && !is_range_weapon( mitm[mmov_x] ))
{
strcat(info, " with ");
it_name(mmov_x, DESC_NOCAP_A, str_pass); // was 7
@@ -2170,7 +2279,7 @@ void monster_attack(int monster_attacking)
{
if (you.equip[EQ_BODY_ARMOUR] != -1)
{
- const int body_arm_mass = mass_item( you.inv[you.equip[EQ_BODY_ARMOUR]] );
+ const int body_arm_mass = item_mass( you.inv[you.equip[EQ_BODY_ARMOUR]] );
if (!player_light_armour() && coinflip()
&& random2(1000) <= body_arm_mass)
@@ -2308,7 +2417,7 @@ void monster_attack(int monster_attacking)
}
damage_taken += extraDamage;
- scrolls_burn(1, OBJ_SCROLLS);
+ expose_player_to_element(BEAM_FIRE, 1);
break;
case MONS_SMALL_SNAKE:
@@ -2402,8 +2511,8 @@ void monster_attack(int monster_attacking)
mpr("You still can't move!", MSGCH_WARN);
else
mpr("You suddenly lose the ability to move!", MSGCH_WARN);
-
- you.paralysis += 1 + random2(3);
+ if ( you.paralysis == 0 || mclas == MONS_RED_WASP )
+ you.paralysis += 1 + random2(3);
}
break;
@@ -2445,7 +2554,7 @@ void monster_attack(int monster_attacking)
mpr(info);
damage_taken += extraDamage;
- scrolls_burn( 1, OBJ_POTIONS );
+ expose_player_to_element(BEAM_COLD, 1);
break;
case MONS_ICE_DEVIL:
@@ -2483,7 +2592,7 @@ void monster_attack(int monster_attacking)
damage_taken += extraDamage;
- scrolls_burn(1, OBJ_POTIONS);
+ expose_player_to_element(BEAM_COLD, 1);
break;
case MONS_ELECTRIC_GOLEM:
@@ -2579,8 +2688,18 @@ void monster_attack(int monster_attacking)
give_bad_mutation();
}
break;
+
+ case MONS_MOTH_OF_WRATH:
+ if (one_chance_in(3)) {
+ simple_monster_message(attacker, " infuriates you!");
+ go_berserk(false);
+ }
+ break;
+
+ default:
+ break;
} // end of switch for special attacks.
- /* use brek for level drain, maybe with beam variables,
+ /* use break for level drain, maybe with beam variables,
because so many creatures use it. */
}
@@ -2912,7 +3031,7 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
int weapon = -1; // monster weapon, if any
int damage_taken = 0;
bool hit = false;
- int mmov_x = 0;
+ // int mmov_x = 0;
bool water_attack = false;
int specdam = 0;
int hand_used = 0;
@@ -2939,19 +3058,14 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
return false;
}
- if (grd[attacker->x][attacker->y] == DNGN_SHALLOW_WATER
- && !mons_flies( attacker )
- && !mons_flag( attacker->type, M_AMPHIBIOUS )
- && habitat == DNGN_FLOOR
- && one_chance_in(4))
+ if (monster_floundering(attacker) && one_chance_in(4))
{
mpr("You hear a splashing noise.");
return true;
}
- if (grd[defender->x][defender->y] == DNGN_SHALLOW_WATER
- && !mons_flies(defender)
- && habitat == DNGN_DEEP_WATER)
+ // habitat is the favoured habitat of the attacker
+ if (monster_floundering(defender) && habitat == DNGN_DEEP_WATER)
{
water_attack = true;
}
@@ -3022,21 +3136,21 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
mons_to_hit = random2(mons_to_hit);
- if (mons_to_hit >= defender->evasion
- || ((defender->speed_increment <= 60
- || defender->behaviour == BEH_SLEEP) && !one_chance_in(20)))
+ if (mons_to_hit >= defender->evasion ||
+ ((mons_is_paralysed(defender) || defender->behaviour == BEH_SLEEP)
+ && !one_chance_in(20)))
{
hit = true;
if (attacker->inv[hand_used] != NON_ITEM
&& mitm[attacker->inv[hand_used]].base_type == OBJ_WEAPONS
- && !launches_things( mitm[attacker->inv[hand_used]].sub_type ))
+ && !is_range_weapon( mitm[attacker->inv[hand_used]] ))
{
damage_taken = random2(property( mitm[attacker->inv[hand_used]],
PWPN_DAMAGE ));
- if (cmp_equip_race(mitm[attacker->inv[hand_used]],ISFLAG_ORCISH)
- && mons_charclass(attacker->type) == MONS_ORC
+ if (get_equip_race(mitm[attacker->inv[hand_used]]) == ISFLAG_ORCISH
+ && mons_species(attacker->type) == MONS_ORC
&& coinflip())
{
damage_taken++;
@@ -3077,7 +3191,11 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
{
strcpy(info, ptr_monam(attacker, DESC_CAP_THE));
strcat(info, " misses ");
- strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
+ if (attacker == defender)
+ strcat(info,
+ mons_pronoun(attacker->type, PRONOUN_REFLEXIVE));
+ else
+ strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
strcat(info, ".");
mpr(info);
}
@@ -3089,8 +3207,11 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
{
strcpy(info, ptr_monam(attacker, DESC_CAP_THE));
strcat(info, " hits ");
- strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
-
+ if ( attacker == defender )
+ strcat(info,
+ mons_pronoun(attacker->type, PRONOUN_REFLEXIVE));
+ else
+ strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
#if DEBUG_DIAGNOSTICS
strcat(info, " for ");
// note: doesn't take account of special weapons etc
@@ -3110,12 +3231,16 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
{
strcpy(info, ptr_monam(attacker, DESC_CAP_THE));
strcat(info, " hits ");
- strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
+ if (attacker == defender)
+ strcat(info,
+ mons_pronoun(attacker->type, PRONOUN_REFLEXIVE));
+ else
+ strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
if (attacker->type != MONS_DANCING_WEAPON
&& attacker->inv[hand_used] != NON_ITEM
&& mitm[attacker->inv[hand_used]].base_type == OBJ_WEAPONS
- && !launches_things( mitm[attacker->inv[hand_used]].sub_type ))
+ && !is_range_weapon( mitm[attacker->inv[hand_used]] ))
{
strcat(info, " with ");
it_name(mmov_x, DESC_NOCAP_A, str_pass); // was 7
@@ -3148,7 +3273,11 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
{
strcpy(info, ptr_monam(attacker, DESC_CAP_THE));
strcat(info, " stings ");
- strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
+ if (attacker == defender)
+ strcat(info, mons_pronoun(attacker->type,
+ PRONOUN_REFLEXIVE));
+ else
+ strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
strcat(info, ".");
mpr(info);
}
@@ -3165,7 +3294,11 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
{
strcpy(info, ptr_monam(attacker, DESC_CAP_THE));
strcat(info, " stings ");
- strcpy(info, ptr_monam(defender, DESC_NOCAP_THE));
+ if (attacker == defender)
+ strcat(info, mons_pronoun(attacker->type,
+ PRONOUN_REFLEXIVE));
+ else
+ strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
strcat(info, ".");
mpr(info);
}
@@ -3218,7 +3351,11 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
{
strcpy(info, ptr_monam(attacker, DESC_CAP_THE));
strcat(info, " stings ");
- strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
+ if (attacker == defender)
+ strcat(info, mons_pronoun(attacker->type,
+ PRONOUN_REFLEXIVE));
+ else
+ strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
strcat(info, ".");
mpr(info);
}
@@ -3295,7 +3432,11 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
{
strcpy(info, ptr_monam(attacker, DESC_CAP_THE));
strcat(info, " freezes ");
- strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
+ if (attacker == defender)
+ strcat(info, mons_pronoun(attacker->type,
+ PRONOUN_REFLEXIVE));
+ else
+ strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
strcat(info, ".");
mpr(info);
}
@@ -3324,7 +3465,11 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
{
strcpy(info, ptr_monam(attacker, DESC_CAP_THE));
strcat(info, " freezes ");
- strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
+ if (attacker == defender)
+ strcat(info, mons_pronoun(attacker->type,
+ PRONOUN_REFLEXIVE));
+ else
+ strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
strcat(info, ".");
mpr(info);
}
@@ -3341,7 +3486,11 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
{
strcpy(info, ptr_monam(attacker, DESC_CAP_THE));
strcat(info, " shocks ");
- strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
+ if (attacker == defender)
+ strcat(info, mons_pronoun(attacker->type,
+ PRONOUN_REFLEXIVE));
+ else
+ strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
strcat(info, ".");
mpr(info);
}
@@ -3405,7 +3554,11 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
{
strcpy(info, ptr_monam(attacker, DESC_CAP_THE));
strcat(info, " burns ");
- strcat(info, ptr_monam(defender, DESC_NOCAP_THE ));
+ if (attacker == defender)
+ strcat(info, mons_pronoun(attacker->type,
+ PRONOUN_REFLEXIVE));
+ else
+ strcat(info, ptr_monam(defender, DESC_NOCAP_THE ));
if (specdam < 3)
strcat(info, ".");
@@ -3429,11 +3582,15 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
{
if (sees)
{
- mmov_x = attacker->inv[hand_used];
+ // mmov_x = attacker->inv[hand_used];
strcpy(info, ptr_monam(attacker, DESC_CAP_THE));
strcat(info, " freezes ");
- strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
+ if (attacker == defender)
+ strcat(info, mons_pronoun(attacker->type,
+ PRONOUN_REFLEXIVE));
+ else
+ strcat(info, ptr_monam(defender, DESC_NOCAP_THE));
if (specdam < 3)
strcat(info, ".");
@@ -3451,7 +3608,7 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
if (attacker->type == MONS_PLAYER_GHOST)
break;
specdam = 0;
- switch (mons_holiness(defender->type))
+ switch (mons_holiness(defender))
{
case MH_HOLY:
// I would think that it would do zero damage {dlb}
@@ -3465,6 +3622,9 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
case MH_DEMONIC:
specdam += 1 + (random2(damage_taken) * 15) / 10;
break;
+
+ default:
+ break;
}
break;
@@ -3496,7 +3656,7 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
break;
case SPWPN_ORC_SLAYING:
- if (mons_charclass(defender->type) == MONS_ORC)
+ if (mons_species(defender->type) == MONS_ORC)
hurt_monster(defender, 1 + random2(damage_taken));
break;
@@ -3563,7 +3723,7 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
specdam = 0;
- if (mons_holiness(defender->type) == MH_UNDEAD
+ if (mons_holiness(defender) == MH_UNDEAD
&& !one_chance_in(3))
{
simple_monster_message(defender, " shudders.");
@@ -3676,7 +3836,7 @@ static int weapon_type_modify( int weapnum, char noise[80], char noise2[80],
else if (you.inv[weapnum].base_type == OBJ_WEAPONS)
weap_type = you.inv[weapnum].sub_type;
- noise2[0] = '\0';
+ noise2[0] = 0;
// All weak hits look the same, except for when the player
// has a non-weapon in hand. -- bwr
@@ -3690,7 +3850,7 @@ static int weapon_type_modify( int weapnum, char noise[80], char noise2[80],
return (damage);
}
- // take transformations into account, if no weapon is weilded
+ // take transformations into account, if no weapon is wielded
if (weap_type == WPN_UNARMED
&& you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE)
{
@@ -3755,6 +3915,7 @@ static int weapon_type_modify( int weapnum, char noise[80], char noise2[80],
return (damage);
case WPN_BOW:
+ case WPN_LONGBOW:
case WPN_CROSSBOW:
case WPN_HAND_CROSSBOW:
if (damage < HIT_STRONG)
@@ -3776,11 +3937,14 @@ static int weapon_type_modify( int weapnum, char noise[80], char noise2[80],
case WPN_SCYTHE:
case WPN_QUICK_BLADE:
case WPN_KATANA:
+ case WPN_LAJATANG:
+ case WPN_LOCHABER_AXE:
case WPN_EXECUTIONERS_AXE:
case WPN_DOUBLE_SWORD:
case WPN_TRIPLE_SWORD:
case WPN_SABRE:
case WPN_DEMON_BLADE:
+ case WPN_BLESSED_BLADE:
if (damage < HIT_MED)
strcpy( noise, "slash" );
else if (damage < HIT_STRONG)
@@ -3797,7 +3961,7 @@ static int weapon_type_modify( int weapnum, char noise[80], char noise2[80],
case WPN_MACE:
case WPN_FLAIL:
case WPN_GREAT_MACE:
- case WPN_GREAT_FLAIL:
+ case WPN_DIRE_FLAIL:
case WPN_QUARTERSTAFF:
case WPN_GIANT_CLUB:
case WPN_HAMMER:
@@ -3857,7 +4021,7 @@ int weapon_str_weight( int wpn_class, int wpn_type )
int ret;
const int wpn_skill = weapon_skill( wpn_class, wpn_type );
- const int hands_reqd = hands_reqd_for_weapon( wpn_class, wpn_type );
+ const int hands = hands_reqd( wpn_class, wpn_type, player_size() );
// These are low values, because we'll be adding some bonus to the
// larger weapons later. Remember also that 1-1/2-hand weapons get
@@ -3898,7 +4062,7 @@ int weapon_str_weight( int wpn_class, int wpn_type )
else if (wpn_type == WPN_QUICK_BLADE) // high dex is very good for these
ret = 1;
- if (hands_reqd == HANDS_TWO_HANDED)
+ if (hands == HANDS_TWO)
ret += 2;
// most weapons are capped at 8
@@ -3929,10 +4093,9 @@ static inline int player_weapon_str_weight( void )
int ret = weapon_str_weight( you.inv[weapon].base_type, you.inv[weapon].sub_type );
const bool shield = (you.equip[EQ_SHIELD] != -1);
- const int hands_reqd = hands_reqd_for_weapon( you.inv[weapon].base_type,
- you.inv[weapon].sub_type );
+ const int hands = hands_reqd(you.inv[weapon], player_size());
- if (hands_reqd == HANDS_ONE_OR_TWO_HANDED && !shield)
+ if (hands == HANDS_HALF && !shield)
ret += 1;
return (ret);
diff --git a/crawl-ref/source/fight.h b/crawl-ref/source/fight.h
index 10515868c6..fb6a1a812b 100644
--- a/crawl-ref/source/fight.h
+++ b/crawl-ref/source/fight.h
@@ -3,6 +3,8 @@
* Summary: Functions used during combat.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -32,7 +34,7 @@ int weapon_str_weight( int wpn_class, int wpn_type );
/* ***********************************************************************
* called from: acr - it_use3
* *********************************************************************** */
-void you_attack(int monster_attacked, bool unarmed_attacks);
+bool you_attack(int monster_attacked, bool unarmed_attacks);
// last updated: 08jun2000 {dlb}
@@ -48,5 +50,9 @@ void monster_attack(int monster_attacking);
* *********************************************************************** */
bool monsters_fight(int monster_attacking, int monster_attacked);
+int calc_your_to_hit( int heavy_armour, bool hand_and_a_half_bonus,
+ bool water_attack, bool random_factor );
+
+int calc_heavy_armour_penalty( bool random_factor );
#endif
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index 367fe30ec4..03b145a45b 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -24,6 +24,7 @@
#include "AppHdr.h"
#include "files.h"
+#include "version.h"
#include <string.h>
#include <string>
@@ -31,6 +32,8 @@
#include <stdio.h>
#include <ctype.h>
+#include <algorithm>
+
#ifdef DOS
#include <conio.h>
#include <file.h>
@@ -43,22 +46,13 @@
#include <unistd.h>
#endif
-#ifdef USE_EMX
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#endif
-
-#ifdef OS9
-#include <stat.h>
-#else
-#include <sys/stat.h>
-#endif
-
#ifdef __MINGW32__
#include <io.h>
+#include <sys/types.h>
#endif
+#include <dirent.h>
+
#include "externs.h"
#include "cloud.h"
@@ -66,12 +60,15 @@
#include "debug.h"
#include "dungeon.h"
#include "itemname.h"
+#include "itemprop.h"
#include "items.h"
+#include "libutil.h"
#include "message.h"
#include "misc.h"
#include "monstuff.h"
#include "mon-util.h"
#include "mstuff2.h"
+#include "notes.h"
#include "player.h"
#include "randart.h"
#include "skills2.h"
@@ -79,7 +76,12 @@
#include "stuff.h"
#include "tags.h"
#include "travel.h"
-#include "wpn-misc.h"
+
+#ifdef SHARED_FILES_CHMOD_PRIVATE
+#define DO_CHMOD_PRIVATE(x) chmod( (x), SHARED_FILES_CHMOD_PRIVATE )
+#else
+#define DO_CHMOD_PRIVATE(x) // empty command
+#endif
void save_level(int level_saved, bool was_a_labyrinth, char where_were_you);
@@ -205,69 +207,340 @@ static void restore_tagged_file( FILE *restoreFile, int fileType,
static void load_ghost();
-std::string get_savedir_filename(const char *prefix, const char *suffix,
- const char *extension)
+static std::string uid_as_string()
{
- char filename[1200];
-#ifdef SAVE_DIR_PATH
- snprintf(filename, sizeof filename, SAVE_DIR_PATH "%s%d%s.%s",
- prefix, (int) getuid(), suffix, extension);
+#ifdef MULTIUSER
+ char struid[20];
+ snprintf( struid, sizeof struid, "%d", (int)getuid() );
+ return std::string(struid);
#else
- snprintf(filename, sizeof filename, "%s%s.%s",
- prefix, suffix, extension);
+ return std::string();
+#endif
+}
+
+static bool is_uid_file(const std::string &name, const std::string &ext)
+{
+ std::string save_suffix = get_savedir_filename("", "", "");
+ save_suffix += ext;
#ifdef DOS
- strupr(filename);
+ // Grumble grumble. Hang all retarded operating systems.
+ uppercase(save_suffix);
#endif
+
+ save_suffix = save_suffix.substr(Options.save_dir.length());
+
+ std::string::size_type suffix_pos = name.find(save_suffix);
+ return (suffix_pos != std::string::npos
+ && suffix_pos == name.length() - save_suffix.length()
+ && suffix_pos != 0
+#ifdef MULTIUSER
+ // See verifyPlayerName() in newgame.cc
+ && !isdigit(name[suffix_pos - 1])
#endif
- return std::string(filename);
+ );
+
}
-std::string get_prefs_filename()
+static bool is_save_file_name(const std::string &name)
{
- return get_savedir_filename("start", "ns", "prf");
+ return is_uid_file(name, ".sav");
}
-void make_filename( char *buf, const char *prefix, int level, int where,
- bool isLabyrinth, bool isGhost )
+#ifdef LOAD_UNPACKAGE_CMD
+static bool is_packed_save(const std::string &name)
{
- UNUSED( isGhost );
+ return is_uid_file(name, PACKAGE_SUFFIX);
+}
+#endif
- char suffix[4], lvl[5];
- char finalprefix[kFileNameLen];
+// Returns a full player struct read from the save.
+static player read_character_info(const std::string &savefile)
+{
+ player fromfile;
+ player backup = you;
- strcpy(suffix, (level < 10) ? "0" : "");
- itoa(level, lvl, 10);
- strcat(suffix, lvl);
- suffix[2] = where + 97;
- suffix[3] = '\0';
+ FILE *charf = fopen(savefile.c_str(), "rb");
+ if (!charf)
+ return fromfile;
+
+ char majorVersion = 0;
+ char minorVersion = 0;
+
+ if (!determine_version(charf, majorVersion, minorVersion))
+ goto done_reading_character;
+
+ if (majorVersion != SAVE_MAJOR_VERSION)
+ goto done_reading_character;
- // init buf
- buf[0] = '\0';
+ restore_tagged_file(charf, TAGTYPE_PLAYER_NAME, minorVersion);
+ fromfile = you;
+ you = backup;
+
+done_reading_character:
+ fclose(charf);
+ return fromfile;
+}
-#ifdef SAVE_DIR_PATH
- strcpy(buf, SAVE_DIR_PATH);
+// Returns the names of all files in the given directory. Note that the
+// filenames returned are relative to the directory.
+static std::vector<std::string> get_dir_files(const std::string &dirname)
+{
+ std::vector<std::string> files;
+
+ DIR *dir = opendir(dirname.c_str());
+ if (!dir)
+ return (files);
+
+ while (dirent *entry = readdir(dir))
+ {
+ std::string name = entry->d_name;
+ if (name == "." || name == "..")
+ continue;
+
+ files.push_back(name);
+ }
+ closedir(dir);
+
+ return (files);
+}
+
+static bool file_exists(const std::string &name)
+{
+ FILE *f = fopen(name.c_str(), "r");
+ const bool exists = !!f;
+ if (f)
+ fclose(f);
+ return (exists);
+}
+
+// Low-tech existence check.
+static bool dir_exists(const std::string &dir)
+{
+ DIR *d = opendir(dir.c_str());
+ const bool exists = !!d;
+ if (d)
+ closedir(d);
+
+ return (exists);
+}
+
+static int create_directory(const char *dir)
+{
+#if defined(MULTIUSER)
+ return mkdir(dir, SHARED_FILES_CHMOD_PUBLIC | 0111);
+#elif defined(DOS)
+ // djgpp doesn't seem to have mkdir.
+ return (-1);
+#else
+ return mkdir(dir);
#endif
+}
- strncpy(finalprefix, prefix, kFileNameLen);
- finalprefix[kFileNameLen] = '\0';
+static bool create_dirs(const std::string &dir)
+{
+ std::string sep = " ";
+ sep[0] = FILE_SEPARATOR;
+ std::vector<std::string> segments =
+ split_string(
+ sep.c_str(),
+ dir,
+ false,
+ false);
+
+ std::string path;
+ for (int i = 0, size = segments.size(); i < size; ++i)
+ {
+ path += segments[i];
+ path += FILE_SEPARATOR;
+
+ if (!dir_exists(path) && create_directory(path.c_str()))
+ return (false);
+ }
+ return (true);
+}
+
+std::string datafile_path(const std::string &basename)
+{
+ std::string cdir = SysEnv.crawl_dir? SysEnv.crawl_dir : "";
+
+ const std::string rawbases[] = {
+#ifdef DATA_DIR_PATH
+ DATA_DIR_PATH,
+#else
+ cdir,
+#endif
+ };
- strcat(buf, finalprefix);
+ const std::string prefixes[] = {
+ std::string("dat") + FILE_SEPARATOR,
+ std::string("data") + FILE_SEPARATOR,
+ std::string("crawl-data") + FILE_SEPARATOR,
+ "",
+ };
-#ifdef SAVE_DIR_PATH
- // everyone sees everyone else's ghosts. :)
- char uid[10];
- if (!isGhost)
+ std::vector<std::string> bases;
+ for (unsigned i = 0; i < sizeof(rawbases) / sizeof(*rawbases); ++i)
{
- itoa( (int) getuid(), uid, 10 );
- strcat(buf, uid);
+ std::string base = rawbases[i];
+ if (base.empty())
+ continue;
+
+ if (base[base.length() - 1] != FILE_SEPARATOR)
+ base += FILE_SEPARATOR;
+ bases.push_back(base);
}
+
+#ifndef DATA_DIR_PATH
+ bases.push_back("");
#endif
- strcat(buf, ".");
- if (isLabyrinth)
- strcat(buf, "lab"); // temporary level
- else
- strcat(buf, suffix);
+ for (unsigned b = 0, size = bases.size(); b < size; ++b)
+ {
+ for (unsigned p = 0; p < sizeof(prefixes) / sizeof(*prefixes); ++p)
+ {
+ std::string name = bases[b] + prefixes[p] + basename;
+ if (file_exists(name))
+ return (name);
+ }
+ }
+
+ // Die horribly.
+ fprintf(stderr, "Cannot find data file '%s' anywhere, aborting\n",
+ basename.c_str());
+ exit(1);
+
+ return ("");
+}
+
+void check_savedir(std::string &dir)
+{
+ if (dir.empty())
+ return;
+
+ std::string sep = " ";
+ sep[0] = FILE_SEPARATOR;
+
+ dir = replace_all(dir, "/", sep);
+ dir = replace_all(dir, "\\", sep);
+
+ // Suffix the separator if necessary
+ if (dir[dir.length() - 1] != FILE_SEPARATOR)
+ dir += FILE_SEPARATOR;
+
+ if (!dir_exists(dir) && !create_dirs(dir))
+ {
+ fprintf(stderr, "Save directory \"%s\" does not exist "
+ "and I can't create it.\n",
+ dir.c_str());
+ exit(1);
+ }
+}
+
+// Given a simple (relative) name of a save file, returns the full path of
+// the file in the Crawl saves directory.
+std::string get_savedir_path(const std::string &shortpath)
+{
+ return (Options.save_dir + shortpath);
+}
+
+/*
+ * Returns a list of the names of characters that are already saved for the
+ * current user.
+ */
+std::vector<player> find_saved_characters()
+{
+ std::string searchpath = Options.save_dir;
+
+ if (searchpath.empty())
+ searchpath = ".";
+
+ std::vector<std::string> allfiles = get_dir_files(searchpath);
+ std::vector<player> chars;
+ for (int i = 0, size = allfiles.size(); i < size; ++i)
+ {
+ std::string filename = allfiles[i];
+#ifdef LOAD_UNPACKAGE_CMD
+ if (!is_packed_save(filename))
+ continue;
+
+ std::string basename =
+ filename.substr(
+ 0,
+ filename.length() - strlen(PACKAGE_SUFFIX));
+
+ std::string zipname = get_savedir_path(basename);
+
+ // This is the filename we actually read ourselves.
+ filename = basename + ".sav";
+
+ char cmd_buff[1024];
+ snprintf( cmd_buff, sizeof(cmd_buff), UNPACK_SPECIFIC_FILE_CMD,
+ zipname.c_str(),
+ filename.c_str() );
+
+ if (system(cmd_buff) != 0)
+ continue;
+#endif
+ if (is_save_file_name(filename))
+ {
+ player p = read_character_info(get_savedir_path(filename));
+ if (p.is_valid())
+ chars.push_back(p);
+ }
+
+#ifdef LOAD_UNPACKAGE_CMD
+ // If we unpacked the .sav file, throw it away now.
+ unlink( get_savedir_path(filename).c_str() );
+#endif
+ }
+
+ std::sort(chars.begin(), chars.end());
+ return (chars);
+}
+
+std::string get_savedir_filename(const char *prefix, const char *suffix,
+ const char *extension, bool suppress_uid)
+{
+ std::string result = Options.save_dir;
+
+ // Shorten string as appropriate
+ result += std::string(prefix).substr(0, kFileNameLen);
+
+ // Technically we should shorten the string first. But if
+ // MULTIUSER is set we'll have long filenames anyway. Caveat
+ // emptor.
+ if ( !suppress_uid )
+ result += uid_as_string();
+
+ result += suffix;
+
+ if ( *extension ) {
+ result += '.';
+ result += extension;
+ }
+
+#ifdef DOS
+ uppercase(result);
+#endif
+ return result;
+}
+
+std::string get_prefs_filename()
+{
+ return get_savedir_filename("start", "ns", "prf");
+}
+
+std::string make_filename( const char *prefix, int level, int where,
+ bool isLabyrinth, bool isGhost )
+{
+ char suffix[4], lvl[5];
+ strcpy(suffix, (level < 10) ? "0" : "");
+ itoa(level, lvl, 10);
+ strcat(suffix, lvl);
+ suffix[2] = where + 97;
+ suffix[3] = 0;
+ return get_savedir_filename( prefix, "", isLabyrinth ? "lab" : suffix,
+ isGhost );
}
static void write_tagged_file( FILE *dataFile, char majorVersion,
@@ -300,16 +573,9 @@ static void write_tagged_file( FILE *dataFile, char majorVersion,
bool travel_load_map( char branch, int absdepth )
{
- char cha_fil[kFileNameSize];
-
- make_filename( cha_fil, you.your_name, absdepth, branch,
- false, false );
-#ifdef DOS
- strupr(cha_fil);
-#endif
-
// Try to open level savefile.
- FILE *levelFile = fopen(cha_fil, "rb");
+ FILE *levelFile = fopen(make_filename(you.your_name, absdepth, branch,
+ false, false).c_str(), "rb");
if (!levelFile)
return false;
@@ -320,7 +586,7 @@ bool travel_load_map( char branch, int absdepth )
char minorVersion;
if (!determine_level_version( levelFile, majorVersion, minorVersion )
- || majorVersion != 4)
+ || majorVersion != SAVE_MAJOR_VERSION)
{
fclose(levelFile);
return false;
@@ -333,37 +599,22 @@ bool travel_load_map( char branch, int absdepth )
return true;
}
+struct follower {
+ monsters mons;
+ std::vector<item_def> items;
+
+ follower() : mons(), items() { }
+ follower(const monsters &m) : mons(m), items() { }
+};
+
void load( unsigned char stair_taken, int load_mode, bool was_a_labyrinth,
char old_level, char where_were_you2 )
{
int j = 0;
int i = 0, count_x = 0, count_y = 0;
- char cha_fil[kFileNameSize];
-
- int foll_class[8];
- int foll_hp[8];
- int foll_hp_max[8];
- unsigned char foll_HD[8];
- int foll_AC[8];
- char foll_ev[8];
- unsigned char foll_speed[8];
- unsigned char foll_speed_inc[8];
-
- unsigned char foll_targ_1_x[8];
- unsigned char foll_targ_1_y[8];
- unsigned char foll_beh[8];
- unsigned char foll_att[8];
- int foll_sec[8];
- unsigned char foll_hit[8];
-
- unsigned char foll_ench[8][NUM_MON_ENCHANTS];
- unsigned char foll_flags[8];
-
- item_def foll_item[8][8];
-
- int itmf = 0;
- int ic = 0;
- int imn = 0;
+
+ std::vector<follower> followers;
+
int val;
bool just_created_level = false;
@@ -372,15 +623,17 @@ void load( unsigned char stair_taken, int load_mode, bool was_a_labyrinth,
window(1, 1, 80, 25);
#endif
- make_filename( cha_fil, you.your_name, you.your_level, you.where_are_you,
- you.level_type != LEVEL_DUNGEON, false );
+ std::string cha_fil = make_filename( you.your_name, you.your_level,
+ you.where_are_you,
+ you.level_type != LEVEL_DUNGEON,
+ false );
if (you.level_type == LEVEL_DUNGEON)
{
if (tmp_file_pairs[you.your_level][you.where_are_you] == false)
{
// make sure old file is gone
- unlink(cha_fil);
+ unlink(cha_fil.c_str());
// save the information for later deletion -- DML 6/11/99
tmp_file_pairs[you.your_level][you.where_are_you] = true;
@@ -389,9 +642,6 @@ void load( unsigned char stair_taken, int load_mode, bool was_a_labyrinth,
you.prev_targ = MHITNOT;
- int following = -1;
- int minvc = 0;
-
// Don't delete clouds just because the player saved and restarted.
if (load_mode != LOAD_RESTART_GAME)
{
@@ -412,13 +662,10 @@ void load( unsigned char stair_taken, int load_mode, bool was_a_labyrinth,
if (count_x == you.x_pos && count_y == you.y_pos)
continue;
- following++;
- foll_class[following] = -1;
-
if (mgrd[count_x][count_y] == NON_MONSTER)
continue;
- struct monsters *fmenv = &menv[mgrd[count_x][count_y]];
+ monsters *fmenv = &menv[mgrd[count_x][count_y]];
if (fmenv->type == MONS_PLAYER_GHOST
&& fmenv->hit_points < fmenv->max_hit_points / 2)
@@ -438,52 +685,23 @@ void load( unsigned char stair_taken, int load_mode, bool was_a_labyrinth,
mpr( info, MSGCH_DIAGNOSTICS );
#endif
- foll_class[following] = fmenv->type;
- foll_hp[following] = fmenv->hit_points;
- foll_hp_max[following] = fmenv->max_hit_points;
- foll_HD[following] = fmenv->hit_dice;
- foll_AC[following] = fmenv->armour_class;
- foll_ev[following] = fmenv->evasion;
- foll_speed[following] = fmenv->speed;
- foll_speed_inc[following] = fmenv->speed_increment;
- foll_targ_1_x[following] = fmenv->target_x;
- foll_targ_1_y[following] = fmenv->target_y;
-
- for (minvc = 0; minvc < NUM_MONSTER_SLOTS; ++minvc)
+ follower f(*fmenv);
+
+ for (int minvc = 0; minvc < NUM_MONSTER_SLOTS; ++minvc)
{
const int item = fmenv->inv[minvc];
if (item == NON_ITEM)
{
- foll_item[following][minvc].quantity = 0;
+ f.items.push_back(item_def());
continue;
}
- foll_item[following][minvc] = mitm[item];
+ f.items.push_back(mitm[item]);
destroy_item( item );
}
- foll_beh[following] = fmenv->behaviour;
- foll_att[following] = fmenv->attitude;
- foll_sec[following] = fmenv->number;
- foll_hit[following] = fmenv->foe;
-
- for (j = 0; j < NUM_MON_ENCHANTS; j++)
- {
- foll_ench[following][j] = fmenv->enchantment[j];
- fmenv->enchantment[j] = ENCH_NONE;
- }
-
- foll_flags[following] = fmenv->flags;
-
- fmenv->flags = 0;
- fmenv->type = -1;
- fmenv->hit_points = 0;
- fmenv->max_hit_points = 0;
- fmenv->hit_dice = 0;
- fmenv->armour_class = 0;
- fmenv->evasion = 0;
-
- mgrd[count_x][count_y] = NON_MONSTER;
+ followers.push_back(f);
+ monster_cleanup(fmenv);
}
} // end of grabbing followers
@@ -495,22 +713,18 @@ void load( unsigned char stair_taken, int load_mode, bool was_a_labyrinth,
// clear out ghost/demon lord information:
strcpy( ghost.name, "" );
- for (ic = 0; ic < NUM_GHOST_VALUES; ++ic)
+ for (int ic = 0; ic < NUM_GHOST_VALUES; ++ic)
ghost.values[ic] = 0;
-#ifdef DOS
- strupr(cha_fil);
-#endif
-
// Try to open level savefile.
- FILE *levelFile = fopen(cha_fil, "rb");
+ FILE *levelFile = fopen(cha_fil.c_str(), "rb");
// GENERATE new level when the file can't be opened:
if (levelFile == NULL)
{
strcpy(ghost.name, "");
- for (imn = 0; imn < NUM_GHOST_VALUES; ++imn)
+ for (int imn = 0; imn < NUM_GHOST_VALUES; ++imn)
ghost.values[imn] = 0;
builder( you.your_level, you.level_type );
@@ -541,7 +755,7 @@ void load( unsigned char stair_taken, int load_mode, bool was_a_labyrinth,
// sanity check - EOF
if (!feof( levelFile ))
{
- snprintf( info, INFO_SIZE, "\nIncomplete read of \"%s\" - aborting.\n", cha_fil);
+ snprintf( info, INFO_SIZE, "\nIncomplete read of \"%s\" - aborting.\n", cha_fil.c_str());
perror(info);
end(-1);
}
@@ -747,15 +961,14 @@ found_stair:
if (you.level_type == LEVEL_LABYRINTH || you.level_type == LEVEL_ABYSS)
grd[you.x_pos][you.y_pos] = DNGN_FLOOR;
*/
- following = 0;
- int fmenv = -1;
+ int following = 0;
// actually "move" the followers if applicable
if ((you.level_type == LEVEL_DUNGEON
|| you.level_type == LEVEL_PANDEMONIUM)
&& load_mode == LOAD_ENTER_LEVEL)
{
- for (ic = 0; ic < 2; ic++)
+ for (int ic = 0; ic < 2; ic++)
{
for (count_x = you.x_pos - 6; count_x < you.x_pos + 7;
count_x++)
@@ -789,64 +1002,41 @@ found_stair:
goto out_of_foll;
}
- while (fmenv < 7)
+ if (followers.size())
{
- fmenv++;
-
- if (foll_class[fmenv] == -1)
- continue;
-
- menv[following].type = foll_class[fmenv];
- menv[following].hit_points = foll_hp[fmenv];
- menv[following].max_hit_points = foll_hp_max[fmenv];
- menv[following].hit_dice = foll_HD[fmenv];
- menv[following].armour_class = foll_AC[fmenv];
- menv[following].evasion = foll_ev[fmenv];
- menv[following].speed = foll_speed[fmenv];
+ follower f = followers.front();
+ followers.erase(followers.begin());
+
+ menv[following] = f.mons;
menv[following].x = count_x;
menv[following].y = count_y;
menv[following].target_x = 0;
menv[following].target_y = 0;
- menv[following].speed_increment = foll_speed_inc[fmenv];
+ menv[following].flags |= MF_JUST_SUMMONED;
- for (minvc = 0; minvc < NUM_MONSTER_SLOTS; minvc++)
+ for (int minvc = 0; minvc < NUM_MONSTER_SLOTS; minvc++)
{
+ menv[following].inv[minvc] = NON_ITEM;
- if (!is_valid_item(foll_item[fmenv][minvc]))
- {
- menv[following].inv[minvc] = NON_ITEM;
- continue;
- }
-
- itmf = get_item_slot(0);
- if (itmf == NON_ITEM)
+ const item_def &minvitem = f.items[minvc];
+ if (minvitem.base_type != OBJ_UNASSIGNED)
{
- menv[following].inv[minvc] = NON_ITEM;
- continue;
+ int itmf = get_item_slot(0);
+ if (itmf == NON_ITEM)
+ {
+ menv[following].inv[minvc] = NON_ITEM;
+ continue;
+ }
+
+ mitm[itmf] = minvitem;
+ mitm[itmf].x = 0;
+ mitm[itmf].y = 0;
+ mitm[itmf].link = NON_ITEM;
+ menv[following].inv[minvc] = itmf;
}
-
- mitm[itmf] = foll_item[fmenv][minvc];
- mitm[itmf].x = 0;
- mitm[itmf].y = 0;
- mitm[itmf].link = NON_ITEM;
-
- menv[following].inv[minvc] = itmf;
}
-
- menv[following].behaviour = foll_beh[fmenv];
- menv[following].attitude = foll_att[fmenv];
- menv[following].number = foll_sec[fmenv];
- menv[following].foe = foll_hit[fmenv];
-
- for (j = 0; j < NUM_MON_ENCHANTS; j++)
- menv[following].enchantment[j]=foll_ench[fmenv][j];
-
- menv[following].flags = foll_flags[fmenv];
- menv[following].flags |= MF_JUST_SUMMONED;
-
mgrd[count_x][count_y] = following;
- break;
- }
+ } // followers.size()
}
}
}
@@ -932,24 +1122,18 @@ found_stair:
void save_level(int level_saved, bool was_a_labyrinth, char where_were_you)
{
- char cha_fil[kFileNameSize];
-
- make_filename( cha_fil, you.your_name, level_saved, where_were_you,
- was_a_labyrinth, false );
+ std::string cha_fil = make_filename( you.your_name, level_saved,
+ where_were_you, was_a_labyrinth,
+ false );
you.prev_targ = MHITNOT;
-#ifdef DOS
- strupr(cha_fil);
-#endif
-
- FILE *saveFile = fopen(cha_fil, "wb");
+ FILE *saveFile = fopen(cha_fil.c_str(), "wb");
if (saveFile == NULL)
{
- strcpy(info, "Unable to open \"");
- strcat(info, cha_fil );
- strcat(info, "\" for writing!");
+ snprintf(info, INFO_SIZE, "Unable to open \"%s\" for writing!",
+ cha_fil.c_str());
perror(info);
end(-1);
}
@@ -957,164 +1141,95 @@ void save_level(int level_saved, bool was_a_labyrinth, char where_were_you)
// nail all items to the ground
fix_item_coordinates();
- // 4.0 initial genesis of saved format
- // 4.1 added attitude tag
- // 4.2 replaced old 'enchantment1' and with 'flags' (bitfield)
- // 4.3 changes to make the item structure more sane
- // 4.4 changes to the ghost save section
- // 4.5 spell and ability letter arrays
- // 4.6 inventory slots of items
- // 4.7 origin tracking for items
- // 4.8 widened env.map to 2 bytes
+ // 0.0 initial genesis of saved format
+ // 0.1 added attitude tag
+ // 0.2 replaced old 'enchantment1' and with 'flags' (bitfield)
+ // 0.3 changes to make the item structure more sane
+ // 0.4 changes to the ghost save section
+ // 0.5 spell and ability letter arrays
+ // 0.6 inventory slots of items
+ // 0.7 origin tracking for items
+ // 0.8 widened env.map to 2 bytes
+ // 0.9 inscriptions (hp)
+ // 0.10 Monster colour and spells separated from mons->number.
- write_tagged_file( saveFile, 4, 8, TAGTYPE_LEVEL );
+ write_tagged_file( saveFile, SAVE_MAJOR_VERSION, 10, TAGTYPE_LEVEL );
fclose(saveFile);
-#ifdef SHARED_FILES_CHMOD_PRIVATE
- chmod(cha_fil, SHARED_FILES_CHMOD_PRIVATE);
-#endif
+ DO_CHMOD_PRIVATE(cha_fil.c_str());
} // end save_level()
+
void save_game(bool leave_game)
{
- char charFile[kFileNameSize];
-#ifdef STASH_TRACKING
- char stashFile[kFileNameSize + 4];
-#endif
- char killFile[kFileNameSize + 4];
- char travelCacheFile[kFileNameSize + 4];
-#ifdef CLUA_BINDINGS
- char luaFile[kFileNameSize + 4];
-#endif
-
-#ifdef SAVE_PACKAGE_CMD
- char cmd_buff[1024];
- char name_buff[kFileNameSize];
-
- snprintf( name_buff, sizeof(name_buff),
- SAVE_DIR_PATH "%s%d", you.your_name, (int) getuid() );
-
- snprintf( cmd_buff, sizeof(cmd_buff),
- SAVE_PACKAGE_CMD, name_buff, name_buff );
#ifdef STASH_TRACKING
- strcpy(stashFile, name_buff);
-#endif
-#ifdef CLUA_BINDINGS
- strcpy(luaFile, name_buff);
-#endif
- strcpy(killFile, name_buff);
- strcpy(travelCacheFile, name_buff);
- snprintf( charFile, sizeof(charFile),
- "%s.sav", name_buff );
-
-#else
- strncpy(charFile, you.your_name, kFileNameLen);
- charFile[kFileNameLen] = 0;
-
-#ifdef STASH_TRACKING
- strcpy(stashFile, charFile);
-#endif
-#ifdef CLUA_BINDINGS
- strcpy(luaFile, charFile);
-#endif
- strcpy(killFile, charFile);
- strcpy(travelCacheFile, charFile);
- strcat(charFile, ".sav");
-
-#ifdef DOS
- strupr(charFile);
-#ifdef STASH_TRACKING
- strupr(stashFile);
-#endif
-#ifdef CLUA_BINDINGS
- strupr(luaFile);
-#endif
- strupr(killFile);
- strupr(travelCacheFile);
-#endif
-#endif
-
-#ifdef STASH_TRACKING
- strcat(stashFile, ".st");
-#endif
-#ifdef CLUA_BINDINGS
- strcat(luaFile, ".lua");
-#endif
- strcat(killFile, ".kil");
- strcat(travelCacheFile, ".tc");
-
-#ifdef STASH_TRACKING
- FILE *stashf = fopen(stashFile, "wb");
- if (stashf)
- {
+ /* Stashes */
+ std::string stashFile = get_savedir_filename( you.your_name, "", "st" );
+ FILE *stashf = fopen(stashFile.c_str(), "wb");
+ if (stashf) {
stashes.save(stashf);
fclose(stashf);
-
-#ifdef SHARED_FILES_CHMOD_PRIVATE
- // change mode (unices)
- chmod(stashFile, SHARED_FILES_CHMOD_PRIVATE);
-#endif
+ DO_CHMOD_PRIVATE(stashFile.c_str());
}
-#endif // STASH_TRACKING
-
-#ifdef CLUA_BINDINGS
- clua.save(luaFile);
-#ifdef SHARED_FILES_CHMOD_PRIVATE
- // change mode; note that luaFile may not exist
- chmod(luaFile, SHARED_FILES_CHMOD_PRIVATE);
#endif
-#endif // CLUA_BINDINGS
- FILE *travelf = fopen(travelCacheFile, "wb");
- if (travelf)
- {
- travel_cache.save(travelf);
- fclose(travelf);
-#ifdef SHARED_FILES_CHMOD_PRIVATE
- // change mode (unices)
- chmod(travelCacheFile, SHARED_FILES_CHMOD_PRIVATE);
+#ifdef CLUA_BINDINGS
+ /* lua */
+ std::string luaFile = get_savedir_filename( you.your_name, "", "lua" );
+ clua.save(luaFile.c_str());
+ // note that luaFile may not exist
+ DO_CHMOD_PRIVATE(luaFile.c_str());
#endif
- }
- FILE *killf = fopen(killFile, "wb");
- if (killf)
- {
+ /* kills */
+ std::string killFile = get_savedir_filename( you.your_name, "", "kil" );
+ FILE *killf = fopen(killFile.c_str(), "wb");
+ if (killf) {
you.kills.save(killf);
fclose(killf);
-
-#ifdef SHARED_FILES_CHMOD_PRIVATE
- // change mode (unices)
- chmod(killFile, SHARED_FILES_CHMOD_PRIVATE);
-#endif
+ DO_CHMOD_PRIVATE(killFile.c_str());
}
- FILE *saveFile = fopen(charFile, "wb");
-
- if (saveFile == NULL)
- {
- strcpy(info, "Unable to open \"");
- strcat(info, charFile );
- strcat(info, "\" for writing!");
- perror(info);
- end(-1);
+ /* travel cache */
+ std::string travelCacheFile = get_savedir_filename(you.your_name,"","tc");
+ FILE *travelf = fopen(travelCacheFile.c_str(), "wb");
+ if (travelf) {
+ travel_cache.save(travelf);
+ fclose(travelf);
+ DO_CHMOD_PRIVATE(travelCacheFile.c_str());
+ }
+
+ /* notes */
+ std::string notesFile = get_savedir_filename(you.your_name, "", "nts");
+ FILE *notesf = fopen(notesFile.c_str(), "wb");
+ if (notesf) {
+ save_notes(notesf);
+ fclose(notesf);
+ DO_CHMOD_PRIVATE(notesFile.c_str());
}
- // 4.0 initial genesis of saved format
- // 4.1 changes to make the item structure more sane
- // 4.2 spell and ability tables
- // 4.3 added you.magic_contamination (05/03/05)
- // 4.4 added item origins
-
- write_tagged_file( saveFile, 4, 4, TAGTYPE_PLAYER );
+ std::string charFile = get_savedir_filename(you.your_name, "", "sav");
+ FILE *charf = fopen(charFile.c_str(), "wb");
+ if (!charf) {
+ snprintf(info, INFO_SIZE, "Unable to open \"%s\" for writing!\n",
+ charFile.c_str());
+ perror(info);
+ end(-1);
+ }
- fclose(saveFile);
+ // 0.0 initial genesis of saved format
+ // 0.1 changes to make the item structure more sane
+ // 0.2 spell and ability tables
+ // 0.3 added you.magic_contamination (05/03/05)
+ // 0.4 added item origins
+ // 0.5 added num_gifts
+ // 0.6 inscriptions
+ write_tagged_file( charf, SAVE_MAJOR_VERSION, 6, TAGTYPE_PLAYER );
-#ifdef SHARED_FILES_CHMOD_PRIVATE
- // change mode (unices)
- chmod(charFile, SHARED_FILES_CHMOD_PRIVATE);
-#endif
+ fclose(charf);
+ DO_CHMOD_PRIVATE(charFile.c_str());
// if just save, early out
if (!leave_game)
@@ -1131,21 +1246,19 @@ void save_game(bool leave_game)
clrscr();
#ifdef SAVE_PACKAGE_CMD
- if (system( cmd_buff ) != 0)
- {
- cprintf( EOL "Warning: Zip command (SAVE_PACKAGE_CMD) returned non-zero value!" EOL );
- }
+ std::string basename = get_savedir_filename(you.your_name, "", "");
+ char cmd_buff[1024];
-#ifdef SHARED_FILES_CHMOD_PRIVATE
- strcat( name_buff, PACKAGE_SUFFIX );
- // change mode (unices)
- chmod( name_buff, SHARED_FILES_CHMOD_PRIVATE );
-#endif
+ snprintf( cmd_buff, sizeof(cmd_buff),
+ SAVE_PACKAGE_CMD, basename.c_str(), basename.c_str() );
+ if (system( cmd_buff ) != 0) {
+ cprintf( EOL "Warning: Zip command (SAVE_PACKAGE_CMD) returned non-zero value!" EOL );
+ }
+ DO_CHMOD_PRIVATE ( (basename + PACKAGE_SUFFIX).c_str() );
#endif
cprintf( "See you soon, %s!" EOL , you.your_name );
-
end(0);
} // end save_game()
@@ -1153,14 +1266,15 @@ void load_ghost(void)
{
char majorVersion;
char minorVersion;
- char cha_fil[kFileNameSize];
int imn;
int i;
- make_filename( cha_fil, "bones", you.your_level, you.where_are_you,
- (you.level_type != LEVEL_DUNGEON), true );
+ std::string cha_fil = make_filename("bones", you.your_level,
+ you.where_are_you,
+ (you.level_type != LEVEL_DUNGEON),
+ true );
- FILE *gfile = fopen(cha_fil, "rb");
+ FILE *gfile = fopen(cha_fil.c_str(), "rb");
if (gfile == NULL)
return; // no such ghost.
@@ -1170,7 +1284,7 @@ void load_ghost(void)
fclose(gfile);
#if DEBUG_DIAGNOSTICS
snprintf( info, INFO_SIZE, "Ghost file \"%s\" seems to be invalid.",
- cha_fil);
+ cha_fil.c_str());
mpr( info, MSGCH_DIAGNOSTICS );
more();
#endif
@@ -1184,8 +1298,8 @@ void load_ghost(void)
{
fclose(gfile);
#if DEBUG_DIAGNOSTICS
- snprintf( info, INFO_SIZE, "Incomplete read of \"%s\".", cha_fil);
- mpr( info, MSGCH_DIAGNOSTICS );
+ mprf(MSGCH_DIAGNOSTICS, "Incomplete read of \"%s\".",
+ cha_fil.c_str() );
more();
#endif
return;
@@ -1198,7 +1312,7 @@ void load_ghost(void)
#endif
// remove bones file - ghosts are hardly permanent.
- unlink(cha_fil);
+ unlink(cha_fil.c_str());
// translate ghost to monster and place.
for (imn = 0; imn < MAX_MONSTERS - 10; imn++)
@@ -1219,17 +1333,9 @@ void load_ghost(void)
menv[imn].flags = 0;
menv[imn].foe = MHITNOT;
menv[imn].foe_memory = 0;
-
+ menv[imn].colour = mons_class_colour(MONS_PLAYER_GHOST);
menv[imn].number = 250;
-
- for (i = GVAL_SPELL_1; i <= GVAL_SPELL_6; i++)
- {
- if (ghost.values[i] != MS_NO_SPELL)
- {
- menv[imn].number = MST_GHOST;
- break;
- }
- }
+ mons_load_spells(&menv[imn], MST_GHOST);
for (i = 0; i < NUM_MONSTER_SLOTS; i++)
menv[imn].inv[i] = NON_ITEM;
@@ -1253,58 +1359,12 @@ void load_ghost(void)
void restore_game(void)
{
- char char_f[kFileNameSize];
- char kill_f[kFileNameSize];
- char travel_f[kFileNameSize];
-#ifdef STASH_TRACKING
- char stash_f[kFileNameSize];
-#endif
-
-#ifdef CLUA_BINDINGS
- char lua_f[kFileNameSize];
-#endif
-
-#ifdef SAVE_DIR_PATH
- snprintf( char_f, sizeof(char_f),
- SAVE_DIR_PATH "%s%d", you.your_name, (int) getuid() );
-#else
- strncpy(char_f, you.your_name, kFileNameLen);
- char_f[kFileNameLen] = 0;
-#endif
-
- strcpy(kill_f, char_f);
- strcpy(travel_f, char_f);
-#ifdef CLUA_BINDINGS
- strcpy(lua_f, char_f);
- strcat(lua_f, ".lua");
-#endif
-#ifdef STASH_TRACKING
- strcpy(stash_f, char_f);
- strcat(stash_f, ".st");
-#endif
- strcat(kill_f, ".kil");
- strcat(travel_f, ".tc");
- strcat(char_f, ".sav");
-
-#ifdef DOS
- strupr(char_f);
-#ifdef STASH_TRACKING
- strupr(stash_f);
-#endif
- strupr(kill_f);
- strupr(travel_f);
-#ifdef CLUA_BINDINGS
- strupr(lua_f);
-#endif
-#endif
-
- FILE *restoreFile = fopen(char_f, "rb");
-
- if (restoreFile == NULL)
+ std::string charFile = get_savedir_filename(you.your_name, "", "sav");
+ FILE *charf = fopen(charFile.c_str(), "rb");
+ if (!charf )
{
- strcpy(info, "Unable to open \"");
- strcat(info, char_f );
- strcat(info, "\" for reading!");
+ snprintf(info, INFO_SIZE, "Unable to open %s for reading!\n",
+ charFile.c_str() );
perror(info);
end(-1);
}
@@ -1312,49 +1372,58 @@ void restore_game(void)
char majorVersion = 0;
char minorVersion = 0;
- if (!determine_version(restoreFile, majorVersion, minorVersion))
+ if (!determine_version(charf, majorVersion, minorVersion))
{
perror("\nSavefile appears to be invalid.\n");
end(-1);
}
- restore_version(restoreFile, majorVersion, minorVersion);
+ restore_version(charf, majorVersion, minorVersion);
// sanity check - EOF
- if (!feof(restoreFile))
+ if (!feof(charf))
{
- snprintf( info, INFO_SIZE, "\nIncomplete read of \"%s\" - aborting.\n", char_f);
+ snprintf( info, INFO_SIZE, "\nIncomplete read of \"%s\" - aborting.\n",
+ charFile.c_str());
perror(info);
end(-1);
}
- fclose(restoreFile);
+ fclose(charf);
#ifdef STASH_TRACKING
- FILE *stashFile = fopen(stash_f, "rb");
- if (stashFile)
- {
- stashes.load(stashFile);
- fclose(stashFile);
+ std::string stashFile = get_savedir_filename( you.your_name, "", "st" );
+ FILE *stashf = fopen(stashFile.c_str(), "rb");
+ if (stashf) {
+ stashes.load(stashf);
+ fclose(stashf);
}
#endif
#ifdef CLUA_BINDINGS
- clua.execfile( lua_f );
-#endif // CLUA_BINDINGS
+ std::string luaFile = get_savedir_filename( you.your_name, "", "lua" );
+ clua.execfile( luaFile.c_str() );
+#endif
- FILE *travelFile = fopen(travel_f, "rb");
- if (travelFile)
- {
- travel_cache.load(travelFile);
- fclose(travelFile);
+ std::string killFile = get_savedir_filename( you.your_name, "", "kil" );
+ FILE *killf = fopen(killFile.c_str(), "rb");
+ if (killf) {
+ you.kills.load(killf);
+ fclose(killf);
}
- FILE *killFile = fopen(kill_f, "rb");
- if (killFile)
- {
- you.kills.load(killFile);
- fclose(killFile);
+ std::string travelCacheFile = get_savedir_filename(you.your_name,"","tc");
+ FILE *travelf = fopen(travelCacheFile.c_str(), "rb");
+ if (travelf) {
+ travel_cache.load(travelf);
+ fclose(travelf);
+ }
+
+ std::string notesFile = get_savedir_filename(you.your_name, "", "nts");
+ FILE *notesf = fopen(notesFile.c_str(), "rb");
+ if (notesf) {
+ load_notes(notesf);
+ fclose(notesf);
}
}
@@ -1366,23 +1435,14 @@ static bool determine_version( FILE *restoreFile,
if (read2(restoreFile, buf, 2) != 2)
return false; // empty file?
- // check for 3.30
- if (buf[0] == you.your_name[0] && buf[1] == you.your_name[1])
- {
- majorVersion = 0;
- minorVersion = 0;
- rewind(restoreFile);
- return true;
- }
-
// otherwise, read version and validate.
majorVersion = buf[0];
minorVersion = buf[1];
- if (majorVersion == 1 || majorVersion == 4)
+ if (majorVersion == SAVE_MAJOR_VERSION)
return true;
- return false; // if its not 1 or 4, no idea!
+ return false; // if its not 0, no idea
}
static void restore_version( FILE *restoreFile,
@@ -1390,7 +1450,7 @@ static void restore_version( FILE *restoreFile,
{
// assuming the following check can be removed once we can read all
// savefile versions.
- if (majorVersion < 4)
+ if (majorVersion != SAVE_MAJOR_VERSION)
{
snprintf( info, INFO_SIZE, "\nSorry, this release cannot read a v%d.%d savefile.\n",
majorVersion, minorVersion);
@@ -1400,7 +1460,7 @@ static void restore_version( FILE *restoreFile,
switch(majorVersion)
{
- case 4:
+ case SAVE_MAJOR_VERSION:
restore_tagged_file(restoreFile, TAGTYPE_PLAYER, minorVersion);
break;
default:
@@ -1423,6 +1483,8 @@ static void restore_tagged_file( FILE *restoreFile, int fileType,
if (i == 0) // no tag!
break;
tags[i] = 0; // tag read
+ if (fileType == TAGTYPE_PLAYER_NAME)
+ break;
}
// go through and init missing tags
@@ -1441,23 +1503,14 @@ static bool determine_level_version( FILE *levelFile,
if (read2(levelFile, buf, 2) != 2)
return false; // empty file?
- // check for 3.30 -- simply started right in with player name.
- if (isprint(buf[0]) && buf[0] > 4) // who knows?
- {
- majorVersion = 0;
- minorVersion = 0;
- rewind(levelFile);
- return true;
- }
-
// otherwise, read version and validate.
majorVersion = buf[0];
minorVersion = buf[1];
- if (majorVersion == 1 || majorVersion == 4)
+ if (majorVersion == SAVE_MAJOR_VERSION)
return true;
- return false; // if its not 1 or 4, no idea!
+ return false; // if its not SAVE_MAJOR_VERSION, no idea
}
static void restore_level_version( FILE *levelFile,
@@ -1465,7 +1518,7 @@ static void restore_level_version( FILE *levelFile,
{
// assuming the following check can be removed once we can read all
// savefile versions.
- if (majorVersion < 4)
+ if (majorVersion != SAVE_MAJOR_VERSION)
{
snprintf( info, INFO_SIZE, "\nSorry, this release cannot read a v%d.%d level file.\n",
majorVersion, minorVersion);
@@ -1475,7 +1528,7 @@ static void restore_level_version( FILE *levelFile,
switch(majorVersion)
{
- case 4:
+ case SAVE_MAJOR_VERSION:
restore_tagged_file(levelFile, TAGTYPE_LEVEL, minorVersion);
break;
default:
@@ -1504,43 +1557,20 @@ static bool determine_ghost_version( FILE *ghostFile,
majorVersion = buf[0];
minorVersion = buf[1];
- if (majorVersion == 4)
+ if (majorVersion == SAVE_MAJOR_VERSION)
return true;
- return false; // if its not 4, no idea!
-}
-
-static void restore_old_ghost( FILE *ghostFile )
-{
- char buf[41];
-
- read2(ghostFile, buf, 41); // 41 causes EOF. 40 will not.
-
- // translate
- memcpy( ghost.name, buf, 20 );
-
- for (int i = 0; i < 20; i++)
- ghost.values[i] = static_cast< unsigned short >( buf[i+20] );
-
- if (ghost.values[ GVAL_RES_FIRE ] >= 97)
- ghost.values[ GVAL_RES_FIRE ] -= 100;
-
- if (ghost.values[ GVAL_RES_COLD ] >= 97)
- ghost.values[ GVAL_RES_COLD ] -= 100;
+ return false; // if its not SAVE_MAJOR_VERSION, no idea!
}
static void restore_ghost_version( FILE *ghostFile,
char majorVersion, char minorVersion )
{
- // currently, we can read all known ghost versions.
switch(majorVersion)
{
- case 4:
+ case SAVE_MAJOR_VERSION:
restore_tagged_file(ghostFile, TAGTYPE_GHOST, minorVersion);
break;
- case 0:
- restore_old_ghost(ghostFile);
- break;
default:
break;
}
@@ -1548,16 +1578,17 @@ static void restore_ghost_version( FILE *ghostFile,
void save_ghost( bool force )
{
- char cha_fil[kFileNameSize];
const int wpn = you.equip[EQ_WEAPON];
if (!force && (you.your_level < 2 || you.is_undead))
return;
- make_filename( cha_fil, "bones", you.your_level, you.where_are_you,
- (you.level_type != LEVEL_DUNGEON), true );
+ std::string cha_fil = make_filename( "bones", you.your_level,
+ you.where_are_you,
+ (you.level_type != LEVEL_DUNGEON),
+ true );
- FILE *gfile = fopen(cha_fil, "rb");
+ FILE *gfile = fopen(cha_fil.c_str(), "rb");
// don't overwrite existing bones!
if (gfile != NULL)
@@ -1566,7 +1597,7 @@ void save_ghost( bool force )
return;
}
- memcpy(ghost.name, you.your_name, 20);
+ snprintf(ghost.name, sizeof ghost.name, "%s", you.your_name);
ghost.values[ GVAL_MAX_HP ] = ((you.hp_max >= 150) ? 150 : you.hp_max);
ghost.values[ GVAL_EV ] = player_evasion();
@@ -1628,20 +1659,20 @@ void save_ghost( bool force )
add_spells(ghost);
- gfile = fopen(cha_fil, "wb");
+ gfile = fopen(cha_fil.c_str(), "wb");
if (gfile == NULL)
{
- strcpy(info, "Error creating ghost file: ");
- strcat(info, cha_fil);
+ snprintf(info, INFO_SIZE, "Error creating ghost file: %s",
+ cha_fil.c_str());
mpr(info);
more();
return;
}
- // 4.0-4.3 old tagged savefile (values as unsigned char)
- // 4.4 new tagged savefile (values as signed short)
- write_tagged_file( gfile, 4, 4, TAGTYPE_GHOST );
+ // 0.0-0.3 old tagged savefile (values as unsigned char)
+ // 0.4 new tagged savefile (values as signed short)
+ write_tagged_file( gfile, SAVE_MAJOR_VERSION, 4, TAGTYPE_GHOST );
fclose(gfile);
@@ -1649,9 +1680,7 @@ void save_ghost( bool force )
mpr( "Saved ghost.", MSGCH_DIAGNOSTICS );
#endif
-#ifdef SHARED_FILES_CHMOD_PUBLIC
- chmod(cha_fil, SHARED_FILES_CHMOD_PUBLIC);
-#endif
+ DO_CHMOD_PRIVATE(cha_fil.c_str());
} // end save_ghost()
/*
@@ -1793,10 +1822,12 @@ unsigned char translate_spell(unsigned char spel)
case MEPHITIC_CLOUD: return ; */
case SPELL_VENOM_BOLT:
return (MS_VENOM_BOLT);
+ case SPELL_POISON_ARROW:
+ return (MS_POISON_ARROW);
case SPELL_TELEPORT_OTHER:
return (MS_TELEPORT_OTHER);
case SPELL_SUMMON_SMALL_MAMMAL:
- return (MS_VAMPIRE_SUMMON); /* approximate */
+ return (MS_SUMMON_SMALL_MAMMALS);
case SPELL_BOLT_OF_DRAINING:
return (MS_NEGATIVE_BOLT);
case SPELL_LEHUDIBS_CRYSTAL_SPEAR:
@@ -1807,6 +1838,8 @@ unsigned char translate_spell(unsigned char spel)
return (MS_ORB_ENERGY);
case SPELL_SUMMON_HORRIBLE_THINGS:
return (MS_LEVEL_SUMMON); /* approximate */
+ case SPELL_SHADOW_CREATURES:
+ return (MS_LEVEL_SUMMON); /* approximate */
case SPELL_ANIMATE_DEAD:
return (MS_ANIMATE_DEAD);
case SPELL_PAIN:
@@ -1861,7 +1894,7 @@ void generate_random_demon(void)
char st_p[ITEMNAME_SIZE];
- make_name(random2(250), random2(250), random2(250), 3, st_p);
+ make_name(random_int(), false, st_p);
strcpy(ghost.name, st_p);
// hp - could be defined below (as could ev, AC etc). Oh well, too late:
@@ -1944,7 +1977,7 @@ void generate_random_demon(void)
menv[rdem].evasion = ghost.values[ GVAL_EV ];
menv[rdem].speed = (one_chance_in(3) ? 10 : 6 + roll_dice(2, 9));
menv[rdem].speed_increment = 70;
- menv[rdem].number = random_colour(); // demon's colour
+ menv[rdem].colour = random_colour(); // demon's colour
for (i = GVAL_SPELL_1; i <= GVAL_SPELL_6; i++)
ghost.values[i] = SPELL_NO_SPELL;
@@ -2079,8 +2112,6 @@ void generate_random_demon(void)
// Largest string we'll save
#define STR_CAP 1000
-using std::string;
-
void writeShort(FILE *file, short s)
{
char data[2];
@@ -2112,7 +2143,7 @@ unsigned char readByte(FILE *file)
return byte;
}
-void writeString(FILE* file, const string &s)
+void writeString(FILE* file, const std::string &s)
{
int length = s.length();
if (length > STR_CAP) length = STR_CAP;
@@ -2120,14 +2151,14 @@ void writeString(FILE* file, const string &s)
write2(file, s.c_str(), length);
}
-string readString(FILE *file)
+std::string readString(FILE *file)
{
char buf[STR_CAP + 1];
short length = readShort(file);
if (length)
read2(file, buf, length);
- buf[length] = '\0';
- return string(buf);
+ buf[length] = 0;
+ return std::string(buf);
}
void writeLong(FILE* file, long num)
diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h
index a2d357cac8..b7fd81a5fd 100644
--- a/crawl-ref/source/files.h
+++ b/crawl-ref/source/files.h
@@ -3,6 +3,8 @@
* Summary: Functions used to save and load levels/games.
* Written by: Linley Henzell and Alexey Guzeev
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -12,9 +14,11 @@
#ifndef FILES_H
#define FILES_H
+#include "externs.h"
#include "FixAry.h"
#include <stdio.h>
#include <string>
+#include <vector>
// referenced in files - newgame - ouch - overmap:
#define MAX_LEVELS 50
@@ -25,20 +29,16 @@
// referenced in files - newgame - ouch:
extern FixedArray<bool, MAX_LEVELS, MAX_BRANCHES> tmp_file_pairs;
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: acr - misc
- * *********************************************************************** */
-#if 0
-void load( unsigned char stair_taken, bool moving_level,
- bool was_a_labyrinth, char old_level, bool want_followers,
- bool is_new_game, char where_were_you2 );
-#endif
+std::string datafile_path(const std::string &basename);
+
+void check_savedir(std::string &dir);
bool travel_load_map( char branch, int absdepth );
+std::vector<player> find_saved_characters();
+
std::string get_savedir_filename(const char *pre, const char *suf,
- const char *ext);
+ const char *ext, bool suppress_uid = false);
std::string get_prefs_filename();
@@ -47,7 +47,7 @@ void load( unsigned char stair_taken, int load_mode, bool was_a_labyrinth,
// last updated 12may2000 {dlb}
/* ***********************************************************************
- * called from: acr - libmac - misc
+ * called from: acr - misc
* *********************************************************************** */
void save_game(bool leave_game);
@@ -69,9 +69,8 @@ void save_ghost( bool force = false );
/* ***********************************************************************
* called from: files hiscores
* *********************************************************************** */
-void make_filename( char *buf, const char *prefix, int level, int where,
- bool isLabyrinth, bool isGhost );
-
+std::string make_filename( const char *prefix, int level, int where,
+ bool isLabyrinth, bool isGhost );
void writeShort(FILE *file, short s);
diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc
index db95c533b8..f124cf3ae4 100644
--- a/crawl-ref/source/food.cc
+++ b/crawl-ref/source/food.cc
@@ -3,6 +3,8 @@
* Summary: Functions for eating and butchering.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <2> 5/20/99 BWR Added CRAWL_PIZZA.
@@ -30,6 +32,7 @@
#include "invent.h"
#include "items.h"
#include "itemname.h"
+#include "itemprop.h"
#include "item_use.h"
#include "it_use2.h"
#include "macro.h"
@@ -41,7 +44,6 @@
#include "skills2.h"
#include "spells2.h"
#include "stuff.h"
-#include "wpn-misc.h"
static int determine_chunk_effect(int which_chunk_type, bool rotten_chunk);
static void eat_chunk( int chunk_effect );
@@ -138,7 +140,7 @@ void weapon_switch( int targ )
// code is a mess... this whole function's purpose was to
// isolate this hack until there's a proper way to do things. -- bwr
if (you.equip[EQ_WEAPON] != -1)
- unwield_item(you.equip[EQ_WEAPON]);
+ unwield_item(you.equip[EQ_WEAPON], false);
you.equip[EQ_WEAPON] = targ;
@@ -147,14 +149,49 @@ void weapon_switch( int targ )
wield_effects( targ, false );
}
+// look for a butchering implement, prompting user if no obvious
+// options exist. Returns whether a weapon was switched.
+static bool find_butchering_implement() {
+
+ // look for a butchering implement in your pack
+ for (int i = 0; i < ENDOFPACK; ++i) {
+ if (is_valid_item( you.inv[i] )
+ && can_cut_meat( you.inv[i] )
+ && you.inv[i].base_type == OBJ_WEAPONS
+ && item_known_uncursed(you.inv[i])
+ && item_ident( you.inv[i], ISFLAG_KNOW_TYPE )
+ && get_weapon_brand(you.inv[i]) != SPWPN_DISTORTION
+ && can_wield( &you.inv[i] ))
+ {
+ mpr("Switching to a butchering implement.");
+ wield_weapon( true, i, false );
+
+ // Account for the weapon switch...we're doing this here
+ // since the above switch may reveal information about the
+ // weapon (curse status, ego type). So even if the
+ // character fails to or decides not to butcher past this
+ // point, they have achieved something and there should be
+ // a cost.
+ start_delay( DELAY_UNINTERRUPTIBLE, 1 );
+ return true;
+ }
+ }
+
+ // if we didn't swap above, then we still can't cut...let's call
+ // wield_weapon() in the "prompt the user" way...
+
+ // prompt for new weapon
+ int old_weapon = you.equip[EQ_WEAPON];
+ mpr( "What would you like to use?", MSGCH_PROMPT );
+ wield_weapon( false );
+
+ // let's see if the user did something...
+ return (you.equip[EQ_WEAPON] != old_weapon);
+}
+
bool butchery(void)
{
char str_pass[ ITEMNAME_SIZE ];
- int items_here = 0;
- int o = igrd[you.x_pos][you.y_pos];
- int k = 0;
- int item_got;
- unsigned char keyin;
bool can_butcher = false;
bool wpn_switch = false;
@@ -162,326 +199,138 @@ bool butchery(void)
int old_weapon = you.equip[EQ_WEAPON];
bool barehand_butcher = (you.equip[ EQ_GLOVES ] == -1)
- && (you.species == SP_TROLL
- || you.species == SP_GHOUL
- || you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS
- || you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON
- || you.mutation[MUT_CLAWS]);
-
-
+ && (you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS ||
+ you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON ||
+ (you.attribute[ATTR_TRANSFORMATION] == TRAN_NONE &&
+ (you.species == SP_TROLL ||
+ you.species == SP_GHOUL ||
+ you.mutation[MUT_CLAWS])));
+
+ can_butcher = barehand_butcher ||
+ (you.equip[EQ_WEAPON] != -1 &&
+ can_cut_meat(you.inv[you.equip[EQ_WEAPON]]));
+
if (igrd[you.x_pos][you.y_pos] == NON_ITEM)
{
mpr("There isn't anything here!");
return (false);
}
- if (player_is_levitating() && !wearing_amulet(AMU_CONTROLLED_FLIGHT))
+ if (!Options.easy_butcher && !can_butcher)
{
- mpr("You can't reach the floor from up here.");
+ mpr("Maybe you should try using a sharper implement.");
return (false);
}
- if (barehand_butcher)
- can_butcher = true;
- else
- {
- if (you.equip[EQ_WEAPON] != -1)
- {
- can_butcher = can_cut_meat( you.inv[you.equip[EQ_WEAPON]].base_type,
- you.inv[you.equip[EQ_WEAPON]].sub_type );
- }
-
- // Should probably check for cursed-weapons, bare hands and
- // non-weapons in hand here, but wield_weapon will be used for
- // this swap and it will do all that (although the player might
- // be annoyed with the excess prompt).
- if (Options.easy_butcher && !can_butcher)
- {
- //mv: check for berserk first
- if (you.berserker)
- {
- mpr ("You are too berserk to search for a butchering knife!");
- return (false);
- }
-
- // We'll now proceed to look through the entire inventory for
- // choppers/slicers. We'll skip special weapons because
- // wielding/unwielding a foo of distortion would be disastrous.
- for (int i = 0; i < ENDOFPACK; ++i)
- {
- if (is_valid_item( you.inv[i] )
- && can_cut_meat( you.inv[i].base_type,
- you.inv[i].sub_type )
- && you.inv[i].base_type == OBJ_WEAPONS
- && item_known_uncursed(you.inv[i])
- && item_ident( you.inv[i], ISFLAG_KNOW_TYPE )
- && get_weapon_brand(you.inv[i])
- != SPWPN_DISTORTION
- && can_wield( you.inv[i] ))
- {
- mpr("Switching to a butchering implement.");
- wpn_switch = true;
- wield_weapon( true, i, false );
- break;
- }
- }
-
- // if we didn't swap above, then we still can't cut... let's
- // call wield_weapon() in the "prompt the user" way...
- if (!wpn_switch)
- {
- // prompt for new weapon
- mpr( "What would you like to use?", MSGCH_PROMPT );
- wield_weapon( false );
-
- // let's see if the user did something...
- if (you.equip[EQ_WEAPON] != old_weapon)
- wpn_switch = true;
- }
- }
-
- // weapon might have changed (to bare hands as well), we'll
- // update the can_butcher status accordingly (note: if we could
- // butcher with our bare hands we wouldn't be here) -- bwr
- if (wpn_switch && you.equip[EQ_WEAPON] != -1)
- {
- can_butcher = can_cut_meat( you.inv[you.equip[EQ_WEAPON]].base_type,
- you.inv[you.equip[EQ_WEAPON]].sub_type );
- }
- }
-
- // Account for the weapon switch above if it happened... we're
- // doing this here since the above switch may reveal information
- // about the weapon (curse status, ego type). So even if the
- // character fails to or decides not to butcher past this point,
- // they have achieved something and there should be a cost.
- if (wpn_switch)
- start_delay( DELAY_UNINTERUPTABLE, 1, old_weapon );
-
- // check to see if the new implement is cursed - if so, set a
- // flag indicating this. If a player actually butchers anything,
- // this flag can be checked before switching back.
- int wpn = you.equip[EQ_WEAPON];
-
- if (wpn != -1
- && you.inv[wpn].base_type == OBJ_WEAPONS
- && item_cursed( you.inv[wpn] ))
- {
- new_cursed = true;
- }
-
- // Final checks and clue-giving...
- if (!barehand_butcher && you.equip[EQ_WEAPON] == -1)
- {
- if (you.equip[ EQ_GLOVES ] == -1)
- mpr("What, with your bare hands?");
- else
- mpr("You can't use your claws with your gloves on!");
-
- // Switching back to avoid possible bug where player can use
- // this to switch weapons in zero time.
- if (wpn_switch)
- weapon_switch( old_weapon );
-
- return (false);
- }
- else if (!can_butcher)
+ if (player_is_levitating() && !wearing_amulet(AMU_CONTROLLED_FLIGHT))
{
- mpr("Maybe you should try using a sharper implement.");
-
- // Switching back to avoid possible bug where player can use
- // this to switch weapons in zero time.
- if (wpn_switch && !new_cursed)
- weapon_switch( old_weapon );
-
+ mpr("You can't reach the floor from up here.");
return (false);
}
- // No turning back at this point, we better be qualified.
- ASSERT( can_butcher );
-
- int last_item = NON_ITEM;
-
- int objl = igrd[you.x_pos][you.y_pos];
- int hrg = 0;
- int counter = 0;
-
- while (objl != NON_ITEM)
- {
- counter++;
-
- last_item = objl;
-
- hrg = mitm[objl].link;
- objl = hrg;
- items_here++;
-
- if (counter > 1000)
- {
- error_message_to_player();
-
- if (wpn_switch && !new_cursed)
- weapon_switch( old_weapon );
-
- return (false);
- }
+ // It makes more sense that you first find out if there's anything
+ // to butcher, *then* decide to actually butcher it.
+ // The old code did it the other way.
+ if ( !can_butcher && you.berserker ) {
+ mpr ("You are too berserk to search for a butchering knife!");
+ return (false);
}
- if (items_here == 1
- && (mitm[igrd[you.x_pos][you.y_pos]].base_type == OBJ_CORPSES &&
- mitm[igrd[you.x_pos][you.y_pos]].sub_type == CORPSE_BODY))
- {
- strcpy(info, "Butcher ");
- it_name(igrd[you.x_pos][you.y_pos], DESC_NOCAP_A, str_pass);
- strcat(info, str_pass);
- strcat(info, "\?");
- mpr(info, MSGCH_PROMPT);
-
- unsigned char keyin = getch();
-
- if (keyin == 0)
- {
- getch();
- keyin = 0;
- }
-
- if (keyin != 'y' && keyin != 'Y')
- {
- if (wpn_switch && !new_cursed)
- weapon_switch( old_weapon );
-
- return (false);
- }
-
- int item_got = igrd[you.x_pos][you.y_pos];
-
- last_item = NON_ITEM;
-
- if (barehand_butcher)
- mpr("You start tearing the corpse apart.");
- else
- mpr("You start hacking away.");
-
- if (you.duration[DUR_PRAYER]
- && (you.religion == GOD_OKAWARU
- || you.religion == GOD_MAKHLEB || you.religion == GOD_TROG))
- {
- offer_corpse(item_got);
- destroy_item(item_got);
- // XXX: need an extra turn here for weapon swapping?
- }
- else
- {
- int work_req = 3 - mitm[item_got].plus2;
- if (work_req < 0)
- work_req = 0;
-
- start_delay( DELAY_BUTCHER, work_req, item_got );
+ int objl;
+
+ for (objl = igrd[you.x_pos][you.y_pos]; objl != NON_ITEM;
+ objl = mitm[objl].link) {
+
+ if ( (mitm[objl].base_type != OBJ_CORPSES) ||
+ (mitm[objl].sub_type != CORPSE_BODY) )
+ continue;
+
+ // offer the possibility of butchering
+ it_name(objl, DESC_NOCAP_A, str_pass);
+ snprintf(info, INFO_SIZE, "Butcher %s?", str_pass);
+ int answer = yesnoquit( info, true, 'n', false );
+ if ( answer == -1 )
+ break;
+ if ( answer == 0 )
+ continue;
+
+ if ( Options.easy_butcher && !can_butcher ) {
+
+ // try to find a butchering implement
+ wpn_switch = find_butchering_implement();
+ const int wpn = you.equip[EQ_WEAPON];
+ if ( wpn_switch ) {
+ new_cursed =
+ (wpn != -1) &&
+ (you.inv[wpn].base_type == OBJ_WEAPONS) &&
+ item_cursed( you.inv[wpn]);
+ }
+
+ // note that barehanded butchery would not reach this
+ // stage, so if wpn == -1 the user selected '-' when
+ // switching weapons
+
+ if (!wpn_switch || wpn == -1 || !can_cut_meat(you.inv[wpn])) {
+
+ // still can't butcher. Early out
+ if ( wpn == -1 ) {
+ if (you.equip[EQ_GLOVES] == -1)
+ mpr("What, with your bare hands?");
+ else
+ mpr("Your gloves aren't that sharp!");
+ }
+ else
+ mpr("Maybe you should try using a sharper implement.");
+
+ if ( !new_cursed && wpn_switch )
+ start_delay( DELAY_WEAPON_SWAP, 1, old_weapon );
+
+ return false;
+ }
+
+ // switched to a good butchering knife
+ can_butcher = true;
+ }
+
+ if ( can_butcher ) {
+
+ // we actually butcher now
+ if ( barehand_butcher )
+ mpr("You start tearing the corpse apart.");
+ else
+ mpr("You start hacking away.");
+
+ if (you.duration[DUR_PRAYER] &&
+ (you.religion == GOD_OKAWARU || you.religion == GOD_MAKHLEB ||
+ you.religion == GOD_TROG)) {
+ offer_corpse(objl);
+ destroy_item(objl);
+ }
+ else {
+ int work_req = 3 - mitm[objl].plus2;
+ if (work_req < 0)
+ work_req = 0;
+
+ start_delay(DELAY_BUTCHER, work_req, objl, mitm[objl].special);
+ }
}
- // cue up switching weapon back
- if (wpn_switch && !new_cursed)
+ // switch weapon back
+ if (!new_cursed && wpn_switch)
start_delay( DELAY_WEAPON_SWAP, 1, old_weapon );
- you.turn_is_over = 1;
-
- return (true);
-
- } // end "if items_here == 1"
- else if (items_here > 1)
- {
- last_item = NON_ITEM;
- o = igrd[you.x_pos][you.y_pos];
-
- for (k = 0; k < items_here; k++)
- {
- if (mitm[o].base_type != OBJ_CORPSES
- || mitm[o].sub_type != CORPSE_BODY)
- {
- goto out_of_eating;
- }
-
- strcpy(info, "Butcher ");
- it_name(o, DESC_NOCAP_A, str_pass);
- strcat(info, str_pass);
- strcat(info, "\?");
- mpr(info, MSGCH_PROMPT);
-
- keyin = getch();
- if (keyin == 0)
- {
- getch();
- keyin = 0;
- }
-
- if (keyin == 'q')
- {
- if (wpn_switch && !new_cursed)
- weapon_switch( old_weapon );
-
- return (false);
- }
-
- if (keyin == 'y')
- {
- item_got = o;
-
- if (barehand_butcher)
- mpr("You start tearing the corpse apart.");
- else
- mpr("You start hacking away.");
-
- if (you.duration[DUR_PRAYER]
- && (you.religion == GOD_OKAWARU
- || you.religion == GOD_MAKHLEB
- || you.religion == GOD_TROG))
- {
- offer_corpse(item_got);
- destroy_item(item_got);
- // XXX: need an extra turn here for weapon swapping?
- }
- else
- {
- int work_req = 3 - mitm[item_got].plus2;
- if (work_req < 0)
- work_req = 0;
-
- start_delay( DELAY_BUTCHER, work_req, item_got );
- }
-
- if (wpn_switch && !new_cursed)
- {
- // weapon_switch( old_weapon );
- // need to count the swap delay in this case
- start_delay( DELAY_WEAPON_SWAP, 1, old_weapon );
- }
-
- you.turn_is_over = 1;
- return (true);
- }
-
- out_of_eating:
-
- if (is_valid_item( mitm[o] ))
- last_item = o;
-
- hrg = mitm[o].link;
- o = hrg;
-
- if (o == NON_ITEM)
- break;
+ you.turn_is_over = true;
- if (items_here == 0)
- break;
- } // end "for k" loop
+ return true;
}
mpr("There isn't anything to dissect here.");
- if (wpn_switch && !new_cursed)
+ if (!new_cursed && wpn_switch) { // should never happen
weapon_switch( old_weapon );
-
- return (false);
+ }
+
+ return false;
} // end butchery()
#ifdef CLUA_BINDINGS
@@ -541,7 +390,12 @@ bool prompt_eat_from_inventory(void)
}
int which_inventory_slot =
- prompt_invent_item( "Eat which item?", OBJ_FOOD );
+ prompt_invent_item(
+ "Eat which item?",
+ MT_INVSELECT,
+ OBJ_FOOD,
+ true, true, true, 0, NULL,
+ OPER_EAT );
if (which_inventory_slot == PROMPT_ABORT)
{
canned_msg( MSG_OK );
@@ -565,7 +419,7 @@ bool prompt_eat_from_inventory(void)
eat_from_inventory(which_inventory_slot);
burden_change();
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return (true);
}
@@ -663,7 +517,7 @@ static bool food_change(bool suppress_message)
} // end food_change()
-// food_increment is positive for eating, negative for hungering
+// food_increment is positive for eating, negative for hungering
static void describe_food_change(int food_increment)
{
int magnitude = (food_increment > 0)?food_increment:(-food_increment);
@@ -693,7 +547,7 @@ void eat_from_inventory(int which_inventory_slot)
// this is a bit easier to read... most compilers should
// handle this the same -- bwr
const int mons_type = you.inv[ which_inventory_slot ].plus;
- const int chunk_type = mons_corpse_thingy( mons_type );
+ const int chunk_type = mons_corpse_effect( mons_type );
const bool rotten = (you.inv[which_inventory_slot].special < 100);
eat_chunk( determine_chunk_effect( chunk_type, rotten ) );
@@ -711,7 +565,7 @@ void eat_floor_item(int item_link)
{
if (mitm[item_link].sub_type == FOOD_CHUNK)
{
- const int chunk_type = mons_corpse_thingy( mitm[item_link].plus );
+ const int chunk_type = mons_corpse_effect( mitm[item_link].plus );
const bool rotten = (mitm[item_link].special < 100);
eat_chunk( determine_chunk_effect( chunk_type, rotten ) );
@@ -721,7 +575,7 @@ void eat_floor_item(int item_link)
eating( mitm[item_link].base_type, mitm[item_link].sub_type );
}
- you.turn_is_over = 1;
+ you.turn_is_over = true;
dec_mitm_item_quantity( item_link, 1 );
}
@@ -767,6 +621,67 @@ bool eat_from_floor(void)
return (false);
}
+static const char *chunk_flavour_phrase(bool likes_chunks)
+{
+ const char *phrase =
+ likes_chunks? "tastes great." : "tastes terrible.";
+
+ const int gourmand = you.duration[DUR_GOURMAND];
+ if (gourmand >= GOURMAND_MAX)
+ phrase =
+ one_chance_in(8)? "tastes like chicken!"
+ : "tastes great.";
+ else if (gourmand > GOURMAND_MAX * 75 / 100)
+ phrase = "tastes very good.";
+ else if (gourmand > GOURMAND_MAX * 50 / 100)
+ phrase = "tastes good.";
+ else if (gourmand > GOURMAND_MAX * 25 / 100)
+ phrase = "is not very appetising.";
+
+ return (phrase);
+}
+
+void chunk_nutrition_message(int nutrition)
+{
+ int perc_nutrition = nutrition * 100 / CHUNK_BASE_NUTRITION;
+ if (perc_nutrition < 15)
+ mpr("That was extremely unsatisfying.");
+ else if (perc_nutrition < 35)
+ mpr("That was not very filling.");
+}
+
+static int chunk_nutrition(bool likes_chunks)
+{
+ int nutrition = CHUNK_BASE_NUTRITION;
+ if (likes_chunks || you.hunger_state < HS_SATIATED)
+ return (nutrition);
+
+ const int gourmand =
+ wearing_amulet(AMU_THE_GOURMAND)?
+ you.duration[DUR_GOURMAND]
+ : 0;
+
+ int effective_nutrition =
+ nutrition * (gourmand + GOURMAND_NUTRITION_BASE)
+ / (GOURMAND_MAX + GOURMAND_NUTRITION_BASE);
+
+#ifdef DEBUG_DIAGNOSTICS
+ const int epercent = effective_nutrition * 100 / nutrition;
+ mprf(MSGCH_DIAGNOSTICS,
+ "Gourmand factor: %d, chunk base: %d, effective: %d, %%: %d",
+ gourmand,
+ nutrition,
+ effective_nutrition,
+ epercent);
+#endif
+
+ return (effective_nutrition);
+}
+
+static void say_chunk_flavour(bool likes_chunks)
+{
+ mprf("This raw flesh %s", chunk_flavour_phrase(likes_chunks));
+}
// never called directly - chunk_effect values must pass
// through food::determine_chunk_effect() first {dlb}:
@@ -781,7 +696,7 @@ static void eat_chunk( int chunk_effect )
{
ghoul_eat_flesh( chunk_effect );
start_delay( DELAY_EAT, 2 );
- lessen_hunger( 1000, true );
+ lessen_hunger( CHUNK_BASE_NUTRITION, true );
}
else
{
@@ -815,16 +730,14 @@ static void eat_chunk( int chunk_effect )
// note that this is the only case that takes time and forces redraw
case CE_CLEAN:
- strcpy(info, "This raw flesh ");
-
- strcat(info, (likes_chunks) ? "tastes good."
- : "is not very appetising.");
- mpr(info);
-
- start_delay( DELAY_EAT, 2 );
- lessen_hunger( 1000, true );
+ {
+ say_chunk_flavour(likes_chunks);
+ const int nutrition = chunk_nutrition(likes_chunks);
+ start_delay( DELAY_EAT, 2, nutrition );
+ lessen_hunger( nutrition, true );
break;
}
+ }
}
return;
@@ -1364,12 +1277,15 @@ static int determine_chunk_effect(int which_chunk_type, bool rotten_chunk)
{
if (you.species == SP_GHOUL)
{
+ // [dshaligram] Leaving rotting chunk effect intact for ghouls.
if (this_chunk_effect == CE_CLEAN)
this_chunk_effect = CE_ROTTEN;
}
else
{
- if (this_chunk_effect == CE_ROTTEN)
+ // [dshaligram] New AotG behaviour - contaminated chunks become
+ // clean, but rotten chunks remain rotten.
+ if (this_chunk_effect == CE_CONTAMINATED)
this_chunk_effect = CE_CLEAN;
}
}
diff --git a/crawl-ref/source/food.h b/crawl-ref/source/food.h
index 1c8e5f5a74..764f577ee0 100644
--- a/crawl-ref/source/food.h
+++ b/crawl-ref/source/food.h
@@ -3,6 +3,8 @@
* Summary: Functions for eating and butchering.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -65,4 +67,6 @@ void eat_from_inventory(int which_inventory_slot);
bool prompt_eat_from_inventory(void);
+void chunk_nutrition_message(int nutrition);
+
#endif
diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc
index ab84678410..bb15621d36 100644
--- a/crawl-ref/source/hiscores.cc
+++ b/crawl-ref/source/hiscores.cc
@@ -3,6 +3,8 @@
* Summary: deal with reading and writing of highscore file
* Written by: Gordon Lipford
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> 16feb2001 gdl Created
@@ -35,9 +37,14 @@
#include "hiscores.h"
#include "itemname.h"
+#include "itemprop.h"
+#include "items.h"
+#include "libutil.h"
+#include "misc.h"
#include "mon-util.h"
#include "player.h"
#include "religion.h"
+#include "shopping.h"
#include "stuff.h"
#include "tags.h"
#include "view.h"
@@ -51,7 +58,7 @@
#endif
// enough memory allocated to snarf in the scorefile entries
-static struct scorefile_entry hs_list[SCORE_FILE_ENTRIES];
+static scorefile_entry hs_list[SCORE_FILE_ENTRIES];
// hackish: scorefile position of newest entry. Will be highlit during
// highscore printing (always -1 when run from command line).
@@ -59,18 +66,19 @@ static int newest_entry = -1;
static FILE *hs_open(const char *mode);
static void hs_close(FILE *handle, const char *mode);
-static bool hs_read(FILE *scores, struct scorefile_entry &dest);
-static void hs_parse_numeric(char *inbuf, struct scorefile_entry &dest);
-static void hs_parse_string(char *inbuf, struct scorefile_entry &dest);
-static void hs_copy(struct scorefile_entry &dest, struct scorefile_entry &src);
-static void hs_write(FILE *scores, struct scorefile_entry &entry);
-static void hs_nextstring(char *&inbuf, char *dest);
+static bool hs_read(FILE *scores, scorefile_entry &dest);
+static void hs_parse_numeric(char *inbuf, scorefile_entry &dest);
+static void hs_parse_string(char *inbuf, scorefile_entry &dest);
+static void hs_write(FILE *scores, scorefile_entry &entry);
+static void hs_nextstring(char *&inbuf, char *dest, size_t bufsize);
static int hs_nextint(char *&inbuf);
static long hs_nextlong(char *&inbuf);
// functions dealing with old scorefile entries
-static void hs_parse_generic_1(char *&inbuf, char *outbuf, const char *stopvalues);
-static void hs_parse_generic_2(char *&inbuf, char *outbuf, const char *continuevalues);
+static void hs_parse_generic_1(char *&inbuf, char *outbuf, size_t outsz,
+ const char *stopvalues);
+static void hs_parse_generic_2(char *&inbuf, char *outbuf, size_t outsz,
+ const char *continuevalues);
static void hs_stripblanks(char *buf);
static void hs_search_death(char *inbuf, struct scorefile_entry &se);
static void hs_search_where(char *inbuf, struct scorefile_entry &se);
@@ -81,7 +89,7 @@ static bool lock_file_handle( FILE *handle, int type );
static bool unlock_file_handle( FILE *handle );
#endif // USE_FILE_LOCKING
-void hiscores_new_entry( struct scorefile_entry &ne )
+void hiscores_new_entry( const scorefile_entry &ne )
{
FILE *scores;
int i, total_entries;
@@ -90,6 +98,9 @@ void hiscores_new_entry( struct scorefile_entry &ne )
// open highscore file (reading) -- note that NULL is not fatal!
scores = hs_open("r");
+ for (i = 0; i < SCORE_FILE_ENTRIES; ++i)
+ hs_list[i].reset();
+
// read highscore file, inserting new entry at appropriate point,
for (i = 0; i < SCORE_FILE_ENTRIES; i++)
{
@@ -105,23 +116,23 @@ void hiscores_new_entry( struct scorefile_entry &ne )
// Fixed a nasty overflow bug here -- Sharp
if (i+1 < SCORE_FILE_ENTRIES)
{
- hs_copy(hs_list[i+1], hs_list[i]);
- hs_copy(hs_list[i], ne);
+ hs_list[i + 1] = hs_list[i];
+ hs_list[i] = ne;
i++;
} else {
- // copy new entry to current position
- hs_copy(hs_list[i], ne);
+ // copy new entry to current position
+ hs_list[i] = ne;
}
}
}
- // special case: lowest score, with room
+ // special case: lowest score, with room
if (!inserted && i < SCORE_FILE_ENTRIES)
{
newest_entry = i;
inserted = true;
// copy new entry
- hs_copy(hs_list[i], ne);
+ hs_list[i] = ne;
i++;
}
@@ -199,16 +210,16 @@ void hiscores_print_list( int display_count, int format )
// print position (tracked implicitly by order score file)
snprintf( info, INFO_SIZE, "%3d.", i + 1 );
if (use_printf)
- printf(info);
+ printf("%s", info);
else
- cprintf(info);
+ cprintf("%s", info);
// format the entry
if (format == SCORE_TERSE)
{
hiscores_format_single( info, hs_list[i] );
// truncate if we want short format
- info[75] = '\0';
+ info[75] = 0;
}
else
{
@@ -219,9 +230,9 @@ void hiscores_print_list( int display_count, int format )
// print entry
strcat(info, EOL);
if(use_printf)
- printf(info);
+ printf("%s", info);
else
- cprintf(info);
+ cprintf("%s", info);
if (i == newest_entry && !use_printf)
textcolor(LIGHTGREY);
@@ -233,7 +244,7 @@ static const char *const range_type_verb( const char *const aux )
{
if (strncmp( aux, "Shot ", 5 ) == 0) // launched
return ("shot");
- else if (aux[0] == '\0' // unknown
+ else if (aux[0] == 0 // unknown
|| strncmp( aux, "Hit ", 4 ) == 0 // thrown
|| strncmp( aux, "volley ", 7 ) == 0) // manticore spikes
{
@@ -243,274 +254,11 @@ static const char *const range_type_verb( const char *const aux )
return ("blasted"); // spells, wands
}
-void hiscores_format_single(char *buf, struct scorefile_entry &se)
+void hiscores_format_single(char *buf, const scorefile_entry &se)
{
- char scratch[100];
-
- // Now that we have a long format, I'm starting to make this
- // more terse, in hopes that it will better fit. -- bwr
-
- // race_class_name overrides race & class
- if (se.race_class_name[0] == '\0')
- {
- snprintf( scratch, sizeof(scratch), "%s%s",
- get_species_abbrev( se.race ), get_class_abbrev( se.cls ) );
- }
- else
- {
- strcpy( scratch, se.race_class_name );
- }
-
- se.name[10]='\0';
- sprintf( buf, "%8ld %-10s %s-%02d%s", se.points, se.name,
- scratch, se.lvl, (se.wiz_mode == 1) ? "W" : "" );
-
- // get monster type & number, if applicable
- int mon_type = se.death_source;
- int mon_number = se.mon_num;
-
- // remember -- we have 36 characters (not including initial space):
- switch (se.death_type)
- {
- case KILLED_BY_MONSTER:
- strcat( buf, " slain by " );
-
- // if death_source_name is non-null, override lookup (names might have
- // changed!)
- if (se.death_source_name[0] != '\0')
- strcat( buf, se.death_source_name );
- else
- strcat( buf, monam( mon_number, mon_type, true, DESC_PLAIN ) );
-
- break;
-
- case KILLED_BY_POISON:
- //if (dam == -9999) strcat(buf, "an overload of ");
- strcat( buf, " succumbed to poison" );
- break;
-
- case KILLED_BY_CLOUD:
- if (se.auxkilldata[0] == '\0')
- strcat( buf, " engulfed by a cloud" );
- else
- {
- const int len = strlen( se.auxkilldata );
-
- // Squeeze out "a cloud of" if required. -- bwr
- snprintf( scratch, sizeof(scratch), " engulfed by %s%s",
- (len < 15) ? "a cloud of " : "",
- se.auxkilldata );
-
- strcat( buf, scratch );
- }
- break;
-
- case KILLED_BY_BEAM:
- // keeping this short to leave room for the deep elf spellcasters:
- snprintf( scratch, sizeof(scratch), " %s by ",
- range_type_verb( se.auxkilldata ) );
- strcat( buf, scratch );
-
- // if death_source_name is non-null, override this
- if (se.death_source_name[0] != '\0')
- strcat( buf, se.death_source_name );
- else
- strcat( buf, monam( mon_number, mon_type, true, DESC_PLAIN ) );
- break;
-
-/*
- case KILLED_BY_DEATHS_DOOR:
- // death's door running out - NOTE: This is no longer fatal
- strcat(buf, " ran out of time");
- break;
-*/
-
- case KILLED_BY_LAVA:
- if (se.race == SP_MUMMY)
- strcat( buf, " turned to ash by lava" );
- else
- strcat( buf, " took a swim in lava" );
- break;
-
- case KILLED_BY_WATER:
- if (se.race == SP_MUMMY)
- strcat( buf, " soaked and fell apart" );
- else
- strcat( buf, " drowned" );
- break;
-
- // these three are probably only possible if you wear a ring
- // of >= +3 ability, get drained to 3, then take it off, or have a very
- // low abil and wear a -ve ring. or, as of 2.7x, mutations can cause this
- // Don't forget decks of cards (they have some nasty code for this) -- bwr
- case KILLED_BY_STUPIDITY:
- strcat( buf, " died of stupidity" );
- break;
-
- case KILLED_BY_WEAKNESS:
- strcat( buf, " became too weak to continue" );
- break;
-
- case KILLED_BY_CLUMSINESS:
- strcat( buf, " slipped on a banana peel" );
- break;
-
- case KILLED_BY_TRAP:
- snprintf( scratch, sizeof(scratch), " triggered a%s trap",
- (se.auxkilldata[0] != '\0') ? se.auxkilldata : "" );
- strcat( buf, scratch );
- break;
-
- case KILLED_BY_LEAVING:
- strcat( buf, " got out of the dungeon alive" );
- break;
-
- case KILLED_BY_WINNING:
- strcat( buf, " escaped with the Orb!" );
- break;
-
- case KILLED_BY_QUITTING:
- strcat( buf, " quit the game" );
- break;
-
- case KILLED_BY_DRAINING:
- strcat( buf, " drained of all life" );
- break;
-
- case KILLED_BY_STARVATION:
- strcat( buf, " starved to death" );
- break;
-
- case KILLED_BY_FREEZING:
- strcat( buf, " froze to death" );
- break;
-
- case KILLED_BY_BURNING: // only sticky flame
- strcat( buf, " burnt to a crisp" );
- break;
-
- case KILLED_BY_WILD_MAGIC:
- if (se.auxkilldata[0] == '\0')
- strcat( buf, " killed by wild magic" );
- else
- {
- const bool need_by = (strncmp( se.auxkilldata, "by ", 3 ) == 0);
- const int len = strlen( se.auxkilldata );
-
- // Squeeze out "killed" if we're getting a bit long. -- bwr
- snprintf( scratch, sizeof(scratch), " %s%s%s",
- (len + 3 * (need_by) < 30) ? "killed" : "",
- (need_by) ? "by " : "",
- se.auxkilldata );
-
- strcat( buf, scratch );
- }
- break;
-
- case KILLED_BY_XOM: // only used for old Xom kills
- strcat( buf, " killed for Xom's enjoyment" );
- break;
-
- case KILLED_BY_STATUE:
- strcat( buf, " killed by a statue" );
- break;
-
- case KILLED_BY_ROTTING:
- strcat( buf, " rotted away" );
- break;
-
- case KILLED_BY_TARGETTING:
- strcat( buf, " killed by bad targeting" );
- break;
-
- case KILLED_BY_SPORE:
- strcat( buf, " killed by an exploding spore" );
- break;
-
- case KILLED_BY_TSO_SMITING:
- strcat( buf, " smote by The Shining One" );
- break;
-
- case KILLED_BY_PETRIFICATION:
- strcat( buf, " turned to stone" );
- break;
-
- case KILLED_BY_SHUGGOTH:
- strcat( buf, " eviscerated by a hatching shuggoth" );
- break;
-
- case KILLED_BY_SOMETHING:
- strcat( buf, " died" );
- break;
-
- case KILLED_BY_FALLING_DOWN_STAIRS:
- strcat( buf, " fell down a flight of stairs" );
- break;
-
- case KILLED_BY_ACID:
- strcat( buf, " splashed by acid" );
- break;
-
- default:
- strcat( buf, " nibbled to death by software bugs" );
- break;
- } // end switch
-
- if (se.death_type != KILLED_BY_LEAVING && se.death_type != KILLED_BY_WINNING)
- {
- if (se.level_type == LEVEL_ABYSS)
- {
- strcat(buf, " (Abyss)");
- return;
- }
- else if (se.level_type == LEVEL_PANDEMONIUM)
- {
- strcat(buf, " (Pan)");
- return;
- }
- else if (se.level_type == LEVEL_LABYRINTH)
- {
- strcat(buf, " (Lab)");
- return;
- }
- else if (se.branch == BRANCH_VESTIBULE_OF_HELL)
- {
- strcat(buf, " (Hell)"); // Gate? Vest?
- return;
- }
- else if (se.branch == BRANCH_HALL_OF_BLADES)
- {
- strcat(buf, " (Blade)");
- return;
- }
- else if (se.branch == BRANCH_ECUMENICAL_TEMPLE)
- {
- strcat(buf, " (Temple)");
- return;
- }
-
- snprintf( scratch, sizeof(scratch), " (%s%d)",
- (se.branch == BRANCH_DIS) ? "Dis " :
- (se.branch == BRANCH_GEHENNA) ? "Geh " :
- (se.branch == BRANCH_COCYTUS) ? "Coc " :
- (se.branch == BRANCH_TARTARUS) ? "Tar " :
- (se.branch == BRANCH_ORCISH_MINES) ? "Orc " :
- (se.branch == BRANCH_HIVE) ? "Hive " :
- (se.branch == BRANCH_LAIR) ? "Lair " :
- (se.branch == BRANCH_SLIME_PITS) ? "Slime " :
- (se.branch == BRANCH_VAULTS) ? "Vault " :
- (se.branch == BRANCH_CRYPT) ? "Crypt " :
- (se.branch == BRANCH_HALL_OF_ZOT) ? "Zot " :
- (se.branch == BRANCH_SNAKE_PIT) ? "Snake " :
- (se.branch == BRANCH_ELVEN_HALLS) ? "Elf " :
- (se.branch == BRANCH_TOMB) ? "Tomb " :
- (se.branch == BRANCH_SWAMP) ? "Swamp " : "DLv ",
- se.dlvl );
-
- strcat( buf, scratch );
- } // endif - killed by winning
-
- return;
+ std::string line = se.hiscore_line(scorefile_entry::DDV_ONELINE);
+ strncpy(buf, line.c_str(), INFO_SIZE);
+ buf[INFO_SIZE - 1] = 0;
}
static bool hiscore_same_day( time_t t1, time_t t2 )
@@ -536,539 +284,21 @@ static void hiscore_date_string( time_t time, char buff[INFO_SIZE] )
date->tm_mday, date->tm_year + 1900 );
}
-static void hiscore_newline( char *buf, int &line_count )
+static std::string hiscore_newline_string()
{
- strncat( buf, EOL " ", HIGHSCORE_SIZE );
- line_count++;
+ return (EOL " ");
}
-int hiscores_format_single_long( char *buf, struct scorefile_entry &se,
+void hiscores_format_single_long( char *buf, const scorefile_entry &se,
bool verbose )
{
- char scratch[INFO_SIZE];
- int line_count = 1;
-
- // race_class_name could/used to override race & class
- // strcpy(scratch, se.race_class_name);
-
- // Please excuse the following bit of mess in the name of flavour ;)
- if (verbose)
- {
- strncpy( scratch, skill_title( se.best_skill, se.best_skill_lvl,
- se.race, se.str, se.dex, se.god ),
- INFO_SIZE );
-
- snprintf( buf, HIGHSCORE_SIZE, "%8ld %s the %s (level %d",
- se.points, se.name, scratch, se.lvl );
-
- }
- else
- {
- snprintf( buf, HIGHSCORE_SIZE, "%8ld %s the %s %s (level %d",
- se.points, se.name, species_name(se.race, se.lvl),
- get_class_name(se.cls), se.lvl );
- }
-
- if (se.final_max_max_hp > 0) // as the other two may be negative
- {
- snprintf( scratch, INFO_SIZE, ", %d/%d", se.final_hp, se.final_max_hp );
- strncat( buf, scratch, HIGHSCORE_SIZE );
-
- if (se.final_max_hp < se.final_max_max_hp)
- {
- snprintf( scratch, INFO_SIZE, " (%d)", se.final_max_max_hp );
- strncat( buf, scratch, HIGHSCORE_SIZE );
- }
-
- strncat( buf, " HPs", HIGHSCORE_SIZE );
- }
-
- strncat( buf, ((se.wiz_mode) ? ") *WIZ*" : ")"), HIGHSCORE_SIZE );
- hiscore_newline( buf, line_count );
-
- if (verbose)
- {
- const char *const race = species_name( se.race, se.lvl );
-
- snprintf( scratch, INFO_SIZE, "Began as a%s %s %s",
- is_vowel(race[0]) ? "n" : "", race, get_class_name(se.cls) );
- strncat( buf, scratch, HIGHSCORE_SIZE );
-
- if (se.birth_time > 0)
- {
- strncat( buf, " on ", HIGHSCORE_SIZE );
- hiscore_date_string( se.birth_time, scratch );
- strncat( buf, scratch, HIGHSCORE_SIZE );
- }
-
- strncat( buf, "." , HIGHSCORE_SIZE );
- hiscore_newline( buf, line_count );
-
- if (se.race != SP_DEMIGOD && se.god != -1)
- {
- if (se.god == GOD_XOM)
- {
- snprintf( scratch, INFO_SIZE, "Was a %sPlaything of Xom.",
- (se.lvl >= 20) ? "Favourite " : "" );
-
- strncat( buf, scratch, HIGHSCORE_SIZE );
- hiscore_newline( buf, line_count );
- }
- else if (se.god != GOD_NO_GOD)
- {
- // Not exactly the same as the religon screen, but
- // good enough to fill this slot for now.
- snprintf( scratch, INFO_SIZE, "Was %s of %s%s",
- (se.piety > 160) ? "the Champion" :
- (se.piety >= 120) ? "a High Priest" :
- (se.piety >= 100) ? "an Elder" :
- (se.piety >= 75) ? "a Priest" :
- (se.piety >= 50) ? "a Believer" :
- (se.piety >= 30) ? "a Follower"
- : "an Initiate",
- god_name( se.god ),
- (se.penance > 0) ? " (penitent)." : "." );
-
- strncat( buf, scratch, HIGHSCORE_SIZE );
- hiscore_newline( buf, line_count );
- }
- }
- }
-
- // get monster type & number, if applicable
- int mon_type = se.death_source;
- int mon_number = se.mon_num;
-
- bool needs_beam_cause_line = false;
- bool needs_called_by_monster_line = false;
- bool needs_damage = false;
-
- switch (se.death_type)
- {
- case KILLED_BY_MONSTER:
- // GDL: here's an example of using final_hp. Verbiage could be better.
- // bwr: changed "blasted" since this is for melee
- snprintf( scratch, INFO_SIZE, "%s %s",
- (se.final_hp > -6) ? "Slain by" :
- (se.final_hp > -14) ? "Mangled by" :
- (se.final_hp > -22) ? "Demolished by"
- : "Annihilated by",
-
- (se.death_source_name[0] != '\0')
- ? se.death_source_name
- : monam( mon_number, mon_type, true, DESC_PLAIN ) );
-
- strncat( buf, scratch, HIGHSCORE_SIZE );
-
- // put the damage on the weapon line if there is one
- if (se.auxkilldata[0] == '\0')
- needs_damage = true;
- break;
-
- case KILLED_BY_POISON:
- //if (dam == -9999) strcat(buf, "an overload of ");
- strcat( buf, "Succumbed to poison" );
- break;
-
- case KILLED_BY_CLOUD:
- if (se.auxkilldata[0] == '\0')
- strcat( buf, "Engulfed by a cloud" );
- else
- {
- snprintf( scratch, sizeof(scratch), "Engulfed by a cloud of %s",
- se.auxkilldata );
- strcat( buf, scratch );
- }
- needs_damage = true;
- break;
-
- case KILLED_BY_BEAM:
- if (isupper( se.auxkilldata[0] )) // already made (ie shot arrows)
- {
- strcat( buf, se.auxkilldata );
- needs_damage = true;
- }
- else if (verbose && strncmp( se.auxkilldata, "by ", 3 ) == 0)
- {
- // "by" is used for priest attacks where the effect is indirect
- // in verbose format we have another line for the monster
- needs_called_by_monster_line = true;
- snprintf( scratch, sizeof(scratch), "Killed %s", se.auxkilldata );
- strncat( buf, scratch, HIGHSCORE_SIZE );
- }
- else
- {
- // Note: This is also used for the "by" cases in non-verbose
- // mode since listing the monster is more imporatant.
- strcat( buf, "Killed from afar by " );
-
- // if death_source_name is non-null, override this
- if (se.death_source_name[0] != '\0')
- strcat(buf, se.death_source_name);
- else
- strcat(buf, monam( mon_number, mon_type, true, DESC_PLAIN ));
-
- if (se.auxkilldata[0] != '\0')
- needs_beam_cause_line = true;
- }
- break;
-
- case KILLED_BY_LAVA:
- if (se.race == SP_MUMMY)
- strcat( buf, "Turned to ash by lava" );
- else
- strcat( buf, "Took a swim in molten lava" );
- break;
-
- case KILLED_BY_WATER:
- if (se.race == SP_MUMMY)
- strcat( buf, "Soaked and fell apart" );
- else
- strcat( buf, "Drowned" );
- break;
-
- case KILLED_BY_STUPIDITY:
- strcat( buf, "Forgot to breathe" );
- break;
-
- case KILLED_BY_WEAKNESS:
- strcat( buf, "Collapsed under their own weight" );
- break;
-
- case KILLED_BY_CLUMSINESS:
- strcat( buf, "Slipped on a banana peel" );
- break;
-
- case KILLED_BY_TRAP:
- snprintf( scratch, sizeof(scratch), "Killed by triggering a%s trap",
- (se.auxkilldata[0] != '\0') ? se.auxkilldata : "" );
- strcat( buf, scratch );
- needs_damage = true;
- break;
-
- case KILLED_BY_LEAVING:
- if (se.num_runes > 0)
- strcat( buf, "Got out of the dungeon" );
- else
- strcat( buf, "Got out of the dungeon alive!" );
- break;
-
- case KILLED_BY_WINNING:
- strcat( buf, "Escaped with the Orb" );
- if (se.num_runes < 1)
- strcat( buf, "!" );
- break;
-
- case KILLED_BY_QUITTING:
- strcat( buf, "Quit the game" );
- break;
-
- case KILLED_BY_DRAINING:
- strcat( buf, "Was drained of all life" );
- break;
-
- case KILLED_BY_STARVATION:
- strcat( buf, "Starved to death" );
- break;
-
- case KILLED_BY_FREEZING: // refrigeration spell
- strcat( buf, "Froze to death" );
- needs_damage = true;
- break;
-
- case KILLED_BY_BURNING: // sticky flame
- strcat( buf, "Burnt to a crisp" );
- needs_damage = true;
- break;
-
- case KILLED_BY_WILD_MAGIC:
- if (se.auxkilldata[0] == '\0')
- strcat( buf, "Killed by wild magic" );
- else
- {
- // A lot of sources for this case... some have "by" already.
- snprintf( scratch, sizeof(scratch), "Killed %s%s",
- (strncmp( se.auxkilldata, "by ", 3 ) != 0) ? "by " : "",
- se.auxkilldata );
-
- strcat( buf, scratch );
- }
-
- needs_damage = true;
- break;
-
- case KILLED_BY_XOM: // only used for old Xom kills
- strcat( buf, "It was good that Xom killed them" );
- needs_damage = true;
- break;
-
- case KILLED_BY_STATUE:
- strcat( buf, "Killed by a statue" );
- needs_damage = true;
- break;
-
- case KILLED_BY_ROTTING:
- strcat( buf, "Rotted away" );
- break;
-
- case KILLED_BY_TARGETTING:
- strcat( buf, "Killed themselves with bad targeting" );
- needs_damage = true;
- break;
-
- case KILLED_BY_SPORE:
- strcat( buf, "Killed by an exploding spore" );
- needs_damage = true;
- break;
-
- case KILLED_BY_TSO_SMITING:
- strcat( buf, "Smote by The Shining One" );
- needs_damage = true;
- break;
-
- case KILLED_BY_PETRIFICATION:
- strcat( buf, "Turned to stone" );
- break;
-
- case KILLED_BY_SHUGGOTH:
- strcat( buf, "Eviscerated by a hatching shuggoth" );
- needs_damage = true;
- break;
-
- case KILLED_BY_SOMETHING:
- strcat( buf, "Died" );
- break;
-
- case KILLED_BY_FALLING_DOWN_STAIRS:
- strcat( buf, "Fell down a flight of stairs" );
- needs_damage = true;
- break;
-
- case KILLED_BY_ACID:
- strcat( buf, "Splashed by acid" );
- needs_damage = true;
- break;
-
- default:
- strcat( buf, "Nibbled to death by software bugs" );
- break;
- } // end switch
-
- // TODO: Eventually, get rid of "..." for cases where the text fits.
- if (verbose)
- {
- bool done_damage = false; // paranoia
-
- if (needs_damage && se.damage > 0)
- {
- snprintf( scratch, INFO_SIZE, " (%d damage)", se.damage );
- strncat( buf, scratch, HIGHSCORE_SIZE );
- needs_damage = false;
- done_damage = true;
- }
-
- if ((se.death_type == KILLED_BY_LEAVING
- || se.death_type == KILLED_BY_WINNING)
- && se.num_runes > 0)
- {
- hiscore_newline( buf, line_count );
-
- snprintf( scratch, INFO_SIZE, "... %s %d rune%s",
- (se.death_type == KILLED_BY_WINNING) ? "and" : "with",
- se.num_runes, (se.num_runes > 1) ? "s" : "" );
- strncat( buf, scratch, HIGHSCORE_SIZE );
-
- if (se.num_diff_runes > 1)
- {
- snprintf( scratch, INFO_SIZE, " (of %d types)",
- se.num_diff_runes );
- strncat( buf, scratch, HIGHSCORE_SIZE );
- }
-
- if (se.death_time > 0
- && !hiscore_same_day( se.birth_time, se.death_time ))
- {
- strcat( buf, " on " );
- hiscore_date_string( se.death_time, scratch );
- strcat( buf, scratch );
- }
-
- strcat( buf, "!" );
- hiscore_newline( buf, line_count );
- }
- else if (se.death_type != KILLED_BY_QUITTING)
- {
- hiscore_newline( buf, line_count );
-
- if (se.death_type == KILLED_BY_MONSTER && se.auxkilldata[0])
- {
- snprintf(scratch, INFO_SIZE, "... wielding %s", se.auxkilldata);
- strncat(buf, scratch, HIGHSCORE_SIZE);
- needs_damage = true;
- }
- else if (needs_beam_cause_line)
- {
- strcat( buf, (is_vowel( se.auxkilldata[0] )) ? "... with an "
- : "... with a " );
- strcat( buf, se.auxkilldata );
- needs_damage = true;
- }
- else if (needs_called_by_monster_line)
- {
- snprintf( scratch, sizeof(scratch), "... called down by %s",
- se.death_source_name );
- strncat( buf, scratch, HIGHSCORE_SIZE );
- needs_damage = true;
- }
-
- if (needs_damage && !done_damage)
- {
- if (se.damage > 0)
- {
- snprintf( scratch, INFO_SIZE, " (%d damage)", se.damage );
- strncat( buf, scratch, HIGHSCORE_SIZE );
- hiscore_newline( buf, line_count );
- }
- }
- }
- }
-
- if (se.death_type == KILLED_BY_LEAVING
- || se.death_type == KILLED_BY_WINNING)
- {
- // TODO: strcat "after reaching level %d"; for LEAVING
- if (!verbose)
- {
- if (se.num_runes > 0)
- strcat( buf, "!" );
-
- hiscore_newline( buf, line_count );
- }
- }
- else
- {
- if (verbose && se.death_type != KILLED_BY_QUITTING)
- strcat( buf, "..." );
-
- if (se.level_type == LEVEL_ABYSS)
- strcat( buf, " in the Abyss" );
- else if (se.level_type == LEVEL_PANDEMONIUM)
- strcat( buf, " in Pandemonium" );
- else if (se.level_type == LEVEL_LABYRINTH)
- strcat( buf, " in a labyrinth" );
- else
- {
- switch (se.branch)
- {
- case BRANCH_ECUMENICAL_TEMPLE:
- strcat( buf, " in the Ecumenical Temple" );
- break;
- case BRANCH_HALL_OF_BLADES:
- strcat( buf, " in the Hall of Blades" );
- break;
- case BRANCH_VESTIBULE_OF_HELL:
- strcat( buf, " in the Vestibule" );
- break;
-
- case BRANCH_DIS:
- strcat( buf, " on Dis" );
- break;
- case BRANCH_GEHENNA:
- strcat( buf, " on Gehenna" );
- break;
- case BRANCH_COCYTUS:
- strcat( buf, " on Cocytus" );
- break;
- case BRANCH_TARTARUS:
- strcat( buf, " on Tartarus" );
- break;
- case BRANCH_ORCISH_MINES:
- strcat( buf, " on Orcish Mines" );
- break;
- case BRANCH_HIVE:
- strcat( buf, " on Hive" );
- break;
- case BRANCH_LAIR:
- strcat( buf, " on Lair" );
- break;
- case BRANCH_SLIME_PITS:
- strcat( buf, " on Slime Pits" );
- break;
- case BRANCH_VAULTS:
- strcat( buf, " on Vault" );
- break;
- case BRANCH_CRYPT:
- strcat( buf, " on Crypt" );
- break;
- case BRANCH_HALL_OF_ZOT:
- strcat( buf, " on Hall of Zot" );
- break;
- case BRANCH_SNAKE_PIT:
- strcat( buf, " on Snake Pit" );
- break;
- case BRANCH_ELVEN_HALLS:
- strcat( buf, " on Elven Halls" );
- break;
- case BRANCH_TOMB:
- strcat( buf, " on Tomb" );
- break;
- case BRANCH_SWAMP:
- strcat( buf, " on Swamp" );
- break;
- case BRANCH_MAIN_DUNGEON:
- strcat( buf, " on Dungeon" );
- break;
- }
-
- if (se.branch != BRANCH_VESTIBULE_OF_HELL
- && se.branch != BRANCH_ECUMENICAL_TEMPLE
- && se.branch != BRANCH_HALL_OF_BLADES)
- {
- snprintf( scratch, sizeof(scratch), " Level %d", se.dlvl );
- strcat( buf, scratch );
- }
- }
-
- if (verbose && se.death_time
- && !hiscore_same_day( se.birth_time, se.death_time ))
- {
- strcat( buf, " on " );
- hiscore_date_string( se.death_time, scratch );
- strcat( buf, scratch );
- }
-
- strcat( buf, "." );
- hiscore_newline( buf, line_count );
- } // endif - killed by winning
-
- if (verbose)
- {
- if (se.real_time > 0)
- {
- char username[80] = "The";
- char tmp[80];
-
-#ifdef MULTIUSER
- if (se.uid > 0)
- {
- struct passwd *pw_entry = getpwuid( se.uid );
- strncpy( username, pw_entry->pw_name, sizeof(username) );
- strncat( username, "'s", sizeof(username) );
- username[0] = toupper( username[0] );
- }
-#endif
-
- make_time_string( se.real_time, tmp, sizeof(tmp) );
-
- snprintf( scratch, INFO_SIZE, "%s game lasted %s (%ld turns).",
- username, tmp, se.num_turns );
-
- strncat( buf, scratch, HIGHSCORE_SIZE );
- hiscore_newline( buf, line_count );
- }
- }
-
- return (line_count);
+ std::string line =
+ se.hiscore_line(
+ verbose?
+ scorefile_entry::DDV_VERBOSE
+ : scorefile_entry::DDV_NORMAL );
+ strncpy(buf, line.c_str(), HIGHSCORE_SIZE);
+ buf[HIGHSCORE_SIZE - 1] = 0;
}
// --------------------------------------------------------------------------
@@ -1158,13 +388,10 @@ static bool unlock_file_handle( FILE *handle )
FILE *hs_open( const char *mode )
{
-#ifdef SAVE_DIR_PATH
- FILE *handle = fopen(SAVE_DIR_PATH "scores", mode);
+ std::string scores = Options.save_dir + "scores";
+ FILE *handle = fopen(scores.c_str(), mode);
#ifdef SHARED_FILES_CHMOD_PUBLIC
- chmod(SAVE_DIR_PATH "scores", SHARED_FILES_CHMOD_PUBLIC);
-#endif
-#else
- FILE *handle = fopen("scores", mode);
+ chmod(scores.c_str(), SHARED_FILES_CHMOD_PUBLIC);
#endif
#ifdef USE_FILE_LOCKING
@@ -1199,104 +426,19 @@ void hs_close( FILE *handle, const char *mode )
#ifdef SHARED_FILES_CHMOD_PUBLIC
if (stricmp(mode, "w") == 0)
{
- #ifdef SAVE_DIR_PATH
- chmod(SAVE_DIR_PATH "scores", SHARED_FILES_CHMOD_PUBLIC);
- #else
- chmod("scores", SHARED_FILES_CHMOD_PUBLIC);
- #endif
+ std::string scores = Options.save_dir + "scores";
+ chmod(scores.c_str(), SHARED_FILES_CHMOD_PUBLIC);
}
#endif
}
-static void hs_init( struct scorefile_entry &dest )
-{
- // simple init
- dest.version = 0;
- dest.release = 0;
- dest.points = -1;
- dest.name[0] = '\0';
- dest.uid = 0;
- dest.race = 0;
- dest.cls = 0;
- dest.lvl = 0;
- dest.race_class_name[0] = '\0';
- dest.best_skill = 0;
- dest.best_skill_lvl = 0;
- dest.death_type = KILLED_BY_SOMETHING;
- dest.death_source = 0;
- dest.mon_num = 0;
- dest.death_source_name[0] = '\0';
- dest.auxkilldata[0] = '\0';
- dest.dlvl = 0;
- dest.level_type = 0;
- dest.branch = 0;
- dest.final_hp = -1;
- dest.final_max_hp = -1;
- dest.final_max_max_hp = -1;
- dest.str = -1;
- dest.intel = -1;
- dest.dex = -1;
- dest.damage = -1;
- dest.god = -1;
- dest.piety = -1;
- dest.penance = -1;
- dest.wiz_mode = 0;
- dest.birth_time = 0;
- dest.death_time = 0;
- dest.real_time = -1;
- dest.num_turns = -1;
- dest.num_diff_runes = 0;
- dest.num_runes = 0;
-}
-
-void hs_copy(struct scorefile_entry &dest, struct scorefile_entry &src)
-{
- // simple field copy -- assume src is well constructed.
-
- dest.version = src.version;
- dest.release = src.release;
- dest.points = src.points;
- strcpy(dest.name, src.name);
- dest.uid = src.uid;
- dest.race = src.race;
- dest.cls = src.cls;
- dest.lvl = src.lvl;
- strcpy(dest.race_class_name, src.race_class_name);
- dest.best_skill = src.best_skill;
- dest.best_skill_lvl = src.best_skill_lvl;
- dest.death_type = src.death_type;
- dest.death_source = src.death_source;
- dest.mon_num = src.mon_num;
- strcpy( dest.death_source_name, src.death_source_name );
- strcpy( dest.auxkilldata, src.auxkilldata );
- dest.dlvl = src.dlvl;
- dest.level_type = src.level_type;
- dest.branch = src.branch;
- dest.final_hp = src.final_hp;
- dest.final_max_hp = src.final_max_hp;
- dest.final_max_max_hp = src.final_max_max_hp;
- dest.str = src.str;
- dest.intel = src.intel;
- dest.dex = src.dex;
- dest.damage = src.damage;
- dest.god = src.god;
- dest.piety = src.piety;
- dest.penance = src.penance;
- dest.wiz_mode = src.wiz_mode;
- dest.birth_time = src.birth_time;
- dest.death_time = src.death_time;
- dest.real_time = src.real_time;
- dest.num_turns = src.num_turns;
- dest.num_diff_runes = src.num_diff_runes;
- dest.num_runes = src.num_runes;
-}
-
-bool hs_read( FILE *scores, struct scorefile_entry &dest )
+bool hs_read( FILE *scores, scorefile_entry &dest )
{
char inbuf[200];
int c = EOF;
- hs_init( dest );
+ memset(inbuf, 0, sizeof inbuf);
+ dest.reset();
// get a character..
if (scores != NULL)
@@ -1327,38 +469,46 @@ bool hs_read( FILE *scores, struct scorefile_entry &dest )
return true;
}
-static void hs_nextstring(char *&inbuf, char *dest)
+static void hs_nextstring(char *&inbuf, char *dest, size_t destsize)
{
+ ASSERT(destsize > 0);
+
char *p = dest;
- if (*inbuf == '\0')
+ if (*inbuf == 0)
{
- *p = '\0';
+ *p = 0;
return;
}
// assume we're on a ':'
- inbuf ++;
- while(*inbuf != ':' && *inbuf != '\0')
+ if (*inbuf == ':')
+ inbuf++;
+
+ while (*inbuf && *inbuf != ':' && (p - dest) < (int) destsize - 1)
*p++ = *inbuf++;
- *p = '\0';
+ // If we ran out of buffer, discard the rest of the field.
+ while (*inbuf && *inbuf != ':')
+ inbuf++;
+
+ *p = 0;
}
static int hs_nextint(char *&inbuf)
{
char num[20];
- hs_nextstring(inbuf, num);
+ hs_nextstring(inbuf, num, sizeof num);
- return (num[0] == '\0' ? 0 : atoi(num));
+ return (num[0] == 0 ? 0 : atoi(num));
}
static long hs_nextlong(char *&inbuf)
{
char num[20];
- hs_nextstring(inbuf, num);
+ hs_nextstring(inbuf, num, sizeof num);
- return (num[0] == '\0' ? 0 : atol(num));
+ return (num[0] == 0 ? 0 : atol(num));
}
static int val_char( char digit )
@@ -1371,7 +521,7 @@ static time_t hs_nextdate(char *&inbuf)
char buff[20];
struct tm date;
- hs_nextstring( inbuf, buff );
+ hs_nextstring(inbuf, buff, sizeof buff);
if (strlen( buff ) < 15)
return (static_cast<time_t>(0));
@@ -1403,13 +553,13 @@ static void hs_parse_numeric(char *inbuf, struct scorefile_entry &se)
se.points = hs_nextlong(inbuf);
- hs_nextstring(inbuf, se.name);
+ hs_nextstring(inbuf, se.name, sizeof se.name);
se.uid = hs_nextlong(inbuf);
se.race = hs_nextint(inbuf);
se.cls = hs_nextint(inbuf);
- hs_nextstring(inbuf, se.race_class_name);
+ hs_nextstring(inbuf, se.race_class_name, sizeof se.race_class_name);
se.lvl = hs_nextint(inbuf);
se.best_skill = hs_nextint(inbuf);
@@ -1418,15 +568,15 @@ static void hs_parse_numeric(char *inbuf, struct scorefile_entry &se)
se.death_source = hs_nextint(inbuf);
se.mon_num = hs_nextint(inbuf);
- hs_nextstring(inbuf, se.death_source_name);
+ hs_nextstring(inbuf, se.death_source_name, sizeof se.death_source_name);
// To try and keep the scorefile backwards compatible,
// we'll branch on version > 4.0 to read the auxkilldata
// text field.
if (se.version == 4 && se.release >= 1)
- hs_nextstring( inbuf, se.auxkilldata );
+ hs_nextstring( inbuf, se.auxkilldata, sizeof se.auxkilldata );
else
- se.auxkilldata[0] = '\0';
+ se.auxkilldata[0] = 0;
se.dlvl = hs_nextint(inbuf);
se.level_type = hs_nextint(inbuf);
@@ -1492,7 +642,7 @@ static void hs_parse_numeric(char *inbuf, struct scorefile_entry &se)
se.num_runes = hs_nextint(inbuf);
}
-static void hs_write( FILE *scores, struct scorefile_entry &se )
+static void hs_write( FILE *scores, scorefile_entry &se )
{
char buff[80]; // should be more than enough for date stamps
@@ -1529,7 +679,7 @@ static void hs_write( FILE *scores, struct scorefile_entry &se )
static void hs_parse_string(char *inbuf, struct scorefile_entry &se)
{
/* old entries are of the following format (Brent introduced some
- spacing at one point, we have to take this into account):
+ spacing at one point, we have to take this into account):
// Actually, I believe it might have been Brian who added the spaces,
// I was quite happy with the condensed version, given the 80 column
@@ -1545,7 +695,7 @@ static void hs_parse_string(char *inbuf, struct scorefile_entry &se)
4. All numerics up to the comma are the clevel
5. From the comma, search for known fixed substrings and
translate to death_type. Leave death source = 0 for old
- scores, and just copy in the monster name.
+ scores, and just copy in the monster name.
6. Look for the branch type (again, substring search for
fixed strings) and level.
@@ -1554,40 +704,50 @@ static void hs_parse_string(char *inbuf, struct scorefile_entry &se)
*/
char scratch[80];
+ const int inlen = strlen(inbuf);
+ char *start = inbuf;
// 1. get score
- hs_parse_generic_2(inbuf, scratch, "0123456789");
+ hs_parse_generic_2(inbuf, scratch, sizeof scratch, "0123456789");
se.version = 0; // version # of converted score
se.release = 0;
se.points = atoi(scratch);
// 2. get name
- hs_parse_generic_1(inbuf, scratch, "-");
+ hs_parse_generic_1(inbuf, scratch, sizeof scratch, "-");
hs_stripblanks(scratch);
- strcpy(se.name, scratch);
+ strncpy(se.name, scratch, sizeof se.name);
+ se.name[ sizeof(se.name) - 1 ] = 0;
// 3. get race, class
- inbuf++; // skip '-'
- hs_parse_generic_1(inbuf, scratch, "0123456789");
+ // skip '-'
+ if (++inbuf - start >= inlen)
+ return;
+
+ hs_parse_generic_1(inbuf, scratch, sizeof scratch, "0123456789");
hs_stripblanks(scratch);
- strcpy(se.race_class_name, scratch);
+ strncpy(se.race_class_name, scratch, sizeof se.race_class_name);
+ se.race_class_name[ sizeof(se.race_class_name) - 1 ] = 0;
se.race = 0;
se.cls = 0;
// 4. get clevel
- hs_parse_generic_2(inbuf, scratch, "0123456789");
+ hs_parse_generic_2(inbuf, scratch, sizeof scratch, "0123456789");
se.lvl = atoi(scratch);
// 4a. get wizard mode
- hs_parse_generic_1(inbuf, scratch, ",");
+ hs_parse_generic_1(inbuf, scratch, sizeof scratch, ",");
if (strstr(scratch, "Wiz") != NULL)
se.wiz_mode = 1;
else
se.wiz_mode = 0;
+ // Skip comma
+ if (++inbuf - start >= inlen)
+ return;
+
// 5. get death type
- inbuf++; // skip comma
hs_search_death(inbuf, se);
// 6. get branch, level
@@ -1613,27 +773,56 @@ static void hs_parse_string(char *inbuf, struct scorefile_entry &se)
se.num_turns = -1;
se.num_runes = 0;
se.num_diff_runes = 0;
- se.auxkilldata[0] = '\0';
+ se.auxkilldata[0] = 0;
}
-static void hs_parse_generic_1(char *&inbuf, char *outbuf, const char *stopvalues)
+static void hs_parse_generic_1(char *&inbuf, char *outbuf, size_t outsz, const char *stopvalues)
{
+ ASSERT(outsz > 0);
+
char *p = outbuf;
- while(strchr(stopvalues, *inbuf) == NULL && *inbuf != '\0')
+ if (!*inbuf)
+ {
+ *p = 0;
+ return;
+ }
+
+ while (strchr(stopvalues, *inbuf) == NULL
+ && *inbuf != 0
+ && (p - outbuf) < (int) outsz - 1)
*p++ = *inbuf++;
- *p = '\0';
+ while (strchr(stopvalues, *inbuf) == NULL
+ && *inbuf != 0)
+ inbuf++;
+
+ *p = 0;
}
-static void hs_parse_generic_2(char *&inbuf, char *outbuf, const char *continuevalues)
+static void hs_parse_generic_2(
+ char *&inbuf, char *outbuf, size_t outsz, const char *continuevalues)
{
+ ASSERT(outsz > 0);
+
char *p = outbuf;
- while(strchr(continuevalues, *inbuf) != NULL && *inbuf != '\0')
+ if (!*inbuf)
+ {
+ *p = 0;
+ return;
+ }
+
+ while (strchr(continuevalues, *inbuf) != NULL
+ && *inbuf
+ && (p - outbuf) < (int) outsz - 1)
*p++ = *inbuf++;
- *p = '\0';
+ while (strchr(continuevalues, *inbuf) != NULL
+ && *inbuf)
+ inbuf++;
+
+ *p = 0;
}
static void hs_stripblanks(char *buf)
@@ -1644,16 +833,14 @@ static void hs_stripblanks(char *buf)
// strip leading
while(*p == ' ')
p++;
- while(*p != '\0')
+
+ while(*p != 0 && p != q)
*q++ = *p++;
- *q-- = '\0';
+ *q-- = 0;
// strip trailing
- while(*q == ' ')
- {
- *q = '\0';
- q--;
- }
+ while (q >= buf && *q == ' ')
+ *q-- = 0;
}
static void hs_search_death(char *inbuf, struct scorefile_entry &se)
@@ -1670,6 +857,8 @@ static void hs_search_death(char *inbuf, struct scorefile_entry &se)
se.death_type = KILLED_BY_BEAM;
else if (strstr(inbuf, "took a swim in molten lava") != NULL)
se.death_type = KILLED_BY_LAVA;
+ else if (strstr(inbuf, "asphyxiated"))
+ se.death_type = KILLED_BY_CURARE;
else if (strstr(inbuf, "soaked and fell apart") != NULL)
{
se.death_type = KILLED_BY_WATER;
@@ -1715,13 +904,15 @@ static void hs_search_death(char *inbuf, struct scorefile_entry &se)
se.death_type = KILLED_BY_TSO_SMITING;
else if (strstr(inbuf, "turned to stone") != NULL)
se.death_type = KILLED_BY_PETRIFICATION;
- else if (strstr(inbuf, "eviscerated by a hatching") != NULL)
- se.death_type = KILLED_BY_SHUGGOTH;
+ else if (strstr(inbuf, "melted into a puddle") != NULL)
+ se.death_type = KILLED_BY_MELTING;
+ else if (strstr(inbuf, "bled to death") != NULL)
+ se.death_type = KILLED_BY_BLEEDING;
// whew!
- // now, if we're still KILLED_BY_MONSTER, make sure that there is
- // a "killed by" somewhere, or else we're setting it to UNKNOWN.
+ // now, if we're still KILLED_BY_MONSTER, make sure that there is
+ // a "killed by" somewhere, or else we're setting it to UNKNOWN.
if (se.death_type == KILLED_BY_MONSTER)
{
if (strstr(inbuf, "killed by") == NULL)
@@ -1731,21 +922,31 @@ static void hs_search_death(char *inbuf, struct scorefile_entry &se)
// set some fields
se.death_source = 0;
se.mon_num = 0;
- strcpy(se.death_source_name, "");
+ *se.death_source_name = 0;
// now try to pull the monster out.
+ // [dshaligram] Holy brain damage, Batman.
if (se.death_type == KILLED_BY_MONSTER || se.death_type == KILLED_BY_BEAM)
{
char *p = strstr(inbuf, " by ");
- p += 4;
- char *q = strstr(inbuf, " on ");
- if (q == NULL)
- q = strstr(inbuf, " in ");
- char *d = se.death_source_name;
- while(p != q)
- *d++ = *p++;
-
- *d = '\0';
+ if (p)
+ {
+ p += 4;
+ char *q = strstr(inbuf, " on ");
+ if (q == NULL)
+ q = strstr(inbuf, " in ");
+
+ if (q && q > p)
+ {
+ char *d = se.death_source_name;
+ const int maxread = sizeof(se.death_source_name) - 1;
+
+ while (p < q && (d - se.death_source_name) < maxread)
+ *d++ = *p++;
+
+ *d = 0;
+ }
+ }
}
}
@@ -1758,7 +959,8 @@ static void hs_search_where(char *inbuf, struct scorefile_entry &se)
se.dlvl = 0;
// early out
- if (se.death_type == KILLED_BY_LEAVING || se.death_type == KILLED_BY_WINNING)
+ if (se.death_type == KILLED_BY_LEAVING
+ || se.death_type == KILLED_BY_WINNING)
return;
// here we go again.
@@ -1780,12 +982,12 @@ static void hs_search_where(char *inbuf, struct scorefile_entry &se)
return;
}
- // from here, we have branch and level.
+ // from here, we have branch and level.
char *p = strstr(inbuf, "on L");
if (p != NULL)
{
p += 4;
- hs_parse_generic_2(p, scratch, "0123456789");
+ hs_parse_generic_2(p, scratch, sizeof scratch, "0123456789");
se.dlvl = atoi( scratch );
}
@@ -1825,3 +1027,1009 @@ static void hs_search_where(char *inbuf, struct scorefile_entry &se)
else if (strstr(inbuf, "of the Swamp") != NULL)
se.branch = BRANCH_SWAMP;
}
+
+//////////////////////////////////////////////////////////////////////////
+// scorefile_entry
+
+scorefile_entry::scorefile_entry(int dam, int dsource, int dtype,
+ const char *aux, bool death_cause_only)
+{
+ reset();
+
+ init_death_cause(dam, dsource, dtype, aux);
+ if (!death_cause_only)
+ init();
+}
+
+scorefile_entry::scorefile_entry()
+{
+ // Completely uninitialized, caveat user.
+ reset();
+}
+
+void scorefile_entry::init_death_cause(int dam, int dsrc,
+ int dtype, const char *aux)
+{
+ death_source = dsrc;
+ death_type = dtype;
+ damage = dam;
+
+ // Set the default aux data value...
+ // If aux is passed in (ie for a trap), we'll default to that.
+ if (aux == NULL)
+ auxkilldata[0] = 0;
+ else
+ {
+ strncpy( auxkilldata, aux, ITEMNAME_SIZE );
+ auxkilldata[ ITEMNAME_SIZE - 1 ] = 0;
+ }
+
+ // for death by monster
+ if ((death_type == KILLED_BY_MONSTER || death_type == KILLED_BY_BEAM)
+ && death_source >= 0 && death_source < MAX_MONSTERS)
+ {
+ const monsters *monster = &menv[death_source];
+
+ if (monster->type > 0 || monster->type <= NUM_MONSTERS)
+ {
+ death_source = monster->type;
+ mon_num = monster->number;
+
+ // Previously the weapon was only used for dancing weapons,
+ // but now we pass it in as a string through the scorefile
+ // entry to be appended in hiscores_format_single in long or
+ // medium scorefile formats.
+ // It still isn't used in monam for anything but flying weapons
+ // though
+ if (death_type == KILLED_BY_MONSTER
+ && monster->inv[MSLOT_WEAPON] != NON_ITEM)
+ {
+ // [ds] The highscore entry may be constructed while the player
+ // is alive (for notes), so make sure we don't reveal info we
+ // shouldn't.
+ if (you.hp <= 0)
+ {
+#if HISCORE_WEAPON_DETAIL
+ set_ident_flags( mitm[monster->inv[MSLOT_WEAPON]],
+ ISFLAG_IDENT_MASK );
+#else
+ // changing this to ignore the pluses to keep it short
+ unset_ident_flags( mitm[monster->inv[MSLOT_WEAPON]],
+ ISFLAG_IDENT_MASK );
+
+ set_ident_flags( mitm[monster->inv[MSLOT_WEAPON]],
+ ISFLAG_KNOW_TYPE );
+
+ // clear "runed" description text to make shorter yet
+ set_equip_desc( mitm[monster->inv[MSLOT_WEAPON]], 0 );
+#endif
+ }
+
+ // Setting this is redundant for dancing weapons, however
+ // we do care about the above indentification. -- bwr
+ if (monster->type != MONS_DANCING_WEAPON)
+ {
+ it_name( monster->inv[MSLOT_WEAPON],
+ DESC_NOCAP_A,
+ info );
+ strncpy( auxkilldata, info, ITEMNAME_SIZE );
+ auxkilldata[ ITEMNAME_SIZE - 1 ] = 0;
+ }
+ }
+
+ strcpy( info,
+ monam( monster->number, monster->type, true, DESC_NOCAP_A,
+ monster->inv[MSLOT_WEAPON] ) );
+
+ strncpy( death_source_name, info, 40 );
+ death_source_name[39] = 0;
+ }
+ }
+ else
+ {
+ death_source = death_source;
+ mon_num = 0;
+ death_source_name[0] = 0;
+ }
+}
+
+void scorefile_entry::reset()
+{
+ // simple init
+ version = 0;
+ release = 0;
+ points = -1;
+ name[0] = 0;
+ uid = 0;
+ race = 0;
+ cls = 0;
+ lvl = 0;
+ race_class_name[0] = 0;
+ best_skill = 0;
+ best_skill_lvl = 0;
+ death_type = KILLED_BY_SOMETHING;
+ death_source = 0;
+ mon_num = 0;
+ death_source_name[0] = 0;
+ auxkilldata[0] = 0;
+ dlvl = 0;
+ level_type = 0;
+ branch = 0;
+ final_hp = -1;
+ final_max_hp = -1;
+ final_max_max_hp = -1;
+ str = -1;
+ intel = -1;
+ dex = -1;
+ damage = -1;
+ god = -1;
+ piety = -1;
+ penance = -1;
+ wiz_mode = 0;
+ birth_time = 0;
+ death_time = 0;
+ real_time = -1;
+ num_turns = -1;
+ num_diff_runes = 0;
+ num_runes = 0;
+}
+
+void scorefile_entry::init()
+{
+ // Score file entry version:
+ //
+ // 4.0 - original versioned entry
+ // 4.1 - added real_time and num_turn fields
+ // 4.2 - stats and god info
+
+ version = 4;
+ release = 2;
+
+ strncpy( name, you.your_name, sizeof name );
+ name[ sizeof(name) - 1 ] = 0;
+
+#ifdef MULTIUSER
+ uid = (int) getuid();
+#else
+ uid = 0;
+#endif
+
+ // do points first.
+ points = you.gold;
+ points += (you.experience * 7) / 10;
+
+ //if (death_type == KILLED_BY_WINNING) points += points / 2;
+ //if (death_type == KILLED_BY_LEAVING) points += points / 10;
+ // these now handled by giving player the value of their inventory
+ char temp_id[4][50];
+
+ for (int d = 0; d < 4; d++)
+ {
+ for (int e = 0; e < 50; e++)
+ temp_id[d][e] = 1;
+ }
+
+ FixedVector< int, NUM_RUNE_TYPES > rune_array;
+
+ num_runes = 0;
+ num_diff_runes = 0;
+
+ for (int i = 0; i < NUM_RUNE_TYPES; i++)
+ rune_array[i] = 0;
+
+ // Calculate value of pack and runes when character leaves dungeon
+ if (death_type == KILLED_BY_LEAVING || death_type == KILLED_BY_WINNING)
+ {
+ for (int d = 0; d < ENDOFPACK; d++)
+ {
+ if (is_valid_item( you.inv[d] ))
+ {
+ points += item_value( you.inv[d], temp_id, true );
+
+ if (you.inv[d].base_type == OBJ_MISCELLANY
+ && you.inv[d].sub_type == MISC_RUNE_OF_ZOT)
+ {
+ if (rune_array[ you.inv[d].plus ] == 0)
+ num_diff_runes++;
+
+ num_runes += you.inv[d].quantity;
+ rune_array[ you.inv[d].plus ] += you.inv[d].quantity;
+ }
+ }
+ }
+
+ // Bonus for exploring different areas, not for collecting a
+ // huge stack of demonic runes in Pandemonium (gold value
+ // is enough for those). -- bwr
+ if (num_diff_runes >= 3)
+ points += ((num_diff_runes + 2) * (num_diff_runes + 2) * 1000);
+ }
+
+ // Players will have a hard time getting 1/10 of this (see XP cap):
+ if (points > 99999999)
+ points = 99999999;
+
+ race = you.species;
+ cls = you.char_class;
+
+ race_class_name[0] = 0;
+
+ lvl = you.experience_level;
+ best_skill = ::best_skill( SK_FIGHTING, NUM_SKILLS - 1, 99 );
+ best_skill_lvl = you.skills[ best_skill ];
+
+ final_hp = you.hp;
+ final_max_hp = you.hp_max;
+ final_max_max_hp = you.hp_max + player_rotted();
+ str = you.strength;
+ intel = you.intel;
+ dex = you.dex;
+
+ god = you.religion;
+ if (you.religion != GOD_NO_GOD)
+ {
+ piety = you.piety;
+ penance = you.penance[you.religion];
+ }
+
+ // main dungeon: level is simply level
+ dlvl = you.your_level + 1;
+ switch (you.where_are_you)
+ {
+ case BRANCH_ORCISH_MINES:
+ case BRANCH_HIVE:
+ case BRANCH_LAIR:
+ case BRANCH_SLIME_PITS:
+ case BRANCH_VAULTS:
+ case BRANCH_CRYPT:
+ case BRANCH_HALL_OF_BLADES:
+ case BRANCH_HALL_OF_ZOT:
+ case BRANCH_ECUMENICAL_TEMPLE:
+ case BRANCH_SNAKE_PIT:
+ case BRANCH_ELVEN_HALLS:
+ case BRANCH_TOMB:
+ case BRANCH_SWAMP:
+ dlvl = you.your_level - you.branch_stairs[you.where_are_you - 10];
+ break;
+
+ case BRANCH_DIS:
+ case BRANCH_GEHENNA:
+ case BRANCH_VESTIBULE_OF_HELL:
+ case BRANCH_COCYTUS:
+ case BRANCH_TARTARUS:
+ case BRANCH_INFERNO:
+ case BRANCH_THE_PIT:
+ dlvl = you.your_level - 26;
+ break;
+ }
+
+ branch = you.where_are_you; // no adjustments necessary.
+ level_type = you.level_type; // pandemonium, labyrinth, dungeon..
+
+ birth_time = you.birth_time; // start time of game
+ death_time = time( NULL ); // end time of game
+
+ if (you.real_time != -1)
+ real_time = you.real_time + (death_time - you.start_time);
+ else
+ real_time = -1;
+
+ num_turns = you.num_turns;
+
+#ifdef WIZARD
+ wiz_mode = (you.wizard ? 1 : 0);
+#else
+ wiz_mode = 0;
+#endif
+}
+
+std::string scorefile_entry::hiscore_line(death_desc_verbosity verbosity) const
+{
+ std::string line = character_description(verbosity);
+ line += death_description(verbosity);
+ line += death_place(verbosity);
+ line += game_time(verbosity);
+
+ return (line);
+}
+
+std::string scorefile_entry::game_time(death_desc_verbosity verbosity) const
+{
+ std::string line;
+
+ if (verbosity == DDV_VERBOSE)
+ {
+ if (real_time > 0)
+ {
+ char username[80] = "The";
+ char scratch[INFO_SIZE];
+ char tmp[80];
+
+#ifdef MULTIUSER
+ if (uid > 0)
+ {
+ struct passwd *pw_entry = getpwuid( uid );
+ strncpy( username, pw_entry->pw_name, sizeof(username) );
+ strncat( username, "'s", sizeof(username) );
+ username[0] = toupper( username[0] );
+ }
+#endif
+
+ make_time_string( real_time, tmp, sizeof(tmp) );
+
+ snprintf( scratch, INFO_SIZE, "%s game lasted %s (%ld turns).",
+ username, tmp, num_turns );
+
+ line += scratch;
+ line += hiscore_newline_string();
+ }
+ }
+
+ return (line);
+}
+
+const char *scorefile_entry::damage_verb() const
+{
+ // GDL: here's an example of using final_hp. Verbiage could be better.
+ // bwr: changed "blasted" since this is for melee
+ return (final_hp > -6) ? "Slain" :
+ (final_hp > -14) ? "Mangled" :
+ (final_hp > -22) ? "Demolished" :
+ "Annihilated";
+}
+
+const char *scorefile_entry::death_source_desc() const
+{
+ if (death_type != KILLED_BY_MONSTER && death_type != KILLED_BY_BEAM)
+ return ("");
+
+ return (*death_source_name?
+ death_source_name
+ : monam( mon_num, death_source, true, DESC_PLAIN ) );
+}
+
+std::string scorefile_entry::damage_string(bool terse) const
+{
+ char scratch[50];
+ snprintf( scratch, sizeof scratch, "(%d%s)", damage,
+ terse? "" : " damage" );
+ return (scratch);
+}
+
+std::string scorefile_entry::strip_article_a(const std::string &s) const
+{
+ if (s.find("a ") == 0)
+ return (s.substr(2));
+ else if (s.find("an ") == 0)
+ return (s.substr(3));
+ return (s);
+}
+
+std::string scorefile_entry::terse_missile_cause() const
+{
+ std::string cause;
+ std::string aux = auxkilldata;
+
+ std::string monster_prefix = " by ";
+ // We're looking for Shot with a%s %s by %s/ Hit by a%s %s thrown by %s
+ std::string::size_type by = aux.rfind(monster_prefix);
+ if (by == std::string::npos)
+ return ("???");
+
+ std::string mcause = aux.substr(by + monster_prefix.length());
+ mcause = strip_article_a(mcause);
+
+ std::string missile;
+ const std::string pre_post[][2] = {
+ { "Shot with a", " by " },
+ { "Hit by a", " thrown by " }
+ };
+
+ for (unsigned i = 0; i < sizeof(pre_post) / sizeof(*pre_post); ++i)
+ {
+ if (aux.find(pre_post[i][0]) != 0)
+ continue;
+
+ std::string::size_type end = aux.rfind(pre_post[i][1]);
+ if (end == std::string::npos)
+ continue;
+
+ int istart = pre_post[i][0].length();
+ int nchars = end - istart;
+ missile = aux.substr(istart, nchars);
+
+ // Was this prefixed by "an"?
+ if (missile.find("n ") == 0)
+ missile = missile.substr(2);
+ }
+
+ if (missile.length())
+ mcause += "/" + missile;
+
+ return (mcause);
+}
+
+std::string scorefile_entry::terse_beam_cause() const
+{
+ std::string cause = auxkilldata;
+ if (cause.find("by ") == 0 || cause.find("By ") == 0)
+ cause = cause.substr(3);
+ return (cause);
+}
+
+std::string scorefile_entry::terse_wild_magic() const
+{
+ return terse_beam_cause();
+}
+
+std::string scorefile_entry::terse_trap() const
+{
+ std::string trap = *auxkilldata? std::string(auxkilldata) + " trap"
+ : "trap";
+ if (trap.find("n ") == 0)
+ trap = trap.substr(2);
+ trim_string(trap);
+
+ return (trap);
+}
+
+std::string scorefile_entry::single_cdesc() const
+{
+ char scratch[INFO_SIZE];
+ char buf[INFO_SIZE];
+
+ if (!*race_class_name)
+ {
+ snprintf( scratch, sizeof(scratch), "%s%s",
+ get_species_abbrev( race ), get_class_abbrev( cls ) );
+ }
+ else
+ {
+ strncpy( scratch, race_class_name, sizeof scratch );
+ scratch[ sizeof(scratch) - 1 ] = 0;
+ }
+
+ std::string scname = name;
+ if (scname.length() > 10)
+ scname = scname.substr(0, 10);
+
+ snprintf( buf, sizeof buf,
+ "%8ld %-10s %s-%02d%s", points, scname.c_str(),
+ scratch, lvl, (wiz_mode == 1) ? "W" : "" );
+
+ return (buf);
+}
+
+std::string
+scorefile_entry::character_description(death_desc_verbosity verbosity) const
+{
+ bool single = verbosity == DDV_TERSE || verbosity == DDV_ONELINE;
+
+ if (single)
+ return single_cdesc();
+
+ bool verbose = verbosity == DDV_VERBOSE;
+ char scratch[INFO_SIZE];
+ char buf[INFO_SIZE];
+
+ std::string desc;
+ // Please excuse the following bit of mess in the name of flavour ;)
+ if (verbose)
+ {
+ strncpy( scratch, skill_title( best_skill, best_skill_lvl,
+ race, str, dex, god ),
+ INFO_SIZE );
+
+ snprintf( buf, HIGHSCORE_SIZE, "%8ld %s the %s (level %d",
+ points, name, scratch, lvl );
+
+ desc = buf;
+ }
+ else
+ {
+ snprintf( buf, HIGHSCORE_SIZE, "%8ld %s the %s %s (level %d",
+ points, name, species_name(race, lvl),
+ get_class_name(cls), lvl );
+ desc = buf;
+ }
+
+ if (final_max_max_hp > 0) // as the other two may be negative
+ {
+ snprintf( scratch, INFO_SIZE, ", %d/%d", final_hp, final_max_hp );
+ desc += scratch;
+
+ if (final_max_hp < final_max_max_hp)
+ {
+ snprintf( scratch, INFO_SIZE, " (%d)", final_max_max_hp );
+ desc += scratch;
+ }
+
+ desc += " HPs";
+ }
+
+ desc += wiz_mode? ") *WIZ*" : ")";
+ desc += hiscore_newline_string();
+
+ if (verbose)
+ {
+ const char *const srace = species_name( race, lvl );
+
+ snprintf( scratch, INFO_SIZE, "Began as a%s %s %s",
+ is_vowel(*srace) ? "n" : "", srace, get_class_name(cls) );
+ desc += scratch;
+
+ if (birth_time > 0)
+ {
+ desc += " on ";
+ hiscore_date_string( birth_time, scratch );
+ desc += scratch;
+ }
+
+ desc += ".";
+ desc += hiscore_newline_string();
+
+ if (race != SP_DEMIGOD && god != -1)
+ {
+ if (god == GOD_XOM)
+ {
+ snprintf( scratch, INFO_SIZE, "Was a %sPlaything of Xom.",
+ (lvl >= 20) ? "Favourite " : "" );
+
+ desc += scratch;
+ desc += hiscore_newline_string();
+ }
+ else if (god != GOD_NO_GOD)
+ {
+ // Not exactly the same as the religon screen, but
+ // good enough to fill this slot for now.
+ snprintf( scratch, INFO_SIZE, "Was %s of %s%s",
+ (piety > 160) ? "the Champion" :
+ (piety >= 120) ? "a High Priest" :
+ (piety >= 100) ? "an Elder" :
+ (piety >= 75) ? "a Priest" :
+ (piety >= 50) ? "a Believer" :
+ (piety >= 30) ? "a Follower"
+ : "an Initiate",
+ god_name( god ),
+ (penance > 0) ? " (penitent)." : "." );
+
+ desc += scratch;
+ desc += hiscore_newline_string();
+ }
+ }
+ }
+
+ return (desc);
+}
+
+std::string scorefile_entry::death_place(death_desc_verbosity verbosity) const
+{
+ bool verbose = verbosity == DDV_VERBOSE;
+ std::string place;
+
+ if (death_type == KILLED_BY_LEAVING || death_type == KILLED_BY_WINNING)
+ return ("");
+
+ char scratch[ INFO_SIZE ];
+
+ if (verbosity == DDV_ONELINE || verbosity == DDV_TERSE)
+ {
+ snprintf( scratch, sizeof scratch, " (%s)",
+ place_name(get_packed_place(branch, dlvl, level_type),
+ false, true).c_str());
+ return (scratch);
+ }
+
+ if (verbose && death_type != KILLED_BY_QUITTING)
+ place += "...";
+
+ // where did we die?
+ std::string placename =
+ place_name(get_packed_place(branch, dlvl, level_type),
+ true, true);
+
+ // add appropriate prefix
+ if (placename.find("Level") == 0)
+ place += " on ";
+ else
+ place += " in ";
+
+ place += placename;
+
+ if (verbose && death_time
+ && !hiscore_same_day( birth_time, death_time ))
+ {
+ place += " on ";
+ hiscore_date_string( death_time, scratch );
+ place += scratch;
+ }
+
+ place += ".";
+ place += hiscore_newline_string();
+
+ return (place);
+}
+
+std::string
+scorefile_entry::death_description(death_desc_verbosity verbosity) const
+{
+ bool needs_beam_cause_line = false;
+ bool needs_called_by_monster_line = false;
+ bool needs_damage = false;
+
+ bool terse = verbosity == DDV_TERSE;
+ bool verbose = verbosity == DDV_VERBOSE;
+ bool oneline = verbosity == DDV_ONELINE;
+
+ char scratch[INFO_SIZE];
+
+ std::string desc;
+
+ if (oneline)
+ desc = " ";
+
+ switch (death_type)
+ {
+ case KILLED_BY_MONSTER:
+ if (terse)
+ desc += death_source_desc();
+ else if (oneline)
+ desc += std::string("slain by ") + death_source_desc();
+ else
+ {
+ snprintf( scratch, sizeof scratch, "%s by %s",
+ damage_verb(),
+ death_source_desc() );
+
+ desc += scratch;
+ }
+
+ // put the damage on the weapon line if there is one
+ if (auxkilldata[0] == 0)
+ needs_damage = true;
+ break;
+
+ case KILLED_BY_POISON:
+ desc += terse? "poison" : "Succumbed to poison";
+ break;
+
+ case KILLED_BY_CLOUD:
+ if (auxkilldata[0] == 0)
+ desc += terse? "cloud" : "Engulfed by a cloud";
+ else
+ {
+ snprintf( scratch, sizeof(scratch), "%scloud of %s",
+ terse? "" : "Engulfed by a ",
+ auxkilldata );
+ desc += scratch;
+ }
+ needs_damage = true;
+ break;
+
+ case KILLED_BY_BEAM:
+ if (oneline)
+ {
+ // keeping this short to leave room for the deep elf spellcasters:
+ snprintf( scratch, sizeof(scratch), "%s by ",
+ range_type_verb( auxkilldata ) );
+ desc += scratch;
+ desc += death_source_desc();
+ }
+ else if (isupper( auxkilldata[0] )) // already made (ie shot arrows)
+ {
+ // If terse we have to parse the information from the string.
+ // Darn it to heck.
+ desc += terse? terse_missile_cause() : auxkilldata;
+ needs_damage = true;
+ }
+ else if (verbose && strncmp( auxkilldata, "by ", 3 ) == 0)
+ {
+ // "by" is used for priest attacks where the effect is indirect
+ // in verbose format we have another line for the monster
+ needs_called_by_monster_line = true;
+ snprintf( scratch, sizeof(scratch), "Killed %s", auxkilldata );
+ desc += scratch;
+ }
+ else
+ {
+ // Note: This is also used for the "by" cases in non-verbose
+ // mode since listing the monster is more imporatant.
+ if (!terse)
+ desc += "Killed from afar by ";
+
+ desc += death_source_desc();
+
+ if (*auxkilldata)
+ needs_beam_cause_line = true;
+
+ needs_damage = true;
+ }
+ break;
+
+ case KILLED_BY_CURARE:
+ desc += terse? "asphyx" : "Asphyxiated";
+ break;
+
+ case KILLED_BY_LAVA:
+ if (terse)
+ desc += "lava";
+ else
+ {
+ if (race == SP_MUMMY)
+ desc += "Turned to ash by lava";
+ else
+ desc += "Took a swim in molten lava";
+ }
+ break;
+
+ case KILLED_BY_WATER:
+ if (race == SP_MUMMY)
+ desc += terse? "fell apart" : "Soaked and fell apart";
+ else
+ desc += terse? "drowned" : "Drowned";
+ break;
+
+ case KILLED_BY_STUPIDITY:
+ desc += terse? "stupidity" : "Forgot to breathe";
+ break;
+
+ case KILLED_BY_WEAKNESS:
+ desc += terse? "collapsed " : "Collapsed under their own weight";
+ break;
+
+ case KILLED_BY_CLUMSINESS:
+ desc += terse? "clumsiness" : "Slipped on a banana peel";
+ break;
+
+ case KILLED_BY_TRAP:
+ if (terse)
+ desc += terse_trap();
+ else
+ {
+ snprintf( scratch, sizeof(scratch), "Killed by triggering a%s trap",
+ (*auxkilldata) ? auxkilldata : "" );
+ desc += scratch;
+ }
+ needs_damage = true;
+ break;
+
+ case KILLED_BY_LEAVING:
+ if (terse)
+ desc += "left";
+ else
+ {
+ if (num_runes > 0)
+ desc += "Got out of the dungeon";
+ else
+ desc += "Got out of the dungeon alive";
+ }
+ break;
+
+ case KILLED_BY_WINNING:
+ desc += terse? "escaped" : "Escaped with the Orb";
+ if (num_runes < 1)
+ desc += "!";
+ break;
+
+ case KILLED_BY_QUITTING:
+ desc += terse? "quit" : "Quit the game";
+ break;
+
+ case KILLED_BY_DRAINING:
+ desc += terse? "drained" : "Was drained of all life";
+ break;
+
+ case KILLED_BY_STARVATION:
+ desc += terse? "starvation" : "Starved to death";
+ break;
+
+ case KILLED_BY_FREEZING: // refrigeration spell
+ desc += terse? "frozen" : "Froze to death";
+ needs_damage = true;
+ break;
+
+ case KILLED_BY_BURNING: // sticky flame
+ desc += terse? "burnt" : "Burnt to a crisp";
+ needs_damage = true;
+ break;
+
+ case KILLED_BY_WILD_MAGIC:
+ if (!*auxkilldata)
+ desc += terse? "wild magic" : "Killed by wild magic";
+ else
+ {
+ if (terse)
+ desc += terse_wild_magic();
+ else
+ {
+ // A lot of sources for this case... some have "by" already.
+ snprintf( scratch, sizeof(scratch), "Killed %s%s",
+ (strncmp( auxkilldata, "by ", 3 ) != 0) ? "by " : "",
+ auxkilldata );
+ desc += scratch;
+ }
+ }
+
+ needs_damage = true;
+ break;
+
+ case KILLED_BY_XOM: // only used for old Xom kills
+ desc += terse? "xom" : "Killed for Xom's enjoyment";
+ needs_damage = true;
+ break;
+
+ case KILLED_BY_STATUE:
+ desc += terse? "statue" : "Killed by a statue";
+ needs_damage = true;
+ break;
+
+ case KILLED_BY_ROTTING:
+ desc += terse? "rotting" : "Rotted away";
+ break;
+
+ case KILLED_BY_TARGETTING:
+ desc += terse? "shot self" : "Killed themselves with bad targeting";
+ needs_damage = true;
+ break;
+
+ case KILLED_BY_SPORE:
+ desc += terse? "spore" : "Killed by an exploding spore";
+ needs_damage = true;
+ break;
+
+ case KILLED_BY_TSO_SMITING:
+ desc += terse? "smote by Shining One" : "Smote by The Shining One";
+ needs_damage = true;
+ break;
+
+ case KILLED_BY_PETRIFICATION:
+ desc += terse? "petrified" : "Turned to stone";
+ break;
+
+ case KILLED_BY_MELTING:
+ desc += terse? "melted" : " melted into a puddle";
+ break;
+
+ case KILLED_BY_BLEEDING:
+ desc += terse? "bleeding" : " bled to death";
+ break;
+
+ case KILLED_BY_SOMETHING:
+ if (auxkilldata)
+ desc += auxkilldata;
+ else
+ desc += terse? "died" : "Died";
+ needs_damage = true;
+ break;
+
+ case KILLED_BY_FALLING_DOWN_STAIRS:
+ desc += terse? "fell downstairs" : "Fell down a flight of stairs";
+ needs_damage = true;
+ break;
+
+ case KILLED_BY_ACID:
+ desc += terse? "acid" : "Splashed by acid";
+ needs_damage = true;
+ break;
+
+ default:
+ desc += terse? "program bug" : "Nibbled to death by software bugs";
+ break;
+ } // end switch
+
+ if (oneline && desc.length() > 2)
+ desc[1] = tolower(desc[1]);
+
+ // TODO: Eventually, get rid of "..." for cases where the text fits.
+ if (terse)
+ {
+ if (death_type == KILLED_BY_MONSTER && *auxkilldata)
+ {
+ desc += "/";
+ desc += strip_article_a(auxkilldata);
+ needs_damage = true;
+ }
+ else if (needs_beam_cause_line)
+ desc += "/" + terse_beam_cause();
+ else if (needs_called_by_monster_line)
+ desc += death_source_name;
+
+ if (needs_damage && damage > 0)
+ desc += " " + damage_string(true);
+ }
+ else if (verbose)
+ {
+ bool done_damage = false; // paranoia
+
+ if (needs_damage && damage > 0)
+ {
+ desc += " " + damage_string();
+ needs_damage = false;
+ done_damage = true;
+ }
+
+ if ((death_type == KILLED_BY_LEAVING
+ || death_type == KILLED_BY_WINNING)
+ && num_runes > 0)
+ {
+ desc += hiscore_newline_string();
+
+ snprintf( scratch, INFO_SIZE, "... %s %d rune%s",
+ (death_type == KILLED_BY_WINNING) ? "and" : "with",
+ num_runes, (num_runes > 1) ? "s" : "" );
+ desc += scratch;
+
+ if (num_diff_runes > 1)
+ {
+ snprintf( scratch, INFO_SIZE, " (of %d types)",
+ num_diff_runes );
+ desc += scratch;
+ }
+
+ if (death_time > 0
+ && !hiscore_same_day( birth_time, death_time ))
+ {
+ desc += " on ";
+ hiscore_date_string( death_time, scratch );
+ desc += scratch;
+ }
+
+ desc += "!";
+ desc += hiscore_newline_string();
+ }
+ else if (death_type != KILLED_BY_QUITTING)
+ {
+ desc += hiscore_newline_string();
+
+ if (death_type == KILLED_BY_MONSTER && auxkilldata[0])
+ {
+ snprintf(scratch, INFO_SIZE, "... wielding %s", auxkilldata);
+ desc += scratch;
+ needs_damage = true;
+ }
+ else if (needs_beam_cause_line)
+ {
+ desc += (is_vowel( auxkilldata[0] )) ? "... with an "
+ : "... with a ";
+ desc += auxkilldata;
+ needs_damage = true;
+ }
+ else if (needs_called_by_monster_line)
+ {
+ snprintf( scratch, sizeof(scratch), "... called down by %s",
+ death_source_name );
+ desc += scratch;
+ needs_damage = true;
+ }
+
+ if (needs_damage && !done_damage && damage > 0)
+ desc += " " + damage_string();
+
+ if (needs_damage)
+ desc += hiscore_newline_string();
+ }
+ }
+
+ if (!oneline)
+ {
+ if (death_type == KILLED_BY_LEAVING
+ || death_type == KILLED_BY_WINNING)
+ {
+ // TODO: strcat "after reaching level %d"; for LEAVING
+ if (verbosity == DDV_NORMAL)
+ {
+ if (num_runes > 0)
+ desc += "!";
+ }
+ desc += hiscore_newline_string();
+ }
+ }
+
+ if (terse)
+ {
+ trim_string(desc);
+ desc = strip_article_a(desc);
+ }
+
+ return (desc);
+}
diff --git a/crawl-ref/source/hiscores.h b/crawl-ref/source/hiscores.h
index 2cb5f4786f..93b22e660d 100644
--- a/crawl-ref/source/hiscores.h
+++ b/crawl-ref/source/hiscores.h
@@ -16,7 +16,7 @@
/* ***********************************************************************
* called from: ouch
* *********************************************************************** */
-void hiscores_new_entry( struct scorefile_entry &se );
+void hiscores_new_entry( const scorefile_entry &se );
// last updated 16feb2001 {gdl}
/* ***********************************************************************
@@ -28,8 +28,8 @@ void hiscores_print_list( int display_count = -1, int format = SCORE_TERSE );
/* ***********************************************************************
* called from: ouch hiscores
* *********************************************************************** */
-void hiscores_format_single( char *buffer, struct scorefile_entry &se );
-int hiscores_format_single_long( char *buffer, struct scorefile_entry &se,
+void hiscores_format_single( char *buffer, const scorefile_entry &se );
+void hiscores_format_single_long( char *buffer, const scorefile_entry &se,
bool verbose = false );
#endif // HISCORES_H
diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc
index 46bf73e40e..a797100754 100644
--- a/crawl-ref/source/initfile.cc
+++ b/crawl-ref/source/initfile.cc
@@ -13,6 +13,8 @@
*/
#include "AppHdr.h"
+#include "externs.h"
+
#include "initfile.h"
#include <stdio.h>
@@ -21,9 +23,9 @@
#include <ctype.h>
#include "clua.h"
+#include "delay.h"
#include "Kills.h"
#include "files.h"
-#include "externs.h"
#include "defines.h"
#include "libutil.h"
#include "player.h"
@@ -33,34 +35,23 @@
#include "items.h"
#include "view.h"
-game_options Options;
-
-extern void (*viewwindow) (char, bool);
-extern unsigned char (*mapch) (unsigned char);
-extern unsigned char (*mapch2) (unsigned char);
-extern unsigned char mapchar3(unsigned char ldfk);
-extern unsigned char mapchar4(unsigned char ldfk);
+const std::string game_options::interrupt_prefix = "interrupt_";
+game_options Options;
-#ifdef UNIX
-extern int character_set; // unices only
-#endif
-
-static std::string & tolower_string( std::string &str );
+std::string &tolower_string( std::string &str );
const static char *obj_syms = ")([/%.?=!.+\\0}X$";
const static int obj_syms_len = 16;
static void read_startup_prefs();
-static void read_options(InitLineInput &il, bool runscript);
-template<class A, class B> void append_vector(
- std::vector<A> &dest, const std::vector<B> &src)
+template<class A, class B> void append_vector(A &dest, const B &src)
{
dest.insert( dest.end(), src.begin(), src.end() );
}
// returns -1 if unmatched else returns 0-15
-static short str_to_colour( const std::string &str )
+int str_to_colour( const std::string &str, int default_colour )
{
int ret;
@@ -71,6 +62,15 @@ static short str_to_colour( const std::string &str )
"lightred", "lightmagenta", "yellow", "white"
};
+ const std::string element_cols[] =
+ {
+ "fire", "ice", "earth", "electricity", "air", "poison", "water",
+ "magic", "mutagenic", "warp", "enchant", "heal", "holy", "dark",
+ "death", "necro", "unholy", "vehumet", "crystal", "blood", "smoke",
+ "slime", "jewel", "elven", "dwarven", "orcish", "gila", "floor",
+ "rock", "stone", "random"
+ };
+
for (ret = 0; ret < 16; ret++)
{
if (str == cols[ret])
@@ -88,6 +88,21 @@ static short str_to_colour( const std::string &str )
if (ret == 16)
{
+ // Maybe we have an element colour attribute.
+ for (unsigned i = 0; i < sizeof(element_cols) / sizeof(*element_cols);
+ ++i)
+ {
+ if (str == element_cols[i])
+ {
+ // Ugh.
+ ret = element_type(EC_FIRE + i);
+ break;
+ }
+ }
+ }
+
+ if (ret == 16)
+ {
// Check if we have a direct colour index
const char *s = str.c_str();
char *es = NULL;
@@ -96,7 +111,7 @@ static short str_to_colour( const std::string &str )
ret = ci;
}
- return ((ret == 16) ? -1 : ret);
+ return ((ret == 16) ? default_colour : ret);
}
// returns -1 if unmatched else returns 0-15
@@ -121,16 +136,16 @@ static int str_to_channel_colour( const std::string &str )
static const std::string message_channel_names[ NUM_MESSAGE_CHANNELS ] =
{
- "plain", "prompt", "god", "duration", "danger", "warning", "food",
- "recovery", "talk", "intrinsic_gain", "mutation", "monster_spell",
- "monster_enchant", "monster_damage", "rotten_meat", "equipment",
- "diagnostic",
+ "plain", "prompt", "god", "pray", "duration", "danger", "warning", "food",
+ "recovery", "sound", "talk", "intrinsic_gain", "mutation", "monster_spell",
+ "monster_enchant", "monster_damage", "monster_target",
+ "rotten_meat", "equipment", "floor", "multiturn", "diagnostic",
};
-// returns -1 if unmatched else returns 0-15
+// returns -1 if unmatched else returns 0--(NUM_MESSAGE_CHANNELS-1)
int str_to_channel( const std::string &str )
{
- short ret;
+ int ret;
for (ret = 0; ret < NUM_MESSAGE_CHANNELS; ret++)
{
@@ -149,6 +164,19 @@ std::string channel_to_str( int channel )
return message_channel_names[channel];
}
+static int str_to_book( const std::string& str )
+{
+ if ( str == "fire" || str == "flame" )
+ return SBT_FIRE;
+ if ( str == "cold" || str == "ice" )
+ return SBT_COLD;
+ if ( str == "summ" || str == "summoning" )
+ return SBT_SUMM;
+ if ( str == "random" )
+ return SBT_RANDOM;
+ return SBT_NO_SELECTION;
+}
+
static int str_to_weapon( const std::string &str )
{
if (str == "shortsword" || str == "short sword")
@@ -249,7 +277,7 @@ static char str_to_race( const std::string &str )
index -= (SP_CENTAUR - SP_RED_DRACONIAN - 1);
// SP_HUMAN is at 1, therefore we must subtract one.
- return ((index != -1) ? index_to_letter( index - 1 ) : '\0');
+ return ((index != -1) ? index_to_letter( index - 1 ) : 0);
}
static char str_to_class( const std::string &str )
@@ -265,10 +293,10 @@ static char str_to_class( const std::string &str )
if (index == -1)
index = get_class_index_by_name( str.c_str() );
- return ((index != -1) ? index_to_letter( index ) : '\0');
+ return ((index != -1) ? index_to_letter( index ) : 0);
}
-static std::string & tolower_string( std::string &str )
+std::string & tolower_string( std::string &str )
{
if (str.length())
{
@@ -285,10 +313,10 @@ static bool read_bool( const std::string &field, bool def_value )
{
bool ret = def_value;
- if (field == "true" || field == "1")
+ if (field == "true" || field == "1" || field == "yes")
ret = true;
- if (field == "false" || field == "0")
+ if (field == "false" || field == "0" || field == "no")
ret = false;
return (ret);
@@ -323,211 +351,379 @@ static unsigned curses_attribute(const std::string &field)
return CHATTR_NORMAL;
}
+void game_options::add_dump_fields(const std::string &text)
+{
+ // Easy; chardump.cc has most of the intelligence.
+ append_vector(dump_order, split_string(",", text, true, true));
+}
-static void reset_startup_options(bool clear_name = true)
+void game_options::reset_startup_options()
{
- if (clear_name)
- you.your_name[0] = '\0';
- Options.race = '\0';
- Options.cls = '\0';
- Options.weapon = WPN_UNKNOWN;
- Options.random_pick = false;
- Options.chaos_knight = GOD_NO_GOD;
- Options.death_knight = DK_NO_SELECTION;
- Options.priest = GOD_NO_GOD;
+ race = 0;
+ cls = 0;
+ weapon = WPN_UNKNOWN;
+ book = SBT_NO_SELECTION;
+ random_pick = false;
+ chaos_knight = GOD_NO_GOD;
+ death_knight = DK_NO_SELECTION;
+ priest = GOD_NO_GOD;
}
-void reset_options(bool clear_name)
+void game_options::set_default_activity_interrupts()
{
- // Option initialization
- Options.activity_interrupts[ ACT_MULTIDROP ] =
- AI_HP_LOSS | AI_STAT_CHANGE | AI_TELEPORT;
- Options.activity_interrupts[ ACT_RUNNING ] =
- 0xFFFF ^ AI_SEE_MONSTER;
- Options.activity_interrupts[ ACT_TRAVELING ] =
- 0xFFFF ^ (AI_MESSAGE | AI_SEE_MONSTER);
-
- reset_startup_options(clear_name);
- Options.prev_race = 0;
- Options.prev_cls = 0;
- Options.prev_ck = GOD_NO_GOD;
- Options.prev_dk = DK_NO_SELECTION;
- Options.prev_pr = GOD_NO_GOD;
- Options.prev_weapon = WPN_UNKNOWN;
- Options.prev_randpick = false;
- Options.remember_name = false;
-
- Options.autopickups = 0x0000;
- Options.verbose_dump = false;
- Options.detailed_stat_dump = true;
- Options.colour_map = false;
- Options.clean_map = false;
- Options.show_uncursed = true;
- Options.always_greet = false;
- Options.easy_open = true;
- Options.easy_armour = true;
- Options.easy_butcher = false;
- Options.easy_confirm = CONFIRM_SAFE_EASY;
- Options.easy_quit_item_prompts = false;
- Options.hp_warning = 10;
- Options.hp_attention = 25;
- Options.terse_hand = true;
- Options.auto_list = false;
- Options.delay_message_clear = false;
- Options.pickup_dropped = true;
- Options.travel_colour = true;
- Options.travel_delay = -1;
- Options.travel_stair_cost = 500;
- Options.travel_exclude_radius2 = 68;
- Options.show_waypoints = true;
- Options.item_colour = false;
-
- Options.detected_item_colour = DARKGREY;
- Options.detected_monster_colour= DARKGREY;
- Options.remembered_monster_colour = 0;
-
- Options.easy_exit_menu = true;
- Options.dos_use_background_intensity = false;
- Options.assign_item_slot = SS_FORWARD;
-
- Options.macro_meta_entry = true;
+ for (int adelay = 0; adelay < NUM_DELAYS; ++adelay)
+ for (int aint = 0; aint < NUM_AINTERRUPTS; ++aint)
+ activity_interrupts[adelay][aint] = true;
+
+ const char *default_activity_interrupts[] = {
+ "interrupt_armour_on = hp_loss, monster_attack",
+ "interrupt_armour_off = interrupt_armour_on",
+ "interrupt_drop_item = interrupt_armour_on",
+ "interrupt_jewellery_on = interrupt_armour_on",
+ "interrupt_memorise = interrupt_armour_on, stat",
+ "interrupt_butcher = interrupt_armour_on, teleport, stat",
+ "interrupt_passwall = interrupt_butcher",
+ "interrupt_multidrop = interrupt_butcher",
+ "interrupt_macro = interrupt_multidrop",
+ "interrupt_travel = interrupt_butcher, statue, hungry, burden, monster",
+ "interrupt_run = interrupt_travel, message",
+ "interrupt_rest = interrupt_run",
+
+ // Stair ascents/descents cannot be interrupted, attempts to interrupt
+ // the delay will just trash all queued delays, including travel.
+ "interrupt_ascending_stairs =",
+ "interrupt_descending_stairs =",
+ "interrupt_uninterruptible =",
+ "interrupt_autopickup =",
+ "interrupt_weapon_swap =",
+
+ NULL
+ };
- // 10 was the cursor step default on Linux.
- Options.level_map_cursor_step = 10;
+ for (int i = 0; default_activity_interrupts[i]; ++i)
+ read_option_line( default_activity_interrupts[i], false );
+}
-#ifdef STASH_TRACKING
- Options.stash_tracking = STM_NONE;
+void game_options::clear_activity_interrupts(
+ FixedVector<bool, NUM_AINTERRUPTS> &eints)
+{
+ for (int i = 0; i < NUM_AINTERRUPTS; ++i)
+ eints[i] = false;
+}
+
+void game_options::set_activity_interrupt(
+ FixedVector<bool, NUM_AINTERRUPTS> &eints,
+ const std::string &interrupt)
+{
+ if (interrupt.find(interrupt_prefix) == 0)
+ {
+ std::string delay_name = interrupt.substr( interrupt_prefix.length() );
+ delay_type delay = get_delay(delay_name);
+ if (delay == NUM_DELAYS)
+ {
+ fprintf(stderr, "Unknown delay: %s\n", delay_name.c_str());
+ return;
+ }
+
+ FixedVector<bool, NUM_AINTERRUPTS> &refints =
+ activity_interrupts[delay];
+
+ for (int i = 0; i < NUM_AINTERRUPTS; ++i)
+ if (refints[i])
+ eints[i] = true;
+
+ return;
+ }
+
+ activity_interrupt_type ai = get_activity_interrupt(interrupt);
+ if (ai == NUM_AINTERRUPTS)
+ {
+ fprintf(stderr, "Delay interrupt name \"%s\" not recognised.\n",
+ interrupt.c_str());
+ return;
+ }
+
+ eints[ai] = true;
+}
+
+void game_options::set_activity_interrupt(const std::string &activity_name,
+ const std::string &interrupt_names,
+ bool append_interrupts)
+{
+ const delay_type delay = get_delay(activity_name);
+ if (delay == NUM_DELAYS)
+ {
+ fprintf(stderr, "Unknown delay: %s\n", activity_name.c_str());
+ return;
+ }
+
+ FixedVector<bool, NUM_AINTERRUPTS> &eints = activity_interrupts[ delay ];
+
+ if (!append_interrupts)
+ clear_activity_interrupts(eints);
+
+ std::vector<std::string> interrupts = split_string(",", interrupt_names);
+ for (int i = 0, size = interrupts.size(); i < size; ++i)
+ set_activity_interrupt(eints, interrupts[i]);
+
+ eints[AI_FORCE_INTERRUPT] = true;
+}
+
+void game_options::reset_options()
+{
+ set_default_activity_interrupts();
+
+ reset_startup_options();
+
+#ifdef SAVE_DIR_PATH
+ save_dir = SAVE_DIR_PATH;
+#else
+ save_dir.clear();
+#endif
+
+ player_name.clear();
+
+ autopickup_on = true;
+ autoprayer_on = false;
+ fizzlecheck_on = false;
+
+ prev_race = 0;
+ prev_cls = 0;
+ prev_ck = GOD_NO_GOD;
+ prev_dk = DK_NO_SELECTION;
+ prev_pr = GOD_NO_GOD;
+ prev_weapon = WPN_UNKNOWN;
+ prev_book = SBT_NO_SELECTION;
+ prev_randpick = false;
+ remember_name = false;
+
+#ifdef USE_ASCII_CHARACTERS
+ char_set = CSET_ASCII;
+#else
+ char_set = CSET_IBM;
+#endif
+ init_char_table(char_set);
+
+ // set it to the .crawlrc default
+ autopickups = ((1L << 15) | // gold
+ (1L << 6) | // scrolls
+ (1L << 8) | // potions
+ (1L << 10) | // books
+ (1L << 7) | // jewellery
+ (1L << 3) | // wands
+ (1L << 4)); // food
+ verbose_dump = false;
+ detailed_stat_dump = true;
+ colour_map = true;
+ clean_map = false;
+ show_uncursed = true;
+ always_greet = true;
+ easy_open = true;
+ easy_unequip = true;
+ easy_butcher = true;
+ easy_confirm = CONFIRM_SAFE_EASY;
+ easy_quit_item_prompts = true;
+ hp_warning = 10;
+ hp_attention = 25;
+ confirm_self_target = true;
+ safe_autopickup = false;
+ use_notes = true;
+ note_skill_max = false;
+ note_all_spells = false;
+ note_hp_percent = 0;
+ ood_interesting = 8;
+ terse_hand = false;
+ increasing_skill_progress = false;
+
+ // [ds] Grumble grumble.
+ auto_list = true;
+
+ delay_message_clear = false;
+ pickup_dropped = false;
+ pickup_thrown = true;
+
+ travel_colour = true;
+ travel_delay = 10;
+ travel_stair_cost = 500;
+ travel_exclude_radius2 = 68;
+
+ sort_menus = false;
+
+ tc_reachable = BLUE;
+ tc_excluded = LIGHTMAGENTA;
+ tc_exclude_circle = RED;
+ tc_dangerous = CYAN;
+ tc_disconnected = DARKGREY;
+
+ show_waypoints = true;
+ item_colour = true;
+
+ // [ds] Default to jazzy colours.
+ detected_item_colour = LIGHTGREEN;
+ detected_monster_colour= LIGHTRED;
+
+ easy_exit_menu = true;
+#ifdef DOS
+ dos_use_background_intensity = false;
+#else
+ dos_use_background_intensity = true;
#endif
- Options.explore_stop = ES_ITEM | ES_STAIR | ES_SHOP | ES_ALTAR;
- Options.target_zero_exp = true;
- Options.target_wrap = false;
- Options.target_oos = true;
- Options.target_los_first = true;
- Options.dump_kill_places = KDO_ONE_PLACE;
- Options.dump_message_count = 4;
- Options.dump_item_origins = IODS_ARTIFACTS | IODS_RODS;
- Options.dump_item_origin_price = -1;
- Options.drop_mode = DM_SINGLE;
+ assign_item_slot = SS_FORWARD;
- Options.flush_input[ FLUSH_ON_FAILURE ] = true;
- Options.flush_input[ FLUSH_BEFORE_COMMAND ] = false;
- Options.flush_input[ FLUSH_ON_MESSAGE ] = false;
- Options.flush_input[ FLUSH_LUA ] = true;
+ macro_meta_entry = true;
+
+ // 10 was the cursor step default on Linux.
+ level_map_cursor_step = 10;
- Options.lowercase_invocations = false;
+#ifdef STASH_TRACKING
+ stash_tracking = STM_ALL;
+#endif
+ explore_stop = ES_ITEM | ES_STAIR | ES_SHOP | ES_ALTAR;
+ safe_zero_exp = true;
+ target_zero_exp = false;
+ target_wrap = true;
+ target_oos = true;
+ target_los_first = true;
+ dump_kill_places = KDO_ONE_PLACE;
+ dump_message_count = 7;
+ dump_item_origins = IODS_ARTIFACTS | IODS_RODS;
+ dump_item_origin_price = -1;
+
+ drop_mode = DM_SINGLE;
+
+ flush_input[ FLUSH_ON_FAILURE ] = true;
+ flush_input[ FLUSH_BEFORE_COMMAND ] = false;
+ flush_input[ FLUSH_ON_MESSAGE ] = false;
+ flush_input[ FLUSH_LUA ] = true;
+
+ lowercase_invocations = false;
// Note: These fire options currently match the old behaviour. -- bwr
- Options.fire_items_start = 0; // start at slot 'a'
+ fire_items_start = 0; // start at slot 'a'
- Options.fire_order[0] = FIRE_LAUNCHER; // fire first from bow...
- Options.fire_order[1] = FIRE_DART; // then only consider darts
+ fire_order[0] = FIRE_LAUNCHER; // fire first from bow...
+ fire_order[1] = FIRE_DART; // then only consider darts
- // clear the reast of the list
+ // clear the rest of the list
for (int i = 2; i < NUM_FIRE_TYPES; i++)
- Options.fire_order[i] = FIRE_NONE;
+ fire_order[i] = FIRE_NONE;
+
+#ifdef WIZARD
+ fsim_rounds = 40000L;
+ fsim_mons = "worm";
+ fsim_str = fsim_int = fsim_dex = 15;
+ fsim_xl = 10;
+ fsim_kit.clear();
+#endif
// These are only used internally, and only from the commandline:
// XXX: These need a better place.
- Options.sc_entries = 0;
- Options.sc_format = SCORE_REGULAR;
+ sc_entries = 0;
+ sc_format = SCORE_REGULAR;
-//#ifdef USE_COLOUR_OPTS
- Options.friend_brand = CHATTR_NORMAL;
- Options.heap_brand = CHATTR_NORMAL;
- Options.stab_brand = CHATTR_NORMAL;
- Options.may_stab_brand = CHATTR_NORMAL;
- Options.no_dark_brand = 0;
-//#endif
+ friend_brand = CHATTR_NORMAL;
+ heap_brand = CHATTR_NORMAL;
+ stab_brand = CHATTR_NORMAL;
+ may_stab_brand = CHATTR_NORMAL;
+ no_dark_brand = 0;
#ifdef WIZARD
- Options.wiz_mode = WIZ_NO;
+ wiz_mode = WIZ_NO;
#endif
// map each colour to itself as default
#ifdef USE_8_COLOUR_TERM_MAP
for (int i = 0; i < 16; i++)
- Options.colour[i] = i % 8;
+ colour[i] = i % 8;
- Options.colour[ DARKGREY ] = COL_TO_REPLACE_DARKGREY;
+ colour[ DARKGREY ] = COL_TO_REPLACE_DARKGREY;
#else
for (int i = 0; i < 16; i++)
- Options.colour[i] = i;
+ colour[i] = i;
#endif
// map each channel to plain (well, default for now since I'm testing)
for (int i = 0; i < NUM_MESSAGE_CHANNELS; i++)
- Options.channels[i] = MSGCOL_DEFAULT;
+ channels[i] = MSGCOL_DEFAULT;
// Clear vector options.
- Options.banned_objects.clear();
- Options.stop_travel.clear();
- Options.sound_mappings.clear();
- Options.menu_colour_mappings.clear();
- Options.drop_filter.clear();
-
- Options.named_options.clear();
+ dump_order.clear();
+ add_dump_fields("header,stats,misc,inventory,skills,"
+ "spells,mutations,messages,screenshot,kills,notes");
+
+ banned_objects.clear();
+ note_monsters.clear();
+ note_messages.clear();
+ autoinscriptions.clear();
+ note_items.clear();
+ note_skill_levels.clear();
+ travel_stop_message.clear();
+ sound_mappings.clear();
+ menu_colour_mappings.clear();
+ drop_filter.clear();
+ map_file_name.clear();
+ named_options.clear();
+
+ clear_cset_overrides();
+ clear_feature_overrides();
// Map each category to itself. The user can override in init.txt
- Options.kill_map[KC_YOU] = KC_YOU;
- Options.kill_map[KC_FRIENDLY] = KC_FRIENDLY;
- Options.kill_map[KC_OTHER] = KC_OTHER;
+ kill_map[KC_YOU] = KC_YOU;
+ kill_map[KC_FRIENDLY] = KC_FRIENDLY;
+ kill_map[KC_OTHER] = KC_OTHER;
// Setup travel information. What's a better place to do this?
initialise_travel();
}
-void read_init_file(bool runscript)
+// returns where the init file was read from
+std::string read_init_file(bool runscript)
{
- FILE *f;
- char name_buff[kPathLen];
+ const char* locations_data[][2] = {
+ { SysEnv.crawl_rc, "" },
+ { SysEnv.crawl_dir, "init.txt" },
+#ifdef MULTIUSER
+ { SysEnv.home, "/.crawlrc" },
+ { SysEnv.home, "init.txt" },
+#endif
+ { "", "init.txt" },
+#ifdef WIN32CONSOLE
+ { "", ".crawlrc" },
+ { "", "_crawlrc" },
+#endif
+ { NULL, NULL } // placeholder to mark end
+ };
- reset_options(!runscript);
+ Options.reset_options();
- if (!runscript)
- you.your_name[0] = '\0';
-
- if (SysEnv.crawl_rc)
- {
- f = fopen(SysEnv.crawl_rc, "r");
+ FILE* f = NULL;
+ char name_buff[kPathLen];
+ // Check all possibilities for init.txt
+ for ( int i = 0; f == NULL && locations_data[i][1] != NULL; ++i ) {
+ // Don't look at unset options
+ if ( locations_data[i][0] != NULL ) {
+ snprintf( name_buff, sizeof name_buff, "%s%s",
+ locations_data[i][0], locations_data[i][1] );
+ f = fopen( name_buff, "r" );
+ }
}
- else if (SysEnv.crawl_dir)
- {
- strncpy(name_buff, SysEnv.crawl_dir, kPathLen);
- name_buff[ kPathLen - 1 ] = '\0';
- strncat(name_buff, "init.txt", kPathLen);
- name_buff[ kPathLen - 1 ] = '\0';
- f = fopen(name_buff, "r");
- }
-#ifdef MULTIUSER
- else if (SysEnv.home)
+ if ( f == NULL )
{
- // init.txt isn't such a good choice if we're looking in
- // the user's home directory, we'll use Un*x standard
- strncpy(name_buff, SysEnv.home, kPathLen);
- name_buff[ kPathLen - 1 ] = '\0';
-
- // likely not to have a closing slash so we'll insert one...
- strncat(name_buff, "/.crawlrc", kPathLen);
- name_buff[ kPathLen - 1 ] = '\0';
-
- f = fopen(name_buff, "r");
- }
+#ifdef MULTIUSER
+ return "not found (~/.crawlrc missing)";
+#else
+ return "not found (init.txt missing from current directory)";
#endif
- else
- {
- f = fopen("init.txt", "r");
}
- if (f == NULL)
- return;
-
+ read_options(f, runscript);
if (!runscript)
read_startup_prefs();
- read_options(f, runscript);
fclose(f);
+ return std::string(name_buff);
} // end read_init_file()
static void read_startup_prefs()
@@ -536,19 +732,21 @@ static void read_startup_prefs()
FILE *f = fopen(fn.c_str(), "r");
if (!f)
return;
- read_options(f);
- fclose(f);
- Options.prev_randpick = Options.random_pick;
- Options.prev_weapon = Options.weapon;
- Options.prev_pr = Options.priest;
- Options.prev_dk = Options.death_knight;
- Options.prev_ck = Options.chaos_knight;
- Options.prev_cls = Options.cls;
- Options.prev_race = Options.race;
- Options.prev_name = you.your_name;
+ game_options temp;
+ FileLineInput fl(f);
+ temp.read_options(fl, false);
+ fclose(f);
- reset_startup_options();
+ Options.prev_randpick = temp.random_pick;
+ Options.prev_weapon = temp.weapon;
+ Options.prev_pr = temp.priest;
+ Options.prev_dk = temp.death_knight;
+ Options.prev_ck = temp.chaos_knight;
+ Options.prev_cls = temp.cls;
+ Options.prev_race = temp.race;
+ Options.prev_book = temp.book;
+ Options.prev_name = temp.player_name;
}
static void write_newgame_options(FILE *f)
@@ -589,6 +787,15 @@ static void write_newgame_options(FILE *f)
Options.prev_pr == GOD_YREDELEMNUL? "yredelemnul" :
"random");
}
+
+ if (Options.prev_book != SBT_NO_SELECTION )
+ {
+ fprintf(f, "book = %s\n",
+ Options.prev_book == SBT_FIRE ? "fire" :
+ Options.prev_book == SBT_COLD ? "cold" :
+ Options.prev_book == SBT_SUMM ? "summ" :
+ "random");
+ }
}
void write_newgame_options_file()
@@ -606,15 +813,9 @@ void save_player_name()
if (!Options.remember_name)
return ;
- std::string playername = you.your_name;
-
// Read other preferences
read_startup_prefs();
- // Put back your name
- strncpy(you.your_name, playername.c_str(), kNameLen);
- you.your_name[kNameLen - 1] = 0;
-
// And save
write_newgame_options_file();
}
@@ -622,16 +823,21 @@ void save_player_name()
void read_options(FILE *f, bool runscript)
{
FileLineInput fl(f);
- read_options(fl, runscript);
+ Options.read_options(fl, runscript);
}
void read_options(const std::string &s, bool runscript)
{
StringLineInput st(s);
- read_options(st, runscript);
+ Options.read_options(st, runscript);
+}
+
+game_options::game_options()
+{
+ reset_options();
}
-static void read_options(InitLineInput &il, bool runscript)
+void game_options::read_options(InitLineInput &il, bool runscript)
{
unsigned int line = 0;
@@ -759,7 +965,7 @@ static void read_options(InitLineInput &il, bool runscript)
continue;
}
- parse_option_line(str, runscript);
+ read_option_line(str, runscript);
}
#ifdef CLUA_BINDINGS
@@ -774,6 +980,9 @@ static void read_options(InitLineInput &il, bool runscript)
}
}
#endif
+
+ // Validate save_dir
+ check_savedir(save_dir);
}
static int str_to_killcategory(const std::string &s)
@@ -791,15 +1000,15 @@ static int str_to_killcategory(const std::string &s)
return -1;
}
-static void do_kill_map(const std::string &from, const std::string &to)
+void game_options::do_kill_map(const std::string &from, const std::string &to)
{
int ifrom = str_to_killcategory(from),
ito = str_to_killcategory(to);
if (ifrom != -1 && ito != -1)
- Options.kill_map[ifrom] = ito;
+ kill_map[ifrom] = ito;
}
-void parse_option_line(const std::string &str, bool runscript)
+void game_options::read_option_line(const std::string &str, bool runscript)
{
std::string key = "";
std::string subkey = "";
@@ -808,6 +1017,8 @@ void parse_option_line(const std::string &str, bool runscript)
int first_equals = str.find('=');
int first_dot = str.find('.');
+ bool plus_equal = false;
+
// all lines with no equal-signs we ignore
if (first_equals < 0)
return;
@@ -828,6 +1039,15 @@ void parse_option_line(const std::string &str, bool runscript)
// Clean up our data...
tolower_string( trim_string( key ) );
+
+ // Is this a case of key += val?
+ if (key.length() && key[key.length() - 1] == '+')
+ {
+ plus_equal = true;
+ key = key.substr(0, key.length() - 1);
+ trim_string(key);
+ }
+
tolower_string( trim_string( subkey ) );
// some fields want capitals... none care about external spaces
@@ -839,7 +1059,12 @@ void parse_option_line(const std::string &str, bool runscript)
if (key != "name" && key != "crawl_dir"
&& key != "race" && key != "class" && key != "ban_pickup"
&& key != "stop_travel" && key != "sound"
- && key != "drop_filter" && key != "lua_file")
+ && key != "travel_stop_message"
+ && key != "drop_filter" && key != "lua_file"
+ && key != "note_items" && key != "autoinscribe"
+ && key != "note_monsters" && key != "note_messages"
+ && key.find("cset") != 0 && key != "dungeon"
+ && key != "feature")
{
tolower_string( field );
}
@@ -847,6 +1072,9 @@ void parse_option_line(const std::string &str, bool runscript)
// everything not a valid line is treated as a comment
if (key == "autopickup")
{
+ // clear out autopickup
+ autopickups = 0L;
+
for (size_t i = 0; i < field.length(); i++)
{
char type = field[i];
@@ -880,7 +1108,7 @@ void parse_option_line(const std::string &str, bool runscript)
;
if (j < obj_syms_len)
- Options.autopickups |= (1L << j);
+ autopickups |= (1L << j);
else
{
fprintf( stderr, "Bad object type '%c' for autopickup.\n",
@@ -891,59 +1119,100 @@ void parse_option_line(const std::string &str, bool runscript)
else if (key == "name")
{
// field is already cleaned up from trim_string()
- strncpy(you.your_name, field.c_str(), kNameLen);
- you.your_name[ kNameLen - 1 ] = '\0';
+ player_name = field;
}
- else if (key == "verbose_dump")
+ else if (key == "char_set" || key == "ascii_display")
{
- // gives verbose info in char dumps
- Options.verbose_dump = read_bool( field, Options.verbose_dump );
+ bool valid = true;
+
+ if (key == "ascii_display")
+ {
+ char_set =
+ read_bool(field, char_set == CSET_ASCII)?
+ CSET_ASCII
+ : CSET_IBM;
+ valid = true;
+ }
+ else
+ {
+ if (field == "ascii")
+ char_set = CSET_ASCII;
+ else if (field == "ibm")
+ char_set = CSET_IBM;
+ else if (field == "dec")
+ char_set = CSET_DEC;
+ else
+ {
+ fprintf( stderr, "Bad character set: %s\n", field.c_str() );
+ valid = false;
+ }
+ }
+ if (valid)
+ init_char_table(char_set);
+ }
+ else if (key == "default_autopickup")
+ {
+ // should autopickup default to on or off?
+ autopickup_on = read_bool( field, autopickup_on );
+ }
+ else if (key == "default_autoprayer")
+ {
+ // should autoprayer default to on or off?
+ autoprayer_on = read_bool( field, autoprayer_on );
+ }
+ else if (key == "default_fizzlecheck")
+ {
+ // should fizzlecheck default to on or off?
+ fizzlecheck_on = read_bool( field, fizzlecheck_on );
}
else if (key == "detailed_stat_dump")
{
- Options.detailed_stat_dump =
- read_bool( field, Options.detailed_stat_dump );
+ detailed_stat_dump =
+ read_bool( field, detailed_stat_dump );
}
else if (key == "clean_map")
{
// removes monsters/clouds from map
- Options.clean_map = read_bool( field, Options.clean_map );
+ clean_map = read_bool( field, clean_map );
}
else if (key == "colour_map" || key == "color_map")
{
// colour-codes play-screen map
- Options.colour_map = read_bool( field, Options.colour_map );
+ colour_map = read_bool( field, colour_map );
}
else if (key == "easy_confirm")
{
// allows both 'Y'/'N' and 'y'/'n' on yesno() prompts
if (field == "none")
- Options.easy_confirm = CONFIRM_NONE_EASY;
+ easy_confirm = CONFIRM_NONE_EASY;
else if (field == "safe")
- Options.easy_confirm = CONFIRM_SAFE_EASY;
+ easy_confirm = CONFIRM_SAFE_EASY;
else if (field == "all")
- Options.easy_confirm = CONFIRM_ALL_EASY;
+ easy_confirm = CONFIRM_ALL_EASY;
}
- else if (key == "easy_quit_item_lists")
+ else if (key == "easy_quit_item_lists"
+ || key == "easy_quit_item_prompts")
{
// allow aborting of item lists with space
- Options.easy_quit_item_prompts = read_bool( field,
- Options.easy_quit_item_prompts );
+ easy_quit_item_prompts = read_bool( field,
+ easy_quit_item_prompts );
}
else if (key == "easy_open")
{
// automatic door opening with movement
- Options.easy_open = read_bool( field, Options.easy_open );
+ easy_open = read_bool( field, easy_open );
}
- else if (key == "easy_armour" || key == "easy_armour")
+ else if (key == "easy_armor"
+ || key == "easy_armour"
+ || key == "easy_unequip")
{
// automatic removal of armour when dropping
- Options.easy_armour = read_bool( field, Options.easy_armour );
+ easy_unequip = read_bool( field, easy_unequip );
}
else if (key == "easy_butcher")
{
// automatic knife switching
- Options.easy_butcher = read_bool( field, Options.easy_butcher );
+ easy_butcher = read_bool( field, easy_butcher );
}
else if (key == "lua_file" && runscript)
{
@@ -960,7 +1229,7 @@ void parse_option_line(const std::string &str, bool runscript)
const int result_col = str_to_colour( field );
if (orig_col != -1 && result_col != -1)
- Options.colour[orig_col] = result_col;
+ colour[orig_col] = result_col;
else
{
fprintf( stderr, "Bad colour -- %s=%d or %s=%d\n",
@@ -973,7 +1242,7 @@ void parse_option_line(const std::string &str, bool runscript)
const int col = str_to_channel_colour( field );
if (chnl != -1 && col != -1)
- Options.channels[chnl] = col;
+ channels[chnl] = col;
else if (chnl == -1)
fprintf( stderr, "Bad channel -- %s\n", subkey.c_str() );
else if (col == -1)
@@ -986,7 +1255,7 @@ void parse_option_line(const std::string &str, bool runscript)
const int col = str_to_colour( field );
if (col != -1)
- Options.background = col;
+ background = col;
else
fprintf( stderr, "Bad colour -- %s\n", field.c_str() );
@@ -995,7 +1264,7 @@ void parse_option_line(const std::string &str, bool runscript)
{
const int col = str_to_colour( field );
if (col != -1)
- Options.detected_item_colour = col;
+ detected_item_colour = col;
else
fprintf( stderr, "Bad detected_item_colour -- %s\n",
field.c_str());
@@ -1004,102 +1273,116 @@ void parse_option_line(const std::string &str, bool runscript)
{
const int col = str_to_colour( field );
if (col != -1)
- Options.detected_monster_colour = col;
+ detected_monster_colour = col;
else
fprintf( stderr, "Bad detected_monster_colour -- %s\n",
field.c_str());
}
- else if (key == "remembered_monster_colour")
+ else if (key.find(interrupt_prefix) == 0)
{
- if (field == "real")
- Options.remembered_monster_colour = 0xFFFFU;
- else if (field == "auto")
- Options.remembered_monster_colour = 0;
- else {
- const int col = str_to_colour( field );
- if (col != -1)
- Options.remembered_monster_colour = col;
- else
- fprintf( stderr, "Bad remembered_monster_colour -- %s\n",
- field.c_str());
- }
+ set_activity_interrupt(key.substr(interrupt_prefix.length()),
+ field,
+ plus_equal);
+ }
+ else if (key.find("cset") == 0)
+ {
+ std::string cset = key.substr(4);
+ if (!cset.empty() && cset[0] == '_')
+ cset = cset.substr(1);
+
+ char_set_type cs = NUM_CSET;
+ if (cset == "ascii")
+ cs = CSET_ASCII;
+ else if (cset == "ibm")
+ cs = CSET_IBM;
+ else if (cset == "dec")
+ cs = CSET_DEC;
+
+ add_cset_override(cs, field);
+ }
+ else if (key == "feature" || key == "dungeon")
+ {
+ std::vector<std::string> defs = split_string(";", field);
+
+ for (int i = 0, size = defs.size(); i < size; ++i)
+ add_feature_override( defs[i] );
}
else if (key == "friend_brand")
{
// Use curses attributes to mark friend
// Some may look bad on some terminals.
// As a suggestion, try "rxvt -rv -fn 10x20" under Un*xes
- Options.friend_brand = curses_attribute(field);
+ friend_brand = curses_attribute(field);
}
else if (key == "stab_brand")
{
- Options.stab_brand = curses_attribute(field);
+ stab_brand = curses_attribute(field);
}
else if (key == "may_stab_brand")
{
- Options.may_stab_brand = curses_attribute(field);
+ may_stab_brand = curses_attribute(field);
}
else if (key == "no_dark_brand")
{
// This is useful for terms where dark grey does
// not have standout modes (since it's black on black).
// This option will use light-grey instead in these cases.
- Options.no_dark_brand = read_bool( field, Options.no_dark_brand );
+ no_dark_brand = read_bool( field, no_dark_brand );
}
else if (key == "heap_brand")
{
// See friend_brand option upstairs. no_dark_brand applies
// here as well.
- Options.heap_brand = curses_attribute(field);
- }
- else if (key == "show_uncursed")
- {
- // label known uncursed items as "uncursed"
- Options.show_uncursed = read_bool( field, Options.show_uncursed );
+ heap_brand = curses_attribute(field);
}
else if (key == "always_greet")
{
// show greeting when reloading game
- Options.always_greet = read_bool( field, Options.always_greet );
+ always_greet = read_bool( field, always_greet );
}
else if (key == "weapon")
{
// choose this weapon for classes that get choice
- Options.weapon = str_to_weapon( field );
+ weapon = str_to_weapon( field );
+ }
+ else if (key == "book")
+ {
+ // choose this book for classes that get choice
+ book = str_to_book( field );
}
else if (key == "chaos_knight")
{
// choose god for Chaos Knights
if (field == "xom")
- Options.chaos_knight = GOD_XOM;
+ chaos_knight = GOD_XOM;
else if (field == "makhleb")
- Options.chaos_knight = GOD_MAKHLEB;
+ chaos_knight = GOD_MAKHLEB;
else if (field == "random")
- Options.chaos_knight = GOD_RANDOM;
+ chaos_knight = GOD_RANDOM;
}
else if (key == "death_knight")
{
if (field == "necromancy")
- Options.death_knight = DK_NECROMANCY;
+ death_knight = DK_NECROMANCY;
else if (field == "yredelemnul")
- Options.death_knight = DK_YREDELEMNUL;
+ death_knight = DK_YREDELEMNUL;
else if (field == "random")
- Options.death_knight = DK_RANDOM;
+ death_knight = DK_RANDOM;
}
else if (key == "priest")
{
// choose this weapon for classes that get choice
if (field == "zin")
- Options.priest = GOD_ZIN;
+ priest = GOD_ZIN;
else if (field == "yredelemnul")
- Options.priest = GOD_YREDELEMNUL;
+ priest = GOD_YREDELEMNUL;
else if (field == "random")
- Options.priest = GOD_RANDOM;
+ priest = GOD_RANDOM;
}
else if (key == "fire_items_start")
{
if (isalpha( field[0] ))
- Options.fire_items_start = letter_to_index( field[0] );
+ fire_items_start = letter_to_index( field[0] );
else
{
fprintf( stderr, "Bad fire item start index -- %s\n",
@@ -1109,39 +1392,69 @@ void parse_option_line(const std::string &str, bool runscript)
else if (key == "assign_item_slot")
{
if (field == "forward")
- Options.assign_item_slot = SS_FORWARD;
+ assign_item_slot = SS_FORWARD;
else if (field == "backward")
- Options.assign_item_slot = SS_BACKWARD;
+ assign_item_slot = SS_BACKWARD;
}
else if (key == "fire_order")
{
- str_to_fire_order( field, Options.fire_order );
+ str_to_fire_order( field, fire_order );
}
else if (key == "random_pick")
{
// randomly generate character
- Options.random_pick = read_bool( field, Options.random_pick );
+ random_pick = read_bool( field, random_pick );
}
else if (key == "remember_name")
{
- Options.remember_name = read_bool( field, Options.remember_name );
+ remember_name = read_bool( field, remember_name );
}
+ else if (key == "save_dir")
+ {
+ // If SAVE_DIR_PATH was defined, there are very likely security issues
+ // with allowing the user to specify a different directory.
+#ifndef SAVE_DIR_PATH
+ save_dir = field;
+#endif
+ }
else if (key == "hp_warning")
{
- Options.hp_warning = atoi( field.c_str() );
- if (Options.hp_warning < 0 || Options.hp_warning > 100)
+ hp_warning = atoi( field.c_str() );
+ if (hp_warning < 0 || hp_warning > 100)
{
- Options.hp_warning = 0;
+ hp_warning = 0;
fprintf( stderr, "Bad HP warning percentage -- %s\n",
field.c_str() );
}
}
+ else if (key == "ood_interesting")
+ {
+ ood_interesting = atoi( field.c_str() );
+ }
+ else if (key == "note_monsters")
+ {
+ append_vector(note_monsters, split_string(",", field));
+ }
+ else if (key == "note_messages")
+ {
+ append_vector(note_messages, split_string(",", field));
+ }
+ else if (key == "note_hp_percent")
+ {
+ note_hp_percent = atoi( field.c_str() );
+ if (note_hp_percent < 0 || note_hp_percent > 100)
+ {
+ note_hp_percent = 0;
+ fprintf( stderr, "Bad HP note percentage -- %s\n",
+ field.c_str() );
+ }
+ }
else if (key == "hp_attention")
{
- Options.hp_attention = atoi( field.c_str() );
- if (Options.hp_attention < 0 || Options.hp_attention > 100)
+ hp_attention = atoi( field.c_str() );
+ if (hp_attention < 0 || hp_attention > 100)
{
- Options.hp_attention = 0;
+ hp_attention = 0;
fprintf( stderr, "Bad HP attention percentage -- %s\n",
field.c_str() );
}
@@ -1155,158 +1468,242 @@ void parse_option_line(const std::string &str, bool runscript)
if (SysEnv.crawl_dir)
{
- strncpy(SysEnv.crawl_dir, field.c_str(), kNameLen - 1);
- SysEnv.crawl_dir[ kNameLen - 1 ] = '\0';
+ strncpy(SysEnv.crawl_dir, field.c_str(), kPathLen - 1);
+ SysEnv.crawl_dir[ kPathLen - 1 ] = 0;
}
}
else if (key == "race")
{
- Options.race = str_to_race( field );
+ race = str_to_race( field );
- if (Options.race == '\0')
+ if (race == 0)
fprintf( stderr, "Unknown race choice: %s\n", field.c_str() );
}
else if (key == "class")
{
- Options.cls = str_to_class( field );
+ cls = str_to_class( field );
- if (Options.cls == '\0')
+ if (cls == 0)
fprintf( stderr, "Unknown class choice: %s\n", field.c_str() );
}
else if (key == "auto_list")
{
- Options.auto_list = read_bool( field, Options.auto_list );
+ auto_list = read_bool( field, auto_list );
+ }
+ else if (key == "confirm_self_target")
+ {
+ confirm_self_target = read_bool( field, confirm_self_target );
+ }
+ else if (key == "safe_autopickup")
+ {
+ safe_autopickup = read_bool( field, safe_autopickup );
+ }
+ else if (key == "use_notes")
+ {
+ use_notes = read_bool( field, use_notes );
+ }
+ else if (key == "note_skill_max")
+ {
+ note_skill_max = read_bool( field, note_skill_max );
+ }
+ else if (key == "note_all_spells")
+ {
+ note_all_spells = read_bool( field, note_all_spells );
}
else if (key == "delay_message_clear")
{
- Options.delay_message_clear = read_bool( field, Options.delay_message_clear );
+ delay_message_clear = read_bool( field, delay_message_clear );
}
else if (key == "terse_hand")
{
- Options.terse_hand = read_bool( field, Options.terse_hand );
+ terse_hand = read_bool( field, terse_hand );
+ }
+ else if (key == "increasing_skill_progress")
+ {
+ increasing_skill_progress = read_bool( field, increasing_skill_progress );
}
else if (key == "flush")
{
if (subkey == "failure")
{
- Options.flush_input[FLUSH_ON_FAILURE]
- = read_bool(field, Options.flush_input[FLUSH_ON_FAILURE]);
+ flush_input[FLUSH_ON_FAILURE]
+ = read_bool(field, flush_input[FLUSH_ON_FAILURE]);
}
else if (subkey == "command")
{
- Options.flush_input[FLUSH_BEFORE_COMMAND]
- = read_bool(field, Options.flush_input[FLUSH_BEFORE_COMMAND]);
+ flush_input[FLUSH_BEFORE_COMMAND]
+ = read_bool(field, flush_input[FLUSH_BEFORE_COMMAND]);
}
else if (subkey == "message")
{
- Options.flush_input[FLUSH_ON_MESSAGE]
- = read_bool(field, Options.flush_input[FLUSH_ON_MESSAGE]);
+ flush_input[FLUSH_ON_MESSAGE]
+ = read_bool(field, flush_input[FLUSH_ON_MESSAGE]);
}
else if (subkey == "lua")
{
- Options.flush_input[FLUSH_LUA]
- = read_bool(field, Options.flush_input[FLUSH_LUA]);
+ flush_input[FLUSH_LUA]
+ = read_bool(field, flush_input[FLUSH_LUA]);
}
}
else if (key == "lowercase_invocations")
{
- Options.lowercase_invocations
- = read_bool(field, Options.lowercase_invocations);
+ lowercase_invocations
+ = read_bool(field, lowercase_invocations);
}
else if (key == "wiz_mode")
{
// wiz_mode is recognized as a legal key in all compiles -- bwr
#ifdef WIZARD
if (field == "never")
- Options.wiz_mode = WIZ_NEVER;
+ wiz_mode = WIZ_NEVER;
else if (field == "no")
- Options.wiz_mode = WIZ_NO;
+ wiz_mode = WIZ_NO;
else if (field == "yes")
- Options.wiz_mode = WIZ_YES;
+ wiz_mode = WIZ_YES;
else
fprintf(stderr, "Unknown wiz_mode option: %s\n", field.c_str());
#endif
}
else if (key == "ban_pickup")
{
- append_vector(Options.banned_objects, split_string(",", field));
+ append_vector(banned_objects, split_string(",", field));
+ }
+ else if (key == "note_items")
+ {
+ append_vector(note_items, split_string(",", field));
+ }
+ else if (key == "autoinscribe")
+ {
+ std::vector<std::string> thesplit =
+ split_string(":", field);
+ autoinscriptions.push_back(
+ std::pair<text_pattern,std::string>(thesplit[0],
+ thesplit[1]));
+ }
+ else if (key == "map_file_name")
+ {
+ map_file_name = field;
+ }
+ else if (key == "note_skill_levels")
+ {
+ std::vector<std::string> thesplit = split_string(",", field);
+ for ( unsigned i = 0; i < thesplit.size(); ++i ) {
+ int num = atoi(thesplit[i].c_str());
+ if ( num > 0 && num <= 27 ) {
+ note_skill_levels.push_back(num);
+ }
+ else {
+ fprintf(stderr, "Bad skill level to note -- %s\n",
+ thesplit[i].c_str());
+ continue;
+ }
+ }
}
else if (key == "pickup_thrown")
{
- Options.pickup_thrown = read_bool(field, Options.pickup_thrown);
+ pickup_thrown = read_bool(field, pickup_thrown);
}
else if (key == "pickup_dropped")
{
- Options.pickup_dropped = read_bool(field, Options.pickup_dropped);
+ pickup_dropped = read_bool(field, pickup_dropped);
}
- else if (key == "show_waypoints")
+#ifdef WIZARD
+ else if (key == "fsim_kit")
{
- Options.show_waypoints = read_bool(field, Options.show_waypoints);
+ append_vector(fsim_kit, split_string(",", field));
+ }
+ else if (key == "fsim_rounds")
+ {
+ fsim_rounds = atol(field.c_str());
+ if (fsim_rounds < 1000)
+ fsim_rounds = 1000;
+ if (fsim_rounds > 500000L)
+ fsim_rounds = 500000L;
+ }
+ else if (key == "fsim_mons")
+ {
+ fsim_mons = field;
+ }
+ else if (key == "fsim_str")
+ {
+ fsim_str = atoi(field.c_str());
+ }
+ else if (key == "fsim_int")
+ {
+ fsim_int = atoi(field.c_str());
+ }
+ else if (key == "fsim_dex")
+ {
+ fsim_dex = atoi(field.c_str());
+ }
+ else if (key == "fsim_xl")
+ {
+ fsim_xl = atoi(field.c_str());
+ }
+#endif // WIZARD
+ else if (key == "sort_menus")
+ {
+ sort_menus = read_bool(field, sort_menus);
}
else if (key == "travel_delay")
{
// Read travel delay in milliseconds.
- Options.travel_delay = atoi( field.c_str() );
- if (Options.travel_delay < -1)
- Options.travel_delay = -1;
- if (Options.travel_delay > 2000)
- Options.travel_delay = 2000;
+ travel_delay = atoi( field.c_str() );
+ if (travel_delay < -1)
+ travel_delay = -1;
+ if (travel_delay > 2000)
+ travel_delay = 2000;
}
else if (key == "level_map_cursor_step")
{
- Options.level_map_cursor_step = atoi( field.c_str() );
- if (Options.level_map_cursor_step < 1)
- Options.level_map_cursor_step = 1;
- if (Options.level_map_cursor_step > 50)
- Options.level_map_cursor_step = 50;
+ level_map_cursor_step = atoi( field.c_str() );
+ if (level_map_cursor_step < 1)
+ level_map_cursor_step = 1;
+ if (level_map_cursor_step > 50)
+ level_map_cursor_step = 50;
}
else if (key == "macro_meta_entry")
{
- Options.macro_meta_entry = read_bool(field, Options.macro_meta_entry);
- }
- else if (key == "travel_stair_cost")
- {
- Options.travel_stair_cost = atoi( field.c_str() );
- if (Options.travel_stair_cost < 1)
- Options.travel_stair_cost = 1;
- else if (Options.travel_stair_cost > 1000)
- Options.travel_stair_cost = 1000;
+ macro_meta_entry = read_bool(field, macro_meta_entry);
}
else if (key == "travel_exclude_radius2")
{
- Options.travel_exclude_radius2 = atoi( field.c_str() );
- if (Options.travel_exclude_radius2 < 0)
- Options.travel_exclude_radius2 = 0;
- else if (Options.travel_exclude_radius2 > 400)
- Options.travel_exclude_radius2 = 400;
+ travel_exclude_radius2 = atoi( field.c_str() );
+ if (travel_exclude_radius2 < 0)
+ travel_exclude_radius2 = 0;
+ else if (travel_exclude_radius2 > 400)
+ travel_exclude_radius2 = 400;
}
- else if (key == "stop_travel")
+ else if (key == "stop_travel" || key == "travel_stop_message")
{
std::vector<std::string> fragments = split_string(",", field);
- for (int i = 0, count = fragments.size(); i < count; ++i) {
+ for (int i = 0, count = fragments.size(); i < count; ++i)
+ {
if (fragments[i].length() == 0)
continue;
std::string::size_type pos = fragments[i].find(":");
- if (pos && pos != std::string::npos) {
+ if (pos && pos != std::string::npos)
+ {
std::string prefix = fragments[i].substr(0, pos);
int channel = str_to_channel( prefix );
- if (channel != -1 || prefix == "any") {
+ if (channel != -1 || prefix == "any")
+ {
std::string s = fragments[i].substr( pos + 1 );
trim_string( s );
- Options.stop_travel.push_back(
+ travel_stop_message.push_back(
message_filter( channel, s ) );
continue;
}
}
- Options.stop_travel.push_back(
+ travel_stop_message.push_back(
message_filter( fragments[i] ) );
}
}
else if (key == "drop_filter")
{
- append_vector(Options.drop_filter, split_string(",", field));
+ append_vector(drop_filter, split_string(",", field));
}
else if (key == "travel_avoid_terrain")
{
@@ -1314,48 +1711,64 @@ void parse_option_line(const std::string &str, bool runscript)
for (int i = 0, count = seg.size(); i < count; ++i)
prevent_travel_to( seg[i] );
}
- else if (key == "travel_colour")
+ else if (key == "tc_reachable")
+ {
+ tc_reachable = str_to_colour(field, tc_reachable);
+ }
+ else if (key == "tc_excluded")
+ {
+ tc_excluded = str_to_colour(field, tc_excluded);
+ }
+ else if (key == "tc_exclude_circle")
{
- Options.travel_colour = read_bool(field, Options.travel_colour);
+ tc_exclude_circle =
+ str_to_colour(field, tc_exclude_circle);
}
- else if (key == "item_colour")
+ else if (key == "tc_dangerous")
{
- Options.item_colour = read_bool(field, Options.item_colour);
+ tc_dangerous = str_to_colour(field, tc_dangerous);
+ }
+ else if (key == "tc_disconnected")
+ {
+ tc_disconnected = str_to_colour(field, tc_disconnected);
+ }
+ else if (key == "item_colour" || key == "item_color")
+ {
+ item_colour = read_bool(field, item_colour);
}
else if (key == "easy_exit_menu")
{
- Options.easy_exit_menu = read_bool(field, Options.easy_exit_menu);
+ easy_exit_menu = read_bool(field, easy_exit_menu);
}
else if (key == "dos_use_background_intensity")
{
- Options.dos_use_background_intensity =
- read_bool(field, Options.dos_use_background_intensity);
+ dos_use_background_intensity =
+ read_bool(field, dos_use_background_intensity);
}
else if (key == "explore_stop")
{
- Options.explore_stop = ES_NONE;
+ explore_stop = ES_NONE;
std::vector<std::string> stops = split_string(",", field);
for (int i = 0, count = stops.size(); i < count; ++i)
{
const std::string &c = stops[i];
if (c == "item" || c == "items")
- Options.explore_stop |= ES_ITEM;
+ explore_stop |= ES_ITEM;
else if (c == "shop" || c == "shops")
- Options.explore_stop |= ES_SHOP;
+ explore_stop |= ES_SHOP;
else if (c == "stair" || c == "stairs")
- Options.explore_stop |= ES_STAIR;
+ explore_stop |= ES_STAIR;
else if (c == "altar" || c == "altars")
- Options.explore_stop |= ES_ALTAR;
+ explore_stop |= ES_ALTAR;
}
}
#ifdef STASH_TRACKING
else if (key == "stash_tracking")
{
- Options.stash_tracking =
- field == "explicit"? STM_EXPLICIT :
+ stash_tracking =
field == "dropped" ? STM_DROPPED :
field == "all" ? STM_ALL :
- STM_NONE;
+ STM_EXPLICIT;
}
else if (key == "stash_filter")
{
@@ -1374,7 +1787,7 @@ void parse_option_line(const std::string &str, bool runscript)
sound_mapping mapping;
mapping.pattern = sub.substr(0, cpos);
mapping.soundfile = sub.substr(cpos + 1);
- Options.sound_mappings.push_back(mapping);
+ sound_mappings.push_back(mapping);
}
}
}
@@ -1389,13 +1802,20 @@ void parse_option_line(const std::string &str, bool runscript)
mapping.pattern = sub.substr(cpos + 1);
mapping.colour = str_to_colour(sub.substr(0, cpos));
if (mapping.colour != -1)
- Options.menu_colour_mappings.push_back(mapping);
+ menu_colour_mappings.push_back(mapping);
}
}
}
+ else if (key == "dump_order")
+ {
+ if (!plus_equal)
+ dump_order.clear();
+
+ add_dump_fields(field);
+ }
else if (key == "dump_kill_places")
{
- Options.dump_kill_places =
+ dump_kill_places =
field == "none"? KDO_NO_PLACES :
field == "all" ? KDO_ALL_PLACES :
KDO_ONE_PLACE;
@@ -1417,66 +1837,66 @@ void parse_option_line(const std::string &str, bool runscript)
else if (key == "dump_message_count")
{
// Capping is implicit
- Options.dump_message_count = atoi( field.c_str() );
+ dump_message_count = atoi( field.c_str() );
}
else if (key == "dump_item_origins")
{
- Options.dump_item_origins = IODS_PRICE;
+ dump_item_origins = IODS_PRICE;
std::vector<std::string> choices = split_string(",", field);
for (int i = 0, count = choices.size(); i < count; ++i)
{
const std::string &ch = choices[i];
if (ch == "artifacts")
- Options.dump_item_origins |= IODS_ARTIFACTS;
+ dump_item_origins |= IODS_ARTIFACTS;
else if (ch == "ego_arm" || ch == "ego armour"
|| ch == "ego_armour")
- Options.dump_item_origins |= IODS_EGO_ARMOUR;
+ dump_item_origins |= IODS_EGO_ARMOUR;
else if (ch == "ego_weap" || ch == "ego weapon"
|| ch == "ego_weapon" || ch == "ego weapons"
|| ch == "ego_weapons")
- Options.dump_item_origins |= IODS_EGO_WEAPON;
+ dump_item_origins |= IODS_EGO_WEAPON;
else if (ch == "jewellery" || ch == "jewelry")
- Options.dump_item_origins |= IODS_JEWELLERY;
+ dump_item_origins |= IODS_JEWELLERY;
else if (ch == "runes")
- Options.dump_item_origins |= IODS_RUNES;
+ dump_item_origins |= IODS_RUNES;
else if (ch == "rods")
- Options.dump_item_origins |= IODS_RODS;
+ dump_item_origins |= IODS_RODS;
else if (ch == "staves")
- Options.dump_item_origins |= IODS_STAVES;
+ dump_item_origins |= IODS_STAVES;
else if (ch == "books")
- Options.dump_item_origins |= IODS_BOOKS;
+ dump_item_origins |= IODS_BOOKS;
else if (ch == "all" || ch == "everything")
- Options.dump_item_origins = IODS_EVERYTHING;
+ dump_item_origins = IODS_EVERYTHING;
}
}
else if (key == "dump_item_origin_price")
{
- Options.dump_item_origin_price = atoi( field.c_str() );
- if (Options.dump_item_origin_price < -1)
- Options.dump_item_origin_price = -1;
+ dump_item_origin_price = atoi( field.c_str() );
+ if (dump_item_origin_price < -1)
+ dump_item_origin_price = -1;
}
- else if (key == "target_zero_exp")
+ else if (key == "safe_zero_exp")
{
- Options.target_zero_exp = read_bool(field, Options.target_zero_exp);
+ safe_zero_exp = read_bool(field, safe_zero_exp);
}
- else if (key == "target_wrap")
+ else if (key == "target_zero_exp")
{
- Options.target_wrap = read_bool(field, Options.target_wrap);
+ target_zero_exp = read_bool(field, target_zero_exp);
}
else if (key == "target_oos")
{
- Options.target_oos = read_bool(field, Options.target_oos);
+ target_oos = read_bool(field, target_oos);
}
else if (key == "target_los_first")
{
- Options.target_los_first = read_bool(field, Options.target_los_first);
+ target_los_first = read_bool(field, target_los_first);
}
else if (key == "drop_mode")
{
if (field.find("multi") != std::string::npos)
- Options.drop_mode = DM_MULTI;
+ drop_mode = DM_MULTI;
else
- Options.drop_mode = DM_SINGLE;
+ drop_mode = DM_SINGLE;
}
// Catch-all else, copies option into map
else
@@ -1490,7 +1910,7 @@ void parse_option_line(const std::string &str, bool runscript)
if (clua.error.length())
mpr(clua.error.c_str());
#endif
- Options.named_options[key] = orig_field;
+ named_options[key] = orig_field;
}
}
}
@@ -1530,8 +1950,19 @@ static const char *cmd_ops[] = { "scores", "name", "race", "class",
const int num_cmd_ops = 10;
bool arg_seen[num_cmd_ops];
+static void set_crawl_path(const std::string &path)
+{
+ const std::string::size_type slash = path.rfind(FILE_SEPARATOR);
+ SysEnv.crawl_executable_path =
+ slash != std::string::npos? path.substr(0, slash + 1)
+ : std::string("");
+}
+
bool parse_args( int argc, char **argv, bool rc_only )
{
+ if (argc >= 1)
+ set_crawl_path(argv[0]);
+
if (argc < 2) // no args!
return (true);
@@ -1630,10 +2061,7 @@ bool parse_args( int argc, char **argv, bool rc_only )
return (false);
if (!rc_only)
- {
- strncpy(you.your_name, next_arg, kNameLen);
- you.your_name[ kNameLen - 1 ] = '\0';
- }
+ Options.player_name = next_arg;
nextUsed = true;
break;
@@ -1673,12 +2101,8 @@ bool parse_args( int argc, char **argv, bool rc_only )
if (!rc_only)
{
- viewwindow = &viewwindow3;
- mapch = &mapchar3;
- mapch2 = &mapchar4;
-#ifdef UNIX
- character_set = 0;
-#endif
+ Options.char_set = CSET_ASCII;
+ init_char_table(Options.char_set);
}
break;
@@ -1709,3 +2133,61 @@ bool parse_args( int argc, char **argv, bool rc_only )
return (true);
}
+
+//////////////////////////////////////////////////////////////////////////
+// game_options
+
+int game_options::o_int(const char *name, int def) const
+{
+ int val = def;
+ opt_map::const_iterator i = named_options.find(name);
+ if (i != named_options.end())
+ {
+ val = atoi(i->second.c_str());
+ }
+ return (val);
+}
+
+long game_options::o_long(const char *name, long def) const
+{
+ long val = def;
+ opt_map::const_iterator i = named_options.find(name);
+ if (i != named_options.end())
+ {
+ const char *s = i->second.c_str();
+ char *es = NULL;
+ long num = strtol(s, &es, 10);
+ if (s != (const char *) es && es)
+ val = num;
+ }
+ return (val);
+}
+
+bool game_options::o_bool(const char *name, bool def) const
+{
+ bool val = def;
+ opt_map::const_iterator i = named_options.find(name);
+ if (i != named_options.end())
+ val = read_bool(i->second, val);
+ return (val);
+}
+
+std::string game_options::o_str(const char *name, const char *def) const
+{
+ std::string val;
+ opt_map::const_iterator i = named_options.find(name);
+ if (i != named_options.end())
+ val = i->second;
+ else if (def)
+ val = def;
+ return (val);
+}
+
+int game_options::o_colour(const char *name, int def) const
+{
+ std::string val = o_str(name);
+ trim_string(val);
+ tolower_string(val);
+ int col = str_to_colour(val);
+ return (col == -1? def : col);
+}
diff --git a/crawl-ref/source/initfile.h b/crawl-ref/source/initfile.h
index d5860fdd77..ffe3ff5c30 100644
--- a/crawl-ref/source/initfile.h
+++ b/crawl-ref/source/initfile.h
@@ -3,6 +3,8 @@
* Summary: Simple reading of init file.
* Written by: David Loewenstern
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> 6/9/99 DML Created
@@ -16,12 +18,14 @@
#include <cstdio>
std::string & trim_string( std::string &str );
+std::string & tolower_string( std::string &str );
+int str_to_colour( const std::string &str, int default_colour = -1 );
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
-void read_init_file(bool runscript = false);
+std::string read_init_file(bool runscript = false);
void read_options(FILE *f, bool runscript = false);
@@ -29,6 +33,8 @@ void read_options(const std::string &s, bool runscript = false);
void parse_option_line(const std::string &line, bool runscript = false);
+void apply_ascii_display(bool ascii);
+
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: acr
diff --git a/crawl-ref/source/insult.cc b/crawl-ref/source/insult.cc
index 1e8c629ab9..bb3b62f11b 100644
--- a/crawl-ref/source/insult.cc
+++ b/crawl-ref/source/insult.cc
@@ -4,6 +4,8 @@
// to link with Linley Henzel's Dungeon Crawl (or Crawl) without change to
// Crawl's license.
//
+// Modified for Crawl Reference by $Author$ on $Date$
+//
// The goal of this stuff is catachronistic feel.
#include "AppHdr.h"
diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc
index 2145f80f72..437b01c4fc 100644
--- a/crawl-ref/source/invent.cc
+++ b/crawl-ref/source/invent.cc
@@ -3,6 +3,8 @@
* Summary: Functions for inventory related commands.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <5> 10/9/99 BCR Added wizard help screen
@@ -35,199 +37,341 @@
#include "view.h"
#include "menu.h"
-const char *command_string( int i );
-const char *wizard_string( int i );
+///////////////////////////////////////////////////////////////////////////////
+// Inventory menu shenanigans
+
+static void get_inv_items_to_show(
+ std::vector<const item_def*> &v, int selector);
-struct InvTitle : public MenuEntry
+InvTitle::InvTitle( Menu *mn, const std::string &title,
+ invtitle_annotator tfn )
+ : MenuEntry( title, MEL_TITLE )
{
- Menu *m;
- std::string (*titlefn)( int menuflags, const std::string &oldt );
-
- InvTitle( Menu *mn, const char *title,
- std::string (*tfn)( int menuflags, const std::string &oldt ) )
- : MenuEntry( title )
+ m = mn;
+ titlefn = tfn;
+}
+
+std::string InvTitle::get_text() const
+{
+ return titlefn? titlefn( m, MenuEntry::get_text() ) :
+ MenuEntry::get_text();
+}
+
+InvEntry::InvEntry( const item_def &i ) : MenuEntry( "", MEL_ITEM ), item( &i )
+{
+ data = const_cast<item_def *>( item );
+
+ char buf[ITEMNAME_SIZE];
+ if (i.base_type == OBJ_GOLD)
+ snprintf(buf, sizeof buf, "%d gold piece%s", i.quantity,
+ (i.quantity > 1? "s" : ""));
+ else
+ item_name(i,
+ in_inventory(i)?
+ DESC_INVENTORY_EQUIP : DESC_NOCAP_A, buf, false);
+ text = buf;
+
+ if (i.base_type != OBJ_GOLD && in_inventory(i))
{
- m = mn;
- titlefn = tfn;
+ // FIXME: This is HORRIBLE! We're skipping the inventory letter prefix
+ // which looks like this: "a - ".
+ text = text.substr( 4 );
+ add_hotkey(index_to_letter( i.link ));
}
-
- std::string get_text() const
+ else
{
- return titlefn? titlefn( m->get_flags(), MenuEntry::get_text() ) :
- MenuEntry::get_text();
+ // Dummy hotkey for gold or non-inventory items.
+ add_hotkey(' ');
}
-};
+ add_class_hotkeys(i);
+
+ quantity = i.quantity;
+}
-class InvShowPrices;
-class InvEntry : public MenuEntry
+std::string InvEntry::get_text() const
{
-private:
- static bool show_prices;
- static char temp_id[4][50];
- static void set_show_prices(bool doshow);
+ char buf[ITEMNAME_SIZE];
+ char suffix[ITEMNAME_SIZE] = "";
- friend class InvShowPrices;
-public:
- const item_def *item;
+ if (InvEntry::show_prices)
+ {
+ int value = item_value(*item, temp_id, true);
+ if (value > 0)
+ snprintf(suffix, sizeof suffix,
+ " (%d gold)", value);
+ }
+ snprintf( buf, sizeof buf,
+ " %c %c %s%s",
+ hotkeys[0],
+ (!selected_qty? '-' : selected_qty < quantity? '#' : '+'),
+ text.c_str(),
+ suffix );
+ return (buf);
+}
- InvEntry( const item_def &i ) : MenuEntry( "", MEL_ITEM ), item( &i )
+void InvEntry::add_class_hotkeys(const item_def &i)
+{
+ switch (i.base_type)
{
- data = const_cast<item_def *>( item );
-
- char buf[ITEMNAME_SIZE];
- if (i.base_type == OBJ_GOLD)
- snprintf(buf, sizeof buf, "%d gold piece%s", i.quantity,
- (i.quantity > 1? "s" : ""));
- else
- item_name(i,
- in_inventory(i)?
- DESC_INVENTORY_EQUIP : DESC_NOCAP_A, buf, false);
- text = buf;
+ case OBJ_GOLD:
+ add_hotkey('$');
+ break;
+ case OBJ_MISSILES:
+ add_hotkey('(');
+ break;
+ case OBJ_WEAPONS:
+ add_hotkey(')');
+ break;
+ case OBJ_ARMOUR:
+ add_hotkey('[');
+ break;
+ case OBJ_WANDS:
+ add_hotkey('/');
+ break;
+ case OBJ_FOOD:
+ add_hotkey('%');
+ break;
+ case OBJ_BOOKS:
+ add_hotkey('+');
+ add_hotkey(':');
+ break;
+ case OBJ_SCROLLS:
+ add_hotkey('?');
+ break;
+ case OBJ_JEWELLERY:
+ add_hotkey(i.sub_type >= AMU_RAGE? '"' : '=');
+ break;
+ case OBJ_POTIONS:
+ add_hotkey('!');
+ break;
+ case OBJ_STAVES:
+ add_hotkey('\\');
+ add_hotkey('|');
+ break;
+ case OBJ_MISCELLANY:
+ add_hotkey('}');
+ break;
+ case OBJ_CORPSES:
+ add_hotkey('&');
+ break;
+ default:
+ break;
+ }
+}
- if (i.base_type != OBJ_GOLD)
- {
- if (in_inventory(i))
- {
- text = text.substr( 4 ); // Skip the inventory letter.
- add_hotkey(index_to_letter( i.link ));
- }
- else
- add_hotkey(' '); // Dummy hotkey
- }
- else
- {
- // Dummy hotkey for gold.
- add_hotkey(' ');
- }
- add_class_hotkeys(i);
+bool InvEntry::show_prices = false;
+char InvEntry::temp_id[4][50];
- quantity = i.quantity;
+void InvEntry::set_show_prices(bool doshow)
+{
+ if ((show_prices = doshow))
+ {
+ memset(temp_id, 1, sizeof temp_id);
}
+}
+
+InvShowPrices::InvShowPrices(bool doshow)
+{
+ InvEntry::set_show_prices(doshow);
+}
+
+InvShowPrices::~InvShowPrices()
+{
+ InvEntry::set_show_prices(false);
+}
+
+// Returns vector of item_def pointers to each item_def in the given
+// vector. Note: make sure the original vector stays around for the lifetime
+// of the use of the item pointers, or mayhem results!
+std::vector<const item_def*>
+InvMenu::xlat_itemvect(const std::vector<item_def> &v)
+{
+ std::vector<const item_def*> xlatitems;
+ for (unsigned i = 0, size = v.size(); i < size; ++i)
+ xlatitems.push_back( &v[i] );
+ return (xlatitems);
+}
+
+void InvMenu::set_type(menu_type t)
+{
+ type = t;
+}
+
+void InvMenu::set_title_annotator(invtitle_annotator afn)
+{
+ title_annotate = afn;
+}
+
+void InvMenu::set_title(MenuEntry *t)
+{
+ Menu::set_title(t);
+}
- std::string get_text() const
+void InvMenu::set_preselect(const std::vector<SelItem> *pre)
+{
+ pre_select = pre;
+}
+
+void InvMenu::set_title(const std::string &s)
+{
+ std::string stitle = s;
+ if (stitle.empty())
{
- char buf[ITEMNAME_SIZE];
- char suffix[ITEMNAME_SIZE] = "";
+ const int cap = carrying_capacity();
- if (InvEntry::show_prices)
- {
- int value = item_value(*item, temp_id, true);
- if (value > 0)
- snprintf(suffix, sizeof suffix,
- " (%d gold)", value);
- }
- snprintf( buf, sizeof buf,
- "%c %c %s%s",
- hotkeys[0],
- (!selected_qty? '-' : selected_qty < quantity? '#' : '+'),
- text.c_str(),
- suffix );
- return (buf);
+ char title_buf[200];
+ snprintf( title_buf, sizeof title_buf,
+ "Inventory: %d.%d/%d.%d aum (%d%%, %d/52 slots)",
+ you.burden / 10, you.burden % 10,
+ cap / 10, cap % 10,
+ (you.burden * 100) / cap,
+ inv_count() );
+ stitle = title_buf;
}
-private:
- void add_class_hotkeys(const item_def &i)
+
+ set_title(new InvTitle(this, stitle, title_annotate));
+}
+
+void InvMenu::load_inv_items(int item_selector,
+ MenuEntry *(*procfn)(MenuEntry *me))
+{
+ std::vector<const item_def *> tobeshown;
+ get_inv_items_to_show(tobeshown, item_selector);
+
+ load_items(tobeshown, procfn);
+ if (!item_count())
{
- switch (i.base_type)
+ std::string s;
+ switch (item_selector)
{
- case OBJ_GOLD:
- add_hotkey('$');
- break;
- case OBJ_MISSILES:
- add_hotkey('(');
+ case OSEL_ANY:
+ s = "You aren't carrying anything.";
break;
+ case OSEL_WIELD:
case OBJ_WEAPONS:
- add_hotkey(')');
- break;
- case OBJ_ARMOUR:
- add_hotkey('[');
- break;
- case OBJ_WANDS:
- add_hotkey('/');
- break;
- case OBJ_FOOD:
- add_hotkey('%');
- break;
- case OBJ_BOOKS:
- add_hotkey('+');
- add_hotkey(':');
- break;
- case OBJ_SCROLLS:
- add_hotkey('?');
- break;
- case OBJ_JEWELLERY:
- add_hotkey(i.sub_type >= AMU_RAGE? '"' : '=');
- break;
- case OBJ_POTIONS:
- add_hotkey('!');
- break;
- case OBJ_STAVES:
- add_hotkey('\\');
- add_hotkey('|');
- break;
- case OBJ_MISCELLANY:
- add_hotkey('}');
- break;
- case OBJ_CORPSES:
- add_hotkey('&');
+ s = "You aren't carrying any weapons.";
break;
default:
+ s = "You aren't carrying any such object.";
break;
}
+ set_title(s);
}
-};
+ else
+ {
+ set_title("");
+ }
+}
-bool InvEntry::show_prices = false;
-char InvEntry::temp_id[4][50];
+static bool compare_menu_entries(const MenuEntry* a, const MenuEntry* b)
+{
+ return (*a < *b);
+}
-void InvEntry::set_show_prices(bool doshow)
+void InvMenu::load_items(const std::vector<const item_def*> &mitems,
+ MenuEntry *(*procfn)(MenuEntry *me))
{
- if ((show_prices = doshow))
+ FixedVector< int, NUM_OBJECT_CLASSES > inv_class(0);
+ for (int i = 0, count = mitems.size(); i < count; ++i)
+ inv_class[ mitems[i]->base_type ]++;
+
+ menu_letter ckey;
+ std::vector<InvEntry*> items_in_class;
+
+ for (int i = 0; i < NUM_OBJECT_CLASSES; ++i)
{
- memset(temp_id, 1, sizeof temp_id);
+ if (!inv_class[i]) continue;
+
+ add_entry( new MenuEntry( item_class_name(i), MEL_SUBTITLE ) );
+ items_in_class.clear();
+
+ for (int j = 0, count = mitems.size(); j < count; ++j)
+ {
+ if (mitems[j]->base_type != i) continue;
+ items_in_class.push_back( new InvEntry(*mitems[j]) );
+ }
+
+ if (Options.sort_menus)
+ std::sort( items_in_class.begin(), items_in_class.end(),
+ compare_menu_entries );
+
+ for (unsigned int j = 0; j < items_in_class.size(); ++j)
+ {
+ InvEntry *ie = items_in_class[j];
+ // If there's no hotkey, provide one.
+ if (ie->hotkeys[0] == ' ')
+ ie->hotkeys[0] = ckey++;
+ do_preselect(ie);
+
+ add_entry( procfn? (*procfn)(ie) : ie );
+ }
}
}
-class InvShowPrices {
-public:
- InvShowPrices(bool doshow = true)
- {
- InvEntry::set_show_prices(doshow);
- }
- ~InvShowPrices()
- {
- InvEntry::set_show_prices(false);
- }
-};
+void InvMenu::do_preselect(InvEntry *ie)
+{
+ if (!pre_select || pre_select->empty())
+ return;
-class InvMenu : public Menu
+ for (int i = 0, size = pre_select->size(); i < size; ++i)
+ if (ie->item && ie->item == (*pre_select)[i].item)
+ {
+ ie->selected_qty = (*pre_select)[i].quantity;
+ break;
+ }
+}
+
+std::vector<SelItem> InvMenu::get_selitems() const
{
-public:
- InvMenu(int flags = MF_MULTISELECT) : Menu(flags) { }
-protected:
- bool process_key(int key);
-};
+ std::vector<SelItem> selected_items;
+ for (int i = 0, count = sel.size(); i < count; ++i)
+ {
+ InvEntry *inv = dynamic_cast<InvEntry*>(sel[i]);
+ selected_items.push_back(
+ SelItem(
+ inv->hotkeys[0],
+ inv->selected_qty,
+ inv->item ) );
+ }
+ return (selected_items);
+}
bool InvMenu::process_key( int key )
{
- if (items.size() && (key == CONTROL('D') || key == '@'))
+ if (items.size()
+ && type == MT_DROP
+ && (key == CONTROL('D') || key == '@'))
{
- int newflag =
+ int newflag =
is_set(MF_MULTISELECT)?
- MF_SINGLESELECT | MF_EASY_EXIT | MF_ANYPRINTABLE
+ MF_SINGLESELECT | MF_ANYPRINTABLE
: MF_MULTISELECT;
- flags &= ~(MF_SINGLESELECT | MF_MULTISELECT |
- MF_EASY_EXIT | MF_ANYPRINTABLE);
+ flags &= ~(MF_SINGLESELECT | MF_MULTISELECT | MF_ANYPRINTABLE);
flags |= newflag;
deselect_all();
- sel->clear();
- draw_select_count(0);
+ sel.clear();
+ draw_select_count(0, true);
return true;
}
return Menu::process_key( key );
}
+unsigned char InvMenu::getkey() const
+{
+ unsigned char mkey = lastch;
+ // Fake an ESCAPE if the menu is empty.
+ if (!item_count())
+ mkey = ESCAPE;
+ if (!isalnum(mkey) && mkey != '$' && mkey != '-' && mkey != '?'
+ && mkey != '*' && mkey != ESCAPE)
+ mkey = ' ';
+ return (mkey);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
bool in_inventory( const item_def &i )
{
return i.x == -1 && i.y == -1;
@@ -235,10 +379,8 @@ bool in_inventory( const item_def &i )
unsigned char get_invent( int invent_type )
{
- unsigned char nothing = invent_select( invent_type );
-
+ unsigned char nothing = invent_select(NULL, MT_INVLIST, invent_type);
redraw_screen();
-
return (nothing);
} // end get_invent()
@@ -291,84 +433,20 @@ std::string item_class_name( int type, bool terse )
return ("");
}
-void populate_item_menu( Menu *menu, const std::vector<item_def> &items,
- void (*callback)(MenuEntry *me) )
-{
- FixedVector< int, NUM_OBJECT_CLASSES > inv_class;
- for (int i = 0; i < NUM_OBJECT_CLASSES; ++i)
- inv_class[i] = 0;
- for (int i = 0, count = items.size(); i < count; ++i)
- inv_class[ items[i].base_type ]++;
-
- menu_letter ckey;
- for (int i = 0; i < NUM_OBJECT_CLASSES; ++i)
- {
- if (!inv_class[i]) continue;
-
- menu->add_entry( new MenuEntry( item_class_name(i), MEL_SUBTITLE ) );
-
- for (int j = 0, count = items.size(); j < count; ++j)
- {
- if (items[j].base_type != i) continue;
-
- InvEntry *ie = new InvEntry( items[j] );
- ie->hotkeys[0] = ckey++;
- callback(ie);
-
- menu->add_entry( ie );
- }
- }
-}
-
-std::vector<SelItem> select_items( std::vector<item_def*> &items,
- const char *title )
+std::vector<SelItem> select_items( const std::vector<const item_def*> &items,
+ const char *title, bool noselect )
{
std::vector<SelItem> selected;
-
- if (items.empty())
- return selected;
-
- FixedVector< int, NUM_OBJECT_CLASSES > inv_class;
- for (int i = 0; i < NUM_OBJECT_CLASSES; ++i)
- inv_class[i] = 0;
- for (int i = 0, count = items.size(); i < count; ++i)
- inv_class[ items[i]->base_type ]++;
-
- Menu menu;
- menu.set_title( new MenuEntry(title) );
-
- char ckey = 'a';
- for (int i = 0; i < NUM_OBJECT_CLASSES; ++i)
+ if (!items.empty())
{
- if (!inv_class[i]) continue;
-
- menu.add_entry( new MenuEntry( item_class_name(i), MEL_SUBTITLE ) );
-
- for (int j = 0, count = items.size(); j < count; ++j)
- {
- if (items[j]->base_type != i) continue;
-
- InvEntry *ie = new InvEntry( *items[j] );
- ie->hotkeys[0] = ckey;
-
- menu.add_entry( ie );
-
- ckey = ckey == 'z'? 'A' :
- ckey == 'Z'? 'a' :
- ckey + 1;
- }
- }
- menu.set_flags( MF_MULTISELECT | MF_SELECT_ANY_PAGE );
- std::vector< MenuEntry * > sel = menu.show();
- for (int i = 0, count = sel.size(); i < count; ++i)
- {
- InvEntry *inv = (InvEntry *) sel[i];
- selected.push_back( SelItem( inv->hotkeys[0],
- inv->selected_qty,
- inv->item ) );
+ InvMenu menu;
+ menu.set_title(title);
+ menu.load_items(items);
+ menu.set_flags(noselect ? MF_NOSELECT : MF_MULTISELECT);
+ menu.show();
+ selected = menu.get_selitems();
}
-
- return selected;
+ return (selected);
}
static bool item_class_selected(const item_def &i, int selector)
@@ -409,7 +487,7 @@ static bool is_item_selected(const item_def &i, int selector)
|| userdef_item_selected(i, selector);
}
-static void get_inv_items_to_show(std::vector<item_def*> &v, int selector)
+static void get_inv_items_to_show(std::vector<const item_def*> &v, int selector)
{
for (int i = 0; i < ENDOFPACK; i++)
{
@@ -418,127 +496,45 @@ static void get_inv_items_to_show(std::vector<item_def*> &v, int selector)
}
}
-static void set_vectitem_classes(const std::vector<item_def*> &v,
- FixedVector<int, NUM_OBJECT_CLASSES> &fv)
-{
- for (int i = 0; i < NUM_OBJECT_CLASSES; i++)
- fv[i] = 0;
-
- for (int i = 0, size = v.size(); i < size; i++)
- fv[ v[i]->base_type ]++;
-}
-
unsigned char invent_select(
+ const char *title,
+ menu_type type,
int item_selector,
int flags,
- std::string (*titlefn)( int menuflags,
- const std::string &oldt ),
+ invtitle_annotator titlefn,
std::vector<SelItem> *items,
std::vector<text_pattern> *filter,
- Menu::selitem_tfn selitemfn )
+ Menu::selitem_tfn selitemfn,
+ const std::vector<SelItem> *pre_select )
{
- InvMenu menu;
+ InvMenu menu(flags);
- menu.selitem_text = selitemfn;
+ menu.set_preselect(pre_select);
+ menu.set_title_annotator(titlefn);
+ menu.f_selitem = selitemfn;
if (filter)
menu.set_select_filter( *filter );
+ menu.load_inv_items(item_selector);
+ menu.set_type(type);
- FixedVector< int, NUM_OBJECT_CLASSES > inv_class2;
- for (int i = 0; i < NUM_OBJECT_CLASSES; i++)
- inv_class2[i] = 0;
+ // Don't override title if there are no items.
+ if (title && menu.item_count())
+ menu.set_title(title);
- int inv_count = 0;
+ menu.show(true);
- for (int i = 0; i < ENDOFPACK; i++)
- {
- if (you.inv[i].quantity)
- {
- inv_class2[ you.inv[i].base_type ]++;
- inv_count++;
- }
- }
-
- if (!inv_count)
- {
- menu.set_title( new MenuEntry( "You aren't carrying anything." ) );
- menu.show();
- return 0;
- }
-
- std::vector<item_def*> tobeshown;
- get_inv_items_to_show( tobeshown, item_selector );
- set_vectitem_classes( tobeshown, inv_class2 );
-
- if (tobeshown.size())
- {
- const int cap = carrying_capacity();
-
- char title_buf[200];
- snprintf( title_buf, sizeof title_buf,
- "Inventory: %d.%d/%d.%d aum (%d%%, %d/52 slots)",
- you.burden / 10, you.burden % 10,
- cap / 10, cap % 10,
- (you.burden * 100) / cap,
- inv_count );
- menu.set_title( new InvTitle( &menu, title_buf, titlefn ) );
-
- for (int i = 0; i < 15; i++)
- {
- if (inv_class2[i] != 0)
- {
- std::string s = item_class_name(i);
- menu.add_entry( new MenuEntry( s, MEL_SUBTITLE ) );
-
- for (int j = 0, size = tobeshown.size(); j < size; ++j)
- {
- if (tobeshown[j]->base_type == i)
- {
- menu.add_entry( new InvEntry( *tobeshown[j] ) );
- }
- } // end of j loop
- } // end of if inv_class2
- } // end of i loop.
- }
- else
- {
- std::string s;
- if (item_selector == -1)
- s = "You aren't carrying anything.";
- else
- {
- if (item_selector == OBJ_WEAPONS || item_selector == OSEL_WIELD)
- s = "You aren't carrying any weapons.";
- else if (item_selector == OBJ_MISSILES)
- s = "You aren't carrying any ammunition.";
- else
- s = "You aren't carrying any such object.";
- }
- menu.set_title( new MenuEntry( s ) );
- }
-
- menu.set_flags( flags );
- std::vector< MenuEntry * > sel = menu.show();
if (items)
- {
- for (int i = 0, count = sel.size(); i < count; ++i)
- items->push_back( SelItem( sel[i]->hotkeys[0],
- sel[i]->selected_qty ) );
- }
+ *items = menu.get_selitems();
- unsigned char mkey = menu.getkey();
- if (!isalnum(mkey) && mkey != '$' && mkey != '-' && mkey != '?'
- && mkey != '*')
- mkey = ' ';
- return mkey;
+ return (menu.getkey());
}
unsigned char invent( int item_class_inv, bool show_price )
{
InvShowPrices show_item_prices(show_price);
- return (invent_select(item_class_inv));
+ return (invent_select(NULL, MT_INVLIST, item_class_inv));
} // end invent()
-
// Reads in digits for a count and apprends then to val, the
// return value is the character that stopped the reading.
static unsigned char get_invent_quant( unsigned char keyin, int &quant )
@@ -577,31 +573,31 @@ static unsigned char get_invent_quant( unsigned char keyin, int &quant )
// Note: This function never checks if the item is appropriate.
std::vector<SelItem> prompt_invent_items(
const char *prompt,
+ menu_type mtype,
int type_expect,
- std::string (*titlefn)( int menuflags,
- const std::string &oldt ),
+ invtitle_annotator titlefn,
bool allow_auto_list,
bool allow_easy_quit,
const char other_valid_char,
std::vector<text_pattern> *select_filter,
- Menu::selitem_tfn fn )
+ Menu::selitem_tfn fn,
+ const std::vector<SelItem> *pre_select )
{
unsigned char keyin = 0;
- int ret = -1;
+ int ret = PROMPT_ABORT;
bool need_redraw = false;
bool need_prompt = true;
bool need_getch = true;
+ bool auto_list = Options.auto_list && allow_auto_list;
- if (Options.auto_list && allow_auto_list)
+ if (auto_list)
{
- need_getch = false;
- need_redraw = false;
- need_prompt = false;
+ need_prompt = need_getch = false;
keyin = '?';
}
- std::vector< SelItem > items;
+ std::vector<SelItem> items;
int count = -1;
for (;;)
{
@@ -630,16 +626,21 @@ std::vector<SelItem> prompt_invent_items(
}
else if (keyin == '?' || keyin == '*' || keyin == ',')
{
- int selmode = Options.drop_mode == DM_SINGLE?
- MF_SINGLESELECT | MF_EASY_EXIT | MF_ANYPRINTABLE :
- MF_MULTISELECT;
+ int selmode =
+ Options.drop_mode == DM_SINGLE
+ && (!pre_select || pre_select->empty())?
+ MF_SINGLESELECT | MF_EASY_EXIT | MF_ANYPRINTABLE :
+ MF_MULTISELECT;
// The "view inventory listing" mode.
int ch = invent_select(
- keyin == '*'? -1 : type_expect,
- selmode | MF_SELECT_ANY_PAGE,
- titlefn, &items, select_filter, fn );
-
- if (selmode & MF_SINGLESELECT)
+ prompt,
+ mtype,
+ keyin == '*'? OSEL_ANY : type_expect,
+ selmode,
+ titlefn, &items, select_filter, fn,
+ pre_select );
+
+ if ((selmode & MF_SINGLESELECT) || ch == ESCAPE)
{
keyin = ch;
need_getch = false;
@@ -653,11 +654,11 @@ std::vector<SelItem> prompt_invent_items(
if (items.size())
{
redraw_screen();
- mesclr( true );
+ mesclr(true);
- for (int i = 0, count = items.size(); i < count; ++i)
+ for (unsigned int i = 0; i < items.size(); ++i)
items[i].slot = letter_to_index( items[i].slot );
- return items;
+ return (items);
}
need_redraw = !(keyin == '?' || keyin == '*'
@@ -694,6 +695,11 @@ std::vector<SelItem> prompt_invent_items(
// we've got a character we don't understand...
canned_msg( MSG_HUH );
}
+ else
+ {
+ // We're going to loop back up, so don't draw another prompt.
+ need_prompt = false;
+ }
}
if (ret != PROMPT_ABORT)
@@ -701,6 +707,52 @@ std::vector<SelItem> prompt_invent_items(
return items;
}
+static int digit_to_index( char digit, operation_types oper ) {
+
+ int i;
+ unsigned int j;
+ char iletter = (char)(oper);
+
+ for ( i = 0; i < ENDOFPACK; ++i ) {
+ if (is_valid_item(you.inv[i])) {
+ const std::string& r(you.inv[i].inscription);
+ /* note that r.size() is unsigned */
+ for ( j = 0; j + 2 < r.size(); ++j ) {
+ if ( r[j] == '@' &&
+ (r[j+1] == iletter || r[j+1] == '*') &&
+ r[j+2] == digit ) {
+ return i;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+/* return true if user OK'd it (or no warning), false otherwise */
+static bool check_warning_inscriptions( const item_def& item,
+ operation_types oper )
+{
+ unsigned int i;
+ char iletter = (char)(oper);
+ char name[ITEMNAME_SIZE];
+ char prompt[ITEMNAME_SIZE + 100];
+ item_name(item, DESC_INVENTORY, name, false);
+ strcpy( prompt, "Really choose ");
+ strncat( prompt, name, ITEMNAME_SIZE );
+ strcat( prompt, "?");
+
+ const std::string& r(item.inscription);
+ for ( i = 0; i + 1 < r.size(); ++i ) {
+ if ( r[i] == '!' &&
+ (r[i+1] == iletter || r[i+1] == '*') ) {
+
+ return yesno(prompt, false, 'n');
+ }
+ }
+ return true;
+}
+
// This function prompts the user for an item, handles the '?' and '*'
// listings, and returns the inventory slot to the caller (which if
// must_exist is true (the default) will be an assigned item, with
@@ -710,45 +762,26 @@ std::vector<SelItem> prompt_invent_items(
// It returns PROMPT_GOT_SPECIAL if the player hits the "other_valid_char".
//
// Note: This function never checks if the item is appropriate.
-int prompt_invent_item( const char *prompt, int type_expect,
+int prompt_invent_item( const char *prompt,
+ menu_type mtype, int type_expect,
bool must_exist, bool allow_auto_list,
bool allow_easy_quit,
const char other_valid_char,
- int *const count )
+ int *const count,
+ operation_types oper )
{
unsigned char keyin = 0;
- int ret = -1;
+ int ret = PROMPT_ABORT;
bool need_redraw = false;
bool need_prompt = true;
bool need_getch = true;
+ bool auto_list = Options.auto_list && allow_auto_list;
- if (Options.auto_list && allow_auto_list)
+ if (auto_list)
{
- std::vector< SelItem > items;
-
- // pretend the player has hit '?' and setup state.
- keyin = invent_select( type_expect,
- MF_SINGLESELECT | MF_ANYPRINTABLE
- | MF_EASY_EXIT,
- NULL, &items );
-
- if (items.size())
- {
- if (count)
- *count = items[0].quantity;
- redraw_screen();
- mesclr( true );
- return letter_to_index( keyin );
- }
-
- need_getch = false;
-
- // Don't redraw if we're just going to display another listing
- need_redraw = (keyin != '?' && keyin != '*');
-
- // A prompt is nice for when we're moving to "count" mode.
- need_prompt = (count != NULL && isdigit( keyin ));
+ need_prompt = need_getch = false;
+ keyin = '?';
}
for (;;)
@@ -780,11 +813,14 @@ int prompt_invent_item( const char *prompt, int type_expect,
{
// The "view inventory listing" mode.
std::vector< SelItem > items;
- keyin = invent_select( keyin == '*'? OSEL_ANY : type_expect,
- MF_SINGLESELECT | MF_ANYPRINTABLE
- | MF_EASY_EXIT,
- NULL,
- &items );
+ keyin = invent_select(
+ prompt,
+ mtype,
+ keyin == '*'? OSEL_ANY : type_expect,
+ MF_SINGLESELECT | MF_ANYPRINTABLE
+ | MF_EASY_EXIT,
+ NULL,
+ &items );
if (items.size())
{
@@ -799,9 +835,7 @@ int prompt_invent_item( const char *prompt, int type_expect,
// Don't redraw if we're just going to display another listing
need_redraw = (keyin != '?' && keyin != '*');
-
- // A prompt is nice for when we're moving to "count" mode.
- need_prompt = (count != NULL && isdigit( keyin ));
+ need_prompt = need_redraw;
}
else if (count != NULL && isdigit( keyin ))
{
@@ -811,6 +845,17 @@ int prompt_invent_item( const char *prompt, int type_expect,
need_prompt = false;
need_getch = false;
}
+ /*** HP CHANGE ***/
+ else if ( count == NULL && isdigit( keyin ) )
+ {
+ /* scan for our item */
+ int res = digit_to_index( keyin, oper );
+ if ( res != -1 ) {
+ ret = res;
+ if ( check_warning_inscriptions( you.inv[ret], oper ) )
+ break;
+ }
+ }
else if (keyin == ESCAPE
|| (Options.easy_quit_item_prompts
&& allow_easy_quit
@@ -825,203 +870,23 @@ int prompt_invent_item( const char *prompt, int type_expect,
if (must_exist && !is_valid_item( you.inv[ret] ))
mpr( "You do not have any such object." );
- else
- break;
+ else {
+ if ( check_warning_inscriptions( you.inv[ret], oper ) ) {
+ break;
+ }
+ }
}
else if (!isspace( keyin ))
{
// we've got a character we don't understand...
canned_msg( MSG_HUH );
}
- }
-
- return (ret);
-}
-
-void list_commands(bool wizard)
-{
- 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
- int moreLength = (get_number_of_lines() - 1) * 2;
-
- for (int i = 0; i < 500; i++)
- {
- if (wizard)
- line = wizard_string( i );
else
- line = command_string( i );
-
- if (strlen( line ) != 0)
{
- // BCR - If we've reached the end of the screen, clear
- if (j == moreLength)
- {
- gotoxy(2, j / 2 + 1);
- cprintf("More...");
- getch();
- clrscr();
- j = 0;
- }
-
- gotoxy( ((j % 2) ? 40 : 2), ((j / 2) + 1) );
- cprintf( line );
-
- j++;
+ // We're going to loop back up, so don't draw another prompt.
+ need_prompt = false;
}
}
- getch();
-
-#ifdef DOS_TERM
- puttext(1, 1, 80, 25, buffer);
-#endif
-
- return;
-} // end list_commands()
-
-const char *wizard_string( int i )
-{
- UNUSED( i );
-
-#ifdef WIZARD
- return((i == 10) ? "a : acquirement" :
- (i == 13) ? "A : set all skills to level" :
- (i == 15) ? "b : controlled blink" :
- (i == 20) ? "B : banish yourself to the Abyss" :
- (i == 30) ? "g : add a skill" :
- (i == 35) ? "G : remove all monsters" :
- (i == 40) ? "h/H : heal yourself (super-Heal)" :
- (i == 50) ? "i/I : identify/unidentify inventory":
- (i == 70) ? "l : make entrance to labyrinth" :
- (i == 80) ? "m/M : create monster by number/name":
- (i == 90) ? "o/%% : create an object" :
- (i == 100) ? "p : make entrance to pandemonium" :
- (i == 110) ? "x : gain an experience level" :
- (i == 115) ? "r : change character's species" :
- (i == 120) ? "s : gain 20000 skill points" :
- (i == 130) ? "S : set skill to level" :
- (i == 140) ? "t : tweak object properties" :
- (i == 150) ? "X : Receive a gift from Xom" :
- (i == 160) ? "z/Z : cast any spell by number/name":
- (i == 200) ? "$ : get 1000 gold" :
- (i == 210) ? "</> : create up/down staircase" :
- (i == 220) ? "u/d : shift up/down one level" :
- (i == 230) ? "~/\" : goto a level" :
- (i == 240) ? "( : create a feature" :
- (i == 250) ? "] : get a mutation" :
- (i == 260) ? "[ : get a demonspawn mutation" :
- (i == 270) ? ": : find branch" :
- (i == 280) ? "{ : magic mapping" :
- (i == 290) ? "^ : gain piety" :
- (i == 300) ? "_ : gain religion" :
- (i == 310) ? "\' : list items" :
- (i == 320) ? "? : list wizard commands" :
- (i == 330) ? "| : acquire all unrand artefacts" :
- (i == 340) ? "+ : turn item into random artefact" :
- (i == 350) ? "= : sum skill points"
- : "");
-
-#else
- return ("");
-#endif
-} // end wizard_string()
-
-const char *command_string( int i )
-{
- /*
- * BCR - Command printing, case statement
- * Note: The numbers in this case indicate the order in which the
- * commands will be printed out. Make sure none of these
- * numbers is greater than 500, because that is the limit.
- *
- * Arranged alpha lower, alpha upper, punctuation, ctrl.
- *
- */
-
- return((i == 10) ? "a : use special ability" :
- (i == 20) ? "d(#) : drop (exact quantity of) items" :
- (i == 30) ? "e : eat food" :
- (i == 40) ? "f : fire first available missile" :
- (i == 50) ? "i : inventory listing" :
- (i == 55) ? "m : check skills" :
- (i == 60) ? "o/c : open / close a door" :
- (i == 65) ? "p : pray" :
- (i == 70) ? "q : quaff a potion" :
- (i == 80) ? "r : read a scroll or book" :
- (i == 90) ? "s : search adjacent tiles" :
- (i == 100) ? "t : throw/shoot an item" :
- (i == 110) ? "v : view item description" :
- (i == 120) ? "w : wield an item" :
- (i == 130) ? "x : examine visible surroundings" :
- (i == 135) ? "z : zap a wand" :
- (i == 140) ? "A : list abilities/mutations" :
- (i == 141) ? "C : check experience" :
- (i == 142) ? "D : dissect a corpse" :
- (i == 145) ? "E : evoke power of wielded item" :
- (i == 150) ? "M : memorise a spell" :
- (i == 155) ? "O : overview of the dungeon" :
- (i == 160) ? "P/R : put on / remove jewellery" :
- (i == 165) ? "Q : quit without saving" :
- (i == 168) ? "S : save game and exit" :
- (i == 179) ? "V : version information" :
- (i == 200) ? "W/T : wear / take off armour" :
- (i == 210) ? "X : examine level map" :
- (i == 220) ? "Z : cast a spell" :
- (i == 240) ? ",/g : pick up items" :
- (i == 242) ? "./del: rest one turn" :
- (i == 250) ? "</> : ascend / descend a staircase" :
- (i == 270) ? "; : examine occupied tile" :
- (i == 280) ? "\\ : check item knowledge" :
-#ifdef WIZARD
- (i == 290) ? "& : invoke your Wizardly powers" :
-#endif
- (i == 300) ? "+/- : scroll up/down [level map only]" :
- (i == 310) ? "! : shout or command allies" :
- (i == 325) ? "^ : describe religion" :
- (i == 337) ? "@ : status" :
- (i == 340) ? "# : dump character to file" :
- (i == 350) ? "= : reassign inventory/spell letters" :
- (i == 360) ? "\' : wield item a, or switch to b" :
-#ifdef USE_MACROS
- (i == 380) ? "` : add macro" :
- (i == 390) ? "~ : save macros" :
-#endif
- (i == 400) ? "] : display worn armour" :
- (i == 410) ? "\" : display worn jewellery" :
- (i == 420) ? "Ctrl-P : see old messages" :
-#ifdef PLAIN_TERM
- (i == 430) ? "Ctrl-R : Redraw screen" :
-#endif
- (i == 440) ? "Ctrl-A : toggle autopickup" :
- (i == 450) ? "Ctrl-X : Save game without query" :
-
-#ifdef ALLOW_DESTROY_ITEM_COMMAND
- (i == 451) ? "Ctrl-D : Destroy inventory item" :
-#endif
- (i == 453) ? "Ctrl-G : interlevel travel" :
- (i == 455) ? "Ctrl-O : explore" :
-
-#ifdef STASH_TRACKING
- (i == 456) ? "Ctrl-S : mark stash" :
- (i == 457) ? "Ctrl-E : forget stash" :
- (i == 458) ? "Ctrl-F : search stashes" :
-#endif
-
- (i == 460) ? "Shift & DIR : long walk" :
- (i == 465) ? "/ DIR : long walk" :
- (i == 470) ? "Ctrl & DIR : door; untrap; attack" :
- (i == 475) ? "* DIR : door; untrap; attack" :
- (i == 478) ? "Shift & 5 on keypad : rest 100 turns"
- : "");
-} // end command_string()
+ return (ret);
+}
diff --git a/crawl-ref/source/invent.h b/crawl-ref/source/invent.h
index 624e603fc1..566bf42b44 100644
--- a/crawl-ref/source/invent.h
+++ b/crawl-ref/source/invent.h
@@ -3,6 +3,8 @@
* Summary: Functions for inventory related commands.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -15,6 +17,7 @@
#include <stddef.h>
#include <vector>
#include "menu.h"
+#include "enum.h"
#define PROMPT_ABORT -1
#define PROMPT_GOT_SPECIAL -2
@@ -32,28 +35,124 @@ struct SelItem
}
};
+typedef std::string (*invtitle_annotator)(
+ const Menu *m, const std::string &oldtitle);
+
+struct InvTitle : public MenuEntry
+{
+ Menu *m;
+ invtitle_annotator titlefn;
+
+ InvTitle( Menu *mn, const std::string &title,
+ invtitle_annotator tfn );
+
+ std::string get_text() const;
+};
-int prompt_invent_item( const char *prompt, int type_expect,
+class InvShowPrices;
+class InvEntry : public MenuEntry
+{
+private:
+ static bool show_prices;
+ static char temp_id[4][50];
+ static void set_show_prices(bool doshow);
+
+ friend class InvShowPrices;
+
+public:
+ const item_def *item;
+
+ InvEntry( const item_def &i );
+ std::string get_text() const;
+
+private:
+ void add_class_hotkeys(const item_def &i);
+};
+
+class InvShowPrices {
+public:
+ InvShowPrices(bool doshow = true);
+ ~InvShowPrices();
+};
+
+class InvMenu : public Menu
+{
+public:
+ InvMenu(int mflags = MF_MULTISELECT)
+ : Menu(mflags), type(MT_INVSELECT), pre_select(NULL),
+ title_annotate(NULL)
+ {
+ }
+
+ unsigned char getkey() const;
+
+ void set_preselect(const std::vector<SelItem> *pre);
+ void set_type(menu_type t);
+
+ // Sets function to annotate the title with meta-information if needed.
+ // If you set this, do so *before* calling set_title, or it won't take
+ // effect.
+ void set_title_annotator(invtitle_annotator fn);
+
+ void set_title(MenuEntry *title);
+ void set_title(const std::string &s);
+
+ // Loads items into the menu. If "procfn" is provided, it'll be called
+ // for each MenuEntry added.
+ // NOTE: Does not set menu title, ever! You *must* set the title explicitly
+ void load_items(const std::vector<const item_def*> &items,
+ MenuEntry *(*procfn)(MenuEntry *me) = NULL);
+
+ // Loads items from the player's inventory into the menu, and sets the
+ // title to the stock title. If "procfn" is provided, it'll be called for
+ // each MenuEntry added, *excluding the title*.
+ void load_inv_items(int item_selector = OSEL_ANY,
+ MenuEntry *(*procfn)(MenuEntry *me) = NULL);
+
+ std::vector<SelItem> get_selitems() const;
+
+ // Returns vector of item_def pointers to each item_def in the given
+ // vector. Note: make sure the original vector stays around for the lifetime
+ // of the use of the item pointers, or mayhem results!
+ static std::vector<const item_def*> xlat_itemvect(
+ const std::vector<item_def> &);
+protected:
+ bool process_key(int key);
+ void do_preselect(InvEntry *ie);
+
+protected:
+ menu_type type;
+ const std::vector<SelItem> *pre_select;
+
+ invtitle_annotator title_annotate;
+};
+
+
+int prompt_invent_item( const char *prompt,
+ menu_type type,
+ int type_expect,
bool must_exist = true,
bool allow_auto_list = true,
bool allow_easy_quit = true,
const char other_valid_char = '\0',
- int *const count = NULL );
+ int *const count = NULL,
+ operation_types oper = OPER_ANY );
-std::vector<SelItem> select_items( std::vector<item_def*> &items,
- const char *title );
+std::vector<SelItem> select_items(
+ const std::vector<const item_def*> &items,
+ const char *title, bool noselect = false );
std::vector<SelItem> prompt_invent_items(
const char *prompt,
+ menu_type type,
int type_expect,
- std::string (*titlefn)( int menuflags,
- const std::string &oldt )
- = NULL,
+ invtitle_annotator titlefn = NULL,
bool allow_auto_list = true,
bool allow_easy_quit = true,
const char other_valid_char = '\0',
std::vector<text_pattern> *filter = NULL,
- Menu::selitem_tfn fn = NULL );
+ Menu::selitem_tfn fn = NULL,
+ const std::vector<SelItem> *pre_select = NULL );
// last updated 12may2000 {dlb}
@@ -62,14 +161,18 @@ std::vector<SelItem> prompt_invent_items(
* *********************************************************************** */
unsigned char invent( int item_class_inv, bool show_price );
-unsigned char invent_select(int item_class_inv,
- int select_flags = MF_NOSELECT,
- std::string (*titlefn)( int menuflags,
- const std::string &oldt )
- = NULL,
+unsigned char invent_select(
+ // Use NULL for stock Inventory title
+ const char *title = NULL,
+ // MT_DROP allows the multidrop toggle
+ menu_type type = MT_INVLIST,
+ int item_selector = OSEL_ANY,
+ int menu_select_flags = MF_NOSELECT,
+ invtitle_annotator titlefn = NULL,
std::vector<SelItem> *sels = NULL,
std::vector<text_pattern> *filter = NULL,
- Menu::selitem_tfn fn = NULL );
+ Menu::selitem_tfn fn = NULL,
+ const std::vector<SelItem> *pre_select = NULL );
// last updated 24may2000 {dlb}
/* ***********************************************************************
@@ -87,7 +190,4 @@ void list_commands(bool wizard);
std::string item_class_name(int type, bool terse = false);
-void populate_item_menu( Menu *menu, const std::vector<item_def> &items,
- void (*callback)(MenuEntry *me) );
-
#endif
diff --git a/crawl-ref/source/it_use2.cc b/crawl-ref/source/it_use2.cc
index 45449716d9..0878c7dbba 100644
--- a/crawl-ref/source/it_use2.cc
+++ b/crawl-ref/source/it_use2.cc
@@ -3,6 +3,8 @@
* Summary: Functions for using wands, potions, and weapon/armour removal.4\3
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* 26jun2000 jmf added ZAP_MAGMA
@@ -105,7 +107,7 @@ bool potion_effect( char pot_eff, int pow )
if (you.might > 80)
you.might = 80;
- naughty( NAUGHTY_STIMULANTS, 4 + random2(4) );
+ did_god_conduct( DID_STIMULANTS, 4 + random2(4) );
}
break;
@@ -279,14 +281,14 @@ bool potion_effect( char pot_eff, int pow )
mutate(100, false);
}
- naughty(NAUGHTY_STIMULANTS, 4 + random2(4));
+ did_god_conduct(DID_STIMULANTS, 4 + random2(4));
break;
}
return (effect);
} // end potion_effect()
-void unwield_item(char unw)
+void unwield_item(char unw, bool showMsgs)
{
you.special_wield = SPWLD_NONE;
you.wield_change = true;
@@ -298,10 +300,12 @@ void unwield_item(char unw)
switch (you.inv[unw].special)
{
case SPWPN_SINGING_SWORD:
- mpr("The Singing Sword sighs.");
+ if (showMsgs)
+ mpr("The Singing Sword sighs.");
break;
case SPWPN_WRATH_OF_TROG:
- mpr("You feel less violent.");
+ if (showMsgs)
+ mpr("You feel less violent.");
break;
case SPWPN_SCYTHE_OF_CURSES:
case SPWPN_STAFF_OF_OLGREB:
@@ -330,42 +334,56 @@ void unwield_item(char unw)
char str_pass[ ITEMNAME_SIZE ];
in_name(unw, DESC_CAP_YOUR, str_pass);
strcpy(info, str_pass);
-
+
switch (brand)
{
case SPWPN_SWORD_OF_CEREBOV:
case SPWPN_FLAMING:
- strcat(info, " stops flaming.");
- mpr(info);
+ if (showMsgs)
+ {
+ strcat(info, " stops flaming.");
+ mpr(info);
+ }
break;
case SPWPN_FREEZING:
case SPWPN_HOLY_WRATH:
- strcat(info, " stops glowing.");
- mpr(info);
+ if (showMsgs)
+ {
+ strcat(info, " stops glowing.");
+ mpr(info);
+ }
break;
case SPWPN_ELECTROCUTION:
- strcat(info, " stops crackling.");
- mpr(info);
+ if (showMsgs)
+ {
+ strcat(info, " stops crackling.");
+ mpr(info);
+ }
break;
case SPWPN_VENOM:
- strcat(info, " stops dripping with poison.");
- mpr(info);
+ if (showMsgs)
+ {
+ strcat(info, " stops dripping with poison.");
+ mpr(info);
+ }
break;
case SPWPN_PROTECTION:
- mpr("You feel less protected.");
+ if (showMsgs)
+ mpr("You feel less protected.");
you.redraw_armour_class = 1;
break;
case SPWPN_VAMPIRICISM:
- mpr("You feel the strange hunger wane.");
+ if (showMsgs)
+ mpr("You feel the strange hunger wane.");
break;
- /* case 8: draining
- case 9: speed, 10 slicing etc */
+ /* case 8: draining
+ case 9: speed, 10 slicing etc */
case SPWPN_DISTORTION:
// Removing the translocations skill reduction of effect,
@@ -385,11 +403,11 @@ void unwield_item(char unw)
// effect in vorpalise weapon scroll effect in read_scoll
} // end switch
-
if (you.duration[DUR_WEAPON_BRAND])
{
you.duration[DUR_WEAPON_BRAND] = 0;
set_item_ego_type( you.inv[unw], OBJ_WEAPONS, SPWPN_NORMAL );
+ // we're letting this through
mpr("Your branding evaporates.");
}
} // end if
@@ -502,10 +520,15 @@ void unwear_armour(char unw)
void unuse_randart(unsigned char unw)
{
- ASSERT( is_random_artefact( you.inv[unw] ) );
+ unuse_randart( you.inv[unw] );
+}
+
+void unuse_randart(const item_def &item)
+{
+ ASSERT( is_random_artefact( item ) );
FixedVector< char, RA_PROPERTIES > proprt;
- randart_wpn_properties( you.inv[unw], proprt );
+ randart_wpn_properties( item, proprt );
if (proprt[RAP_AC])
you.redraw_armour_class = 1;
diff --git a/crawl-ref/source/it_use2.h b/crawl-ref/source/it_use2.h
index 2177b4083b..8351086bea 100644
--- a/crawl-ref/source/it_use2.h
+++ b/crawl-ref/source/it_use2.h
@@ -28,6 +28,7 @@ bool potion_effect(char pot_eff, int pow);
* *********************************************************************** */
void unuse_randart(unsigned char unw);
+void unuse_randart(const item_def &item);
/* ***********************************************************************
* called from: item_use - transfor
@@ -38,6 +39,6 @@ void unwear_armour(char unw);
/* ***********************************************************************
* called from: decks - it_use3 - item_use - items - spells3 - transfor
* *********************************************************************** */
-void unwield_item(char unw);
+void unwield_item(char unw, bool showMsgs = true);
#endif
diff --git a/crawl-ref/source/it_use3.cc b/crawl-ref/source/it_use3.cc
index f3973806b2..3de5614691 100644
--- a/crawl-ref/source/it_use3.cc
+++ b/crawl-ref/source/it_use3.cc
@@ -3,6 +3,8 @@
* Summary: Functions for using some of the wackier inventory items.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <4> 6/13/99 BWR Auto ID Channel staff
@@ -27,6 +29,7 @@
#include "items.h"
#include "it_use2.h"
#include "itemname.h"
+#include "itemprop.h"
#include "misc.h"
#include "monplace.h"
#include "monstuff.h"
@@ -42,7 +45,6 @@
#include "spl-util.h"
#include "stuff.h"
#include "view.h"
-#include "wpn-misc.h"
static bool ball_of_energy(void);
static bool ball_of_fixation(void);
@@ -102,7 +104,7 @@ void special_wielded(void)
(temp_rand == 29) ? "speaks gibberish." :
(temp_rand == 30) ? "raves incoherently."
: "yells in some weird language.");
- mpr(info);
+ mpr(info, MSGCH_SOUND);
}
break;
@@ -142,8 +144,8 @@ void special_wielded(void)
if (one_chance_in(200))
{
- torment( you.x_pos, you.y_pos );
- naughty( NAUGHTY_UNHOLY, 1 );
+ torment( TORMENT_SPWLD, you.x_pos, you.y_pos );
+ did_god_conduct( DID_UNHOLY, 1 );
}
break;
@@ -153,7 +155,7 @@ void special_wielded(void)
if (one_chance_in(5))
{
animate_dead( 1 + random2(3), BEH_HOSTILE, MHITYOU, 1 );
- naughty( NAUGHTY_NECROMANCY, 1 );
+ did_god_conduct( DID_NECROMANCY, 1 );
}
break;
@@ -185,7 +187,7 @@ void special_wielded(void)
if (random2(8) <= player_spec_death())
{
- naughty( NAUGHTY_NECROMANCY, 1 );
+ did_god_conduct( DID_NECROMANCY, 1 );
create_monster( MONS_SHADOW, ENCH_ABJ_II, BEH_FRIENDLY,
you.x_pos, you.y_pos, you.pet_target, 250 );
}
@@ -199,7 +201,7 @@ void special_wielded(void)
in_name(wpn, DESC_CAP_YOUR, str_pass);
strcpy(info, str_pass);
strcat(info, " lets out a weird humming sound.");
- mpr(info);
+ mpr(info, MSGCH_SOUND);
}
break; // to noisy() call at foot 2apr2000 {dlb}
@@ -209,18 +211,18 @@ void special_wielded(void)
in_name(wpn, DESC_CAP_YOUR, str_pass);
strcpy(info, str_pass);
strcat(info, " chimes like a gong.");
- mpr(info);
+ mpr(info, MSGCH_SOUND);
}
break;
case SPWLD_BECKON:
if (makes_noise)
- mpr("You hear a voice call your name.");
+ mpr("You hear a voice call your name.", MSGCH_SOUND);
break;
case SPWLD_SHOUT:
if (makes_noise)
- mpr("You hear a shout.");
+ mpr("You hear a shout.", MSGCH_SOUND);
break;
//case SPWLD_PRUNE:
@@ -250,7 +252,7 @@ static void reaching_weapon_attack(void)
mpr("Attack whom?", MSGCH_PROMPT);
- direction( beam, DIR_TARGET, TARG_ENEMY );
+ direction( beam, DIR_TARGET, TARG_ENEMY, true );
if (!beam.isValid)
return;
@@ -372,7 +374,7 @@ bool evoke_wielded( void )
mpr("You feel the staff feeding on your energy!");
- dec_hp( 5 + random2avg(19, 2), false );
+ dec_hp( 5 + random2avg(19, 2), false, "Staff of Dispater" );
dec_mp( 2 + random2avg(5, 2) );
make_hungry( 100, false );
@@ -484,8 +486,12 @@ bool evoke_wielded( void )
if (item_is_rod( you.inv[wield] ))
{
pract = staff_spell( wield );
+ // [ds] Early exit, no turns are lost.
+ if (pract == -1)
+ return (false);
+
did_work = true; // staff_spell() will handle messages
- }
+ }
else if (you.inv[wield].sub_type == STAFF_CHANNELING)
{
if (you.magic_points < you.max_magic_points
@@ -497,8 +503,8 @@ bool evoke_wielded( void )
pract = (one_chance_in(5) ? 1 : 0);
did_work = true;
- if (item_not_ident( you.inv[you.equip[EQ_WEAPON]],
- ISFLAG_KNOW_TYPE ))
+ if (!item_ident( you.inv[you.equip[EQ_WEAPON]],
+ ISFLAG_KNOW_TYPE ))
{
set_ident_flags( you.inv[you.equip[EQ_WEAPON]],
ISFLAG_KNOW_TYPE );
@@ -575,8 +581,28 @@ bool evoke_wielded( void )
{
opened_gates++;
+ // [dshaligram] New approach to placing Hell
+ // portals to handle the possibility of a mirrored
+ // Vestibule.
+ int surround_grid = DNGN_FLOOR;
+
+ for (int y = -1; y <= 1; ++y)
+ for (int x = -1; x <= 1; ++x)
+ {
+ if (!x && !y)
+ continue;
+ const int grid =
+ grd[count_x + x][count_y + y];
+
+ if (grid != DNGN_FLOOR
+ && grid != DNGN_SECRET_DOOR
+ && grid != DNGN_CLOSED_DOOR
+ && grid != DNGN_OPEN_DOOR)
+ surround_grid = grid;
+ }
+
// this may generate faulty [][] values {dlb}
- switch (grd[count_x + 2][count_y])
+ switch (surround_grid)
{
case DNGN_FLOOR:
grd[count_x][count_y] = DNGN_ENTER_DIS;
@@ -604,9 +630,13 @@ bool evoke_wielded( void )
else
{
mpr("You produce a hideous howling noise!");
- pract = (one_chance_in(3) ? 1 : 0);
- create_monster( MONS_BEAST, ENCH_ABJ_IV, BEH_HOSTILE,
- you.x_pos, you.y_pos, MHITYOU, 250 );
+ int midx = create_monster( MONS_BEAST, ENCH_ABJ_IV,
+ BEH_HOSTILE, you.x_pos, you.y_pos,
+ MHITYOU, 250 );
+ // avoid scumming; also prevents it from showing up on notes
+ if ( midx != -1 )
+ menv[midx].flags |= MF_CREATED_FRIENDLY;
+ // no practice
}
break;
@@ -681,7 +711,7 @@ bool evoke_wielded( void )
else if (pract > 0)
exercise( SK_EVOCATIONS, pract );
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return (did_work);
} // end evoke_wielded()
@@ -750,7 +780,6 @@ static bool ball_of_seeing(void)
static bool disc_of_storms(void)
{
int temp_rand = 0; // probability determination {dlb}
- struct bolt beam;
int disc_count = 0;
unsigned char which_zap = 0;
@@ -771,6 +800,8 @@ static bool disc_of_storms(void)
while (disc_count)
{
+ bolt beam;
+
temp_rand = random2(3);
which_zap = ((temp_rand > 1) ? ZAP_LIGHTNING :
@@ -811,7 +842,7 @@ void tome_of_power(char sc_read_2)
strcat( info, "." );
mpr( info );
- you.turn_is_over = 1;
+ you.turn_is_over = true;
if (!yesno("Read it?"))
return;
@@ -870,14 +901,15 @@ void tome_of_power(char sc_read_2)
beam.flavour = BEAM_FIRE;
beam.target_x = you.x_pos;
beam.target_y = you.y_pos;
- strcpy( beam.beam_name, "fiery explosion" );
+ beam.name = "fiery explosion";
beam.colour = RED;
// your explosion, (not someone else's explosion)
beam.beam_source = NON_MONSTER;
beam.thrower = KILL_YOU;
beam.aux_source = "an exploding Tome of Power";
beam.ex_size = 2;
- beam.isTracer = false;
+ beam.is_tracer = false;
+ beam.is_explosion = true;
explosion(beam);
return;
@@ -933,7 +965,7 @@ void skill_manual(char sc_read_2)
strcat(info, "!");
mpr(info);
- you.turn_is_over = 1;
+ you.turn_is_over = true;
if (!yesno("Read it?"))
return;
diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc
index 7ea1db4900..f683822891 100644
--- a/crawl-ref/source/item_use.cc
+++ b/crawl-ref/source/item_use.cc
@@ -3,6 +3,8 @@
* Summary: Functions for making use of inventory items.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <8> 28July2000 GDL Revised player throwing
@@ -45,6 +47,7 @@
#include "it_use3.h"
#include "items.h"
#include "itemname.h"
+#include "itemprop.h"
#include "misc.h"
#include "monplace.h"
#include "monstuff.h"
@@ -64,66 +67,103 @@
#include "stuff.h"
#include "transfor.h"
#include "view.h"
-#include "wpn-misc.h"
bool drink_fountain(void);
-static void throw_it(struct bolt &pbolt, int throw_2);
-void use_randart(unsigned char item_wield_2);
-static bool enchant_weapon( int which_stat, bool quiet = false );
static bool enchant_armour( void );
// Rather messy - we've gathered all the can't-wield logic from wield_weapon()
// here.
-bool can_wield(const item_def& weapon)
+bool can_wield(const item_def *weapon, bool say_reason)
{
- if (you.berserker) return false;
+#define SAY(x) if (say_reason) { x; } else
+
+ if (you.berserker)
+ {
+ SAY(canned_msg(MSG_TOO_BERSERK));
+ return false;
+ }
if (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE
&& !can_equip( EQ_WEAPON ))
+ {
+ SAY(mpr("You can't wield anything in your present form."));
return false;
+ }
if (you.equip[EQ_WEAPON] != -1
&& you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS
&& item_cursed( you.inv[you.equip[EQ_WEAPON]] ))
+ {
+ SAY(mpr("You can't unwield your weapon to draw a new one!"));
return false;
+ }
- if (weapon.base_type != OBJ_WEAPONS && weapon.base_type == OBJ_STAVES
- && you.equip[EQ_SHIELD] != -1)
- return false;
+ // If we don't have an actual weapon to check, return now.
+ if (!weapon)
+ return (true);
+
+ for (int i = EQ_CLOAK; i <= EQ_AMULET; i++)
+ {
+ if (you.equip[i] != -1 && &you.inv[you.equip[i]] == weapon)
+ {
+ SAY(mpr("You are wearing that object!"));
+ return (false);
+ }
+ }
+
+ if (is_shield_incompatible(*weapon))
+ {
+ SAY(mpr("You can't wield that with a shield."));
+ return (false);
+ }
+
+ // We don't have to check explicitly for staves - all staves are wieldable
+ // by everyone.
+ if (weapon->base_type != OBJ_WEAPONS)
+ return (true);
if ((you.species < SP_OGRE || you.species > SP_OGRE_MAGE)
- && mass_item( weapon ) >= 500)
+ && item_mass( *weapon ) >= 300)
+ {
+ SAY(mpr("That's too large and heavy for you to wield."));
return false;
+ }
if ((you.species == SP_HALFLING || you.species == SP_GNOME
|| you.species == SP_KOBOLD || you.species == SP_SPRIGGAN)
- && (weapon.sub_type == WPN_GREAT_SWORD
- || weapon.sub_type == WPN_TRIPLE_SWORD
- || weapon.sub_type == WPN_GREAT_MACE
- || weapon.sub_type == WPN_GREAT_FLAIL
- || weapon.sub_type == WPN_BATTLEAXE
- || weapon.sub_type == WPN_EXECUTIONERS_AXE
- || weapon.sub_type == WPN_HALBERD
- || weapon.sub_type == WPN_GLAIVE
- || weapon.sub_type == WPN_GIANT_CLUB
- || weapon.sub_type == WPN_GIANT_SPIKED_CLUB
- || weapon.sub_type == WPN_SCYTHE))
+ && (weapon->sub_type == WPN_GREAT_SWORD
+ || weapon->sub_type == WPN_TRIPLE_SWORD
+ || weapon->sub_type == WPN_GREAT_MACE
+ || weapon->sub_type == WPN_DIRE_FLAIL
+ || weapon->sub_type == WPN_BATTLEAXE
+ || weapon->sub_type == WPN_EXECUTIONERS_AXE
+ || weapon->sub_type == WPN_LOCHABER_AXE
+ || weapon->sub_type == WPN_HALBERD
+ || weapon->sub_type == WPN_GLAIVE
+ || weapon->sub_type == WPN_GIANT_CLUB
+ || weapon->sub_type == WPN_GIANT_SPIKED_CLUB
+ || weapon->sub_type == WPN_LONGBOW
+ || weapon->sub_type == WPN_SCYTHE))
+ {
+ SAY(mpr("That's too large for you to wield."));
return false;
+ }
- if (hands_reqd_for_weapon( weapon.base_type,
- weapon.sub_type ) == HANDS_TWO_HANDED
- && you.equip[EQ_SHIELD] != -1)
- return false;
-
- int weap_brand = get_weapon_brand( weapon );
-
+ int weap_brand = get_weapon_brand( *weapon );
if ((you.is_undead || you.species == SP_DEMONSPAWN)
- && (!is_fixed_artefact( weapon )
+ && (!is_fixed_artefact( *weapon )
&& (weap_brand == SPWPN_HOLY_WRATH
- || weap_brand == SPWPN_DISRUPTION)))
+ || weap_brand == SPWPN_DISRUPTION
+ || (weapon->base_type == OBJ_WEAPONS
+ && weapon->sub_type == WPN_BLESSED_BLADE))))
+ {
+ SAY(mpr("This weapon will not allow you to wield it."));
return false;
+ }
// We can wield this weapon. Phew!
return true;
+
+#undef SAY
}
bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages)
@@ -137,28 +177,9 @@ bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages)
return (false);
}
- if (you.berserker)
- {
- canned_msg(MSG_TOO_BERSERK);
- return (false);
- }
-
- if (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE)
- {
- if (!can_equip( EQ_WEAPON ))
- {
- mpr("You can't wield anything in your present form.");
- return (false);
- }
- }
-
- if (you.equip[EQ_WEAPON] != -1
- && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS
- && item_cursed( you.inv[you.equip[EQ_WEAPON]] ))
- {
- mpr("You can't unwield your weapon to draw a new one!");
+ // Any general reasons why we can't wield a new object?
+ if (!can_wield(NULL, true))
return (false);
- }
if (you.sure_blade)
{
@@ -185,8 +206,10 @@ bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages)
if (!auto_wield || !is_valid_item(you.inv[item_slot]) || force_unwield)
{
if (!auto_wield)
- item_slot = prompt_invent_item( "Wield which item (- for none)?",
- OSEL_WIELD, true, true, true, '-' );
+ item_slot = prompt_invent_item(
+ "Wield which item (- for none)?",
+ MT_INVSELECT, OSEL_WIELD,
+ true, true, true, '-', NULL, OPER_WIELD);
else
item_slot = PROMPT_GOT_SPECIAL;
@@ -199,8 +222,8 @@ bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages)
{
if (you.equip[EQ_WEAPON] != -1)
{
- unwield_item(you.equip[EQ_WEAPON]);
- you.turn_is_over = 1;
+ unwield_item(you.equip[EQ_WEAPON], show_weff_messages);
+ you.turn_is_over = true;
you.equip[EQ_WEAPON] = -1;
canned_msg( MSG_EMPTY_HANDED );
@@ -221,83 +244,14 @@ bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages)
return (true);
}
- for (int i = EQ_CLOAK; i <= EQ_AMULET; i++)
- {
- if (item_slot == you.equip[i])
- {
- mpr("You are wearing that object!");
- return (false);
- }
- }
-
- if (you.inv[item_slot].base_type != OBJ_WEAPONS)
- {
- if (you.inv[item_slot].base_type == OBJ_STAVES
- && you.equip[EQ_SHIELD] != -1)
- {
- mpr("You can't wield that with a shield.");
- return (false);
- }
-
- if (you.equip[EQ_WEAPON] != -1)
- unwield_item(you.equip[EQ_WEAPON]);
-
- you.equip[EQ_WEAPON] = item_slot;
- }
- else
- {
- if ((you.species < SP_OGRE || you.species > SP_OGRE_MAGE)
- && mass_item( you.inv[item_slot] ) >= 500)
- {
- mpr("That's too large and heavy for you to wield.");
- return (false);
- }
-
- if ((you.species == SP_HALFLING || you.species == SP_GNOME
- || you.species == SP_KOBOLD || you.species == SP_SPRIGGAN)
-
- && (you.inv[item_slot].sub_type == WPN_GREAT_SWORD
- || you.inv[item_slot].sub_type == WPN_TRIPLE_SWORD
- || you.inv[item_slot].sub_type == WPN_GREAT_MACE
- || you.inv[item_slot].sub_type == WPN_GREAT_FLAIL
- || you.inv[item_slot].sub_type == WPN_BATTLEAXE
- || you.inv[item_slot].sub_type == WPN_EXECUTIONERS_AXE
- || you.inv[item_slot].sub_type == WPN_HALBERD
- || you.inv[item_slot].sub_type == WPN_GLAIVE
- || you.inv[item_slot].sub_type == WPN_GIANT_CLUB
- || you.inv[item_slot].sub_type == WPN_GIANT_SPIKED_CLUB
- || you.inv[item_slot].sub_type == WPN_SCYTHE))
- {
- mpr("That's too large for you to wield.");
- return (false);
-
- }
-
- if (hands_reqd_for_weapon( you.inv[item_slot].base_type,
- you.inv[item_slot].sub_type ) == HANDS_TWO_HANDED
- && you.equip[EQ_SHIELD] != -1)
- {
- mpr("You can't wield that with a shield.");
- return (false);
- }
-
- int weap_brand = get_weapon_brand( you.inv[item_slot] );
-
- if ((you.is_undead || you.species == SP_DEMONSPAWN)
- && (!is_fixed_artefact( you.inv[item_slot] )
- && (weap_brand == SPWPN_HOLY_WRATH
- || weap_brand == SPWPN_DISRUPTION)))
- {
- mpr("This weapon will not allow you to wield it.");
- you.turn_is_over = 1;
- return (false);
- }
+ if (!can_wield(&you.inv[item_slot], true))
+ return (false);
- if (you.equip[EQ_WEAPON] != -1)
- unwield_item(you.equip[EQ_WEAPON]);
+ // Go ahead and wield the weapon.
+ if (you.equip[EQ_WEAPON] != -1)
+ unwield_item(you.equip[EQ_WEAPON], show_weff_messages);
- you.equip[EQ_WEAPON] = item_slot;
- }
+ you.equip[EQ_WEAPON] = item_slot;
// any oddness on wielding taken care of here
wield_effects(item_slot, show_weff_messages);
@@ -313,13 +267,77 @@ bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages)
you.time_taken /= 10;
you.wield_change = true;
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return (true);
}
+static const char *shield_base_name(const item_def *shield)
+{
+ return (shield->sub_type == ARM_BUCKLER? "buckler"
+ : "shield");
+}
+
+static const char *shield_impact_degree(int impact)
+{
+ return (impact > 160? "severely " :
+ impact > 130? "significantly " :
+ impact > 110? "" :
+ NULL);
+}
+
+static void warn_rod_shield_interference(const item_def &)
+{
+ const int leakage = rod_shield_leakage();
+ const char *leak_degree = shield_impact_degree(leakage);
+
+ // Any way to avoid the double entendre? :-)
+ if (leak_degree)
+ mprf(MSGCH_WARN,
+ "Your %s %sreduces the effectiveness of your rod.",
+ shield_base_name(player_shield()),
+ leak_degree);
+}
+
+static void warn_launcher_shield_slowdown(const item_def &launcher)
+{
+ const int slowspeed =
+ launcher_final_speed(launcher, player_shield()) * player_speed() / 100;
+ const int normspeed =
+ launcher_final_speed(launcher, NULL) * player_speed() / 100;
+
+ // Don't warn the player unless the slowdown is real.
+ if (slowspeed > normspeed)
+ {
+ const char *slow_degree =
+ shield_impact_degree(slowspeed * 100 / normspeed);
+ if (slow_degree)
+ mprf(MSGCH_WARN,
+ "Your %s %sslows your rate of fire.",
+ shield_base_name(player_shield()),
+ slow_degree);
+ }
+}
+
+// Warn if your shield is greatly impacting the effectiveness of your weapon?
+void warn_shield_penalties()
+{
+ if (!player_shield())
+ return;
+
+ // Warnings are limited to rods and bows at the moment.
+ const item_def *weapon = player_weapon();
+ if (!weapon)
+ return;
+
+ if (item_is_rod(*weapon))
+ warn_rod_shield_interference(*weapon);
+ else if (is_range_weapon(*weapon))
+ warn_launcher_shield_slowdown(*weapon);
+}
+
// provide a function for handling initial wielding of 'special'
-// weapons, or those whose function is annoying to reproduce in
+// weapons, or those whose function is annoying to reproduce in
// other places *cough* auto-butchering *cough* {gdl}
void wield_effects(int item_wield_2, bool showMsgs)
@@ -356,7 +374,7 @@ void wield_effects(int item_wield_2, bool showMsgs)
if (you.inv[item_wield_2].base_type == OBJ_WEAPONS)
{
- if (is_demonic(you.inv[item_wield_2].sub_type)
+ if (is_demonic(you.inv[item_wield_2])
&& (you.religion == GOD_ZIN || you.religion == GOD_SHINING_ONE
|| you.religion == GOD_ELYVILON))
{
@@ -554,6 +572,9 @@ void wield_effects(int item_wield_2, bool showMsgs)
if (item_cursed( you.inv[item_wield_2] ))
mpr("It sticks to your hand!");
}
+
+ if (showMsgs)
+ warn_shield_penalties();
} // end wield_weapon()
//---------------------------------------------------------------
@@ -564,7 +585,7 @@ void wield_effects(int item_wield_2, bool showMsgs)
// something legit.
//
//---------------------------------------------------------------
-bool armour_prompt( const std::string & mesg, int *index )
+bool armour_prompt( const std::string & mesg, int *index, operation_types oper)
{
ASSERT(index != NULL);
@@ -577,7 +598,9 @@ bool armour_prompt( const std::string & mesg, int *index )
canned_msg(MSG_TOO_BERSERK);
else
{
- slot = prompt_invent_item( mesg.c_str(), OBJ_ARMOUR );
+ slot = prompt_invent_item( mesg.c_str(), MT_INVSELECT, OBJ_ARMOUR,
+ true, true, true, 0, NULL,
+ oper );
if (slot != PROMPT_ABORT)
{
@@ -609,43 +632,28 @@ void wear_armour(void)
{
int armour_wear_2;
- if (!armour_prompt("Wear which item?", &armour_wear_2))
+ if (!armour_prompt("Wear which item?", &armour_wear_2, OPER_WEAR))
return;
do_wear_armour( armour_wear_2, false );
}
-int armour_equip_slot(const item_def &item)
+static int armour_equip_delay(const item_def &item)
{
- int wh_equip = EQ_BODY_ARMOUR;
+ int delay = property( item, PARM_AC );
- switch (item.sub_type)
- {
- case ARM_BUCKLER:
- case ARM_LARGE_SHIELD:
- case ARM_SHIELD:
- wh_equip = EQ_SHIELD;
- break;
- case ARM_CLOAK:
- wh_equip = EQ_CLOAK;
- break;
- case ARM_HELMET:
- wh_equip = EQ_HELMET;
- break;
- case ARM_GLOVES:
- wh_equip = EQ_GLOVES;
- break;
- case ARM_BOOTS:
- wh_equip = EQ_BOOTS;
- break;
- }
- return (wh_equip);
+ // Shields are comparatively easy to wear.
+ if (is_shield( item ))
+ delay = delay / 2 + 1;
+
+ if (delay < 1)
+ delay = 1;
+
+ return (delay);
}
bool do_wear_armour( int item, bool quiet )
{
- char wh_equip = 0;
-
if (!is_valid_item( you.inv[item] ))
{
if (!quiet)
@@ -654,7 +662,8 @@ bool do_wear_armour( int item, bool quiet )
return (false);
}
- if (you.inv[item].base_type != OBJ_ARMOUR)
+ const int base_type = you.inv[item].base_type;
+ if (base_type != OBJ_ARMOUR)
{
if (!quiet)
mpr("You can't wear that.");
@@ -662,6 +671,10 @@ bool do_wear_armour( int item, bool quiet )
return (false);
}
+ const int sub_type = you.inv[item].sub_type;
+ const item_def &invitem = you.inv[item];
+ const equipment_type slot = get_armour_slot(invitem);
+
if (item == you.equip[EQ_WEAPON])
{
if (!quiet)
@@ -684,12 +697,10 @@ bool do_wear_armour( int item, bool quiet )
// if you're wielding something,
if (you.equip[EQ_WEAPON] != -1
// attempting to wear a shield,
- && (you.inv[item].sub_type == ARM_SHIELD
- || you.inv[item].sub_type == ARM_BUCKLER
- || you.inv[item].sub_type == ARM_LARGE_SHIELD)
- // weapon is two-handed
- && hands_reqd_for_weapon(you.inv[you.equip[EQ_WEAPON]].base_type,
- you.inv[you.equip[EQ_WEAPON]].sub_type) == HANDS_TWO_HANDED)
+ && is_shield(you.inv[item])
+ && is_shield_incompatible(
+ you.inv[you.equip[EQ_WEAPON]],
+ &you.inv[item]))
{
if (!quiet)
mpr("You'd need three hands to do that!");
@@ -697,21 +708,26 @@ bool do_wear_armour( int item, bool quiet )
return (false);
}
- if (you.inv[item].sub_type == ARM_BOOTS)
- {
- if (you.species != SP_NAGA && you.inv[item].plus2 == TBOOT_NAGA_BARDING)
- {
- if (!quiet)
- mpr("You can't wear that!");
+ bool can_wear = true;
+ if (sub_type == ARM_NAGA_BARDING)
+ can_wear = (you.species == SP_NAGA);
- return (false);
- }
+ if (sub_type == ARM_CENTAUR_BARDING)
+ can_wear = (you.species == SP_CENTAUR);
+
+ if (!can_wear)
+ {
+ if (!quiet)
+ mpr("You can't wear that!");
+ return (false);
+ }
- if (you.species != SP_CENTAUR && you.inv[item].plus2 == TBOOT_CENTAUR_BARDING)
+ if (you.inv[item].sub_type == ARM_BOOTS)
+ {
+ if (you.species == SP_NAGA || you.species == SP_CENTAUR)
{
if (!quiet)
- mpr("You can't wear that!");
-
+ mpr("You can't wear that!");
return (false);
}
@@ -724,28 +740,24 @@ bool do_wear_armour( int item, bool quiet )
}
}
- wh_equip = armour_equip_slot(you.inv[item]);
-
- if (you.species == SP_NAGA && you.inv[item].sub_type == ARM_BOOTS
- && you.inv[item].plus2 == TBOOT_NAGA_BARDING
+ if (you.species == SP_NAGA && sub_type == ARM_NAGA_BARDING
&& !player_is_shapechanged())
{
// it fits
}
else if (you.species == SP_CENTAUR
- && you.inv[item].sub_type == ARM_BOOTS
- && you.inv[item].plus2 == TBOOT_CENTAUR_BARDING
+ && sub_type == ARM_CENTAUR_BARDING
&& !player_is_shapechanged())
{
// it fits
}
- else if (you.inv[item].sub_type == ARM_HELMET
- && (cmp_helmet_type( you.inv[item], THELM_CAP )
- || cmp_helmet_type( you.inv[item], THELM_WIZARD_HAT )))
+ else if (sub_type == ARM_HELMET
+ && (get_helmet_type(invitem) == THELM_CAP
+ || get_helmet_type(invitem) == THELM_WIZARD_HAT))
{
// caps & wiz hats always fit, unless your head's too big (ogres &c)
}
- else if (!can_equip( wh_equip ))
+ else if (!can_equip( slot ))
{
if (!quiet)
mpr("You can't wear that in your present form.");
@@ -755,8 +767,8 @@ bool do_wear_armour( int item, bool quiet )
// Cannot swim in heavy armour
if (player_is_swimming()
- && wh_equip == EQ_BODY_ARMOUR
- && !is_light_armour( you.inv[item] ))
+ && slot == EQ_BODY_ARMOUR
+ && !is_light_armour( invitem ))
{
if (!quiet)
mpr("You can't swim in that!");
@@ -768,14 +780,14 @@ bool do_wear_armour( int item, bool quiet )
if ((you.species >= SP_OGRE && you.species <= SP_OGRE_MAGE)
|| player_genus(GENPC_DRACONIAN))
{
- if ((you.inv[item].sub_type >= ARM_LEATHER_ARMOUR
- && you.inv[item].sub_type <= ARM_PLATE_MAIL)
- || (you.inv[item].sub_type >= ARM_GLOVES
- && you.inv[item].sub_type <= ARM_BUCKLER)
- || you.inv[item].sub_type == ARM_CRYSTAL_PLATE_MAIL
- || (you.inv[item].sub_type == ARM_HELMET
- && (cmp_helmet_type( you.inv[item], THELM_HELM )
- || cmp_helmet_type( you.inv[item], THELM_HELMET ))))
+ if ((sub_type >= ARM_LEATHER_ARMOUR
+ && sub_type <= ARM_PLATE_MAIL)
+ || (sub_type >= ARM_GLOVES
+ && sub_type <= ARM_BUCKLER)
+ || sub_type == ARM_CRYSTAL_PLATE_MAIL
+ || (sub_type == ARM_HELMET
+ && (get_helmet_type(invitem) == THELM_HELM
+ || get_helmet_type(invitem) == THELM_HELMET)))
{
if (!quiet)
mpr("This armour doesn't fit on your body.");
@@ -787,16 +799,16 @@ bool do_wear_armour( int item, bool quiet )
// Tiny races
if (you.species == SP_SPRIGGAN)
{
- if ((you.inv[item].sub_type >= ARM_LEATHER_ARMOUR
- && you.inv[item].sub_type <= ARM_PLATE_MAIL)
- || you.inv[item].sub_type == ARM_GLOVES
- || you.inv[item].sub_type == ARM_BOOTS
- || you.inv[item].sub_type == ARM_SHIELD
- || you.inv[item].sub_type == ARM_LARGE_SHIELD
- || you.inv[item].sub_type == ARM_CRYSTAL_PLATE_MAIL
- || (you.inv[item].sub_type == ARM_HELMET
- && (cmp_helmet_type( you.inv[item], THELM_HELM )
- || cmp_helmet_type( you.inv[item], THELM_HELMET ))))
+ if ((sub_type >= ARM_LEATHER_ARMOUR
+ && sub_type <= ARM_PLATE_MAIL)
+ || sub_type == ARM_GLOVES
+ || sub_type == ARM_BOOTS
+ || sub_type == ARM_SHIELD
+ || sub_type == ARM_LARGE_SHIELD
+ || sub_type == ARM_CRYSTAL_PLATE_MAIL
+ || (sub_type == ARM_HELMET
+ && (get_helmet_type(invitem) == THELM_HELM
+ || get_helmet_type(invitem) == THELM_HELMET)))
{
if (!quiet)
mpr("This armour doesn't fit on your body.");
@@ -808,11 +820,10 @@ bool do_wear_armour( int item, bool quiet )
bool removedCloak = false;
int cloak = -1;
- if ((you.inv[item].sub_type < ARM_SHIELD
- || you.inv[item].sub_type > ARM_LARGE_SHIELD)
- && (you.equip[EQ_CLOAK] != -1 && !cloak_is_being_removed()))
+ if (slot == EQ_BODY_ARMOUR
+ && you.equip[EQ_CLOAK] != -1 && !cloak_is_being_removed())
{
- if (item_uncursed( you.inv[you.equip[EQ_CLOAK]] ))
+ if (!item_cursed( you.inv[you.equip[EQ_CLOAK]] ))
{
cloak = you.equip[ EQ_CLOAK ];
if (!takeoff_armour(you.equip[EQ_CLOAK]))
@@ -829,54 +840,45 @@ bool do_wear_armour( int item, bool quiet )
}
}
- if (you.inv[item].sub_type == ARM_CLOAK && you.equip[EQ_CLOAK] != -1)
+ if (slot == EQ_CLOAK && you.equip[EQ_CLOAK] != -1)
{
if (!takeoff_armour(you.equip[EQ_CLOAK]))
return (false);
}
- if (you.inv[item].sub_type == ARM_HELMET && you.equip[EQ_HELMET] != -1)
+ if (slot == EQ_HELMET && you.equip[EQ_HELMET] != -1)
{
if (!takeoff_armour(you.equip[EQ_HELMET]))
return (false);
}
- if (you.inv[item].sub_type == ARM_GLOVES && you.equip[EQ_GLOVES] != -1)
+ if (slot == EQ_GLOVES && you.equip[EQ_GLOVES] != -1)
{
if (!takeoff_armour(you.equip[EQ_GLOVES]))
return (false);
}
- if (you.inv[item].sub_type == ARM_BOOTS && you.equip[EQ_BOOTS] != -1)
+ if (slot == EQ_BOOTS && you.equip[EQ_BOOTS] != -1)
{
if (!takeoff_armour(you.equip[EQ_BOOTS]))
return (false);
}
- if ((you.inv[item].sub_type == ARM_SHIELD
- || you.inv[item].sub_type == ARM_LARGE_SHIELD
- || you.inv[item].sub_type == ARM_BUCKLER)
- && you.equip[EQ_SHIELD] != -1)
+ if (slot == EQ_SHIELD && you.equip[EQ_SHIELD] != -1)
{
if (!takeoff_armour(you.equip[EQ_SHIELD]))
return (false);
}
- if ((you.inv[item].sub_type < ARM_SHIELD
- || you.inv[item].sub_type > ARM_LARGE_SHIELD)
- && you.equip[EQ_BODY_ARMOUR] != -1)
+ if (slot == EQ_BODY_ARMOUR && you.equip[EQ_BODY_ARMOUR] != -1)
{
if (!takeoff_armour(you.equip[EQ_BODY_ARMOUR]))
return (false);
}
- you.turn_is_over = 1;
-
- int delay = property( you.inv[item], PARM_AC );
-
- if (delay < 1)
- delay = 1;
+ you.turn_is_over = true;
+ int delay = armour_equip_delay( you.inv[item] );
if (delay)
start_delay( DELAY_ARMOUR_ON, delay, item );
@@ -910,13 +912,13 @@ bool takeoff_armour(int item)
bool removedCloak = false;
int cloak = -1;
+ const equipment_type slot = get_armour_slot(you.inv[item]);
- if (you.inv[item].sub_type < ARM_SHIELD
- || you.inv[item].sub_type > ARM_LARGE_SHIELD)
+ if (slot == EQ_BODY_ARMOUR)
{
if (you.equip[EQ_CLOAK] != -1 && !cloak_is_being_removed())
{
- if (item_uncursed( you.inv[you.equip[EQ_CLOAK]] ))
+ if (!item_cursed( you.inv[you.equip[EQ_CLOAK]] ))
{
cloak = you.equip[ EQ_CLOAK ];
if (!takeoff_armour(you.equip[EQ_CLOAK]))
@@ -941,11 +943,9 @@ bool takeoff_armour(int item)
}
else
{
- switch (you.inv[item].sub_type)
+ switch (slot)
{
- case ARM_BUCKLER:
- case ARM_LARGE_SHIELD:
- case ARM_SHIELD:
+ case EQ_SHIELD:
if (item != you.equip[EQ_SHIELD])
{
mpr("You aren't wearing that!");
@@ -953,7 +953,7 @@ bool takeoff_armour(int item)
}
break;
- case ARM_CLOAK:
+ case EQ_CLOAK:
if (item != you.equip[EQ_CLOAK])
{
mpr("You aren't wearing that!");
@@ -961,7 +961,7 @@ bool takeoff_armour(int item)
}
break;
- case ARM_HELMET:
+ case EQ_HELMET:
if (item != you.equip[EQ_HELMET])
{
mpr("You aren't wearing that!");
@@ -969,8 +969,7 @@ bool takeoff_armour(int item)
}
break;
-
- case ARM_GLOVES:
+ case EQ_GLOVES:
if (item != you.equip[EQ_GLOVES])
{
mpr("You aren't wearing that!");
@@ -978,23 +977,22 @@ bool takeoff_armour(int item)
}
break;
- case ARM_BOOTS:
+ case EQ_BOOTS:
if (item != you.equip[EQ_BOOTS])
{
mpr("You aren't wearing that!");
return false;
}
break;
+
+ default:
+ break;
}
}
- you.turn_is_over = 1;
-
- int delay = property( you.inv[item], PARM_AC );
-
- if (delay < 1)
- delay = 1;
+ you.turn_is_over = true;
+ int delay = armour_equip_delay( you.inv[item] );
start_delay( DELAY_ARMOUR_OFF, delay, item );
if (removedCloak)
@@ -1019,7 +1017,9 @@ void throw_anything(void)
return;
}
- throw_slot = prompt_invent_item( "Throw which item?", OBJ_MISSILES );
+ throw_slot = prompt_invent_item( "Throw which item?", MT_INVSELECT,
+ OBJ_MISSILES, true, true, true, 0, NULL,
+ OPER_THROW );
if (throw_slot == PROMPT_ABORT)
{
canned_msg( MSG_OK );
@@ -1108,9 +1108,9 @@ int get_fire_item_index( void )
// check if we have ammo for a wielded launcher:
if (weapon != -1
&& you.inv[ weapon ].base_type == OBJ_WEAPONS
- && launches_things( you.inv[ weapon ].sub_type ))
+ && is_range_weapon( you.inv[ weapon ] ))
{
- int type_wanted = launched_by( you.inv[ weapon ].sub_type );
+ int type_wanted = fires_ammo_type( you.inv[ weapon ] );
item = try_finding_missile( type_wanted );
}
break;
@@ -1179,9 +1179,103 @@ void shoot_thing(void)
throw_it( beam, item );
} // end shoot_thing()
+// Returns delay multiplier numerator (denominator should be 100) for the
+// launcher with the currently equipped shield.
+int launcher_shield_slowdown(const item_def &launcher, const item_def *shield)
+{
+ int speed_adjust = 100;
+ if (!shield)
+ return (speed_adjust);
+
+ const int shield_type = shield->sub_type;
+ hands_reqd_type hands = hands_reqd(launcher, player_size());
+
+ switch (hands)
+ {
+ default:
+ case HANDS_ONE:
+ case HANDS_HALF:
+ speed_adjust = shield_type == ARM_BUCKLER ? 105 :
+ shield_type == ARM_SHIELD ? 125 :
+ 150;
+ break;
+
+ case HANDS_TWO:
+ speed_adjust = shield_type == ARM_BUCKLER ? 125 :
+ shield_type == ARM_SHIELD ? 150 :
+ 200;
+ break;
+ }
+
+ // Adjust for shields skill.
+ if (speed_adjust > 100)
+ speed_adjust -= ((speed_adjust - 100) * 5 / 10)
+ * you.skills[SK_SHIELDS] / 27;
+
+ return (speed_adjust);
+}
+
+// Returns the attack cost of using the launcher, taking skill and shields
+// into consideration. NOTE: You must pass in the shield; if you send in
+// NULL, this function assumes no shield is in use.
+int launcher_final_speed(const item_def &launcher, const item_def *shield)
+{
+ const int str_weight = weapon_str_weight( launcher );
+ const int dex_weight = 10 - str_weight;
+ const skill_type launcher_skill = range_skill( launcher );
+ const int shoot_skill = you.skills[launcher_skill];
+ const int bow_brand = get_weapon_brand( launcher );
+
+ int speed_base = 10 * property( launcher, PWPN_SPEED );
+ int speed_min = 70;
+ int speed_stat = str_weight * you.strength + dex_weight * you.dex;
+
+ // Reduce runaway bow overpoweredness.
+ if (launcher_skill == SK_BOWS)
+ speed_min = 60;
+
+ if (shield)
+ {
+ const int speed_adjust = launcher_shield_slowdown(launcher, shield);
+
+ // Shields also reduce the speed cap.
+ speed_base = speed_base * speed_adjust / 100;
+ speed_min = speed_min * speed_adjust / 100;
+ }
+
+ int speed = speed_base - 4 * shoot_skill * speed_stat / 250;
+ if (speed < speed_min)
+ speed = speed_min;
+
+ if (bow_brand == SPWPN_SPEED)
+ {
+ // Speed nerf as per 4.1. Even with the nerf, bows of speed are the
+ // best bows, bar none.
+ speed = 2 * speed / 3;
+ }
+
+ return (speed);
+}
+
+// Determines if the end result of the combined launcher + ammo brands a
+// fire/frost beam.
+bool elemental_missile_beam(int launcher_brand, int ammo_brand)
+{
+ int element = (launcher_brand == SPWPN_FROST)
+ + (ammo_brand == SPMSL_ICE)
+ - (launcher_brand == SPWPN_FLAME)
+ - (ammo_brand == SPMSL_FLAME);
+ return (element);
+}
+
// throw_it - currently handles player throwing only. Monster
// throwing is handled in mstuff2:mons_throw()
-static void throw_it(struct bolt &pbolt, int throw_2)
+// Note: If dummy_target is non-NULL, throw_it fakes a bolt and calls
+// affect() on the monster's square.
+//
+// Return value is only relevant if dummy_target is non-NULL, and returns
+// true if dummy_target is hit.
+bool throw_it(struct bolt &pbolt, int throw_2, monsters *dummy_target)
{
struct dist thr;
char shoot_skill = 0;
@@ -1194,31 +1288,50 @@ static void throw_it(struct bolt &pbolt, int throw_2)
int lnchHitBonus = 0, lnchDamBonus = 0; // special add from launcher
int exHitBonus = 0, exDamBonus = 0; // 'extra' bonus from skill/dex/str
int effSkill = 0; // effective launcher skill
+ int dice_mult = 100;
bool launched = false; // item is launched
bool thrown = false; // item is sensible thrown item
+ int slayDam = 0;
- // Making a copy of the item: changed only for venom launchers
- item_def item = you.inv[throw_2];
- item.quantity = 1;
- item.slot = index_to_letter(item.link);
- origin_set_unknown(item);
-
- char str_pass[ ITEMNAME_SIZE ];
-
- mpr( STD_DIRECTION_PROMPT, MSGCH_PROMPT );
-
- message_current_target();
-
- direction( thr, DIR_NONE, TARG_ENEMY );
+ if (dummy_target)
+ {
+ thr.isValid = true;
+ thr.isCancel = false;
+ thr.tx = dummy_target->x;
+ thr.ty = dummy_target->y;
+ }
+ else
+ {
+ mpr( STD_DIRECTION_PROMPT, MSGCH_PROMPT );
+ message_current_target();
+ direction( thr, DIR_NONE, TARG_ENEMY );
+ }
if (!thr.isValid)
{
if (thr.isCancel)
canned_msg(MSG_OK);
- return;
+ return (false);
+ }
+
+ // Must unwield before fire_beam() makes a copy in order to remove things
+ // like temporary branding. -- bwr
+ if (throw_2 == you.equip[EQ_WEAPON] && you.inv[throw_2].quantity == 1)
+ {
+ unwield_item( throw_2 );
+ you.equip[EQ_WEAPON] = -1;
+ canned_msg( MSG_EMPTY_HANDED );
}
+ // Making a copy of the item: changed only for venom launchers
+ item_def item = you.inv[throw_2];
+ item.quantity = 1;
+ item.slot = index_to_letter(item.link);
+ origin_set_unknown(item);
+
+ char str_pass[ ITEMNAME_SIZE ];
+
if (you.conf)
{
thr.isTarget = true;
@@ -1226,10 +1339,9 @@ static void throw_it(struct bolt &pbolt, int throw_2)
thr.ty = you.y_pos + random2(13) - 6;
}
- // even though direction is allowed, we're throwing so we
+ // even though direction is allowed, we're throwing so we
// want to use tx, ty to make the missile fly to map edge.
- pbolt.target_x = thr.tx;
- pbolt.target_y = thr.ty;
+ pbolt.set_target(thr);
pbolt.flavour = BEAM_MISSILE;
// pbolt.range is set below
@@ -1257,10 +1369,10 @@ static void throw_it(struct bolt &pbolt, int throw_2)
pbolt.colour = item.colour;
item_name( item, DESC_PLAIN, str_pass );
- strcpy( pbolt.beam_name, str_pass );
+ pbolt.name = str_pass;
pbolt.thrower = KILL_YOU_MISSILE;
- pbolt.aux_source = NULL;
+ pbolt.aux_source.clear();
// get the ammo/weapon type. Convenience.
wepClass = item.base_type;
@@ -1281,11 +1393,11 @@ static void throw_it(struct bolt &pbolt, int throw_2)
}
// baseHit and damage for generic objects
- baseHit = you.strength - mass_item(item) / 10;
+ baseHit = you.strength - item_mass(item) / 10;
if (baseHit > 0)
baseHit = 0;
- baseDam = mass_item(item) / 100;
+ baseDam = item_mass(item) / 100;
// special: might be throwing generic weapon;
// use base wep. damage, w/ penalty
@@ -1313,21 +1425,49 @@ static void throw_it(struct bolt &pbolt, int throw_2)
// CALCULATIONS FOR LAUNCHED WEAPONS
if (launched)
{
- const int bow_brand = get_weapon_brand( you.inv[you.equip[EQ_WEAPON]] );
+ const item_def &launcher = you.inv[you.equip[EQ_WEAPON]];
+ const int bow_brand = get_weapon_brand( launcher );
const int ammo_brand = get_ammo_brand( item );
bool poisoned = (ammo_brand == SPMSL_POISONED
|| ammo_brand == SPMSL_POISONED_II);
+ const int rc_skill = you.skills[SK_RANGED_COMBAT];
- // this is deliberately confusing: the 'hit' value for
- // ammo is the _damage_ when used with a launcher. Geez.
- baseHit = 0;
- baseDam = property( item, PWPN_HIT );
+ const int item_base_dam = property( item, PWPN_DAMAGE );
+ const int lnch_base_dam = property( launcher, PWPN_DAMAGE );
+
+ const skill_type launcher_skill = range_skill( launcher );
+
+ baseHit = property( launcher, PWPN_HIT );
+ baseDam = lnch_base_dam + random2(1 + item_base_dam);
+
+ // Slings are terribly weakened otherwise
+ if (lnch_base_dam == 0)
+ baseDam = item_base_dam;
+
+ // If we've a zero base damage + an elemental brand, up the damage
+ // slightly so the brand has something to work with. This should
+ // only apply to needles.
+ if (!baseDam && elemental_missile_beam(bow_brand, ammo_brand))
+ baseDam = 4;
+
+ // [dshaligram] This is a horrible hack - we force beam.cc to consider
+ // this beam "needle-like".
+ if (wepClass == OBJ_MISSILES && wepType == MI_NEEDLE)
+ pbolt.ench_power = AUTOMATIC_HIT;
+
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS,
+ "Base hit == %d; Base damage == %d "
+ "(item %d + launcher %d)",
+ baseHit, baseDam,
+ item_base_dam, lnch_base_dam);
+#endif
// fix ammo damage bonus, since missiles only use inv_plus
ammoDamBonus = ammoHitBonus;
// check for matches; dwarven,elven,orcish
- if (!cmp_equip_race( you.inv[you.equip[EQ_WEAPON]], 0 ))
+ if (!get_equip_race(you.inv[you.equip[EQ_WEAPON]]) == 0)
{
if (get_equip_race( you.inv[you.equip[EQ_WEAPON]] )
== get_equip_race( item ))
@@ -1336,7 +1476,8 @@ static void throw_it(struct bolt &pbolt, int throw_2)
baseDam += 1;
// elves with elven bows
- if (cmp_equip_race(you.inv[you.equip[EQ_WEAPON]], ISFLAG_ELVEN)
+ if (get_equip_race(you.inv[you.equip[EQ_WEAPON]])
+ == ISFLAG_ELVEN
&& player_genus(GENPC_ELVEN))
{
baseHit += 1;
@@ -1344,86 +1485,78 @@ static void throw_it(struct bolt &pbolt, int throw_2)
}
}
- if (you.inv[you.equip[EQ_WEAPON]].sub_type == WPN_CROSSBOW)
- {
- // extra time taken, as a percentage. range from 30 -> 12
- int extraTime = 30 - ((you.skills[SK_CROSSBOWS] * 2) / 3);
-
- you.time_taken = (100 + extraTime) * you.time_taken;
- you.time_taken /= 100;
- }
-
- if (bow_brand == SPWPN_SPEED)
- {
- you.time_taken *= 5;
- you.time_taken /= 10;
- }
-
- // for all launched weapons, maximum effective specific skill
+ // for all launched weapons, maximum effective specific skill
// is twice throwing skill. This models the fact that no matter
- // how 'good' you are with a bow, if you know nothing about
+ // how 'good' you are with a bow, if you know nothing about
// trajectories you're going to be a damn poor bowman. Ditto
// for crossbows and slings.
- switch (lnchType)
- {
- case WPN_SLING:
- shoot_skill = you.skills[SK_SLINGS];
- break;
- case WPN_BOW:
- shoot_skill = you.skills[SK_BOWS];
- break;
- case WPN_BLOWGUN:
- shoot_skill = you.skills[SK_DARTS];
- break;
- case WPN_CROSSBOW:
- case WPN_HAND_CROSSBOW:
- shoot_skill = you.skills[SK_CROSSBOWS];
- break;
- default:
- shoot_skill = 0;
- break;
- }
- effSkill = you.skills[SK_THROWING] * 2 + 1;
- effSkill = (shoot_skill > effSkill) ? effSkill : shoot_skill;
+ // [dshaligram] Throwing now two parts launcher skill, one part
+ // ranged combat. Removed the old model which is... silly.
+
+ shoot_skill = you.skills[launcher_skill];
+ effSkill = (shoot_skill * 2 + rc_skill) / 3;
+
+ const int speed = launcher_final_speed(launcher, player_shield());
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Final launcher speed: %d", speed);
+#endif
+ you.time_taken = speed * you.time_taken / 100;
+
+ // effSkill = you.skills[SK_RANGED_COMBAT] * 2 + 1;
+ // effSkill = (shoot_skill > effSkill) ? effSkill : shoot_skill;
+
+ // [dshaligram] Improving missile weapons:
+ // - Remove the strength/enchantment cap where you need to be strong
+ // to exploit a launcher bonus.
+ // - Add on launcher and missile pluses to extra damage.
+
+ // [dshaligram] This can get large...
+ exDamBonus = lnchDamBonus + random2(1 + ammoDamBonus);
+ exDamBonus = exDamBonus > 0? random2(exDamBonus + 1)
+ : -random2(-exDamBonus + 1);
+ exHitBonus = lnchHitBonus > 0? random2(lnchHitBonus + 1)
+ : -random2(-lnchHitBonus + 1);
// removed 2 random2(2)s from each of the learning curves, but
// left slings because they're hard enough to develop without
// a good source of shot in the dungeon.
- switch (lnchType)
+ switch (launcher_skill)
+ {
+ case SK_SLINGS:
{
- case WPN_SLING:
// Slings are really easy to learn because they're not
// really all that good, and its harder to get ammo anyways.
exercise(SK_SLINGS, 1 + random2avg(3, 2));
baseHit += 0;
- exHitBonus = (effSkill * 3) / 2;
+ exHitBonus += (effSkill * 3) / 2;
// strength is good if you're using a nice sling.
- exDamBonus = (10 * (you.strength - 10)) / 9;
- exDamBonus = (exDamBonus * (2 * baseDam + ammoDamBonus)) / 20;
+ int strbonus = (10 * (you.strength - 10)) / 9;
+ strbonus = (strbonus * (2 * baseDam + ammoDamBonus)) / 20;
// cap
- if (exDamBonus > lnchDamBonus + 1)
- exDamBonus = lnchDamBonus + 1;
+ if (strbonus > lnchDamBonus + 1)
+ strbonus = lnchDamBonus + 1;
+ exDamBonus += strbonus;
// add skill for slings.. helps to find those vulnerable spots
- exDamBonus += effSkill / 2;
+ dice_mult = dice_mult * (14 + random2(1 + effSkill)) / 14;
// now kill the launcher damage bonus
if (lnchDamBonus > 0)
lnchDamBonus = 0;
break;
-
+ }
// blowguns take a _very_ steady hand; a lot of the bonus
// comes from dexterity. (Dex bonus here as well as below)
- case WPN_BLOWGUN:
- exercise(SK_DARTS, (coinflip()? 2 : 1));
+ case SK_DARTS:
baseHit -= 2;
- exHitBonus = (effSkill * 3) / 2 + you.dex / 2;
+ exercise(SK_DARTS, (coinflip()? 2 : 1));
+ exHitBonus += (effSkill * 3) / 2 + you.dex / 2;
// no extra damage for blowguns
- exDamBonus = 0;
+ // exDamBonus = 0;
// now kill the launcher damage and ammo bonuses
if (lnchDamBonus > 0)
@@ -1432,52 +1565,70 @@ static void throw_it(struct bolt &pbolt, int throw_2)
ammoDamBonus = 0;
break;
-
- case WPN_BOW:
+ case SK_BOWS:
+ {
+ baseHit -= 3;
exercise(SK_BOWS, (coinflip()? 2 : 1));
- baseHit -= 4;
- exHitBonus = (effSkill * 2);
+ exHitBonus += (effSkill * 2);
// strength is good if you're using a nice bow
- exDamBonus = (10 * (you.strength - 10)) / 4;
- exDamBonus = (exDamBonus * (2 * baseDam + ammoDamBonus)) / 20;
+ int strbonus = (10 * (you.strength - 10)) / 4;
+ strbonus = (strbonus * (2 * baseDam + ammoDamBonus)) / 20;
- // cap
- if (exDamBonus > (lnchDamBonus + 1) * 3)
- exDamBonus = (lnchDamBonus + 1) * 3;
+ // cap; reduced this cap, because we don't want to allow
+ // the extremely-strong to quadruple the enchantment bonus.
+ if (strbonus > lnchDamBonus + 1)
+ strbonus = lnchDamBonus + 1;
+
+ exDamBonus += strbonus;
// add in skill for bows.. help you to find those vulnerable spots.
- exDamBonus += effSkill;
+ // exDamBonus += effSkill;
+
+ dice_mult = dice_mult * (17 + random2(1 + effSkill)) / 17;
// now kill the launcher damage bonus
if (lnchDamBonus > 0)
lnchDamBonus = 0;
break;
-
+ }
// Crossbows are easy for unskilled people.
- case WPN_CROSSBOW:
+ case SK_CROSSBOWS:
exercise(SK_CROSSBOWS, (coinflip()? 2 : 1));
- baseHit += 2;
- exHitBonus = (3 * effSkill) / 2 + 6;
- exDamBonus = effSkill / 2 + 4;
+ baseHit++;
+ exHitBonus += (3 * effSkill) / 2 + 6;
+ // exDamBonus += effSkill * 2 / 3 + 4;
+
+ dice_mult = dice_mult * (22 + random2(1 + effSkill)) / 22;
+
+ if (lnchType == WPN_HAND_CROSSBOW)
+ {
+ exHitBonus -= 2;
+ dice_mult = dice_mult * 26 / 30;
+ }
break;
- case WPN_HAND_CROSSBOW:
- exercise(SK_CROSSBOWS, (coinflip()? 2 : 1));
- baseHit += 1;
- exHitBonus = (3 * effSkill) / 2 + 4;
- exDamBonus = effSkill / 2 + 2;
+ default:
break;
}
// all launched weapons have a slight chance of improving
// throwing skill
if (coinflip())
- exercise(SK_THROWING, 1);
+ exercise(SK_RANGED_COMBAT, 1);
+
+ // all launched weapons get a minor tohit boost from throwing skill.
+ exHitBonus += you.skills[SK_RANGED_COMBAT] / 5;
- // all launched weapons get a tohit boost from throwing skill.
- exHitBonus += (3 * you.skills[SK_THROWING]) / 4;
+ if (bow_brand == SPWPN_VORPAL)
+ {
+ // Vorpal brand adds 30% damage bonus. Increased from 25%
+ // because at 25%, vorpal brand is completely inferior to
+ // speed. At 30% it's marginally better than speed when
+ // fighting monsters with very heavy armour.
+ dice_mult = dice_mult * 130 / 100;
+ }
// special cases for flame, frost, poison, etc.
// check for venom brand (usually only available for blowguns)
@@ -1486,25 +1637,27 @@ static void throw_it(struct bolt &pbolt, int throw_2)
// poison brand the ammo
set_item_ego_type( item, OBJ_MISSILES, SPMSL_POISONED );
item_name( item, DESC_PLAIN, str_pass );
- strcpy( pbolt.beam_name, str_pass );
+ pbolt.name = str_pass;
}
// Note that bow_brand is known since the bow is equiped.
if ((bow_brand == SPWPN_FLAME || ammo_brand == SPMSL_FLAME)
&& ammo_brand != SPMSL_ICE && bow_brand != SPWPN_FROST)
{
- baseDam += 1 + random2(5);
+ // [dshaligram] Branded arrows are much stronger.
+ dice_mult = dice_mult * 150 / 100;
+
pbolt.flavour = BEAM_FIRE;
- strcpy(pbolt.beam_name, "bolt of ");
+ pbolt.name = "bolt of ";
if (poisoned)
- strcat(pbolt.beam_name, "poison ");
+ pbolt.name += "poison ";
- strcat(pbolt.beam_name, "flame");
+ pbolt.name += "flame";
pbolt.colour = RED;
pbolt.type = SYM_BOLT;
pbolt.thrower = KILL_YOU_MISSILE;
- pbolt.aux_source = NULL;
+ pbolt.aux_source.clear();
// ammo known if we can't attribute it to the bow
if (bow_brand != SPWPN_FLAME)
@@ -1517,18 +1670,20 @@ static void throw_it(struct bolt &pbolt, int throw_2)
if ((bow_brand == SPWPN_FROST || ammo_brand == SPMSL_ICE)
&& ammo_brand != SPMSL_FLAME && bow_brand != SPWPN_FLAME)
{
- baseDam += 1 + random2(5);
+ // [dshaligram] Branded arrows are much stronger.
+ dice_mult = dice_mult * 150 / 100;
+
pbolt.flavour = BEAM_COLD;
- strcpy(pbolt.beam_name, "bolt of ");
+ pbolt.name = "bolt of ";
if (poisoned)
- strcat(pbolt.beam_name, "poison ");
+ pbolt.name += "poison ";
- strcat(pbolt.beam_name, "frost");
+ pbolt.name += "frost";
pbolt.colour = WHITE;
pbolt.type = SYM_BOLT;
pbolt.thrower = KILL_YOU_MISSILE;
- pbolt.aux_source = NULL;
+ pbolt.aux_source.clear();
// ammo known if we can't attribute it to the bow
if (bow_brand != SPWPN_FROST)
@@ -1554,8 +1709,19 @@ static void throw_it(struct bolt &pbolt, int throw_2)
* and vice versa */
// ID check
- if (item_not_ident( you.inv[you.equip[EQ_WEAPON]], ISFLAG_KNOW_PLUSES )
- && random2(100) < shoot_skill)
+ if (item_ident(you.inv[you.equip[EQ_WEAPON]], ISFLAG_KNOW_PLUSES))
+ {
+ if ( !item_ident(you.inv[throw_2], ISFLAG_KNOW_PLUSES) &&
+ random2(100) < rc_skill )
+ {
+ set_ident_flags( item, ISFLAG_KNOW_PLUSES );
+ set_ident_flags( you.inv[throw_2], ISFLAG_KNOW_PLUSES );
+ in_name( throw_2, DESC_NOCAP_A, str_pass);
+ snprintf(info, INFO_SIZE, "You are firing %s.", str_pass);
+ mpr(info);
+ }
+ }
+ else if (random2(100) < shoot_skill)
{
set_ident_flags(you.inv[you.equip[EQ_WEAPON]], ISFLAG_KNOW_PLUSES);
@@ -1568,6 +1734,7 @@ static void throw_it(struct bolt &pbolt, int throw_2)
more();
you.wield_change = true;
}
+
}
// CALCULATIONS FOR THROWN WEAPONS
@@ -1584,7 +1751,8 @@ static void throw_it(struct bolt &pbolt, int throw_2)
|| (wepClass == OBJ_MISSILES && wepType == MI_STONE))
{
// elves with elven weapons
- if (cmp_equip_race(item, ISFLAG_ELVEN) && player_genus(GENPC_ELVEN))
+ if (get_equip_race(item) == ISFLAG_ELVEN
+ && player_genus(GENPC_ELVEN))
baseHit += 1;
// give an appropriate 'tohit' -
@@ -1608,14 +1776,14 @@ static void throw_it(struct bolt &pbolt, int throw_2)
}
}
- exHitBonus = you.skills[SK_THROWING] * 2;
+ exHitBonus = you.skills[SK_RANGED_COMBAT] * 2;
baseDam = property( item, PWPN_DAMAGE );
exDamBonus =
- (10 * (you.skills[SK_THROWING] / 2 + you.strength - 10)) / 12;
+ (10 * (you.skills[SK_RANGED_COMBAT] / 2 + you.strength - 10)) / 12;
// now, exDamBonus is a multiplier. The full multiplier
- // is applied to base damage, but only a third is applied
+ // is applied to base damage, but only a third is applied
// to the magical modifier.
exDamBonus = (exDamBonus * (3 * baseDam + ammoDamBonus)) / 30;
}
@@ -1627,16 +1795,35 @@ static void throw_it(struct bolt &pbolt, int throw_2)
baseDam = property( item, PWPN_DAMAGE );
exHitBonus = you.skills[SK_DARTS] * 2;
- exHitBonus += (you.skills[SK_THROWING] * 2) / 3;
- exDamBonus = you.skills[SK_DARTS] / 4;
+ exHitBonus += (you.skills[SK_RANGED_COMBAT] * 2) / 3;
+ exDamBonus = you.skills[SK_DARTS] / 3;
+ exDamBonus += you.skills[SK_RANGED_COMBAT] / 5;
// exercise skills
exercise(SK_DARTS, 1 + random2avg(3, 2));
}
+ // [dshaligram] The defined base damage applies only when used
+ // for launchers. Hand-thrown stones and darts do only half
+ // base damage. Yet another evil 4.0ism.
+ if (wepClass == OBJ_MISSILES
+ && (wepType == MI_DART || wepType == MI_STONE))
+ baseDam = div_rand_round(baseDam, 2);
+
// exercise skill
if (coinflip())
- exercise(SK_THROWING, 1);
+ exercise(SK_RANGED_COMBAT, 1);
+
+ // ID check
+ if ( !item_ident(you.inv[throw_2], ISFLAG_KNOW_PLUSES) &&
+ random2(100) < you.skills[SK_RANGED_COMBAT] )
+ {
+ set_ident_flags( item, ISFLAG_KNOW_PLUSES );
+ set_ident_flags( you.inv[throw_2], ISFLAG_KNOW_PLUSES );
+ in_name( throw_2, DESC_NOCAP_A, str_pass);
+ snprintf(info, INFO_SIZE, "You are throwing %s.", str_pass);
+ mpr(info);
+ }
}
// range, dexterity bonus, possible skill increase for silly throwing
@@ -1659,7 +1846,11 @@ static void throw_it(struct bolt &pbolt, int throw_2)
// slaying bonuses
if (!(launched && wepType == MI_NEEDLE))
- exDamBonus += slaying_bonus(PWPN_DAMAGE);
+ {
+ slayDam = slaying_bonus(PWPN_DAMAGE);
+ slayDam = slayDam < 0? -random2(1 - slayDam)
+ : random2(1 + slayDam);
+ }
exHitBonus += slaying_bonus(PWPN_HIT);
}
@@ -1667,7 +1858,7 @@ static void throw_it(struct bolt &pbolt, int throw_2)
else
{
// range based on mass & strength, between 1 and 9
- pbolt.range = you.strength - mass_item(item) / 10 + 3;
+ pbolt.range = you.strength - item_mass(item) / 10 + 3;
if (pbolt.range < 1)
pbolt.range = 1;
@@ -1678,9 +1869,22 @@ static void throw_it(struct bolt &pbolt, int throw_2)
pbolt.rangeMax = pbolt.range;
if (one_chance_in(20))
- exercise(SK_THROWING, 1);
+ exercise(SK_RANGED_COMBAT, 1);
exHitBonus = you.dex / 4;
+
+ if (wepClass == OBJ_MISSILES && wepType == MI_NEEDLE)
+ {
+ // Throwing needles is now seriously frowned upon; it's difficult
+ // to grip a fiddly little needle, and not penalising it cheapens
+ // blowguns.
+ exHitBonus -= (30 - you.skills[SK_DARTS]) / 3;
+ baseHit -= (30 - you.skills[SK_DARTS]) / 3;
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Needle base hit = %d, exHitBonus = %d",
+ baseHit, exHitBonus);
+#endif
+ }
}
// FINALIZE tohit and damage
@@ -1694,6 +1898,11 @@ static void throw_it(struct bolt &pbolt, int throw_2)
else
pbolt.damage = dice_def( 1, baseDam - random2(0 - (exDamBonus - 1)) );
+ pbolt.damage.size = dice_mult * pbolt.damage.size / 100;
+ pbolt.damage.size += slayDam;
+
+ scale_dice( pbolt.damage );
+
// only add bonuses if we're throwing something sensible
if (thrown || launched || wepClass == OBJ_WEAPONS)
{
@@ -1702,49 +1911,43 @@ static void throw_it(struct bolt &pbolt, int throw_2)
}
#if DEBUG_DIAGNOSTICS
- snprintf( info, INFO_SIZE,
- "H:%d+%d;a%dl%d. D:%d+%d;a%dl%d -> %d,%dd%d",
+ mprf( MSGCH_DIAGNOSTICS,
+ "H:%d+%d;a%dl%d. D:%d+%d;a%dl%d -> %d,%dd%d",
baseHit, exHitBonus, ammoHitBonus, lnchHitBonus,
baseDam, exDamBonus, ammoDamBonus, lnchDamBonus,
pbolt.hit, pbolt.damage.num, pbolt.damage.size );
-
- mpr( info, MSGCH_DIAGNOSTICS );
#endif
- // Must unwield before fire_beam() makes a copy in order to remove things
- // like temporary branding. -- bwr
- if (throw_2 == you.equip[EQ_WEAPON] && you.inv[throw_2].quantity == 1)
- {
- unwield_item( throw_2 );
- you.equip[EQ_WEAPON] = -1;
- canned_msg( MSG_EMPTY_HANDED );
- }
-
// create message
if (launched)
strcpy(info, "You shoot ");
else
strcpy(info, "You throw ");
- item_name( item, DESC_NOCAP_A, str_pass );
+ item_name( item, DESC_NOCAP_A, str_pass );
strcat(info, str_pass);
strcat(info, ".");
mpr(info);
// ensure we're firing a 'missile'-type beam
- pbolt.isBeam = false;
- pbolt.isTracer = false;
+ pbolt.is_beam = false;
+ pbolt.is_tracer = false;
// mark this item as thrown if it's a missile, so that we'll pick it up
// when we walk over it.
if (wepClass == OBJ_MISSILES || wepClass == OBJ_WEAPONS)
item.flags |= ISFLAG_THROWN;
+ bool hit = false;
// using copy, since the launched item might be differect (venom blowgun)
- fire_beam( pbolt, &item );
-
- dec_inv_item_quantity( throw_2, 1 );
+ if (dummy_target)
+ hit = (affect( pbolt, dummy_target->x, dummy_target->y ) != 0);
+ else
+ {
+ fire_beam( pbolt, &item );
+ dec_inv_item_quantity( throw_2, 1 );
+ }
// throwing and blowguns are silent
if (launched && lnchType != WPN_BLOWGUN)
@@ -1753,108 +1956,16 @@ static void throw_it(struct bolt &pbolt, int throw_2)
// but any monster nearby can see that something has been thrown:
alert_nearby_monsters();
- you.turn_is_over = 1;
+ you.turn_is_over = true;
+
+ return (hit);
} // end throw_it()
-bool puton_item(int item_slot, bool prompt_finger)
+void jewellery_wear_effects(item_def &item)
{
- if (item_slot == you.equip[EQ_LEFT_RING]
- || item_slot == you.equip[EQ_RIGHT_RING]
- || item_slot == you.equip[EQ_AMULET])
- {
- mpr("You've already put that on!");
- return (true);
- }
-
- if (item_slot == you.equip[EQ_WEAPON])
- {
- mpr("You are wielding that object.");
- return (false);
- }
-
- if (you.inv[item_slot].base_type != OBJ_JEWELLERY)
- {
- //jmf: let's not take our inferiority complex out on players, eh? :-p
- //mpr("You're sadly mistaken if you consider that jewellery.")
- mpr("You can only put on jewellery.");
- return (false);
- }
-
- bool is_amulet = (you.inv[item_slot].sub_type >= AMU_RAGE);
-
- if (!is_amulet) // ie it's a ring
- {
- if (you.equip[EQ_GLOVES] != -1
- && item_cursed( you.inv[you.equip[EQ_GLOVES]] ))
- {
- mpr("You can't take your gloves off to put on a ring!");
- return (false);
- }
-
- if (you.inv[item_slot].base_type == OBJ_JEWELLERY
- && you.equip[EQ_LEFT_RING] != -1
- && you.equip[EQ_RIGHT_RING] != -1)
- {
- // and you are trying to wear body you.equip.
- mpr("You've already put a ring on each hand.");
- return (false);
- }
- }
- else if (you.equip[EQ_AMULET] != -1)
- {
- strcpy(info, "You are already wearing an amulet.");
-
- if (one_chance_in(20))
- {
- strcat(info, " And I must say it looks quite fetching.");
- }
-
- mpr(info);
- return (false);
- }
-
- int hand_used = 0;
-
- if (you.equip[EQ_LEFT_RING] != -1)
- hand_used = 1;
-
- if (you.equip[EQ_RIGHT_RING] != -1)
- hand_used = 0;
-
- if (is_amulet)
- hand_used = 2;
- else if (you.equip[EQ_LEFT_RING] == -1 && you.equip[EQ_RIGHT_RING] == -1)
- {
- if (prompt_finger)
- {
- mpr("Put on which hand (l or r)?", MSGCH_PROMPT);
-
- int keyin = get_ch();
-
- if (keyin == 'l')
- hand_used = 0;
- else if (keyin == 'r')
- hand_used = 1;
- else if (keyin == ESCAPE)
- return (false);
- else
- {
- mpr("You don't have such a hand!");
- return (false);
- }
- }
- else
- {
- // First ring goes on left hand if we're choosing automatically.
- hand_used = 0;
- }
- }
-
- you.equip[ EQ_LEFT_RING + hand_used ] = item_slot;
-
int ident = ID_TRIED_TYPE;
- switch (you.inv[item_slot].sub_type)
+ switch (item.sub_type)
{
case RING_FIRE:
case RING_HUNGER:
@@ -1871,11 +1982,12 @@ bool puton_item(int item_slot, bool prompt_finger)
case RING_TELEPORTATION:
case RING_WIZARDRY:
case RING_REGENERATION:
+ case RING_TELEPORT_CONTROL:
break;
case RING_PROTECTION:
you.redraw_armour_class = 1;
- if (you.inv[item_slot].plus != 0)
+ if (item.plus != 0)
ident = ID_KNOWN_TYPE;
break;
@@ -1889,25 +2001,25 @@ bool puton_item(int item_slot, bool prompt_finger)
case RING_EVASION:
you.redraw_evasion = 1;
- if (you.inv[item_slot].plus != 0)
+ if (item.plus != 0)
ident = ID_KNOWN_TYPE;
break;
case RING_STRENGTH:
- modify_stat(STAT_STRENGTH, you.inv[item_slot].plus, true);
- if (you.inv[item_slot].plus != 0)
+ modify_stat(STAT_STRENGTH, item.plus, true);
+ if (item.plus != 0)
ident = ID_KNOWN_TYPE;
break;
case RING_DEXTERITY:
- modify_stat(STAT_DEXTERITY, you.inv[item_slot].plus, true);
- if (you.inv[item_slot].plus != 0)
+ modify_stat(STAT_DEXTERITY, item.plus, true);
+ if (item.plus != 0)
ident = ID_KNOWN_TYPE;
break;
case RING_INTELLIGENCE:
- modify_stat(STAT_INTELLIGENCE, you.inv[item_slot].plus, true);
- if (you.inv[item_slot].plus != 0)
+ modify_stat(STAT_INTELLIGENCE, item.plus, true);
+ if (item.plus != 0)
ident = ID_KNOWN_TYPE;
break;
@@ -1921,46 +2033,181 @@ bool puton_item(int item_slot, bool prompt_finger)
ident = ID_KNOWN_TYPE;
break;
- case RING_TELEPORT_CONTROL:
- // XXX: is this safe or should we make it a function -- bwr
- you.attribute[ATTR_CONTROL_TELEPORT]++;
- break;
-
case AMU_RAGE:
mpr("You feel a brief urge to hack something to bits.");
ident = ID_KNOWN_TYPE;
break;
- }
- you.turn_is_over = 1;
+ case AMU_THE_GOURMAND:
+ you.duration[DUR_GOURMAND] = 0;
+ break;
+ }
// Artefacts have completely different appearance than base types
// so we don't allow them to make the base types known
- if (is_random_artefact( you.inv[item_slot] ))
- use_randart(item_slot);
+ if (is_random_artefact( item ))
+ use_randart(item);
else
+ set_ident_type( item.base_type, item.sub_type, ident );
+
+ if (ident == ID_KNOWN_TYPE)
+ set_ident_flags( item, ISFLAG_EQ_JEWELLERY_MASK );
+
+ if (item_cursed( item ))
+ mprf("Oops, that %s feels deathly cold.",
+ jewellery_is_amulet(item)? "amulet" : "ring");
+
+ // cursed or not, we know that since we've put the ring on
+ set_ident_flags( item, ISFLAG_KNOW_CURSE );
+
+ mpr( item_name( item, DESC_INVENTORY_EQUIP ) );
+}
+
+static int prompt_ring_to_remove(int new_ring)
+{
+ const item_def &left = you.inv[ you.equip[EQ_LEFT_RING] ];
+ const item_def &right = you.inv[ you.equip[EQ_RIGHT_RING] ];
+
+ if (item_cursed(left) && item_cursed(right))
{
- set_ident_type( you.inv[item_slot].base_type,
- you.inv[item_slot].sub_type, ident );
+ mprf("You're already wearing two cursed rings!");
+ return (-1);
}
- if (ident == ID_KNOWN_TYPE)
- set_ident_flags( you.inv[item_slot], ISFLAG_EQ_JEWELLERY_MASK );
+ mesclr();
+ mprf("Wearing %s.", in_name(new_ring, DESC_NOCAP_A));
+
+ char lslot = index_to_letter(left.link),
+ rslot = index_to_letter(right.link);
+
+ mprf(MSGCH_PROMPT,
+ "You're wearing two rings. Remove which one? (%c/%c/Esc)",
+ lslot, rslot);
+ mprf(" %s", item_name( left, DESC_INVENTORY ));
+ mprf(" %s", item_name( right, DESC_INVENTORY ));
+
+ int c;
+ do
+ c = getch();
+ while (c != lslot && c != rslot && c != ESCAPE && c != ' ');
+
+ mesclr();
+
+ if (c == ESCAPE || c == ' ')
+ return (-1);
- if (item_cursed( you.inv[item_slot] ))
+ int eqslot = c == lslot? EQ_LEFT_RING : EQ_RIGHT_RING;
+ return (you.equip[eqslot]);
+}
+
+// Assumptions:
+// you.inv[ring_slot] is a valid ring.
+// EQ_LEFT_RING and EQ_RIGHT_RING are both occupied, and ring_slot is not
+// one of the worn rings.
+//
+// Does not do amulets.
+static bool swap_rings(int ring_slot)
+{
+ // Ask the player which existing ring is persona non grata.
+ int unwanted = prompt_ring_to_remove(ring_slot);
+ if (unwanted == -1)
+ return (false);
+
+ if (!remove_ring(unwanted, false))
+ return (false);
+
+ start_delay(DELAY_JEWELLERY_ON, 1, ring_slot);
+
+ return (true);
+}
+
+bool puton_item(int item_slot, bool prompt_finger)
+{
+ if (item_slot == you.equip[EQ_LEFT_RING]
+ || item_slot == you.equip[EQ_RIGHT_RING]
+ || item_slot == you.equip[EQ_AMULET])
{
- snprintf( info, INFO_SIZE,
- "Oops, that %s feels deathly cold.", (is_amulet) ? "amulet"
- : "ring" );
- mpr(info);
+ mpr("You've already put that on!");
+ return (true);
}
- // cursed or not, we know that since we've put the ring on
- set_ident_flags( you.inv[item_slot], ISFLAG_KNOW_CURSE );
+ if (item_slot == you.equip[EQ_WEAPON])
+ {
+ mpr("You are wielding that object.");
+ return (false);
+ }
- char str_pass[ ITEMNAME_SIZE ];
- in_name( item_slot, DESC_INVENTORY_EQUIP, str_pass );
- mpr( str_pass );
+ if (you.inv[item_slot].base_type != OBJ_JEWELLERY)
+ {
+ mpr("You can only put on jewellery.");
+ return (false);
+ }
+
+ bool is_amulet = jewellery_is_amulet( you.inv[item_slot] );
+
+ if (!is_amulet) // ie it's a ring
+ {
+ if (you.equip[EQ_GLOVES] != -1
+ && item_cursed( you.inv[you.equip[EQ_GLOVES]] ))
+ {
+ mpr("You can't take your gloves off to put on a ring!");
+ return (false);
+ }
+
+ if (you.equip[EQ_LEFT_RING] != -1
+ && you.equip[EQ_RIGHT_RING] != -1)
+ return swap_rings(item_slot);
+ }
+ else if (you.equip[EQ_AMULET] != -1)
+ {
+ if (!remove_ring( you.equip[EQ_AMULET], true ))
+ return (false);
+
+ start_delay(DELAY_JEWELLERY_ON, 1, item_slot);
+
+ // Assume it's going to succeed.
+ return (true);
+ }
+
+ // First ring goes on left hand if we're choosing automatically.
+ int hand_used = 0;
+
+ if (you.equip[EQ_LEFT_RING] != -1)
+ hand_used = 1;
+
+ if (you.equip[EQ_RIGHT_RING] != -1)
+ hand_used = 0;
+
+ if (is_amulet)
+ hand_used = 2;
+ else if (prompt_finger
+ && you.equip[EQ_LEFT_RING] == -1
+ && you.equip[EQ_RIGHT_RING] == -1)
+ {
+ mpr("Put on which hand (l or r)?", MSGCH_PROMPT);
+
+ int keyin = get_ch();
+
+ if (keyin == 'l')
+ hand_used = 0;
+ else if (keyin == 'r')
+ hand_used = 1;
+ else if (keyin == ESCAPE)
+ return (false);
+ else
+ {
+ mpr("You don't have such a hand!");
+ return (false);
+ }
+ }
+
+ you.equip[ EQ_LEFT_RING + hand_used ] = item_slot;
+
+ jewellery_wear_effects( you.inv[item_slot] );
+
+ // Putting on jewellery is as fast as wielding weapons.
+ you.time_taken = you.time_taken * 5 / 10;
+ you.turn_is_over = true;
return (true);
}
@@ -1985,7 +2232,7 @@ bool puton_ring(int slot, bool prompt_finger)
item_slot = slot;
else
item_slot = prompt_invent_item( "Put on which piece of jewellery?",
- OBJ_JEWELLERY );
+ MT_INVSELECT, OBJ_JEWELLERY );
if (item_slot == PROMPT_ABORT)
{
@@ -1996,11 +2243,91 @@ bool puton_ring(int slot, bool prompt_finger)
return puton_item(item_slot, prompt_finger);
} // end puton_ring()
-bool remove_ring(int slot)
+void jewellery_remove_effects(item_def &item)
+{
+ // The ring/amulet must already be removed from you.equip at this point.
+
+ // Turn off show_uncursed before getting the item name, because this item
+ // was just removed, and the player knows it's uncursed.
+ bool old_showuncursed = Options.show_uncursed;
+ Options.show_uncursed = false;
+
+ mprf("You remove %s.", item_name(item, DESC_NOCAP_YOUR));
+
+ Options.show_uncursed = old_showuncursed;
+
+ switch (item.sub_type)
+ {
+ case RING_FIRE:
+ case RING_HUNGER:
+ case RING_ICE:
+ case RING_LIFE_PROTECTION:
+ case RING_POISON_RESISTANCE:
+ case RING_PROTECTION_FROM_COLD:
+ case RING_PROTECTION_FROM_FIRE:
+ case RING_PROTECTION_FROM_MAGIC:
+ case RING_REGENERATION:
+ case RING_SEE_INVISIBLE:
+ case RING_SLAYING:
+ case RING_SUSTAIN_ABILITIES:
+ case RING_SUSTENANCE:
+ case RING_TELEPORTATION:
+ case RING_WIZARDRY:
+ case RING_TELEPORT_CONTROL:
+ break;
+
+ case RING_PROTECTION:
+ you.redraw_armour_class = 1;
+ break;
+
+ case RING_EVASION:
+ you.redraw_evasion = 1;
+ break;
+
+ case RING_STRENGTH:
+ modify_stat(STAT_STRENGTH, -item.plus, true);
+ break;
+
+ case RING_DEXTERITY:
+ modify_stat(STAT_DEXTERITY, -item.plus, true);
+ break;
+
+ case RING_INTELLIGENCE:
+ modify_stat(STAT_INTELLIGENCE, -item.plus, true);
+ break;
+
+ case RING_INVISIBILITY:
+ // removing this ring effectively cancels all invisibility {dlb}
+ if (you.invis)
+ you.invis = 1;
+ break;
+
+ case RING_LEVITATION:
+ // removing this ring effectively cancels all levitation {dlb}
+ if (you.levitation)
+ you.levitation = 1;
+ break;
+
+ case RING_MAGICAL_POWER:
+ // dec_max_mp(9);
+ break;
+
+ case AMU_THE_GOURMAND:
+ you.duration[DUR_GOURMAND] = 0;
+ break;
+ }
+
+ if (is_random_artefact(item))
+ unuse_randart(item);
+
+ // must occur after ring is removed -- bwr
+ calc_mp();
+}
+
+bool remove_ring(int slot, bool announce)
{
int hand_used = 10;
int ring_wear_2;
- char str_pass[ ITEMNAME_SIZE ];
if (you.equip[EQ_LEFT_RING] == -1 && you.equip[EQ_RIGHT_RING] == -1
&& you.equip[EQ_AMULET] == -1)
@@ -2045,7 +2372,9 @@ bool remove_ring(int slot)
{
int equipn =
slot == -1? prompt_invent_item( "Remove which piece of jewellery?",
- OBJ_JEWELLERY )
+ MT_INVSELECT,
+ OBJ_JEWELLERY, true, true, true,
+ 0, NULL, OPER_REMOVE)
: slot;
if (equipn == PROMPT_ABORT)
@@ -2081,99 +2410,33 @@ bool remove_ring(int slot)
return (false);
}
- if (you.equip[hand_used + 7] == -1)
+ if (you.equip[hand_used + EQ_LEFT_RING] == -1)
{
mpr("I don't think you really meant that.");
return (false);
}
- if (item_cursed( you.inv[you.equip[hand_used + 7]] ))
+ if (item_cursed( you.inv[you.equip[hand_used + EQ_LEFT_RING]] ))
{
- mpr("It's stuck to you!");
+ if (announce)
+ mprf("%s is stuck to you!",
+ in_name(you.equip[hand_used + EQ_LEFT_RING],
+ DESC_CAP_YOUR));
+ else
+ mpr("It's stuck to you!");
- set_ident_flags( you.inv[you.equip[hand_used + 7]], ISFLAG_KNOW_CURSE );
+ set_ident_flags( you.inv[you.equip[hand_used + EQ_LEFT_RING]],
+ ISFLAG_KNOW_CURSE );
return (false);
}
- strcpy(info, "You remove ");
- in_name(you.equip[hand_used + 7], DESC_NOCAP_YOUR, str_pass);
+ ring_wear_2 = you.equip[hand_used + EQ_LEFT_RING];
+ you.equip[hand_used + EQ_LEFT_RING] = -1;
- strcat(info, str_pass);
- strcat(info, ".");
- mpr(info);
+ jewellery_remove_effects(you.inv[ring_wear_2]);
- // I'll still use ring_wear_2 here.
- ring_wear_2 = you.equip[hand_used + 7];
-
- switch (you.inv[ring_wear_2].sub_type)
- {
- case RING_FIRE:
- case RING_HUNGER:
- case RING_ICE:
- case RING_LIFE_PROTECTION:
- case RING_POISON_RESISTANCE:
- case RING_PROTECTION_FROM_COLD:
- case RING_PROTECTION_FROM_FIRE:
- case RING_PROTECTION_FROM_MAGIC:
- case RING_REGENERATION:
- case RING_SEE_INVISIBLE:
- case RING_SLAYING:
- case RING_SUSTAIN_ABILITIES:
- case RING_SUSTENANCE:
- case RING_TELEPORTATION:
- case RING_WIZARDRY:
- break;
-
- case RING_PROTECTION:
- you.redraw_armour_class = 1;
- break;
-
- case RING_EVASION:
- you.redraw_evasion = 1;
- break;
-
- case RING_STRENGTH:
- modify_stat(STAT_STRENGTH, -you.inv[ring_wear_2].plus, true);
- break;
-
- case RING_DEXTERITY:
- modify_stat(STAT_DEXTERITY, -you.inv[ring_wear_2].plus, true);
- break;
-
- case RING_INTELLIGENCE:
- modify_stat(STAT_INTELLIGENCE, -you.inv[ring_wear_2].plus, true);
- break;
-
- case RING_INVISIBILITY:
- // removing this ring effectively cancels all invisibility {dlb}
- if (you.invis)
- you.invis = 1;
- break;
-
- case RING_LEVITATION:
- // removing this ring effectively cancels all levitation {dlb}
- if (you.levitation)
- you.levitation = 1;
- break;
-
- case RING_MAGICAL_POWER:
- // dec_max_mp(9);
- break;
-
- case RING_TELEPORT_CONTROL:
- you.attribute[ATTR_CONTROL_TELEPORT]--;
- break;
- }
-
- if (is_random_artefact( you.inv[ring_wear_2] ))
- unuse_randart(ring_wear_2);
-
- you.equip[hand_used + 7] = -1;
-
- // must occur after ring is removed -- bwr
- calc_mp();
-
- you.turn_is_over = 1;
+ you.time_taken = you.time_taken * 5 / 10;
+ you.turn_is_over = true;
return (true);
} // end remove_ring()
@@ -2189,7 +2452,7 @@ void zap_wand(void)
// system will default to cycling through all monsters. -- bwr
int targ_mode = TARG_ANY;
- beam.obviousEffect = false;
+ beam.obvious_effect = false;
if (inv_count() < 1)
{
@@ -2203,21 +2466,46 @@ void zap_wand(void)
return;
}
- item_slot = prompt_invent_item( "Zap which item?", OBJ_WANDS );
+ item_slot = prompt_invent_item( "Zap which item?",
+ MT_INVSELECT,
+ OBJ_WANDS,
+ true, true, true, 0, NULL,
+ OPER_ZAP );
if (item_slot == PROMPT_ABORT)
{
canned_msg( MSG_OK );
return;
}
- if (you.inv[item_slot].base_type != OBJ_WANDS
- || you.inv[item_slot].plus < 1)
+ if (you.inv[item_slot].base_type != OBJ_WANDS)
{
canned_msg(MSG_NOTHING_HAPPENS);
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return;
}
+ // if you happen to be wielding the wand, its display might change
+ if (you.equip[EQ_WEAPON] == item_slot)
+ you.wield_change = true;
+
+ if ( you.inv[item_slot].plus < 1 ) {
+ // it's an empty wand, inscribe it that way
+ canned_msg(MSG_NOTHING_HAPPENS);
+ you.turn_is_over = true;
+ if ( !item_ident(you.inv[item_slot], ISFLAG_KNOW_PLUSES) ) {
+
+ if ( you.inv[item_slot].inscription.find("empty") ==
+ std::string::npos ) {
+
+ if ( !you.inv[item_slot].inscription.empty() )
+ you.inv[item_slot].inscription += ' ';
+ you.inv[item_slot].inscription += "[empty]";
+
+ }
+ }
+ return;
+ }
+
if (item_ident( you.inv[item_slot], ISFLAG_KNOW_TYPE ))
{
if (you.inv[item_slot].sub_type == WAND_HASTING
@@ -2275,12 +2563,11 @@ void zap_wand(void)
beam.source_x = you.x_pos;
beam.source_y = you.y_pos;
- beam.target_x = zap_wand.tx;
- beam.target_y = zap_wand.ty;
+ beam.set_target(zap_wand);
zapping( type_zapped, 30 + roll_dice(2, you.skills[SK_EVOCATIONS]), beam );
- if (beam.obviousEffect == 1 || you.inv[item_slot].sub_type == WAND_FIREBALL)
+ if (beam.obvious_effect == 1 || you.inv[item_slot].sub_type == WAND_FIREBALL)
{
if (get_ident_type( you.inv[item_slot].base_type,
you.inv[item_slot].sub_type ) != ID_KNOWN_TYPE)
@@ -2309,7 +2596,7 @@ void zap_wand(void)
&& (item_ident( you.inv[item_slot], ISFLAG_KNOW_PLUSES )
|| you.skills[SK_EVOCATIONS] > 5 + random2(15)))
{
- if (item_not_ident( you.inv[item_slot], ISFLAG_KNOW_PLUSES ))
+ if (!item_ident( you.inv[item_slot], ISFLAG_KNOW_PLUSES ))
{
mpr("Your skill with magical items lets you calculate the power of this device...");
}
@@ -2325,9 +2612,34 @@ void zap_wand(void)
exercise( SK_EVOCATIONS, 1 );
alert_nearby_monsters();
- you.turn_is_over = 1;
+ you.turn_is_over = true;
} // end zap_wand()
+/*** HP CHANGE ***/
+void inscribe_item()
+{
+ int item_slot;
+ char buf[79];
+ if (inv_count() < 1)
+ {
+ mpr("You don't have anything to inscribe.");
+ return;
+ }
+ item_slot = prompt_invent_item(
+ "Inscribe which item? ",
+ MT_INVSELECT,
+ OSEL_ANY );
+ if (item_slot == PROMPT_ABORT)
+ {
+ canned_msg( MSG_OK );
+ return;
+ }
+ mpr( "Inscribe with what? ", MSGCH_PROMPT );
+ get_input_line( buf, sizeof(buf) );
+ you.inv[item_slot].inscription = std::string(buf);
+ you.wield_change = true;
+}
+
void drink(void)
{
int item_slot;
@@ -2357,7 +2669,10 @@ void drink(void)
return;
}
- item_slot = prompt_invent_item( "Drink which item?", OBJ_POTIONS );
+ item_slot = prompt_invent_item( "Drink which item?",
+ MT_INVSELECT, OBJ_POTIONS,
+ true, true, true, 0, NULL,
+ OPER_QUAFF );
if (item_slot == PROMPT_ABORT)
{
canned_msg( MSG_OK );
@@ -2384,7 +2699,7 @@ void drink(void)
}
dec_inv_item_quantity( item_slot, 1 );
- you.turn_is_over = 1;
+ you.turn_is_over = true;
lessen_hunger(40, true);
} // end drink()
@@ -2474,7 +2789,7 @@ bool drink_fountain(void)
grd[you.x_pos][you.y_pos] = DNGN_DRY_FOUNTAIN_II;
}
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return true;
} // end drink_fountain()
@@ -2491,8 +2806,7 @@ static bool affix_weapon_enchantment( void )
switch (get_weapon_brand( you.inv[wpn] ))
{
case SPWPN_VORPAL:
- if (damage_type( you.inv[wpn].base_type,
- you.inv[wpn].sub_type ) != DVORP_CRUSHING)
+ if (get_vorpal_type( you.inv[wpn] ) != DVORP_CRUSHING)
{
strcat(info, "'s sharpness seems more permanent.");
}
@@ -2512,12 +2826,13 @@ static bool affix_weapon_enchantment( void )
beam.flavour = 2;
beam.target_x = you.x_pos;
beam.target_y = you.y_pos;
- strcpy(beam.beam_name, "fiery explosion");
+ beam.name = "fiery explosion";
beam.colour = RED;
beam.thrower = KILL_YOU;
beam.aux_source = "a fiery explosion";
beam.ex_size = 2;
- beam.isTracer = false;
+ beam.is_tracer = false;
+ beam.is_explosion = true;
explosion(beam);
break;
@@ -2541,11 +2856,15 @@ static bool affix_weapon_enchantment( void )
break;
case SPWPN_DISTORTION:
+ // [dshaligram] Attempting to fix a distortion brand gets you a free
+ // distortion effect, and no permabranding. Sorry, them's the breaks.
strcat(info, " twongs alarmingly.");
mpr(info);
// from unwield_item
- miscast_effect( SPTYP_TRANSLOCATION, 9, 90, 100, "a distortion effect" );
+ miscast_effect( SPTYP_TRANSLOCATION, 9, 90, 100,
+ "a distortion effect" );
+ success = false;
break;
default:
@@ -2559,7 +2878,7 @@ static bool affix_weapon_enchantment( void )
return (success);
}
-static bool enchant_weapon( int which_stat, bool quiet )
+bool enchant_weapon( int which_stat, bool quiet )
{
const int wpn = you.equip[ EQ_WEAPON ];
bool affected = true;
@@ -2693,7 +3012,7 @@ static bool enchant_armour( void )
you.redraw_armour_class = 1;
- hide2armour( &(you.inv[nthing].sub_type) );
+ hide2armour(you.inv[nthing]);
return (true);
}
@@ -2824,7 +3143,7 @@ void read_scroll(void)
char str_pass[ ITEMNAME_SIZE ];
// added: scroll effects are never tracers.
- beam.isTracer = false;
+ beam.is_tracer = false;
if (you.berserker)
{
@@ -2838,7 +3157,10 @@ void read_scroll(void)
return;
}
- int item_slot = prompt_invent_item( "Read which item?", OBJ_SCROLLS );
+ int item_slot = prompt_invent_item(
+ "Read which item?",
+ MT_INVSELECT,
+ OBJ_SCROLLS );
if (item_slot == PROMPT_ABORT)
{
canned_msg( MSG_OK );
@@ -2866,7 +3188,7 @@ void read_scroll(void)
}
// ok - now we FINALLY get to read a scroll !!! {dlb}
- you.turn_is_over = 1;
+ you.turn_is_over = true;
// imperfect vision prevents players from reading actual content {dlb}:
if (you.mutation[MUT_BLURRY_VISION]
@@ -2909,6 +3231,8 @@ void read_scroll(void)
case SCR_PAPER:
// remember paper scrolls handled as special case above, too:
mpr("This scroll appears to be blank.");
+ if (you.mutation[MUT_BLURRY_VISION] == 3)
+ id_the_scroll = false;
break;
case SCR_RANDOM_USELESSNESS:
@@ -2977,17 +3301,19 @@ void read_scroll(void)
break;
case SCR_TORMENT:
- torment( you.x_pos, you.y_pos );
+ torment( TORMENT_SCROLL, you.x_pos, you.y_pos );
// is only naughty if you know you're doing it
if (get_ident_type( OBJ_SCROLLS, SCR_TORMENT ) == ID_KNOWN_TYPE)
{
- naughty(NAUGHTY_UNHOLY, 10);
+ did_god_conduct(DID_UNHOLY, 10);
}
break;
case SCR_IMMOLATION:
mpr("The scroll explodes in your hands!");
+ // we do this here to prevent it from blowing itself up
+ dec_inv_item_quantity( item_slot, 1 );
beam.type = SYM_BURST;
beam.damage = dice_def( 3, 10 );
@@ -2995,17 +3321,23 @@ void read_scroll(void)
beam.flavour = BEAM_FIRE;
beam.target_x = you.x_pos;
beam.target_y = you.y_pos;
- strcpy(beam.beam_name, "fiery explosion");
+ beam.name = "fiery explosion";
beam.colour = RED;
// your explosion, (not someone else's explosion)
beam.thrower = KILL_YOU;
beam.aux_source = "reading a scroll of immolation";
beam.ex_size = 2;
+ beam.is_explosion = true;
explosion(beam);
break;
case SCR_IDENTIFY:
+ if ( get_ident_type( OBJ_SCROLLS, scroll_type ) != ID_KNOWN_TYPE ) {
+ mpr("This is a scroll of identify!");
+ more();
+ }
+
set_ident_flags( you.inv[item_slot], ISFLAG_IDENT_MASK );
// important {dlb}
@@ -3083,7 +3415,7 @@ void read_scroll(void)
|| (you.inv[ nthing ].base_type == OBJ_WEAPONS
&& (is_fixed_artefact( you.inv[ nthing ] )
|| is_random_artefact( you.inv[ nthing ] )
- || launches_things( you.inv[ nthing ].sub_type ))))
+ || you.inv[nthing].sub_type == WPN_BLOWGUN)))
{
canned_msg(MSG_NOTHING_HAPPENS);
break;
@@ -3136,7 +3468,7 @@ void read_scroll(void)
affected = EQ_WEAPON;
for (i = EQ_CLOAK; i <= EQ_BODY_ARMOUR; i++)
{
- if (you.equip[i] != -1 && item_uncursed( you.inv[you.equip[i]] ))
+ if (you.equip[i] != -1 && !item_cursed( you.inv[you.equip[i]] ))
{
count++;
if (one_chance_in( count ))
@@ -3162,7 +3494,8 @@ void read_scroll(void)
} // end switch
// finally, destroy and identify the scroll
- if (scroll_type != SCR_PAPER)
+ // scrolls of immolation were already destroyed earlier
+ if (scroll_type != SCR_PAPER && scroll_type != SCR_IMMOLATION)
{
dec_inv_item_quantity( item_slot, 1 );
}
@@ -3171,9 +3504,12 @@ void read_scroll(void)
(id_the_scroll) ? ID_KNOWN_TYPE : ID_TRIED_TYPE );
} // end read_scroll()
-void original_name(void)
+void examine_object(void)
{
- int item_slot = prompt_invent_item( "Examine which item?", -1 );
+ int item_slot = prompt_invent_item( "Examine which item?",
+ MT_INVSELECT, -1,
+ true, true, true, 0, NULL,
+ OPER_EXAMINE );
if (item_slot == PROMPT_ABORT)
{
canned_msg( MSG_OK );
@@ -3182,14 +3518,20 @@ void original_name(void)
describe_item( you.inv[item_slot] );
redraw_screen();
+ mesclr(true);
} // end original_name()
void use_randart(unsigned char item_wield_2)
{
- ASSERT( is_random_artefact( you.inv[ item_wield_2 ] ) );
+ use_randart( you.inv[ item_wield_2 ] );
+}
+
+void use_randart(const item_def &item)
+{
+ ASSERT( is_random_artefact( item ) );
FixedVector< char, RA_PROPERTIES > proprt;
- randart_wpn_properties( you.inv[item_wield_2], proprt );
+ randart_wpn_properties( item, proprt );
if (proprt[RAP_AC])
you.redraw_armour_class = 1;
diff --git a/crawl-ref/source/item_use.h b/crawl-ref/source/item_use.h
index 87c8e31455..5f79db1476 100644
--- a/crawl-ref/source/item_use.h
+++ b/crawl-ref/source/item_use.h
@@ -3,6 +3,8 @@
* Summary: Functions for making use of inventory items.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <2> 5/26/99 JDJ Exposed armour_prompt. takeoff_armour takes an index argument.
@@ -15,13 +17,16 @@
#include <string>
+#include "externs.h"
+#include "enum.h"
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: acr - item_use
* *********************************************************************** */
-bool armour_prompt(const std::string & mesg, int *index);
+bool armour_prompt(const std::string & mesg, int *index,
+ operation_types oper);
// last updated 12may2000 {dlb}
@@ -37,12 +42,13 @@ bool takeoff_armour(int index);
* *********************************************************************** */
void drink(void);
+bool elemental_missile_beam(int launcher_brand, int ammo_brand);
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
-void original_name(void);
+void examine_object(void);
// last updated 12may2000 {dlb}
@@ -63,7 +69,7 @@ void read_scroll(void);
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
-bool remove_ring(int slot = -1);
+bool remove_ring(int slot = -1, bool announce = false);
// last updated 12may2000 {dlb}
@@ -98,7 +104,7 @@ struct item_def;
/* ***********************************************************************
* called from: food
* *********************************************************************** */
-bool can_wield(const item_def& weapon);
+bool can_wield(const item_def *weapon, bool say_why = false);
// last updated 12may2000 {dlb}
/* ***********************************************************************
@@ -125,9 +131,20 @@ void wield_effects(int item_wield_2, bool showMsgs);
* called from: delay.cc item_use.cc it_use2.cc
* *********************************************************************** */
void use_randart( unsigned char item_wield_2 );
+void use_randart(const item_def &item);
bool puton_item(int slot, bool prompt_finger = true);
-int armour_equip_slot(const item_def &item);
+bool enchant_weapon( int which_stat, bool quiet = false );
+
+bool throw_it(struct bolt &pbolt, int throw_2, monsters *dummy_target = NULL);
+
+void inscribe_item();
+int launcher_shield_slowdown(const item_def &launcher,
+ const item_def *shield);
+int launcher_final_speed(const item_def &launcher,
+ const item_def *shield);
+
+void warn_shield_penalties();
#endif
diff --git a/crawl-ref/source/itemname.cc b/crawl-ref/source/itemname.cc
index b92dcfc387..4524ab919b 100644
--- a/crawl-ref/source/itemname.cc
+++ b/crawl-ref/source/itemname.cc
@@ -28,25 +28,28 @@
#include "externs.h"
#include "invent.h"
+#include "itemprop.h"
#include "macro.h"
#include "mon-util.h"
+#include "notes.h"
#include "randart.h"
#include "skills2.h"
#include "stuff.h"
-#include "wpn-misc.h"
#include "view.h"
+#include "items.h"
+char id[NUM_IDTYPE][MAX_SUBTYPES];
-char id[4][50];
-int prop[4][50][3];
-FixedArray < int, 20, 50 > mss;
+static bool is_random_name_space( char let );
+static bool is_random_name_vowel( char let);
+static const char *item_name_2(
+ const item_def &item, char buff[ ITEMNAME_SIZE ], bool terse );
-static bool is_random_name_vowel(unsigned char let);
-static char item_name_2( const item_def &item, char buff[ ITEMNAME_SIZE ], bool terse );
+static char retvow(int sed);
+static char retlet(int sed );
-char reduce(unsigned char reducee);
-char retbit(char sed);
-char retvow(char sed);
+// [dshaligram] For calls to item_name without a pre-allocated buffer.
+static char default_itembuf[ITEMNAME_SIZE];
bool is_vowel( const char chr )
{
@@ -55,42 +58,6 @@ bool is_vowel( const char chr )
return (low == 'a' || low == 'e' || low == 'i' || low == 'o' || low == 'u');
}
-// Some convenient functions to hide the bit operations and create
-// an interface layer between the code and the data in case this
-// gets changed again. -- bwr
-bool item_cursed( const item_def &item )
-{
- return (item.flags & ISFLAG_CURSED);
-}
-
-bool item_uncursed( const item_def &item )
-{
- return !(item.flags & ISFLAG_CURSED);
-}
-
-bool item_known_cursed( const item_def &item )
-{
- return ((item.flags & ISFLAG_KNOW_CURSE) && (item.flags & ISFLAG_CURSED));
-}
-
-bool item_known_uncursed( const item_def &item )
-{
- return ((item.flags & ISFLAG_KNOW_CURSE) && !(item.flags & ISFLAG_CURSED));
-}
-
-#if 0
-// currently unused
-bool fully_identified( const item_def &item )
-{
- return ((item.flags & ISFLAG_IDENT_MASK) == ISFLAG_IDENT_MASK);
-}
-#endif
-
-bool item_ident( const item_def &item, unsigned long flags )
-{
- return (item.flags & flags);
-}
-
bool item_type_known( const item_def &item )
{
return item_ident(item, ISFLAG_KNOW_TYPE)
@@ -98,293 +65,35 @@ bool item_type_known( const item_def &item )
&& id[IDTYPE_JEWELLERY][item.sub_type] == ID_KNOWN_TYPE);
}
-bool item_not_ident( const item_def &item, unsigned long flags )
-{
- return ( !(item.flags & flags) );
-}
-
-void do_curse_item( item_def &item )
-{
- item.flags |= ISFLAG_CURSED;
-}
-
-void do_uncurse_item( item_def &item )
-{
- item.flags &= (~ISFLAG_CURSED);
-}
-
-void set_ident_flags( item_def &item, unsigned long flags )
-{
- item.flags |= flags;
-}
-
-void unset_ident_flags( item_def &item, unsigned long flags )
-{
- item.flags &= (~flags);
-}
-
-// These six functions might seem silly, but they provide a nice layer
-// for later changes to these systems. -- bwr
-unsigned long get_equip_race( const item_def &item )
-{
- return (item.flags & ISFLAG_RACIAL_MASK);
-}
-
-unsigned long get_equip_desc( const item_def &item )
-{
- return (item.flags & ISFLAG_COSMETIC_MASK);
-}
-
-bool cmp_equip_race( const item_def &item, unsigned long val )
-{
- return (get_equip_race( item ) == val);
-}
-
-bool cmp_equip_desc( const item_def &item, unsigned long val )
-{
- return (get_equip_desc( item ) == val);
-}
-
-void set_equip_race( item_def &item, unsigned long flags )
-{
- ASSERT( (flags & ~ISFLAG_RACIAL_MASK) == 0 );
-
- // first check for base-sub pairs that can't ever have racial types
- switch (item.base_type)
- {
- case OBJ_WEAPONS:
- if (item.sub_type == WPN_GIANT_CLUB
- || item.sub_type == WPN_GIANT_SPIKED_CLUB
- || item.sub_type == WPN_KATANA
- || item.sub_type == WPN_SLING
- || item.sub_type == WPN_KNIFE
- || item.sub_type == WPN_QUARTERSTAFF
- || item.sub_type == WPN_DEMON_BLADE
- || item.sub_type == WPN_DEMON_WHIP
- || item.sub_type == WPN_DEMON_TRIDENT)
- {
- return;
- }
- break;
-
- case OBJ_ARMOUR:
- if (item.sub_type >= ARM_DRAGON_HIDE)
- {
- return;
- }
- break;
-
- case OBJ_MISSILES:
- if (item.sub_type == MI_STONE || item.sub_type == MI_LARGE_ROCK)
- {
- return;
- }
- break;
-
- default:
- return;
- }
-
- // check that item is appropriate for racial type
- switch (flags)
- {
- case ISFLAG_ELVEN:
- if (item.base_type == OBJ_ARMOUR
- && (item.sub_type == ARM_SPLINT_MAIL
- || item.sub_type == ARM_BANDED_MAIL
- || item.sub_type == ARM_PLATE_MAIL))
- {
- return;
- }
- break;
-
- case ISFLAG_DWARVEN:
- if (item.base_type == OBJ_ARMOUR
- && (item.sub_type == ARM_ROBE
- || item.sub_type == ARM_LEATHER_ARMOUR))
- {
- return;
- }
- break;
-
- case ISFLAG_ORCISH:
- default:
- break;
- }
-
- item.flags &= ~ISFLAG_RACIAL_MASK; // delete previous
- item.flags |= flags;
-}
-
-void set_equip_desc( item_def &item, unsigned long flags )
-{
- ASSERT( (flags & ~ISFLAG_COSMETIC_MASK) == 0 );
-
- item.flags &= ~ISFLAG_COSMETIC_MASK; // delete previous
- item.flags |= flags;
-}
-
-short get_helmet_type( const item_def &item )
-{
- ASSERT( item.base_type == OBJ_ARMOUR && item.sub_type == ARM_HELMET );
-
- return (item.plus2 & THELM_TYPE_MASK);
-}
-
-short get_helmet_desc( const item_def &item )
-{
- ASSERT( item.base_type == OBJ_ARMOUR && item.sub_type == ARM_HELMET );
-
- return (item.plus2 & THELM_DESC_MASK);
-}
-
-void set_helmet_type( item_def &item, short type )
-{
- ASSERT( (type & ~THELM_TYPE_MASK) == 0 );
- ASSERT( item.base_type == OBJ_ARMOUR && item.sub_type == ARM_HELMET );
-
- item.plus2 &= ~THELM_TYPE_MASK;
- item.plus2 |= type;
-}
-
-void set_helmet_desc( item_def &item, short type )
-{
- ASSERT( (type & ~THELM_DESC_MASK) == 0 );
- ASSERT( item.base_type == OBJ_ARMOUR && item.sub_type == ARM_HELMET );
-
- item.plus2 &= ~THELM_DESC_MASK;
- item.plus2 |= type;
-}
-
-void set_helmet_random_desc( item_def &item )
-{
- ASSERT( item.base_type == OBJ_ARMOUR && item.sub_type == ARM_HELMET );
-
- item.plus2 &= ~THELM_DESC_MASK;
- item.plus2 |= (random2(8) << 8);
-}
-
-bool cmp_helmet_type( const item_def &item, short val )
-{
- ASSERT( item.base_type == OBJ_ARMOUR && item.sub_type == ARM_HELMET );
-
- return (get_helmet_type( item ) == val);
-}
-
-bool cmp_helmet_desc( const item_def &item, short val )
-{
- ASSERT( item.base_type == OBJ_ARMOUR && item.sub_type == ARM_HELMET );
-
- return (get_helmet_desc( item ) == val);
-}
-
-bool set_item_ego_type( item_def &item, int item_type, int ego_type )
-{
- if (item.base_type == item_type
- && !is_random_artefact( item )
- && !is_fixed_artefact( item ))
- {
- item.special = ego_type;
- return (true);
- }
-
- return (false);
-}
-
-int get_weapon_brand( const item_def &item )
-{
- // Weapon ego types are "brands", so we do the randart lookup here.
-
- // Staves "brands" handled specially
- if (item.base_type != OBJ_WEAPONS)
- return (SPWPN_NORMAL);
-
- if (is_fixed_artefact( item ))
- {
- switch (item.special)
- {
- case SPWPN_SWORD_OF_CEREBOV:
- return (SPWPN_FLAMING);
-
- case SPWPN_STAFF_OF_OLGREB:
- return (SPWPN_VENOM);
-
- case SPWPN_VAMPIRES_TOOTH:
- return (SPWPN_VAMPIRICISM);
-
- default:
- return (SPWPN_NORMAL);
- }
- }
- else if (is_random_artefact( item ))
- {
- return (randart_wpn_property( item, RAP_BRAND ));
- }
-
- return (item.special);
-}
-
-int get_ammo_brand( const item_def &item )
-{
- // no artefact arrows yet -- bwr
- if (item.base_type != OBJ_MISSILES || is_random_artefact( item ))
- return (SPMSL_NORMAL);
-
- return (item.special);
-}
-
-int get_armour_ego_type( const item_def &item )
-{
- // artefact armours have no ego type, must look up powers separately
- if (item.base_type != OBJ_ARMOUR
- || (is_random_artefact( item ) && !is_unrandom_artefact( item )))
- {
- return (SPARM_NORMAL);
- }
-
- return (item.special);
-}
-
-bool item_is_rod( const item_def &item )
-{
- return (item.base_type == OBJ_STAVES
- && item.sub_type >= STAFF_SMITING && item.sub_type < STAFF_AIR);
-}
-
-bool item_is_staff( const item_def &item )
-{
- // Isn't De Morgan's law wonderful. -- bwr
- return (item.base_type == OBJ_STAVES
- && (item.sub_type < STAFF_SMITING || item.sub_type >= STAFF_AIR));
-}
-
// it_name() and in_name() are now somewhat obsolete now that itemname
-// takes item_def, so consider them depricated.
-void it_name( int itn, char des, char buff[ ITEMNAME_SIZE ], bool terse )
+// takes item_def, so consider them deprecated.
+const char *it_name( int itn, char des, char *buff, bool terse )
{
- item_name( mitm[itn], des, buff, terse );
+ return item_name( mitm[itn], des, buff, terse );
} // end it_name()
-void in_name( int inn, char des, char buff[ ITEMNAME_SIZE ], bool terse )
+const char *in_name( int inn, char des, char *buff, bool terse )
{
- item_name( you.inv[inn], des, buff, terse );
+ return item_name( you.inv[inn], des, buff, terse );
} // end in_name()
// quant_name is usful since it prints out a different number of items
// than the item actually contains.
-void quant_name( const item_def &item, int quant, char des,
+const char *quant_name( const item_def &item, int quant, char des,
char buff[ ITEMNAME_SIZE ], bool terse )
{
// item_name now requires a "real" item, so we'll mangle a tmp
item_def tmp = item;
tmp.quantity = quant;
- item_name( tmp, des, buff, terse );
+ return item_name( tmp, des, buff, terse );
} // end quant_name()
-char item_name( const item_def &item, char descrip, char buff[ ITEMNAME_SIZE ],
- bool terse )
+// buff must be at least ITEMNAME_SIZE if non-NULL. If NULL, a static
+// item buffer will be used.
+const char *item_name( const item_def &item, char descrip,
+ char *buff, bool terse )
{
const int item_clas = item.base_type;
const int item_typ = item.sub_type;
@@ -393,6 +102,9 @@ char item_name( const item_def &item, char descrip, char buff[ ITEMNAME_SIZE ],
char tmp_quant[20];
char itm_name[ ITEMNAME_SIZE ] = "";
+ if (!buff)
+ buff = default_itembuf;
+
item_name_2( item, itm_name, terse );
buff[0] = '\0';
@@ -400,7 +112,7 @@ char item_name( const item_def &item, char descrip, char buff[ ITEMNAME_SIZE ],
if (descrip == DESC_INVENTORY_EQUIP || descrip == DESC_INVENTORY)
{
if (in_inventory(item)) // actually in inventory
- snprintf( buff, ITEMNAME_SIZE, (terse) ? "%c) " : "%c - ",
+ snprintf( buff, ITEMNAME_SIZE, (terse) ? "%c) " : "%c - ",
index_to_letter( item.link ) );
else
descrip = DESC_CAP_A;
@@ -561,15 +273,24 @@ char item_name( const item_def &item, char descrip, char buff[ ITEMNAME_SIZE ],
strncat( buff, " (around neck)", ITEMNAME_SIZE );
}
}
+ /*** HP CHANGE -- warning -- possible stack overflow error ***/
+ if ( item.inscription.size() > 0 ) // has an inscription
+ {
+ strncat( buff, " {", 2 );
+ strncat( buff, item.inscription.c_str(), ITEMNAME_SIZE );
+ strncat( buff, "}", 1 );
+ }
- return (1);
+ return (buff);
} // end item_name()
// Note that "terse" is only currently used for the "in hand" listing on
// the game screen.
-static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
- bool terse )
+static const char *item_name_2(
+ const item_def &item,
+ char buff[ITEMNAME_SIZE],
+ bool terse )
{
const int item_clas = item.base_type;
const int item_typ = item.sub_type;
@@ -598,7 +319,7 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
if (item_cursed( item ))
strncat(buff, "cursed ", ITEMNAME_SIZE );
else if (Options.show_uncursed
- && item_not_ident( item, ISFLAG_KNOW_PLUSES ))
+ && !item_ident( item, ISFLAG_KNOW_PLUSES ))
{
strncat(buff, "uncursed ", ITEMNAME_SIZE );
}
@@ -687,7 +408,7 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
// Now that we can have "glowing elven" weapons, it's
// probably a good idea to cut out the descriptive
// term once it's become obsolete. -- bwr
- if (item_not_ident( item, ISFLAG_KNOW_PLUSES ) && !terse)
+ if (!item_ident( item, ISFLAG_KNOW_PLUSES ) && !terse)
{
switch (get_equip_desc( item ))
{
@@ -760,7 +481,14 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
strncat(buff, (terse) ? " (speed)" : " of speed", ITEMNAME_SIZE );
break;
case SPWPN_VORPAL:
- switch (damage_type(item_clas, item_typ))
+ if (is_range_weapon( item ))
+ {
+ strncat(buff, (terse) ? " (velocity)" : " of velocity",
+ ITEMNAME_SIZE );
+ break;
+ }
+
+ switch (get_vorpal_type(item))
{
case DVORP_CRUSHING:
strncat(buff, (terse) ? " (crush)" : " of crushing", ITEMNAME_SIZE );
@@ -774,6 +502,12 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
case DVORP_CHOPPING:
strncat(buff, (terse) ? " (chop)" : " of chopping", ITEMNAME_SIZE );
break;
+ case DVORP_SLASHING:
+ strncat(buff, (terse) ? " (slash)" : " of slashing", ITEMNAME_SIZE );
+ break;
+ case DVORP_STABBING:
+ strncat(buff, (terse) ? " (stab)" : " of stabbing", ITEMNAME_SIZE );
+ break;
}
break;
@@ -819,6 +553,11 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
{
strncat( buff, (terse) ? "poison " : "poisoned ", ITEMNAME_SIZE );
}
+
+ if (brand == SPMSL_CURARE)
+ {
+ strncat( buff, (terse) ? "curare " : "curare-tipped ", ITEMNAME_SIZE);
+ }
if (item_ident( item, ISFLAG_KNOW_PLUSES ))
{
@@ -848,8 +587,8 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
(item_typ == MI_BOLT) ? "bolt" :
(item_typ == MI_DART) ? "dart" :
(item_typ == MI_NEEDLE) ? "needle" :
- (item_typ == MI_EGGPLANT) ? "eggplant" :
- (item_typ == MI_LARGE_ROCK) ? "large rock" : "", ITEMNAME_SIZE);
+ (item_typ == MI_LARGE_ROCK) ? "large rock" :
+ "hysterical raisin", ITEMNAME_SIZE);
// this should probably be "" {dlb}
if (it_quant > 1)
@@ -862,7 +601,9 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
(brand == SPMSL_ICE) ? ((terse) ? " (ice)" : " of ice") :
(brand == SPMSL_NORMAL) ? "" :
(brand == SPMSL_POISONED) ? "" :
- (brand == SPMSL_POISONED_II) ? "" : " (buggy)", ITEMNAME_SIZE );
+ (brand == SPMSL_POISONED_II) ? "" :
+ (brand == SPMSL_CURARE) ? "" :
+ " (buggy)", ITEMNAME_SIZE );
}
break;
@@ -872,7 +613,7 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
if (item_cursed( item ))
strncat(buff, "cursed ", ITEMNAME_SIZE );
else if (Options.show_uncursed
- && item_not_ident( item, ISFLAG_KNOW_PLUSES ))
+ && !item_ident( item, ISFLAG_KNOW_PLUSES ))
{
strncat(buff, "uncursed ", ITEMNAME_SIZE );
}
@@ -889,8 +630,7 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
strncat(buff, " ", ITEMNAME_SIZE );
}
- if (item_typ == ARM_GLOVES
- || (item_typ == ARM_BOOTS && item_plus2 == TBOOT_BOOTS))
+ if (item_typ == ARM_GLOVES || item_typ == ARM_BOOTS)
{
strncat( buff, "pair of ", ITEMNAME_SIZE );
}
@@ -904,7 +644,7 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
// Now that we can have "glowing elven" armour, it's
// probably a good idea to cut out the descriptive
// term once it's become obsolete. -- bwr
- if (item_not_ident( item, ISFLAG_KNOW_PLUSES ) && !terse)
+ if (!item_ident( item, ISFLAG_KNOW_PLUSES ) && !terse)
{
switch (get_equip_desc( item ))
{
@@ -1129,43 +869,36 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
}
else
{
- char primary = item.special / 14;
- char secondary = item.special % 14;
-
- strncat(buff,
- (primary == 0) ? "" :
- (primary == 1) ? "bubbling " :
- (primary == 2) ? "lumpy " :
- (primary == 3) ? "fuming " :
- (primary == 4) ? "smoky " :
- (primary == 5) ? "fizzy " :
- (primary == 6) ? "glowing " :
- (primary == 7) ? "sedimented " :
- (primary == 8) ? "metallic " :
- (primary == 9) ? "murky " :
- (primary == 10) ? "gluggy " :
- (primary == 11) ? "viscous " :
- (primary == 12) ? "oily " :
- (primary == 13) ? "slimy " :
- (primary == 14) ? "emulsified " : "buggy ", ITEMNAME_SIZE);
-
- strncat(buff,
- (secondary == 0) ? "clear" :
- (secondary == 1) ? "blue" :
- (secondary == 2) ? "black" :
- (secondary == 3) ? "silvery" :
- (secondary == 4) ? "cyan" :
- (secondary == 5) ? "purple" :
- (secondary == 6) ? "orange" :
- (secondary == 7) ? "inky" :
- (secondary == 8) ? "red" :
- (secondary == 9) ? "yellow" :
- (secondary == 10) ? "green" :
- (secondary == 11) ? "brown" :
- (secondary == 12) ? "pink" :
- (secondary == 13) ? "white" : "buggy", ITEMNAME_SIZE);
-
- strncat(buff, " potion", ITEMNAME_SIZE );
+ int pqual = PQUAL(item.special);
+ int pcolour = PCOLOUR(item.special);
+
+ static const char *potion_qualifiers[] = {
+ "", "bubbling ", "fuming ", "fizzy ", "viscous ", "lumpy ",
+ "smoky ", "glowing ", "sedimented ", "metallic ", "murky ",
+ "gluggy ", "oily ", "slimy ", "emulsified "
+ };
+ ASSERT( sizeof(potion_qualifiers) / sizeof(*potion_qualifiers)
+ == PDQ_NQUALS );
+
+ static const char *potion_colours[] = {
+ "clear", "blue", "black", "silvery", "cyan", "purple",
+ "orange", "inky", "red", "yellow", "green", "brown", "pink",
+ "white"
+ };
+ ASSERT( sizeof(potion_colours) / sizeof(*potion_colours)
+ == PDC_NCOLOURS );
+
+ const char *qualifier =
+ (pqual < 0 || pqual >= PDQ_NQUALS)? "bug-filled "
+ : potion_qualifiers[pqual];
+
+ const char *colour =
+ (pcolour < 0 || pcolour >= PDC_NCOLOURS)? "bogus"
+ : potion_colours[pcolour];
+
+ strncat(buff, qualifier, ITEMNAME_SIZE - strlen(buff));
+ strncat(buff, colour, ITEMNAME_SIZE - strlen(buff));
+ strncat(buff, " potion", ITEMNAME_SIZE - strlen(buff) );
if (it_quant > 1)
strncat(buff, "s", ITEMNAME_SIZE );
@@ -1309,7 +1042,11 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
strncat(buff, "labeled ", ITEMNAME_SIZE );
char buff3[ ITEMNAME_SIZE ];
- make_name( item.special, it_plus, item_clas, 2, buff3 );
+ const unsigned long sseed =
+ item.special
+ + static_cast<unsigned long>(it_plus)
+ + (static_cast<unsigned long>(item_clas) << 16);
+ make_name( sseed, true, buff3 );
strncat( buff, buff3 , ITEMNAME_SIZE );
if (id[ IDTYPE_SCROLLS ][item_typ] == ID_TRIED_TYPE)
@@ -1328,8 +1065,14 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
{
if (item_cursed( item ))
strncat(buff, "cursed ", ITEMNAME_SIZE );
- else if (Options.show_uncursed
- && item_not_ident( item, ISFLAG_KNOW_PLUSES ))
+ else if (Options.show_uncursed
+ && !terse
+ && (!ring_has_pluses(item)
+ || !item_ident(item, ISFLAG_KNOW_PLUSES))
+
+ // If the item is worn, its curse status is known,
+ // no need to belabour the obvious.
+ && get_equip_slot( &item ) == -1)
{
strncat(buff, "uncursed ", ITEMNAME_SIZE );
}
@@ -1683,7 +1426,7 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
switch (item_typ)
{
case MISC_RUNE_OF_ZOT:
- strncat( buff, (it_plus == RUNE_DIS) ? "iron" :
+ strncat(buff, (it_plus == RUNE_DIS) ? "iron" :
(it_plus == RUNE_GEHENNA) ? "obsidian" :
(it_plus == RUNE_COCYTUS) ? "icy" :
(it_plus == RUNE_TARTARUS) ? "bone" :
@@ -1721,7 +1464,7 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
case MISC_DECK_OF_TRICKS:
case MISC_DECK_OF_WONDERS:
strncat(buff, "deck of ", ITEMNAME_SIZE );
- strncat(buff, item_not_ident( item, ISFLAG_KNOW_TYPE ) ? "cards" :
+ strncat(buff, !item_ident( item, ISFLAG_KNOW_TYPE ) ? "cards" :
(item_typ == MISC_DECK_OF_WONDERS) ? "wonders" :
(item_typ == MISC_DECK_OF_SUMMONINGS) ? "summonings" :
(item_typ == MISC_DECK_OF_TRICKS) ? "tricks" :
@@ -1773,7 +1516,7 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
break;
case MISC_LANTERN_OF_SHADOWS:
- if (item_not_ident( item, ISFLAG_KNOW_TYPE ))
+ if (!item_ident( item, ISFLAG_KNOW_TYPE ))
strncat(buff, "bone ", ITEMNAME_SIZE );
strncat(buff, "lantern", ITEMNAME_SIZE );
@@ -1782,7 +1525,7 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
break;
case MISC_HORN_OF_GERYON:
- if (item_not_ident( item, ISFLAG_KNOW_TYPE ))
+ if (!item_ident( item, ISFLAG_KNOW_TYPE ))
strncat(buff, "silver ", ITEMNAME_SIZE );
strncat(buff, "horn", ITEMNAME_SIZE );
@@ -1791,7 +1534,7 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
break;
case MISC_DISC_OF_STORMS:
- if (item_not_ident( item, ISFLAG_KNOW_TYPE ))
+ if (!item_ident( item, ISFLAG_KNOW_TYPE ))
strncat(buff, "grey ", ITEMNAME_SIZE );
strncat(buff, "disc", ITEMNAME_SIZE );
@@ -1800,7 +1543,7 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
break;
case MISC_STONE_OF_EARTH_ELEMENTALS:
- if (item_not_ident( item, ISFLAG_KNOW_TYPE ))
+ if (!item_ident( item, ISFLAG_KNOW_TYPE ))
strncat(buff, "nondescript ", ITEMNAME_SIZE );
strncat(buff, "stone", ITEMNAME_SIZE );
@@ -1809,7 +1552,7 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
break;
case MISC_BOTTLED_EFREET:
- strncat(buff, (item_not_ident( item, ISFLAG_KNOW_TYPE ))
+ strncat(buff, (!item_ident( item, ISFLAG_KNOW_TYPE ))
? "sealed bronze flask" : "bottled efreet",
ITEMNAME_SIZE );
break;
@@ -1826,7 +1569,7 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
// compacted 15 Apr 2000 {dlb}:
case OBJ_BOOKS:
- if (item_not_ident( item, ISFLAG_KNOW_TYPE ))
+ if (!item_ident( item, ISFLAG_KNOW_TYPE ))
{
char primary = (item.special / 10);
char secondary = (item.special % 10);
@@ -1923,7 +1666,7 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
// compacted 15 Apr 2000 {dlb}:
case OBJ_STAVES:
- if (item_not_ident( item, ISFLAG_KNOW_TYPE ))
+ if (!item_ident( item, ISFLAG_KNOW_TYPE ))
{
strncat(buff, (item.special == 0) ? "curved" :
(item.special == 1) ? "glowing" :
@@ -1989,6 +1732,19 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
(item_typ == STAFF_CHANNELING) ? "channeling"
: "bugginess", ITEMNAME_SIZE );
}
+
+ if (item_is_rod( item ) && item.sub_type != STAFF_STRIKING
+ && item_ident( item, ISFLAG_KNOW_TYPE ))
+ {
+ strncat( buff, " (", ITEMNAME_SIZE );
+ itoa( item.plus / ROD_CHARGE_MULT, tmp_quant, 10 );
+ strncat( buff, tmp_quant, ITEMNAME_SIZE );
+ strncat( buff, "/", ITEMNAME_SIZE );
+ itoa( item.plus2 / ROD_CHARGE_MULT, tmp_quant, 10 );
+ strncat( buff, tmp_quant, ITEMNAME_SIZE );
+ strncat( buff, ")", ITEMNAME_SIZE );
+ }
+
break;
@@ -2133,7 +1889,7 @@ static char item_name_2( const item_def &item, char buff[ITEMNAME_SIZE],
strncat(buff, "s", ITEMNAME_SIZE );
}
- return 1;
+ return (buff);
} // end item_name_2()
void save_id(char identy[4][50])
@@ -2219,1035 +1975,401 @@ char get_ident_type(char cla, int ty)
}
} // end get_ident_type()
-int property( const item_def &item, int prop_type )
+static MenuEntry *discoveries_item_mangle(MenuEntry *me)
{
- switch (item.base_type)
- {
- case OBJ_ARMOUR:
- case OBJ_WEAPONS:
- case OBJ_MISSILES:
- return (prop[ item.base_type ][ item.sub_type ][ prop_type ]);
-
- case OBJ_STAVES:
- if (item_is_staff( item ))
- return (prop[ OBJ_WEAPONS ][ WPN_QUARTERSTAFF ][ prop_type ]);
- else if (prop_type == PWPN_SPEED) // item is rod
- return (10); // extra protection against speed 0
- else
- return (0);
-
- default:
- return (0);
- }
+ InvEntry *ie = dynamic_cast<InvEntry*>(me);
+ MenuEntry *newme = new MenuEntry;
+ std::string txt = item_name(*ie->item, DESC_PLAIN);
+ newme->text = " " + txt;
+ newme->quantity = 0;
+ delete me;
+
+ return (newme);
}
-int mass_item( const item_def &item )
+void check_item_knowledge()
{
- int unit_mass = 0;
-
- if (item.base_type == OBJ_GOLD)
- {
- unit_mass = 0;
+ int i,j;
+
+ std::vector<const item_def*> items;
+
+ int idx_to_objtype[4] = { OBJ_WANDS, OBJ_SCROLLS,
+ OBJ_JEWELLERY, OBJ_POTIONS };
+ int idx_to_maxtype[4] = { NUM_WANDS, NUM_SCROLLS,
+ NUM_JEWELLERY, NUM_POTIONS };
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < idx_to_maxtype[i]; j++) {
+ if (id[i][j] == ID_KNOWN_TYPE) {
+ item_def* ptmp = new item_def;
+ if ( ptmp != 0 ) {
+ ptmp->base_type = idx_to_objtype[i];
+ ptmp->sub_type = j;
+ ptmp->colour = 1;
+ ptmp->quantity = 1;
+ items.push_back(ptmp);
+ }
+ }
+ }
}
- else if (item.base_type == OBJ_CORPSES)
- {
- unit_mass = mons_weight( item.plus );
- if (item.sub_type == CORPSE_SKELETON)
- unit_mass /= 2;
- }
- else
- {
- unit_mass = mss[ item.base_type ][ item.sub_type ];
+ if (items.empty())
+ mpr("You don't recognise anything yet!");
+ else {
+ InvMenu menu;
+ menu.set_title("You recognise:");
+ menu.load_items(items, discoveries_item_mangle);
+ menu.set_flags(MF_NOSELECT);
+ menu.show();
+ redraw_screen();
+
+ for ( std::vector<const item_def*>::iterator iter = items.begin();
+ iter != items.end(); ++iter )
+ delete *iter;
}
+} // end check_item_knowledge()
- return (unit_mass > 0 ? unit_mass : 0);
-}
-void init_properties(void)
+// Used for: Pandemonium demonlords, shopkeepers, scrolls, random artefacts
+int make_name( unsigned long seed, bool all_cap, char buff[ ITEMNAME_SIZE ] )
{
- prop[OBJ_ARMOUR][ARM_ROBE][PARM_AC] = 1;
- prop[OBJ_ARMOUR][ARM_ROBE][PARM_EVASION] = 0;
- mss[OBJ_ARMOUR][ARM_ROBE] = 60;
-
- prop[OBJ_ARMOUR][ARM_LEATHER_ARMOUR][PARM_AC] = 2;
- prop[OBJ_ARMOUR][ARM_LEATHER_ARMOUR][PARM_EVASION] = -1;
- mss[OBJ_ARMOUR][ARM_LEATHER_ARMOUR] = 150;
-
- prop[OBJ_ARMOUR][ARM_RING_MAIL][PARM_AC] = 4;
- prop[OBJ_ARMOUR][ARM_RING_MAIL][PARM_EVASION] = -2;
- mss[OBJ_ARMOUR][ARM_RING_MAIL] = 300;
-
- prop[OBJ_ARMOUR][ARM_SCALE_MAIL][PARM_AC] = 5;
- prop[OBJ_ARMOUR][ARM_SCALE_MAIL][PARM_EVASION] = -2;
- mss[OBJ_ARMOUR][ARM_SCALE_MAIL] = 400;
-
- prop[OBJ_ARMOUR][ARM_CHAIN_MAIL][PARM_AC] = 6;
- prop[OBJ_ARMOUR][ARM_CHAIN_MAIL][PARM_EVASION] = -3;
- mss[OBJ_ARMOUR][ARM_CHAIN_MAIL] = 450;
-
- prop[OBJ_ARMOUR][ARM_SPLINT_MAIL][PARM_AC] = 8;
- prop[OBJ_ARMOUR][ARM_SPLINT_MAIL][PARM_EVASION] = -5;
- mss[OBJ_ARMOUR][ARM_SPLINT_MAIL] = 550;
-
- prop[OBJ_ARMOUR][ARM_BANDED_MAIL][PARM_AC] = 7;
- prop[OBJ_ARMOUR][ARM_BANDED_MAIL][PARM_EVASION] = -4;
- mss[OBJ_ARMOUR][ARM_BANDED_MAIL] = 500;
-
- prop[OBJ_ARMOUR][ARM_PLATE_MAIL][PARM_AC] = 9;
- prop[OBJ_ARMOUR][ARM_PLATE_MAIL][PARM_EVASION] = -5;
- mss[OBJ_ARMOUR][ARM_PLATE_MAIL] = 650;
-
- prop[OBJ_ARMOUR][ARM_DRAGON_HIDE][PARM_AC] = 2;
- prop[OBJ_ARMOUR][ARM_DRAGON_HIDE][PARM_EVASION] = -2;
- mss[OBJ_ARMOUR][ARM_DRAGON_HIDE] = 220;
-
- prop[OBJ_ARMOUR][ARM_TROLL_HIDE][PARM_AC] = 1;
- prop[OBJ_ARMOUR][ARM_TROLL_HIDE][PARM_EVASION] = -1;
- mss[OBJ_ARMOUR][ARM_TROLL_HIDE] = 180;
-
- prop[OBJ_ARMOUR][ARM_CRYSTAL_PLATE_MAIL][PARM_AC] = 16;
- prop[OBJ_ARMOUR][ARM_CRYSTAL_PLATE_MAIL][PARM_EVASION] = -8;
- mss[OBJ_ARMOUR][ARM_CRYSTAL_PLATE_MAIL] = 1200;
-
- prop[OBJ_ARMOUR][ARM_DRAGON_ARMOUR][PARM_AC] = 8;
- prop[OBJ_ARMOUR][ARM_DRAGON_ARMOUR][PARM_EVASION] = -2;
- mss[OBJ_ARMOUR][ARM_DRAGON_ARMOUR] = 220;
-
- prop[OBJ_ARMOUR][ARM_TROLL_LEATHER_ARMOUR][PARM_AC] = 3;
- prop[OBJ_ARMOUR][ARM_TROLL_LEATHER_ARMOUR][PARM_EVASION] = -1;
- mss[OBJ_ARMOUR][ARM_TROLL_LEATHER_ARMOUR] = 180;
-
- prop[OBJ_ARMOUR][ARM_ICE_DRAGON_HIDE][PARM_AC] = 2;
- prop[OBJ_ARMOUR][ARM_ICE_DRAGON_HIDE][PARM_EVASION] = -2;
- mss[OBJ_ARMOUR][ARM_ICE_DRAGON_HIDE] = 220;
-
- prop[OBJ_ARMOUR][ARM_ICE_DRAGON_ARMOUR][PARM_AC] = 9;
- prop[OBJ_ARMOUR][ARM_ICE_DRAGON_ARMOUR][PARM_EVASION] = -2;
- mss[OBJ_ARMOUR][ARM_ICE_DRAGON_ARMOUR] = 220;
-
- prop[OBJ_ARMOUR][ARM_STEAM_DRAGON_HIDE][PARM_AC] = 0;
- prop[OBJ_ARMOUR][ARM_STEAM_DRAGON_HIDE][PARM_EVASION] = 0;
- mss[OBJ_ARMOUR][ARM_STEAM_DRAGON_HIDE] = 120;
-
- prop[OBJ_ARMOUR][ARM_STEAM_DRAGON_ARMOUR][PARM_AC] = 3;
- prop[OBJ_ARMOUR][ARM_STEAM_DRAGON_ARMOUR][PARM_EVASION] = 0;
- mss[OBJ_ARMOUR][ARM_STEAM_DRAGON_ARMOUR] = 120;
-
- prop[OBJ_ARMOUR][ARM_MOTTLED_DRAGON_HIDE][PARM_AC] = 1;
- prop[OBJ_ARMOUR][ARM_MOTTLED_DRAGON_HIDE][PARM_EVASION] = -1;
- mss[OBJ_ARMOUR][ARM_MOTTLED_DRAGON_HIDE] = 150;
-
- prop[OBJ_ARMOUR][ARM_MOTTLED_DRAGON_ARMOUR][PARM_AC] = 5;
- prop[OBJ_ARMOUR][ARM_MOTTLED_DRAGON_ARMOUR][PARM_EVASION] = -1;
- mss[OBJ_ARMOUR][ARM_MOTTLED_DRAGON_ARMOUR] = 150;
-
- prop[OBJ_ARMOUR][ARM_STORM_DRAGON_HIDE][PARM_AC] = 2;
- prop[OBJ_ARMOUR][ARM_STORM_DRAGON_HIDE][PARM_EVASION] = -5;
- mss[OBJ_ARMOUR][ARM_STORM_DRAGON_HIDE] = 400;
-
- prop[OBJ_ARMOUR][ARM_STORM_DRAGON_ARMOUR][PARM_AC] = 10;
- prop[OBJ_ARMOUR][ARM_STORM_DRAGON_ARMOUR][PARM_EVASION] = -5;
- mss[OBJ_ARMOUR][ARM_STORM_DRAGON_ARMOUR] = 400;
-
- prop[OBJ_ARMOUR][ARM_GOLD_DRAGON_HIDE][PARM_AC] = 2;
- prop[OBJ_ARMOUR][ARM_GOLD_DRAGON_HIDE][PARM_EVASION] = -10;
- mss[OBJ_ARMOUR][ARM_GOLD_DRAGON_HIDE] = 1100;
-
- prop[OBJ_ARMOUR][ARM_GOLD_DRAGON_ARMOUR][PARM_AC] = 13;
- prop[OBJ_ARMOUR][ARM_GOLD_DRAGON_ARMOUR][PARM_EVASION] = -10;
- mss[OBJ_ARMOUR][ARM_GOLD_DRAGON_ARMOUR] = 1100;
-
- prop[OBJ_ARMOUR][ARM_ANIMAL_SKIN][PARM_AC] = 1;
- prop[OBJ_ARMOUR][ARM_ANIMAL_SKIN][PARM_EVASION] = 0;
- mss[OBJ_ARMOUR][ARM_ANIMAL_SKIN] = 100;
-
- prop[OBJ_ARMOUR][ARM_SWAMP_DRAGON_HIDE][PARM_AC] = 1;
- prop[OBJ_ARMOUR][ARM_SWAMP_DRAGON_HIDE][PARM_EVASION] = -2;
- mss[OBJ_ARMOUR][ARM_SWAMP_DRAGON_HIDE] = 200;
-
- prop[OBJ_ARMOUR][ARM_SWAMP_DRAGON_ARMOUR][PARM_AC] = 7;
- prop[OBJ_ARMOUR][ARM_SWAMP_DRAGON_ARMOUR][PARM_EVASION] = -2;
- mss[OBJ_ARMOUR][ARM_SWAMP_DRAGON_ARMOUR] = 200;
-
- prop[OBJ_ARMOUR][ARM_SHIELD][PARM_AC] = 0;
- prop[OBJ_ARMOUR][ARM_SHIELD][PARM_EVASION] = 0;
- mss[OBJ_ARMOUR][ARM_SHIELD] = 100;
-
- prop[OBJ_ARMOUR][ARM_CLOAK][PARM_AC] = 1;
- prop[OBJ_ARMOUR][ARM_CLOAK][PARM_EVASION] = 0;
- mss[OBJ_ARMOUR][ARM_CLOAK] = 20;
-
- prop[OBJ_ARMOUR][ARM_HELMET][PARM_AC] = 1;
- prop[OBJ_ARMOUR][ARM_HELMET][PARM_EVASION] = 0;
- mss[OBJ_ARMOUR][ARM_HELMET] = 80;
-
- prop[OBJ_ARMOUR][ARM_GLOVES][PARM_AC] = 1;
- prop[OBJ_ARMOUR][ARM_GLOVES][PARM_EVASION] = 0;
- mss[OBJ_ARMOUR][ARM_GLOVES] = 20;
-
- prop[OBJ_ARMOUR][ARM_BOOTS][PARM_AC] = 1;
- prop[OBJ_ARMOUR][ARM_BOOTS][PARM_EVASION] = 0;
- mss[OBJ_ARMOUR][ARM_BOOTS] = 40;
-
- prop[OBJ_ARMOUR][ARM_BUCKLER][PARM_AC] = 0;
- prop[OBJ_ARMOUR][ARM_BUCKLER][PARM_EVASION] = 0;
- mss[OBJ_ARMOUR][ARM_BUCKLER] = 50;
-
- prop[OBJ_ARMOUR][ARM_LARGE_SHIELD][PARM_AC] = 0;
- prop[OBJ_ARMOUR][ARM_LARGE_SHIELD][PARM_EVASION] = 0;
- mss[OBJ_ARMOUR][ARM_LARGE_SHIELD] = 250;
+ char name[ITEMNAME_SIZE];
+ int numb[17];
int i = 0;
+ bool want_vowel = false;
+ bool has_space = false;
+
+ for (i = 0; i < ITEMNAME_SIZE; i++)
+ name[i] = '\0';
+
+ const int var1 = (seed & 0xFF);
+ const int var2 = ((seed >> 8) & 0xFF);
+ const int var3 = ((seed >> 16) & 0xFF);
+ const int var4 = ((seed >> 24) & 0xFF);
+
+ numb[0] = 373 * var1 + 409 * var2 + 281 * var3;
+ numb[1] = 163 * var4 + 277 * var2 + 317 * var3;
+ numb[2] = 257 * var1 + 179 * var4 + 83 * var3;
+ numb[3] = 61 * var1 + 229 * var2 + 241 * var4;
+ numb[4] = 79 * var1 + 263 * var2 + 149 * var3;
+ numb[5] = 233 * var4 + 383 * var2 + 311 * var3;
+ numb[6] = 199 * var1 + 211 * var4 + 103 * var3;
+ numb[7] = 139 * var1 + 109 * var2 + 349 * var4;
+ numb[8] = 43 * var1 + 389 * var2 + 359 * var3;
+ numb[9] = 367 * var4 + 101 * var2 + 251 * var3;
+ numb[10] = 293 * var1 + 59 * var4 + 151 * var3;
+ numb[11] = 331 * var1 + 107 * var2 + 307 * var4;
+ numb[12] = 73 * var1 + 157 * var2 + 347 * var3;
+ numb[13] = 379 * var4 + 353 * var2 + 227 * var3;
+ numb[14] = 181 * var1 + 173 * var4 + 193 * var3;
+ numb[15] = 131 * var1 + 167 * var2 + 53 * var4;
+ numb[16] = 313 * var1 + 127 * var2 + 401 * var3 + 337 * var4;
+
+ int len = 3 + numb[0] % 5 + ((numb[1] % 5 == 0) ? numb[2] % 6 : 1);
+
+ if (all_cap)
+ len += 6;
+
+ int j = numb[3] % 17;
+ const int k = numb[4] % 17;
+ int count = 0;
- for (i = 0; i < 50; i++)
- {
- mss[OBJ_WANDS][i] = 100;
- mss[OBJ_FOOD][i] = 100;
- mss[OBJ_UNKNOWN_I][i] = 200; // labeled as "books" elsewhere
-
- //jmf: made scrolls, jewellery and potions weigh less.
- mss[OBJ_SCROLLS][i] = 20;
- mss[OBJ_JEWELLERY][i] = 10;
- mss[OBJ_POTIONS][i] = 40;
- mss[OBJ_UNKNOWN_II][i] = 5; // "gems"
- mss[OBJ_BOOKS][i] = 70;
-
- mss[OBJ_STAVES][i] = 130;
- mss[OBJ_ORBS][i] = 300;
- mss[OBJ_MISCELLANY][i] = 100;
- mss[OBJ_CORPSES][i] = 100;
- }
-
- // rods are lighter than staves
- for (i = STAFF_SMITING; i < STAFF_AIR; i++)
- {
- mss[OBJ_STAVES][i] = 70;
- }
-
- // this is food, right?
- mss[OBJ_FOOD][FOOD_MEAT_RATION] = 80;
- mss[OBJ_FOOD][FOOD_BREAD_RATION] = 80;
- mss[OBJ_FOOD][FOOD_PEAR] = 20;
- mss[OBJ_FOOD][FOOD_APPLE] = 20;
- mss[OBJ_FOOD][FOOD_CHOKO] = 30;
- mss[OBJ_FOOD][FOOD_HONEYCOMB] = 40;
- mss[OBJ_FOOD][FOOD_ROYAL_JELLY] = 55;
- mss[OBJ_FOOD][FOOD_SNOZZCUMBER] = 50;
- mss[OBJ_FOOD][FOOD_PIZZA] = 40;
- mss[OBJ_FOOD][FOOD_APRICOT] = 15;
- mss[OBJ_FOOD][FOOD_ORANGE] = 20;
- mss[OBJ_FOOD][FOOD_BANANA] = 20;
- mss[OBJ_FOOD][FOOD_STRAWBERRY] = 5;
- mss[OBJ_FOOD][FOOD_RAMBUTAN] = 10;
- mss[OBJ_FOOD][FOOD_LEMON] = 20;
- mss[OBJ_FOOD][FOOD_GRAPE] = 5;
- mss[OBJ_FOOD][FOOD_SULTANA] = 3;
- mss[OBJ_FOOD][FOOD_LYCHEE] = 10;
- mss[OBJ_FOOD][FOOD_BEEF_JERKY] = 20;
- mss[OBJ_FOOD][FOOD_CHEESE] = 40;
- mss[OBJ_FOOD][FOOD_SAUSAGE] = 40;
- mss[OBJ_FOOD][FOOD_CHUNK] = 100;
- /* mss [OBJ_FOOD] [21] = 40;
- mss [OBJ_FOOD] [22] = 50;
- mss [OBJ_FOOD] [23] = 60;
- mss [OBJ_FOOD] [24] = 60;
- mss [OBJ_FOOD] [25] = 100; */
-
- mss[OBJ_MISCELLANY][MISC_BOTTLED_EFREET] = 250;
-
- mss[OBJ_MISCELLANY][MISC_CRYSTAL_BALL_OF_SEEING] = 200;
- mss[OBJ_MISCELLANY][MISC_CRYSTAL_BALL_OF_ENERGY] = 200;
- mss[OBJ_MISCELLANY][MISC_CRYSTAL_BALL_OF_FIXATION] = 200;
-
- // weapons: blunt weapons are first to help grouping them together
- // note: AC prop can't be 0 or less because of division.
- // If it's 1, makes no difference
-
- // NOTE: I have *removed* AC bit for weapons - just doesn't work
- // prop [x] [2] is speed
-
- prop[OBJ_WEAPONS][WPN_CLUB][PWPN_DAMAGE] = 5;
- prop[OBJ_WEAPONS][WPN_CLUB][PWPN_HIT] = 4; // helps to get past evasion
- prop[OBJ_WEAPONS][WPN_CLUB][PWPN_SPEED] = 12;
- mss[OBJ_WEAPONS][WPN_CLUB] = 50;
-
- prop[OBJ_WEAPONS][WPN_MACE][PWPN_DAMAGE] = 8;
- prop[OBJ_WEAPONS][WPN_MACE][PWPN_HIT] = 3; // helps to get past evasion
- prop[OBJ_WEAPONS][WPN_MACE][PWPN_SPEED] = 14;
- mss[OBJ_WEAPONS][WPN_MACE] = 140;
-
- prop[OBJ_WEAPONS][WPN_GREAT_MACE][PWPN_DAMAGE] = 16;
- prop[OBJ_WEAPONS][WPN_GREAT_MACE][PWPN_HIT] = -3;
- prop[OBJ_WEAPONS][WPN_GREAT_MACE][PWPN_SPEED] = 18;
- mss[OBJ_WEAPONS][WPN_GREAT_MACE] = 260;
-
- prop[OBJ_WEAPONS][WPN_FLAIL][PWPN_DAMAGE] = 9;
- prop[OBJ_WEAPONS][WPN_FLAIL][PWPN_HIT] = 2; // helps to get past evasion
- prop[OBJ_WEAPONS][WPN_FLAIL][PWPN_SPEED] = 15;
- mss[OBJ_WEAPONS][WPN_FLAIL] = 150;
-
- prop[OBJ_WEAPONS][WPN_SPIKED_FLAIL][PWPN_DAMAGE] = 12;
- prop[OBJ_WEAPONS][WPN_SPIKED_FLAIL][PWPN_HIT] = 1;
- prop[OBJ_WEAPONS][WPN_SPIKED_FLAIL][PWPN_SPEED] = 16;
- mss[OBJ_WEAPONS][WPN_SPIKED_FLAIL] = 170;
-
- prop[OBJ_WEAPONS][WPN_GREAT_FLAIL][PWPN_DAMAGE] = 17;
- prop[OBJ_WEAPONS][WPN_GREAT_FLAIL][PWPN_HIT] = -4;
- prop[OBJ_WEAPONS][WPN_GREAT_FLAIL][PWPN_SPEED] = 19;
- mss[OBJ_WEAPONS][WPN_GREAT_FLAIL] = 300;
-
- prop[OBJ_WEAPONS][WPN_DAGGER][PWPN_DAMAGE] = 3;
- prop[OBJ_WEAPONS][WPN_DAGGER][PWPN_HIT] = 6; // helps to get past evasion
- prop[OBJ_WEAPONS][WPN_DAGGER][PWPN_SPEED] = 11;
- mss[OBJ_WEAPONS][WPN_DAGGER] = 20;
-
- prop[OBJ_WEAPONS][WPN_KNIFE][PWPN_DAMAGE] = 2;
- prop[OBJ_WEAPONS][WPN_KNIFE][PWPN_HIT] = 0; // helps to get past evasion
- prop[OBJ_WEAPONS][WPN_KNIFE][PWPN_SPEED] = 11;
- mss[OBJ_WEAPONS][WPN_KNIFE] = 10;
-
- prop[OBJ_WEAPONS][WPN_MORNINGSTAR][PWPN_DAMAGE] = 10;
- prop[OBJ_WEAPONS][WPN_MORNINGSTAR][PWPN_HIT] = 2;
- prop[OBJ_WEAPONS][WPN_MORNINGSTAR][PWPN_SPEED] = 15;
- mss[OBJ_WEAPONS][WPN_MORNINGSTAR] = 150;
-
- prop[OBJ_WEAPONS][WPN_SHORT_SWORD][PWPN_DAMAGE] = 6;
- prop[OBJ_WEAPONS][WPN_SHORT_SWORD][PWPN_HIT] = 5;
- prop[OBJ_WEAPONS][WPN_SHORT_SWORD][PWPN_SPEED] = 12;
- mss[OBJ_WEAPONS][WPN_SHORT_SWORD] = 100;
-
- prop[OBJ_WEAPONS][WPN_LONG_SWORD][PWPN_DAMAGE] = 10;
- prop[OBJ_WEAPONS][WPN_LONG_SWORD][PWPN_HIT] = 3;
- prop[OBJ_WEAPONS][WPN_LONG_SWORD][PWPN_SPEED] = 14;
- mss[OBJ_WEAPONS][WPN_LONG_SWORD] = 160;
-
- prop[OBJ_WEAPONS][WPN_GREAT_SWORD][PWPN_DAMAGE] = 16;
- prop[OBJ_WEAPONS][WPN_GREAT_SWORD][PWPN_HIT] = -1;
- prop[OBJ_WEAPONS][WPN_GREAT_SWORD][PWPN_SPEED] = 17;
- mss[OBJ_WEAPONS][WPN_GREAT_SWORD] = 250;
-
- prop[OBJ_WEAPONS][WPN_FALCHION][PWPN_DAMAGE] = 8;
- prop[OBJ_WEAPONS][WPN_FALCHION][PWPN_HIT] = 2;
- prop[OBJ_WEAPONS][WPN_FALCHION][PWPN_SPEED] = 13;
- mss[OBJ_WEAPONS][WPN_FALCHION] = 130;
-
- prop[OBJ_WEAPONS][WPN_SCIMITAR][PWPN_DAMAGE] = 11;
- prop[OBJ_WEAPONS][WPN_SCIMITAR][PWPN_HIT] = 1;
- prop[OBJ_WEAPONS][WPN_SCIMITAR][PWPN_SPEED] = 14;
- mss[OBJ_WEAPONS][WPN_SCIMITAR] = 170;
-
- prop[OBJ_WEAPONS][WPN_HAND_AXE][PWPN_DAMAGE] = 7;
- prop[OBJ_WEAPONS][WPN_HAND_AXE][PWPN_HIT] = 2;
- prop[OBJ_WEAPONS][WPN_HAND_AXE][PWPN_SPEED] = 13;
- mss[OBJ_WEAPONS][WPN_HAND_AXE] = 110;
-
- prop[OBJ_WEAPONS][WPN_WAR_AXE][PWPN_DAMAGE] = 11;
- prop[OBJ_WEAPONS][WPN_WAR_AXE][PWPN_HIT] = 0;
- prop[OBJ_WEAPONS][WPN_WAR_AXE][PWPN_SPEED] = 16;
- mss[OBJ_WEAPONS][WPN_WAR_AXE] = 150;
-
- prop[OBJ_WEAPONS][WPN_BROAD_AXE][PWPN_DAMAGE] = 14;
- prop[OBJ_WEAPONS][WPN_BROAD_AXE][PWPN_HIT] = 1;
- prop[OBJ_WEAPONS][WPN_BROAD_AXE][PWPN_SPEED] = 17;
- mss[OBJ_WEAPONS][WPN_BROAD_AXE] = 180;
-
- prop[OBJ_WEAPONS][WPN_BATTLEAXE][PWPN_DAMAGE] = 17;
- prop[OBJ_WEAPONS][WPN_BATTLEAXE][PWPN_HIT] = -2;
- prop[OBJ_WEAPONS][WPN_BATTLEAXE][PWPN_SPEED] = 18;
- mss[OBJ_WEAPONS][WPN_BATTLEAXE] = 200;
-
- prop[OBJ_WEAPONS][WPN_SPEAR][PWPN_DAMAGE] = 5;
- prop[OBJ_WEAPONS][WPN_SPEAR][PWPN_HIT] = 3;
- prop[OBJ_WEAPONS][WPN_SPEAR][PWPN_SPEED] = 13;
- mss[OBJ_WEAPONS][WPN_SPEAR] = 50;
-
- prop[OBJ_WEAPONS][WPN_TRIDENT][PWPN_DAMAGE] = 9;
- prop[OBJ_WEAPONS][WPN_TRIDENT][PWPN_HIT] = -2;
- prop[OBJ_WEAPONS][WPN_TRIDENT][PWPN_SPEED] = 17;
- mss[OBJ_WEAPONS][WPN_TRIDENT] = 160;
-
- prop[OBJ_WEAPONS][WPN_DEMON_TRIDENT][PWPN_DAMAGE] = 15;
- prop[OBJ_WEAPONS][WPN_DEMON_TRIDENT][PWPN_HIT] = -2;
- prop[OBJ_WEAPONS][WPN_DEMON_TRIDENT][PWPN_SPEED] = 17;
- mss[OBJ_WEAPONS][WPN_DEMON_TRIDENT] = 160;
-
- prop[OBJ_WEAPONS][WPN_HALBERD][PWPN_DAMAGE] = 13;
- prop[OBJ_WEAPONS][WPN_HALBERD][PWPN_HIT] = -3;
- prop[OBJ_WEAPONS][WPN_HALBERD][PWPN_SPEED] = 19;
- mss[OBJ_WEAPONS][WPN_HALBERD] = 200;
-
- // sling
- // - the three properties are _not_ irrelevant here
- // - when something hits something else (either may be you)
- // in melee, these are used.
- prop[OBJ_WEAPONS][WPN_SLING][PWPN_DAMAGE] = 1;
- prop[OBJ_WEAPONS][WPN_SLING][PWPN_HIT] = -1;
- prop[OBJ_WEAPONS][WPN_SLING][PWPN_SPEED] = 11;
- mss[OBJ_WEAPONS][WPN_SLING] = 10;
-
- prop[OBJ_WEAPONS][WPN_BOW][PWPN_DAMAGE] = 2;
- prop[OBJ_WEAPONS][WPN_BOW][PWPN_HIT] = -3; // helps to get past evasion
- prop[OBJ_WEAPONS][WPN_BOW][PWPN_SPEED] = 11;
- mss[OBJ_WEAPONS][WPN_BOW] = 100;
-
- prop[OBJ_WEAPONS][WPN_BLOWGUN][PWPN_DAMAGE] = 1;
- prop[OBJ_WEAPONS][WPN_BLOWGUN][PWPN_HIT] = 0; // helps to get past evasion
- prop[OBJ_WEAPONS][WPN_BLOWGUN][PWPN_SPEED] = 10;
- mss[OBJ_WEAPONS][WPN_BLOWGUN] = 50;
-
- prop[OBJ_WEAPONS][WPN_CROSSBOW][PWPN_DAMAGE] = 2;
- prop[OBJ_WEAPONS][WPN_CROSSBOW][PWPN_HIT] = -1;
- prop[OBJ_WEAPONS][WPN_CROSSBOW][PWPN_SPEED] = 15;
- mss[OBJ_WEAPONS][WPN_CROSSBOW] = 250;
-
- prop[OBJ_WEAPONS][WPN_HAND_CROSSBOW][PWPN_DAMAGE] = 1;
- prop[OBJ_WEAPONS][WPN_HAND_CROSSBOW][PWPN_HIT] = -1;
- prop[OBJ_WEAPONS][WPN_HAND_CROSSBOW][PWPN_SPEED] = 15;
- mss[OBJ_WEAPONS][WPN_HAND_CROSSBOW] = 70;
-
- prop[OBJ_WEAPONS][WPN_GLAIVE][PWPN_DAMAGE] = 15;
- prop[OBJ_WEAPONS][WPN_GLAIVE][PWPN_HIT] = -3;
- prop[OBJ_WEAPONS][WPN_GLAIVE][PWPN_SPEED] = 18;
- mss[OBJ_WEAPONS][WPN_GLAIVE] = 200;
-
- // staff - hmmm
- prop[OBJ_WEAPONS][WPN_QUARTERSTAFF][PWPN_DAMAGE] = 7;
- prop[OBJ_WEAPONS][WPN_QUARTERSTAFF][PWPN_HIT] = 6;
- prop[OBJ_WEAPONS][WPN_QUARTERSTAFF][PWPN_SPEED] = 12;
- mss[OBJ_WEAPONS][WPN_QUARTERSTAFF] = 130;
-
- prop[OBJ_WEAPONS][WPN_SCYTHE][PWPN_DAMAGE] = 14;
- prop[OBJ_WEAPONS][WPN_SCYTHE][PWPN_HIT] = -4;
- prop[OBJ_WEAPONS][WPN_SCYTHE][PWPN_SPEED] = 22;
- mss[OBJ_WEAPONS][WPN_SCYTHE] = 230;
-
- // these two should have the same speed because of 2-h ogres.
- prop[OBJ_WEAPONS][WPN_GIANT_CLUB][PWPN_DAMAGE] = 15;
- prop[OBJ_WEAPONS][WPN_GIANT_CLUB][PWPN_HIT] = -5;
- prop[OBJ_WEAPONS][WPN_GIANT_CLUB][PWPN_SPEED] = 16;
- mss[OBJ_WEAPONS][WPN_GIANT_CLUB] = 750;
-
- prop[OBJ_WEAPONS][WPN_GIANT_SPIKED_CLUB][PWPN_DAMAGE] = 18;
- prop[OBJ_WEAPONS][WPN_GIANT_SPIKED_CLUB][PWPN_HIT] = -6;
- prop[OBJ_WEAPONS][WPN_GIANT_SPIKED_CLUB][PWPN_SPEED] = 17;
- mss[OBJ_WEAPONS][WPN_GIANT_SPIKED_CLUB] = 850;
- // these two should have the same speed because of 2-h ogres.
-
- prop[OBJ_WEAPONS][WPN_EVENINGSTAR][PWPN_DAMAGE] = 12;
- prop[OBJ_WEAPONS][WPN_EVENINGSTAR][PWPN_HIT] = 2;
- prop[OBJ_WEAPONS][WPN_EVENINGSTAR][PWPN_SPEED] = 15;
- mss[OBJ_WEAPONS][WPN_EVENINGSTAR] = 150;
-
- prop[OBJ_WEAPONS][WPN_QUICK_BLADE][PWPN_DAMAGE] = 5;
- prop[OBJ_WEAPONS][WPN_QUICK_BLADE][PWPN_HIT] = 6;
- prop[OBJ_WEAPONS][WPN_QUICK_BLADE][PWPN_SPEED] = 7;
- mss[OBJ_WEAPONS][WPN_QUICK_BLADE] = 100;
-
- prop[OBJ_WEAPONS][WPN_KATANA][PWPN_DAMAGE] = 13;
- prop[OBJ_WEAPONS][WPN_KATANA][PWPN_HIT] = 4;
- prop[OBJ_WEAPONS][WPN_KATANA][PWPN_SPEED] = 13;
- mss[OBJ_WEAPONS][WPN_KATANA] = 160;
-
- prop[OBJ_WEAPONS][WPN_EXECUTIONERS_AXE][PWPN_DAMAGE] = 20;
- prop[OBJ_WEAPONS][WPN_EXECUTIONERS_AXE][PWPN_HIT] = -4;
- prop[OBJ_WEAPONS][WPN_EXECUTIONERS_AXE][PWPN_SPEED] = 20;
- mss[OBJ_WEAPONS][WPN_EXECUTIONERS_AXE] = 320;
-
- prop[OBJ_WEAPONS][WPN_DOUBLE_SWORD][PWPN_DAMAGE] = 15;
- prop[OBJ_WEAPONS][WPN_DOUBLE_SWORD][PWPN_HIT] = 3;
- prop[OBJ_WEAPONS][WPN_DOUBLE_SWORD][PWPN_SPEED] = 16;
- mss[OBJ_WEAPONS][WPN_DOUBLE_SWORD] = 220;
-
- prop[OBJ_WEAPONS][WPN_TRIPLE_SWORD][PWPN_DAMAGE] = 19;
- prop[OBJ_WEAPONS][WPN_TRIPLE_SWORD][PWPN_HIT] = -1;
- prop[OBJ_WEAPONS][WPN_TRIPLE_SWORD][PWPN_SPEED] = 19;
- mss[OBJ_WEAPONS][WPN_TRIPLE_SWORD] = 300;
-
- prop[OBJ_WEAPONS][WPN_HAMMER][PWPN_DAMAGE] = 7;
- prop[OBJ_WEAPONS][WPN_HAMMER][PWPN_HIT] = 2;
- prop[OBJ_WEAPONS][WPN_HAMMER][PWPN_SPEED] = 13;
- mss[OBJ_WEAPONS][WPN_HAMMER] = 130;
-
- prop[OBJ_WEAPONS][WPN_ANCUS][PWPN_DAMAGE] = 9;
- prop[OBJ_WEAPONS][WPN_ANCUS][PWPN_HIT] = 1;
- prop[OBJ_WEAPONS][WPN_ANCUS][PWPN_SPEED] = 14;
- mss[OBJ_WEAPONS][WPN_ANCUS] = 160;
-
- prop[OBJ_WEAPONS][WPN_WHIP][PWPN_DAMAGE] = 3;
- prop[OBJ_WEAPONS][WPN_WHIP][PWPN_HIT] = 1; // helps to get past evasion
- prop[OBJ_WEAPONS][WPN_WHIP][PWPN_SPEED] = 14;
- mss[OBJ_WEAPONS][WPN_WHIP] = 30;
-
- prop[OBJ_WEAPONS][WPN_SABRE][PWPN_DAMAGE] = 7;
- prop[OBJ_WEAPONS][WPN_SABRE][PWPN_HIT] = 4;
- prop[OBJ_WEAPONS][WPN_SABRE][PWPN_SPEED] = 12;
- mss[OBJ_WEAPONS][WPN_SABRE] = 110;
-
- prop[OBJ_WEAPONS][WPN_DEMON_BLADE][PWPN_DAMAGE] = 13;
- prop[OBJ_WEAPONS][WPN_DEMON_BLADE][PWPN_HIT] = 2;
- prop[OBJ_WEAPONS][WPN_DEMON_BLADE][PWPN_SPEED] = 15;
- mss[OBJ_WEAPONS][WPN_DEMON_BLADE] = 200;
-
- prop[OBJ_WEAPONS][WPN_DEMON_WHIP][PWPN_DAMAGE] = 10;
- prop[OBJ_WEAPONS][WPN_DEMON_WHIP][PWPN_HIT] = 1;
- prop[OBJ_WEAPONS][WPN_DEMON_WHIP][PWPN_SPEED] = 14;
- mss[OBJ_WEAPONS][WPN_DEMON_WHIP] = 30;
-
-
- // MISSILES:
-
- prop[OBJ_MISSILES][MI_STONE][PWPN_DAMAGE] = 2;
- prop[OBJ_MISSILES][MI_STONE][PWPN_HIT] = 4;
- mss[OBJ_MISSILES][MI_STONE] = 5;
-
- prop[OBJ_MISSILES][MI_ARROW][PWPN_DAMAGE] = 2;
- prop[OBJ_MISSILES][MI_ARROW][PWPN_HIT] = 6;
- mss[OBJ_MISSILES][MI_ARROW] = 10;
-
- prop[OBJ_MISSILES][MI_NEEDLE][PWPN_DAMAGE] = 0;
- prop[OBJ_MISSILES][MI_NEEDLE][PWPN_HIT] = 1;
- mss[OBJ_MISSILES][MI_NEEDLE] = 1;
-
- prop[OBJ_MISSILES][MI_BOLT][PWPN_DAMAGE] = 2;
- prop[OBJ_MISSILES][MI_BOLT][PWPN_HIT] = 8;
- mss[OBJ_MISSILES][MI_BOLT] = 12;
-
- prop[OBJ_MISSILES][MI_DART][PWPN_DAMAGE] = 2;
- prop[OBJ_MISSILES][MI_DART][PWPN_HIT] = 4; //whatever - for hand crossbow
- mss[OBJ_MISSILES][MI_DART] = 5;
-
- // large rock
- prop[OBJ_MISSILES][MI_LARGE_ROCK][PWPN_DAMAGE] = 20;
- prop[OBJ_MISSILES][MI_LARGE_ROCK][PWPN_HIT] = 10;
- mss[OBJ_MISSILES][MI_LARGE_ROCK] = 1000;
-}
-
-
-unsigned char check_item_knowledge(void)
-{
- char st_pass[ITEMNAME_SIZE] = "";
- int i, j;
- char lines = 0;
- unsigned char anything = 0;
- int ft = 0;
- int max = 0;
- int yps = 0;
- int inv_count = 0;
- unsigned char ki = 0;
-
- const int num_lines = get_number_of_lines();
-
-#ifdef DOS_TERM
- char buffer[2400];
-
- gettext(35, 1, 80, 25, buffer);
-#endif
-
-#ifdef DOS_TERM
- window(35, 1, 80, 25);
-#endif
-
- clrscr();
-
- for (i = 0; i < 4; i++)
+ for (i = 0; i < len; i++)
{
- for (j = 0; j < 30; j++)
+ j = (j + 1) % 17;
+ if (j == 0)
{
- if (id[i][j] == ID_KNOWN_TYPE)
- inv_count++;
+ count++;
+ if (count > 9)
+ break;
}
- }
-
- if (inv_count == 0)
- {
- cprintf("You don't recognise anything yet!");
- if (getch() == 0)
- getch();
- goto putty;
- }
-
- textcolor(BLUE);
- cprintf(" You recognise:");
- textcolor(LIGHTGREY);
- lines++;
- for (i = 0; i < 4; i++)
- {
- switch (i)
+ if (!has_space && i > 5 && i < len - 4
+ && (numb[(k + 10 * j) % 17] % 5) != 3)
{
- case IDTYPE_WANDS:
- ft = OBJ_WANDS;
- max = NUM_WANDS;
- break;
- case IDTYPE_SCROLLS:
- ft = OBJ_SCROLLS;
- max = NUM_SCROLLS;
- break;
- case IDTYPE_JEWELLERY:
- ft = OBJ_JEWELLERY;
- max = NUM_JEWELLERY;
- break;
- case IDTYPE_POTIONS:
- ft = OBJ_POTIONS;
- max = NUM_POTIONS;
- break;
+ want_vowel = true;
+ name[i] = ' ';
}
-
- for (j = 0; j < max; j++)
+ else if (i > 0
+ && (want_vowel
+ || (i > 1
+ && is_random_name_vowel( name[i - 1] )
+ && !is_random_name_vowel( name[i - 2] )
+ && (numb[(k + 4 * j) % 17] % 5) <= 1 )))
{
- if (lines > num_lines - 2 && inv_count > 0)
- {
- gotoxy(1, num_lines);
- cprintf("-more-");
-
- ki = getch();
+ want_vowel = true;
+ name[i] = retvow( numb[(k + 7 * j) % 17] );
- if (ki == ESCAPE)
+ if (is_random_name_space( name[i] ))
+ {
+ if (i == 0)
{
-#ifdef DOS_TERM
- puttext(35, 1, 80, 25, buffer);
-#endif
- return ESCAPE;
+ want_vowel = false;
+ name[i] = retlet( numb[(k + 14 * j) % 17] );
}
- if (ki >= 'A' && ki <= 'z')
+ else if (len < 7
+ || i <= 2 || i >= len - 3
+ || is_random_name_space( name[i - 1] )
+ || (i > 1 && is_random_name_space( name[i - 2] ))
+ || (i > 2
+ && !is_random_name_vowel( name[i - 1] )
+ && !is_random_name_vowel( name[i - 2] )))
{
-#ifdef DOS_TERM
- puttext(35, 1, 80, 25, buffer);
-#endif
- return ki;
+ i--;
+ continue;
}
-
- if (ki == 0)
- ki = getch();
-
- lines = 0;
- clrscr();
- gotoxy(1, 1);
- anything = 0;
}
-
- int ident_level = get_ident_type( ft, j );
-
- if (ident_level == ID_KNOWN_TYPE)
+ else if (i > 1
+ && name[i] == name[i - 1]
+ && (name[i] == 'y' || name[i] == 'i'
+ || (numb[(k + 12 * j) % 17] % 5) <= 1))
{
- anything++;
-
- if (lines > 0)
- cprintf(EOL);
- lines++;
- cprintf(" ");
-
- yps = wherey();
-
- // item_name now requires a "real" item, so we'll create a tmp
- item_def tmp;// = { ft, j, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
- tmp.base_type = ft;
- tmp.sub_type = j;
- tmp.colour = 1;
-
- item_name( tmp, DESC_PLAIN, st_pass );
-
- cprintf(st_pass);
-
- inv_count--;
-
- if (wherey() != yps)
- lines++;
+ i--;
+ continue;
}
- } // end of j loop
- }
-
- if (anything > 0)
- {
- ki = getch();
- //ki = getch();
- //ki = anything;
-
- if (ki >= 'A' && ki <= 'z')
- {
-#ifdef DOS_TERM
- puttext(35, 1, 80, 25, buffer);
-#endif
- return ki;
}
-
- if (ki == 0)
- ki = getch();
-#ifdef DOS_TERM
- puttext(35, 1, 80, 25, buffer);
-#endif
- return anything;
- }
-
- putty:
-#ifdef DOS_TERM
- puttext(35, 1, 80, 25, buffer);
-#endif
-
- return ki;
-} // end check_item_knowledge()
-
-
-// must be certain that you are passing the subtype
-// to an OBJ_ARMOUR and nothing else, or as they say,
-// "Bad Things Will Happen" {dlb}:
-bool hide2armour( unsigned char *which_subtype )
-{
- switch (*which_subtype)
- {
- case ARM_DRAGON_HIDE:
- *which_subtype = ARM_DRAGON_ARMOUR;
- return true;
- case ARM_TROLL_HIDE:
- *which_subtype = ARM_TROLL_LEATHER_ARMOUR;
- return true;
- case ARM_ICE_DRAGON_HIDE:
- *which_subtype = ARM_ICE_DRAGON_ARMOUR;
- return true;
- case ARM_MOTTLED_DRAGON_HIDE:
- *which_subtype = ARM_MOTTLED_DRAGON_ARMOUR;
- return true;
- case ARM_STORM_DRAGON_HIDE:
- *which_subtype = ARM_STORM_DRAGON_ARMOUR;
- return true;
- case ARM_GOLD_DRAGON_HIDE:
- *which_subtype = ARM_GOLD_DRAGON_ARMOUR;
- return true;
- case ARM_SWAMP_DRAGON_HIDE:
- *which_subtype = ARM_SWAMP_DRAGON_ARMOUR;
- return true;
- case ARM_STEAM_DRAGON_HIDE:
- *which_subtype = ARM_STEAM_DRAGON_ARMOUR;
- return true;
- default:
- return false;
- }
-} // end hide2armour()
-
-
-void make_name(unsigned char var1, unsigned char var2, unsigned char var3,
- char ncase, char buff[ITEMNAME_SIZE])
-{
- char name[ ITEMNAME_SIZE ] = "";
- FixedVector < unsigned char, 15 > numb;
- int len;
- int i = 0;
- int nexty = 0;
- int j = 0;
- int x = 0;
-
- numb[0] = var1 * var2;
- numb[1] = var1 * var3;
- numb[2] = var2 * var3;
- numb[3] = var1 * var2 * var3;
- numb[4] = var1 + var2;
- numb[5] = var2 + var3;
- numb[6] = var1 * var2 + var3;
- numb[7] = var1 * var3 + var2;
- numb[8] = var2 * var3 + var1;
- numb[9] = var1 * var2 * var3 - var1;
- numb[10] = var1 + var2 + var2;
- numb[11] = var2 + var3 * var1;
- numb[12] = var1 * var2 * var3;
- numb[13] = var1 * var3 * var1;
- numb[14] = var2 * var3 * var3;
-
- for (i = 0; i < 15; i++)
- {
- while (numb[i] >= 25)
+ else
{
- numb[i] -= 25;
- }
- }
-
- j = numb[6];
-
- len = reduce(numb[reduce(numb[11]) / 2]);
-
- while (len < 5 && j < 10)
- {
- len += 1 + reduce(1 + numb[j]);
- j++;
- }
-
- while (len > 14)
- {
- len -= 8;
- }
-
- nexty = retbit(numb[4]);
-
- char k = 0;
+ if ((len > 3 || i != 0)
+ && (numb[(k + 13 * j) % 17] % 7) <= 1
+ && (i < len - 2 || (i > 0 && !is_random_name_space(name[i - 1]))))
+ {
+ const bool beg = ((i < 1) || is_random_name_space(name[i - 1]));
+ const bool end = (i >= len - 2);
- j = 0;
+ const int first = (beg ? 0 : (end ? 14 : 0));
+ const int last = (beg ? 27 : (end ? 56 : 67));
- for (i = 0; i < len; i++)
- {
- j++;
-
- if (j >= 15)
- {
- j = 0;
+ const int num = last - first;
- k++;
+ i++;
- if (k > 9)
- break;
- }
-
- if (nexty == 1 || (i > 0 && !is_random_name_vowel(name[i])))
- {
- name[i] = retvow(numb[j]);
- if ((i == 0 || i == len - 1) && name[i] == 32)
+ switch (numb[(k + 11 * j) % 17] % num + first)
+ {
+ // start, middle
+ case 0: strcat(name, "kl"); break;
+ case 1: strcat(name, "gr"); break;
+ case 2: strcat(name, "cl"); break;
+ case 3: strcat(name, "cr"); break;
+ case 4: strcat(name, "fr"); break;
+ case 5: strcat(name, "pr"); break;
+ case 6: strcat(name, "tr"); break;
+ case 7: strcat(name, "tw"); break;
+ case 8: strcat(name, "br"); break;
+ case 9: strcat(name, "pl"); break;
+ case 10: strcat(name, "bl"); break;
+ case 11: strcat(name, "str"); i++; len++; break;
+ case 12: strcat(name, "shr"); i++; len++; break;
+ case 13: strcat(name, "thr"); i++; len++; break;
+ // start, middle, end
+ case 14: strcat(name, "sm"); break;
+ case 15: strcat(name, "sh"); break;
+ case 16: strcat(name, "ch"); break;
+ case 17: strcat(name, "th"); break;
+ case 18: strcat(name, "ph"); break;
+ case 19: strcat(name, "pn"); break;
+ case 20: strcat(name, "kh"); break;
+ case 21: strcat(name, "gh"); break;
+ case 22: strcat(name, "mn"); break;
+ case 23: strcat(name, "ps"); break;
+ case 24: strcat(name, "st"); break;
+ case 25: strcat(name, "sk"); break;
+ case 26: strcat(name, "sch"); i++; len++; break;
+ // middle, end
+ case 27: strcat(name, "ts"); break;
+ case 28: strcat(name, "cs"); break;
+ case 29: strcat(name, "xt"); break;
+ case 30: strcat(name, "nt"); break;
+ case 31: strcat(name, "ll"); break;
+ case 32: strcat(name, "rr"); break;
+ case 33: strcat(name, "ss"); break;
+ case 34: strcat(name, "wk"); break;
+ case 35: strcat(name, "wn"); break;
+ case 36: strcat(name, "ng"); break;
+ case 37: strcat(name, "cw"); break;
+ case 38: strcat(name, "mp"); break;
+ case 39: strcat(name, "ck"); break;
+ case 40: strcat(name, "nk"); break;
+ case 41: strcat(name, "dd"); break;
+ case 42: strcat(name, "tt"); break;
+ case 43: strcat(name, "bb"); break;
+ case 44: strcat(name, "pp"); break;
+ case 45: strcat(name, "nn"); break;
+ case 46: strcat(name, "mm"); break;
+ case 47: strcat(name, "kk"); break;
+ case 48: strcat(name, "gg"); break;
+ case 49: strcat(name, "ff"); break;
+ case 50: strcat(name, "pt"); break;
+ case 51: strcat(name, "tz"); break;
+ case 52: strcat(name, "dgh"); i++; len++; break;
+ case 53: strcat(name, "rgh"); i++; len++; break;
+ case 54: strcat(name, "rph"); i++; len++; break;
+ case 55: strcat(name, "rch"); i++; len++; break;
+ // middle only
+ case 56: strcat(name, "cz"); break;
+ case 57: strcat(name, "xk"); break;
+ case 58: strcat(name, "zx"); break;
+ case 59: strcat(name, "xz"); break;
+ case 60: strcat(name, "cv"); break;
+ case 61: strcat(name, "vv"); break;
+ case 62: strcat(name, "nl"); break;
+ case 63: strcat(name, "rh"); break;
+ case 64: strcat(name, "dw"); break;
+ case 65: strcat(name, "nw"); break;
+ case 66: strcat(name, "khl"); i++; len++; break;
+ default:
+ i--;
+ break;
+ }
+ }
+ else
{
- i--;
- continue;
+ if (i == 0)
+ {
+ name[i] = 'a' + (numb[(k + 8 * j) % 17] % 26);
+ want_vowel = is_random_name_vowel( name[i] );
+ }
+ else
+ {
+ name[i] = retlet( numb[(k + 3 * j) % 17] );
+ }
}
}
- else
+
+ if (name[i] == '\0')
{
- if (numb[i / 2] <= 1 && i > 3 && is_random_name_vowel(name[i]))
- goto two_letter;
- else
- name[i] = numb[j];
+ i--;
+ continue;
}
- hello:
-
- if ((nexty == 0 && is_random_name_vowel(name[i]))
- || (nexty == 1 && !is_random_name_vowel(name[i])))
+ if (want_vowel && !is_random_name_vowel( name[i] )
+ || (!want_vowel && is_random_name_vowel( name[i] )))
{
- if (nexty == 1 && i > 0 && !is_random_name_vowel(name[i - 1]))
- i--;
-
i--;
continue;
}
- if (!is_random_name_vowel(name[i]))
- nexty = 1;
+ if (is_random_name_space( name[i] ))
+ has_space = true;
+
+ if (!is_random_name_vowel( name[i] ))
+ want_vowel = true;
else
- nexty = 0;
+ want_vowel = false;
+ }
- x++;
+ // catch break and try to give a final letter
+ if (i > 0
+ && !is_random_name_space( name[i - 1] )
+ && name[i - 1] != 'y'
+ && is_random_name_vowel( name[i - 1] )
+ && (count > 9 || (i < 8 && numb[16] % 3)))
+ {
+ name[i] = retlet( numb[j] );
}
+
+ len = strlen( name );
- switch (ncase)
+ if (len)
{
- case 2:
- for (i = 0; i < len + 1; i++)
+ for (i = len - 1; i > 0; i--)
{
- if (i > 3 && name[i] == 0 && name[i + 1] == 0)
- {
- name[i] = 0;
- if (name[i - 1] == 32)
- name[i - 1] = 0;
+ if (!isspace( name[i] ))
break;
- }
- if (name[i] != 32 && name[i] < 30)
- name[i] += 65;
- if (name[i] > 96)
- name[i] -= 32;
- }
- break;
-
- case 3:
- for (i = 0; i < len + 0; i++)
- {
- if (i != 0 && name[i] >= 65 && name[i] < 97)
+ else
{
- if (name[i - 1] == 32)
- name[i] += 32;
- }
-
- if (name[i] > 97)
- {
- if (i == 0 || name[i - 1] == 32)
- name[i] -= 32;
- }
-
- if (name[i] < 30)
- {
- if (i == 0 || (name[i] != 32 && name[i - 1] == 32))
- name[i] += 65;
- else
- name[i] += 97;
+ name[i] = '\0';
+ len--;
}
}
- break;
-
- case 0:
- for (i = 0; i < len; i++)
- {
- if (name[i] != 32 && name[i] < 30)
- name[i] += 97;
- }
- break;
-
- case 1:
- name[i] += 65;
-
- for (i = 1; i < len; i++)
- {
- if (name[i] != 32 && name[i] < 30)
- name[i] += 97; //97;
- }
- break;
}
- if (strlen( name ) == 0)
- strncpy( buff, "Plog", 80 );
+ if (len >= 3)
+ strncpy( buff, name, ITEMNAME_SIZE );
else
- strncpy( buff, name, 80 );
-
- buff[79] = '\0';
- return;
-
- two_letter:
- if (nexty == 1)
- goto hello;
-
- if (!is_random_name_vowel(name[i - 1]))
- goto hello;
+ {
+ strncpy( buff, "plog", ITEMNAME_SIZE );
+ len = 4;
+ }
- i++;
+ buff[ ITEMNAME_SIZE - 1 ] = '\0';
- switch (i * (retbit(j) + 1))
+ for (i = 0; i < len; i++)
{
- case 0:
- strcat(name, "sh");
- break;
- case 1:
- strcat(name, "ch");
- break;
- case 2:
- strcat(name, "tz");
- break;
- case 3:
- strcat(name, "ts");
- break;
- case 4:
- strcat(name, "cs");
- break;
- case 5:
- strcat(name, "cz");
- break;
- case 6:
- strcat(name, "xt");
- break;
- case 7:
- strcat(name, "xk");
- break;
- case 8:
- strcat(name, "kl");
- break;
- case 9:
- strcat(name, "cl");
- break;
- case 10:
- strcat(name, "fr");
- break;
- case 11:
- strcat(name, "sh");
- break;
- case 12:
- strcat(name, "ch");
- break;
- case 13:
- strcat(name, "gh");
- break;
- case 14:
- strcat(name, "pr");
- break;
- case 15:
- strcat(name, "tr");
- break;
- case 16:
- strcat(name, "mn");
- break;
- case 17:
- strcat(name, "ph");
- break;
- case 18:
- strcat(name, "pn");
- break;
- case 19:
- strcat(name, "cv");
- break;
- case 20:
- strcat(name, "zx");
- break;
- case 21:
- strcat(name, "xz");
- break;
- case 23:
- strcat(name, "dd");
- break;
- case 24:
- strcat(name, "tt");
- break;
- case 25:
- strcat(name, "ll");
- break;
- //case 26: strcat(name, "sh"); break;
- //case 12: strcat(name, "sh"); break;
- //case 13: strcat(name, "sh"); break;
- default:
- i--;
- goto hello;
+ if (all_cap || i == 0 || buff[i - 1] == ' ')
+ buff[i] = toupper( buff[i] );
}
- x += 2;
-
- goto hello;
+ return (len);
} // end make_name()
-
-char reduce(unsigned char reducee)
+bool is_random_name_space(char let)
{
- while (reducee >= 26)
- {
- reducee -= 26;
- }
-
- return reducee;
-} // end reduce()
+ return (let == ' ');
+}
-bool is_random_name_vowel(unsigned char let)
+static bool is_random_name_vowel( char let )
{
- return (let == 0 || let == 4 || let == 8 || let == 14 || let == 20
- || let == 24 || let == 32);
+ return (let == 'a' || let == 'e' || let == 'i' || let == 'o' || let == 'u'
+ || let == 'y' || let == ' ');
} // end is_random_name_vowel()
-char retvow(char sed)
+static char retvow( int sed )
{
+ static const char vowels[] = "aeiouaeiouaeiouy ";
+ return (vowels[ sed % (sizeof(vowels) - 1) ]);
+} // end retvow()
- while (sed > 6)
- sed -= 6;
+static char retlet( int sed )
+{
+ static const char consonants[] = "bcdfghjklmnpqrstvwxzcdfghlmnrstlmnrst";
+ return (consonants[ sed % (sizeof(consonants) - 1) ]);
+}
- switch (sed)
- {
- case 0:
- return 0;
- case 1:
- return 4;
- case 2:
- return 8;
- case 3:
- return 14;
- case 4:
- return 20;
- case 5:
- return 24;
- case 6:
- return 32;
- }
+bool is_interesting_item( const item_def& item ) {
+ if ( is_random_artefact(item) ||
+ is_unrandom_artefact(item) ||
+ is_fixed_artefact(item) )
+ return true;
- return 0;
-} // end retvow()
+ char name[ITEMNAME_SIZE];
+ item_name(item, DESC_PLAIN, name, false);
+ std::string iname(name);
+ for (unsigned i = 0; i < Options.note_items.size(); ++i)
+ if (Options.note_items[i].matches(iname))
+ return true;
+ return false;
+}
-char retbit(char sed)
-{
- return (sed % 2);
-} // end retbit()
+bool fully_identified( const item_def& item ) {
+ long flagset = ISFLAG_IDENT_MASK;
+ switch ( item.base_type ) {
+ case OBJ_BOOKS:
+ case OBJ_MISCELLANY:
+ case OBJ_ORBS:
+ case OBJ_SCROLLS:
+ case OBJ_POTIONS:
+ flagset = ISFLAG_KNOW_TYPE;
+ break;
+ case OBJ_FOOD:
+ flagset = 0;
+ break;
+ case OBJ_WANDS:
+ flagset = (ISFLAG_KNOW_TYPE | ISFLAG_KNOW_PLUSES);
+ break;
+ case OBJ_JEWELLERY:
+ flagset = (ISFLAG_KNOW_CURSE | ISFLAG_KNOW_TYPE);
+ if ( ring_has_pluses(item) )
+ flagset |= ISFLAG_KNOW_PLUSES;
+ break;
+ default:
+ break;
+ }
+ if ( is_random_artefact(item) ||
+ is_fixed_artefact(item) ||
+ is_unrandom_artefact(item) )
+ flagset |= ISFLAG_KNOW_PROPERTIES;
+
+ return item_ident( item, flagset );
+}
diff --git a/crawl-ref/source/itemname.h b/crawl-ref/source/itemname.h
index 0d1ccc79a2..9bdc87360e 100644
--- a/crawl-ref/source/itemname.h
+++ b/crawl-ref/source/itemname.h
@@ -3,6 +3,8 @@
* Summary: Misc functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -27,18 +29,12 @@ char get_ident_type(char cla, int ty);
* it_use2 - item_use - items - monstuff - mstuff2 - ouch -
* shopping - spells1 - spells2 - spells3
* *********************************************************************** */
-char item_name( const item_def &item, char descrip, char buff[ITEMNAME_SIZE],
+const char *item_name( const item_def &item, char descrip,
+ char *buff = NULL,
bool terse = false );
/* ***********************************************************************
- * called from: beam - describe - fight - item_use - items - monstuff -
- * player
- * *********************************************************************** */
-int mass_item( const item_def &item );
-
-
-/* ***********************************************************************
* called from: debug - describe - dungeon - fight - files - item_use -
* monstuff - mstuff2 - players - spells0
* *********************************************************************** */
@@ -48,7 +44,7 @@ int property( const item_def &item, int prop_type );
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
-unsigned char check_item_knowledge(void);
+void check_item_knowledge(void);
/* ***********************************************************************
@@ -61,59 +57,30 @@ void clear_ids(void);
* called from: direct - fight - food - items - monstuff - religion -
* shopping
* *********************************************************************** */
-void it_name(int itn, char des, char buff[ITEMNAME_SIZE], bool terse = false);
+const char *it_name(int itn, char des, char *buff = NULL, bool terse = false);
/* ***********************************************************************
* called from: acr - chardump - command - effects - fight - invent -
* it_use2 - it_use3 - item_use - items - ouch - output -
* spell - spells1 - spells2 - spells3 - spells4 - transfor
* *********************************************************************** */
-void in_name(int inn, char des, char buff[ITEMNAME_SIZE], bool terse = false);
+const char *in_name(int inn, char des, char *buff = NULL, bool terse = false);
/* ***********************************************************************
* called from: itemname.cc items.cc item_use.cc mstuff2.cc
* *********************************************************************** */
-void quant_name( const item_def &item, int quant, char des,
+const char *quant_name( const item_def &item, int quant, char des,
char buff[ITEMNAME_SIZE], bool terse = false );
/* ***********************************************************************
* bit operations called from a large number of files
* *********************************************************************** */
bool item_cursed( const item_def &item );
-bool item_uncursed( const item_def &item );
-
bool item_known_cursed( const item_def &item );
bool item_known_uncursed( const item_def &item );
-// bool fully_indentified( const item_def &item );
+bool fully_identified( const item_def &item );
-bool item_ident( const item_def &item, unsigned long flags );
bool item_type_known( const item_def &item );
-bool item_not_ident( const item_def &item, unsigned long flags );
-
-void do_curse_item( item_def &item );
-void do_uncurse_item( item_def &item );
-
-void set_ident_flags( item_def &item, unsigned long flags );
-void unset_ident_flags( item_def &item, unsigned long flags );
-
-void set_equip_race( item_def &item, unsigned long flags );
-void set_equip_desc( item_def &item, unsigned long flags );
-
-unsigned long get_equip_race( const item_def &item );
-unsigned long get_equip_desc( const item_def &item );
-
-bool cmp_equip_race( const item_def &item, unsigned long val );
-bool cmp_equip_desc( const item_def &item, unsigned long val );
-
-void set_helmet_type( item_def &item, short flags );
-void set_helmet_desc( item_def &item, short flags );
-void set_helmet_random_desc( item_def &item );
-
-short get_helmet_type( const item_def &item );
-short get_helmet_desc( const item_def &item );
-
-bool cmp_helmet_type( const item_def &item, short val );
-bool cmp_helmet_desc( const item_def &item, short val );
bool set_item_ego_type( item_def &item, int item_type, int ego_type );
@@ -121,20 +88,12 @@ int get_weapon_brand( const item_def &item );
int get_ammo_brand( const item_def &item );
int get_armour_ego_type( const item_def &item );
-bool item_is_rod( const item_def &item );
-bool item_is_staff( const item_def &item );
-
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
void init_properties(void);
-/* ***********************************************************************
- * called from: files - randart - shopping
- * *********************************************************************** */
-void make_name( unsigned char var1, unsigned char var2, unsigned char var3,
- char ncase, char buff[ITEMNAME_SIZE] );
-
+int make_name( unsigned long seed, bool all_caps, char buff[ ITEMNAME_SIZE ] );
/* ***********************************************************************
* called from: files - shopping
@@ -153,5 +112,6 @@ void set_ident_type( char cla, int ty, char setting, bool force = false );
* *********************************************************************** */
bool hide2armour( unsigned char *which_subtype );
+bool is_interesting_item( const item_def& item );
#endif
diff --git a/crawl-ref/source/itemprop.cc b/crawl-ref/source/itemprop.cc
new file mode 100644
index 0000000000..e3a70c440b
--- /dev/null
+++ b/crawl-ref/source/itemprop.cc
@@ -0,0 +1,2085 @@
+/*
+ * File: itemprop.cc
+ * Summary: Misc functions.
+ * Written by: Brent Ross
+ *
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
+ * Change History (most recent first):
+ *
+ * <1> -/--/-- BWR Created
+ */
+
+#include "AppHdr.h"
+#include "itemname.h"
+
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef DOS
+#include <conio.h>
+#endif
+
+#include "externs.h"
+
+#include "items.h"
+#include "itemprop.h"
+#include "macro.h"
+#include "mon-util.h"
+#include "notes.h"
+#include "player.h"
+#include "randart.h"
+#include "skills2.h"
+#include "stuff.h"
+#include "transfor.h"
+#include "view.h"
+
+
+// XXX: name strings in most of the following are currently unused!
+struct armour_def
+{
+ armour_type id;
+ const char *name;
+ int ac;
+ int ev;
+ int mass;
+
+ bool light;
+ equipment_type slot;
+ size_type fit_min;
+ size_type fit_max;
+};
+
+// Note: the Little-Giant range is used to make armours which are very
+// flexible and adjustable and can be worn by any player character...
+// providing they also pass the shape test, of course.
+static int Armour_index[NUM_ARMOURS];
+static armour_def Armour_prop[NUM_ARMOURS] =
+{
+ { ARM_ANIMAL_SKIN, "animal skin", 2, 0, 100,
+ true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+ { ARM_ROBE, "robe", 2, 0, 60,
+ true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_BIG },
+ { ARM_LEATHER_ARMOUR, "leather armour", 3, -1, 150,
+ true, EQ_BODY_ARMOUR, SIZE_SMALL, SIZE_MEDIUM },
+ { ARM_STUDDED_LEATHER_ARMOUR,"studded leather armour",4, -1, 180,
+ true, EQ_BODY_ARMOUR, SIZE_SMALL, SIZE_MEDIUM },
+
+ { ARM_RING_MAIL, "ring mail", 4, -2, 250,
+ false, EQ_BODY_ARMOUR, SIZE_SMALL, SIZE_MEDIUM },
+ { ARM_SCALE_MAIL, "scale mail", 5, -3, 350,
+ false, EQ_BODY_ARMOUR, SIZE_SMALL, SIZE_MEDIUM },
+ { ARM_CHAIN_MAIL, "chain mail", 6, -4, 400,
+ false, EQ_BODY_ARMOUR, SIZE_SMALL, SIZE_MEDIUM },
+ { ARM_BANDED_MAIL, "banded mail", 7, -5, 500,
+ false, EQ_BODY_ARMOUR, SIZE_MEDIUM, SIZE_MEDIUM },
+ { ARM_SPLINT_MAIL, "splint mail", 8, -5, 550,
+ false, EQ_BODY_ARMOUR, SIZE_MEDIUM, SIZE_MEDIUM },
+ { ARM_PLATE_MAIL, "plate mail", 10, -6, 650,
+ false, EQ_BODY_ARMOUR, SIZE_MEDIUM, SIZE_MEDIUM },
+ { ARM_CRYSTAL_PLATE_MAIL, "crystal plate mail", 14, -8, 1200,
+ false, EQ_BODY_ARMOUR, SIZE_MEDIUM, SIZE_MEDIUM },
+
+ { ARM_TROLL_HIDE, "troll hide", 2, -1, 220,
+ true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+ { ARM_TROLL_LEATHER_ARMOUR, "troll leather armour", 4, -1, 220,
+ true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+ { ARM_STEAM_DRAGON_HIDE, "steam dragon hide", 2, 0, 120,
+ true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+ { ARM_STEAM_DRAGON_ARMOUR, "steam dragon armour", 4, 0, 120,
+ true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+ { ARM_MOTTLED_DRAGON_HIDE, "mottled dragon hide", 2, -1, 150,
+ true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+ { ARM_MOTTLED_DRAGON_ARMOUR,"mottled dragon armour", 5, -1, 150,
+ true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+
+ { ARM_SWAMP_DRAGON_HIDE, "swamp dragon hide", 3, -2, 200,
+ false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+ { ARM_SWAMP_DRAGON_ARMOUR, "swamp dragon armour", 5, -2, 200,
+ false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+ { ARM_DRAGON_HIDE, "dragon hide", 3, -3, 350,
+ false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+ { ARM_DRAGON_ARMOUR, "dragon armour", 6, -3, 350,
+ false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+ { ARM_ICE_DRAGON_HIDE, "ice dragon hide", 3, -3, 350,
+ false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+ { ARM_ICE_DRAGON_ARMOUR, "ice dragon armour", 6, -3, 350,
+ false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+ { ARM_STORM_DRAGON_HIDE, "storm dragon hide", 4, -5, 600,
+ false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+ { ARM_STORM_DRAGON_ARMOUR, "storm dragon armour", 8, -5, 600,
+ false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+ { ARM_GOLD_DRAGON_HIDE, "gold dragon hide", 5, -8, 1100,
+ false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+ { ARM_GOLD_DRAGON_ARMOUR, "gold dragon armour", 10, -8, 1100,
+ false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
+
+ { ARM_CLOAK, "cloak", 1, 0, 40,
+ true, EQ_CLOAK, SIZE_LITTLE, SIZE_BIG },
+ { ARM_GLOVES, "gloves", 1, 0, 20,
+ true, EQ_GLOVES, SIZE_SMALL, SIZE_MEDIUM },
+
+ { ARM_HELMET, "helmet", 1, 0, 80,
+ false, EQ_HELMET, SIZE_SMALL, SIZE_MEDIUM },
+ { ARM_CAP, "cap", 0, 0, 40,
+ true, EQ_HELMET, SIZE_LITTLE, SIZE_LARGE },
+
+ // Note that barding size is compared against torso so it currently
+ // needs to fit medium, but that doesn't matter as much as race
+ // and shapeshift status.
+ { ARM_BOOTS, "boots", 1, 0, 30,
+ true, EQ_BOOTS, SIZE_SMALL, SIZE_MEDIUM },
+ { ARM_CENTAUR_BARDING, "centaur barding", 4, -2, 100,
+ true, EQ_BOOTS, SIZE_MEDIUM, SIZE_MEDIUM },
+ { ARM_NAGA_BARDING, "naga barding", 4, -2, 100,
+ true, EQ_BOOTS, SIZE_MEDIUM, SIZE_MEDIUM },
+
+ // Note: shields use ac-value as sh-value, EV pen is used for heavy_shield
+ { ARM_BUCKLER, "buckler", 3, 0, 90,
+ true, EQ_SHIELD, SIZE_LITTLE, SIZE_MEDIUM },
+ { ARM_SHIELD, "shield", 5, -1, 150,
+ false, EQ_SHIELD, SIZE_SMALL, SIZE_BIG },
+ { ARM_LARGE_SHIELD, "large shield", 7, -2, 230,
+ false, EQ_SHIELD, SIZE_MEDIUM, SIZE_GIANT },
+};
+
+struct weapon_def
+{
+ int id;
+ const char *name;
+ int dam;
+ int hit;
+ int speed;
+ int mass;
+ int str_weight;
+
+ skill_type skill;
+ hands_reqd_type hands;
+ size_type fit_size; // actual size is one size smaller
+ missile_type ammo; // MI_NONE for non-launchers
+ bool throwable;
+
+ int dam_type;
+};
+
+static int Weapon_index[NUM_WEAPONS];
+static weapon_def Weapon_prop[NUM_WEAPONS] =
+{
+ // Maces & Flails
+ { WPN_WHIP, "whip", 4, 2, 13, 30, 2,
+ SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_SLASHING },
+ { WPN_CLUB, "club", 5, 3, 13, 50, 7,
+ SK_MACES_FLAILS, HANDS_ONE, SIZE_SMALL, MI_NONE, true,
+ DAMV_CRUSHING },
+ { WPN_HAMMER, "hammer", 7, 3, 13, 90, 7,
+ SK_MACES_FLAILS, HANDS_ONE, SIZE_SMALL, MI_NONE, false,
+ DAMV_CRUSHING },
+ { WPN_MACE, "mace", 8, 3, 14, 120, 8,
+ SK_MACES_FLAILS, HANDS_ONE, SIZE_SMALL, MI_NONE, false,
+ DAMV_CRUSHING },
+ { WPN_FLAIL, "flail", 9, 2, 15, 130, 8,
+ SK_MACES_FLAILS, HANDS_ONE, SIZE_SMALL, MI_NONE, false,
+ DAMV_CRUSHING },
+ { WPN_ANCUS, "ancus", 9, 2, 14, 120, 8,
+ SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_CRUSHING },
+ { WPN_MORNINGSTAR, "morningstar", 10, -1, 15, 140, 8,
+ SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_PIERCING | DAM_BLUDGEON },
+ { WPN_DEMON_WHIP, "demon whip", 10, 1, 13, 30, 2,
+ SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_SLASHING },
+ { WPN_SPIKED_FLAIL, "spiked flail", 12, -2, 16, 190, 8,
+ SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_PIERCING | DAM_BLUDGEON },
+ { WPN_EVENINGSTAR, "eveningstar", 12, -1, 15, 180, 8,
+ SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_PIERCING | DAM_BLUDGEON },
+ { WPN_DIRE_FLAIL, "dire flail", 13, -3, 14, 240, 9,
+ SK_MACES_FLAILS, HANDS_DOUBLE, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_PIERCING | DAM_BLUDGEON },
+ { WPN_GREAT_MACE, "great mace", 16, -4, 18, 270, 9,
+ SK_MACES_FLAILS, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
+ DAMV_CRUSHING },
+ { WPN_GIANT_CLUB, "giant club", 18, -6, 19, 330, 10,
+ SK_MACES_FLAILS, HANDS_TWO, SIZE_BIG, MI_NONE, false,
+ DAMV_CRUSHING },
+ { WPN_GIANT_SPIKED_CLUB, "giant spiked club", 20, -7, 20, 350, 10,
+ SK_MACES_FLAILS, HANDS_TWO, SIZE_BIG, MI_NONE, false,
+ DAMV_PIERCING | DAM_BLUDGEON },
+
+ // Short blades
+ { WPN_KNIFE, "knife", 3, 5, 10, 10, 1,
+ SK_SHORT_BLADES, HANDS_ONE, SIZE_LITTLE, MI_NONE, false,
+ DAMV_STABBING | DAM_SLICE },
+ { WPN_DAGGER, "dagger", 4, 6, 10, 20, 1,
+ SK_SHORT_BLADES, HANDS_ONE, SIZE_LITTLE, MI_NONE, true,
+ DAMV_STABBING | DAM_SLICE },
+ { WPN_QUICK_BLADE, "quick blade", 5, 6, 7, 50, 0,
+ SK_SHORT_BLADES, HANDS_ONE, SIZE_LITTLE, MI_NONE, false,
+ DAMV_STABBING | DAM_SLICE },
+ { WPN_SHORT_SWORD, "short sword", 6, 4, 11, 80, 2,
+ SK_SHORT_BLADES, HANDS_ONE, SIZE_SMALL, MI_NONE, false,
+ DAMV_SLICING | DAM_PIERCE },
+ { WPN_SABRE, "sabre", 7, 4, 12, 90, 2,
+ SK_SHORT_BLADES, HANDS_ONE, SIZE_SMALL, MI_NONE, false,
+ DAMV_SLICING | DAM_PIERCE },
+
+ // Long swords
+ { WPN_FALCHION, "falchion", 8, 2, 13, 170, 4,
+ SK_LONG_SWORDS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_SLICING }, // or perhaps DAMV_CHOPPING is more apt?
+ { WPN_LONG_SWORD, "long sword", 10, 1, 14, 160, 3,
+ SK_LONG_SWORDS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_SLICING },
+ { WPN_SCIMITAR, "scimitar", 11, -1, 14, 170, 3,
+ SK_LONG_SWORDS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_SLICING },
+ { WPN_KATANA, "katana", 13, 2, 13, 160, 3,
+ SK_LONG_SWORDS, HANDS_HALF, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_SLICING },
+ { WPN_DEMON_BLADE, "demon blade", 13, -1, 15, 200, 4,
+ SK_LONG_SWORDS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_SLICING },
+ { WPN_BLESSED_BLADE, "blessed blade", 14, 0, 14, 200, 4,
+ SK_LONG_SWORDS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_SLICING },
+ { WPN_DOUBLE_SWORD, "double sword", 15, -2, 16, 220, 5,
+ SK_LONG_SWORDS, HANDS_HALF, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_SLICING },
+ { WPN_GREAT_SWORD, "great sword", 16, -3, 17, 250, 6,
+ SK_LONG_SWORDS, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
+ DAMV_SLICING },
+ { WPN_TRIPLE_SWORD, "triple sword", 19, -4, 19, 260, 6,
+ SK_LONG_SWORDS, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
+ DAMV_SLICING },
+
+ // Axes
+ { WPN_HAND_AXE, "hand axe", 7, 3, 13, 80, 6,
+ SK_AXES, HANDS_ONE, SIZE_SMALL, MI_NONE, true,
+ DAMV_CHOPPING },
+ { WPN_WAR_AXE, "war axe", 11, 0, 16, 180, 7,
+ SK_AXES, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_CHOPPING },
+ { WPN_BROAD_AXE, "broad axe", 14, -2, 17, 230, 8,
+ SK_AXES, HANDS_HALF, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_CHOPPING },
+ { WPN_BATTLEAXE, "battleaxe", 17, -4, 18, 250, 8,
+ SK_AXES, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
+ DAMV_CHOPPING },
+ { WPN_EXECUTIONERS_AXE, "executioner\'s axe", 20, -6, 20, 280, 9,
+ SK_AXES, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
+ DAMV_CHOPPING },
+
+ // Polearms
+ { WPN_SPEAR, "spear", 6, 3, 12, 50, 3,
+ SK_POLEARMS, HANDS_HALF, SIZE_SMALL, MI_NONE, true,
+ DAMV_PIERCING },
+ { WPN_TRIDENT, "trident", 9, 2, 14, 160, 4,
+ SK_POLEARMS, HANDS_HALF, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_PIERCING },
+ { WPN_DEMON_TRIDENT, "demon trident", 13, 0, 14, 160, 4,
+ SK_POLEARMS, HANDS_HALF, SIZE_MEDIUM, MI_NONE, false,
+ DAMV_PIERCING },
+ { WPN_HALBERD, "halberd", 13, -3, 16, 200, 5,
+ SK_POLEARMS, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
+ DAMV_CHOPPING | DAM_PIERCE },
+ { WPN_SCYTHE, "scythe", 14, -4, 20, 220, 7,
+ SK_POLEARMS, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
+ DAMV_SLICING },
+ { WPN_GLAIVE, "glaive", 15, -3, 18, 200, 6,
+ SK_POLEARMS, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
+ DAMV_CHOPPING },
+ { WPN_LOCHABER_AXE, "lochaber axe", 18, -6, 20, 200, 8,
+ SK_POLEARMS, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
+ DAMV_CHOPPING },
+
+ { WPN_QUARTERSTAFF, "quarterstaff", 9, 2, 12, 180, 7,
+ SK_STAVES, HANDS_DOUBLE, SIZE_LARGE, MI_NONE, false,
+ DAMV_CRUSHING },
+ { WPN_LAJATANG, "lajatang", 14, -3, 14, 200, 3,
+ SK_STAVES, HANDS_DOUBLE, SIZE_LARGE, MI_NONE, false,
+ DAMV_SLICING },
+
+ // Range weapons
+ // Notes:
+ // - HANDS_HALF means a reloading time penalty if using shield
+ // - damage field is used for bonus strength damage (string tension)
+ // - slings get a bonus from dex, not str (as tension is meaningless)
+ // - str weight is used for speed and applying dex to skill
+ { WPN_BLOWGUN, "blowgun", 0, 2, 10, 20, 0,
+ SK_DARTS, HANDS_HALF, SIZE_LITTLE, MI_NEEDLE, false,
+ DAMV_NON_MELEE },
+ { WPN_SLING, "sling", 0, 2, 11, 20, 1,
+ SK_SLINGS, HANDS_HALF, SIZE_LITTLE, MI_STONE, false,
+ DAMV_NON_MELEE },
+ { WPN_HAND_CROSSBOW, "hand crossbow", 3, 4, 15, 70, 5,
+ SK_CROSSBOWS, HANDS_HALF, SIZE_SMALL, MI_DART, false,
+ DAMV_NON_MELEE },
+ { WPN_CROSSBOW, "crossbow", 5, 4, 15, 150, 8,
+ SK_CROSSBOWS, HANDS_TWO, SIZE_MEDIUM, MI_BOLT, false,
+ DAMV_NON_MELEE },
+ { WPN_BOW, "bow", 4, 1, 11, 90, 2,
+ SK_BOWS, HANDS_TWO, SIZE_MEDIUM, MI_ARROW, false,
+ DAMV_NON_MELEE },
+ { WPN_LONGBOW, "longbow", 5, 0, 12, 120, 3,
+ SK_BOWS, HANDS_TWO, SIZE_LARGE, MI_ARROW, false,
+ DAMV_NON_MELEE },
+};
+
+struct missile_def
+{
+ int id;
+ const char *name;
+ int dam;
+ int mass;
+ bool throwable;
+};
+
+static int Missile_index[NUM_MISSILES];
+static missile_def Missile_prop[NUM_MISSILES] =
+{
+ { MI_NEEDLE, "needle", 0, 1, false },
+ { MI_STONE, "stone", 4, 2, true },
+ { MI_DART, "dart", 5, 3, true },
+ { MI_ARROW, "arrow", 6, 5, false },
+ { MI_BOLT, "bolt", 8, 5, false },
+ { MI_LARGE_ROCK, "large rock", 20, 1000, true },
+};
+
+struct food_def
+{
+ int id;
+ const char *name;
+ int value;
+ int carn_mod;
+ int herb_mod;
+ int mass;
+ int turns;
+};
+
+// NOTE: Any food with special random messages or side effects
+// currently only takes one turn to eat (except ghouls and chunks)...
+// if this changes then those items will have to have special code
+// (like ghoul chunks) to guarantee that the special thing is only
+// done once. See the ghoul eating code over in food.cc.
+static int Food_index[NUM_FOODS];
+static food_def Food_prop[NUM_FOODS] =
+{
+ { FOOD_MEAT_RATION, "meat ration", 5000, 500, -1500, 80, 4 },
+ { FOOD_SAUSAGE, "sausage", 1500, 150, -400, 40, 1 },
+ { FOOD_CHUNK, "chunk", 1000, 100, -500, 100, 3 },
+ { FOOD_BEEF_JERKY, "beef jerky", 800, 100, -250, 20, 1 },
+
+ { FOOD_BREAD_RATION, "bread ration", 4400, -1500, 750, 80, 4 },
+ { FOOD_SNOZZCUMBER, "snozzcumber", 1500, -500, 500, 50, 1 },
+ { FOOD_ORANGE, "orange", 1000, -350, 400, 20, 1 },
+ { FOOD_BANANA, "banana", 1000, -350, 400, 20, 1 },
+ { FOOD_LEMON, "lemon", 1000, -350, 400, 20, 1 },
+ { FOOD_PEAR, "pear", 700, -250, 300, 20, 1 },
+ { FOOD_APPLE, "apple", 700, -250, 300, 20, 1 },
+ { FOOD_APRICOT, "apricot", 700, -250, 300, 15, 1 },
+ { FOOD_CHOKO, "choko", 600, -200, 250, 30, 1 },
+ { FOOD_RAMBUTAN, "rambutan", 600, -200, 250, 10, 1 },
+ { FOOD_LYCHEE, "lychee", 600, -200, 250, 10, 1 },
+ { FOOD_STRAWBERRY, "strawberry", 200, -80, 100, 5, 1 },
+ { FOOD_GRAPE, "grape", 100, -40, 50, 2, 1 },
+ { FOOD_SULTANA, "sultana", 70, -30, 30, 1, 1 },
+
+ { FOOD_ROYAL_JELLY, "royal jelly", 4000, 0, 0, 55, 1 },
+ { FOOD_HONEYCOMB, "honeycomb", 2000, 0, 0, 40, 1 },
+ { FOOD_PIZZA, "pizza", 1500, 0, 0, 40, 1 },
+ { FOOD_CHEESE, "cheese", 1200, 0, 0, 40, 1 },
+};
+
+// Must call this functions early on so that the above tables can
+// be accessed correctly.
+void init_properties(void)
+{
+ int i;
+
+ for (i = 0; i < NUM_ARMOURS; i++)
+ Armour_index[ Armour_prop[i].id ] = i;
+
+ for (i = 0; i < NUM_WEAPONS; i++)
+ Weapon_index[ Weapon_prop[i].id ] = i;
+
+ for (i = 0; i < NUM_MISSILES; i++)
+ Missile_index[ Missile_prop[i].id ] = i;
+
+ for (i = 0; i < NUM_FOODS; i++)
+ Food_index[ Food_prop[i].id ] = i;
+}
+
+
+// Some convenient functions to hide the bit operations and create
+// an interface layer between the code and the data in case this
+// gets changed again. -- bwr
+
+//
+// Item cursed status functions:
+//
+bool item_cursed( const item_def &item )
+{
+ return (item.flags & ISFLAG_CURSED);
+}
+
+bool item_known_cursed( const item_def &item )
+{
+ return ((item.flags & ISFLAG_KNOW_CURSE) && (item.flags & ISFLAG_CURSED));
+}
+
+bool item_known_uncursed( const item_def &item )
+{
+ return ((item.flags & ISFLAG_KNOW_CURSE) && !(item.flags & ISFLAG_CURSED));
+}
+
+void do_curse_item( item_def &item )
+{
+ item.flags |= ISFLAG_CURSED;
+}
+
+void do_uncurse_item( item_def &item )
+{
+ item.flags &= (~ISFLAG_CURSED);
+}
+
+//
+// Item identification status:
+//
+bool item_ident( const item_def &item, unsigned long flags )
+{
+ return ((item.flags & flags) == flags);
+}
+
+void set_ident_flags( item_def &item, unsigned long flags )
+{
+ bool known_before = fully_identified(item);
+ item.flags |= flags;
+ if ( !known_before && fully_identified(item) ) {
+ /* make a note of it */
+ if ( is_interesting_item(item) ) {
+ char buf[ITEMNAME_SIZE];
+ char buf2[ITEMNAME_SIZE];
+ item_name( item, DESC_NOCAP_A, buf );
+ strcpy(buf2, origin_desc(item).c_str());
+ take_note(Note(NOTE_ID_ITEM, 0, 0, buf, buf2));
+ }
+ }
+}
+
+void unset_ident_flags( item_def &item, unsigned long flags )
+{
+ item.flags &= (~flags);
+}
+
+//
+// Equipment race and description:
+//
+unsigned long get_equip_race( const item_def &item )
+{
+ return (item.flags & ISFLAG_RACIAL_MASK);
+}
+
+unsigned long get_equip_desc( const item_def &item )
+{
+ return (item.flags & ISFLAG_COSMETIC_MASK);
+}
+
+void set_equip_race( item_def &item, unsigned long flags )
+{
+ ASSERT( (flags & ~ISFLAG_RACIAL_MASK) == 0 );
+
+ // first check for base-sub pairs that can't ever have racial types
+ switch (item.base_type)
+ {
+ case OBJ_WEAPONS:
+ if (item.sub_type == WPN_GIANT_CLUB
+ || item.sub_type == WPN_GIANT_SPIKED_CLUB
+ || item.sub_type == WPN_KATANA
+ || item.sub_type == WPN_LAJATANG
+ || item.sub_type == WPN_SLING
+ || item.sub_type == WPN_KNIFE
+ || item.sub_type == WPN_QUARTERSTAFF
+ || item.sub_type == WPN_DEMON_BLADE
+ || item.sub_type == WPN_DEMON_WHIP
+ || item.sub_type == WPN_DEMON_TRIDENT)
+ {
+ return;
+ }
+ break;
+
+ case OBJ_ARMOUR:
+ // not hides, dragon armour, crystal plate, or barding
+ if (item.sub_type >= ARM_DRAGON_HIDE
+ && item.sub_type <= ARM_SWAMP_DRAGON_ARMOUR
+ && item.sub_type != ARM_CENTAUR_BARDING
+ && item.sub_type != ARM_NAGA_BARDING)
+ {
+ return;
+ }
+ break;
+
+ case OBJ_MISSILES:
+ if (item.sub_type == MI_STONE || item.sub_type == MI_LARGE_ROCK)
+ return;
+ break;
+
+ default:
+ return;
+ }
+
+ // check that item is appropriate for racial type
+ switch (flags)
+ {
+ case ISFLAG_ELVEN:
+ if (item.base_type == OBJ_ARMOUR
+ && (item.sub_type == ARM_SPLINT_MAIL
+ || item.sub_type == ARM_BANDED_MAIL
+ || item.sub_type == ARM_PLATE_MAIL))
+ {
+ return;
+ }
+ break;
+
+ case ISFLAG_DWARVEN:
+ if (item.base_type == OBJ_ARMOUR
+ && (item.sub_type == ARM_ROBE
+ || item.sub_type == ARM_LEATHER_ARMOUR
+ || item.sub_type == ARM_STUDDED_LEATHER_ARMOUR))
+ {
+ return;
+ }
+ break;
+
+ case ISFLAG_ORCISH:
+ default:
+ break;
+ }
+
+ item.flags &= ~ISFLAG_RACIAL_MASK; // delete previous
+ item.flags |= flags;
+}
+
+void set_equip_desc( item_def &item, unsigned long flags )
+{
+ ASSERT( (flags & ~ISFLAG_COSMETIC_MASK) == 0 );
+
+ item.flags &= ~ISFLAG_COSMETIC_MASK; // delete previous
+ item.flags |= flags;
+}
+
+//
+// These functions handle the description and subtypes for helmets/caps
+//
+short get_helmet_type( const item_def &item )
+{
+ ASSERT( item.base_type == OBJ_ARMOUR
+ && get_armour_slot( item ) == EQ_HELMET );
+
+ return (item.plus2 & THELM_TYPE_MASK);
+}
+
+short get_helmet_desc( const item_def &item )
+{
+ ASSERT( item.base_type == OBJ_ARMOUR
+ && get_armour_slot( item ) == EQ_HELMET );
+
+ return (item.plus2 & THELM_DESC_MASK);
+}
+
+void set_helmet_type( item_def &item, short type )
+{
+ ASSERT( (type & ~THELM_TYPE_MASK) == 0 );
+ ASSERT( item.base_type == OBJ_ARMOUR
+ && get_armour_slot( item ) == EQ_HELMET );
+
+ // make sure we have the right sub_type (to get properties correctly)
+ if (type == THELM_HELMET || type == THELM_HELM)
+ item.sub_type = ARM_HELMET;
+
+ // [dshaligram] FIXME: This is for when we import caps
+ // else
+ // item.sub_type = ARM_CAP;
+
+ item.plus2 &= ~THELM_TYPE_MASK;
+ item.plus2 |= type;
+}
+
+void set_helmet_desc( item_def &item, short type )
+{
+ ASSERT( (type & ~THELM_DESC_MASK) == 0 );
+ ASSERT( item.base_type == OBJ_ARMOUR
+ && get_armour_slot( item ) == EQ_HELMET );
+
+ const int helmtype = get_helmet_type(item);
+ if ((helmtype == THELM_CAP || helmtype == THELM_WIZARD_HAT)
+ && type > THELM_DESC_PLUMED)
+ type = THELM_DESC_PLAIN;
+
+ item.plus2 &= ~THELM_DESC_MASK;
+ item.plus2 |= type;
+}
+
+bool is_hard_helmet(const item_def &item)
+{
+ return (item.base_type == OBJ_ARMOUR
+ && item.sub_type == ARM_HELMET
+ && (get_helmet_type(item) == THELM_HELM
+ || get_helmet_type(item) == THELM_HELMET));
+}
+
+void set_helmet_random_desc( item_def &item )
+{
+ ASSERT( item.base_type == OBJ_ARMOUR
+ && get_armour_slot( item ) == EQ_HELMET );
+
+ item.plus2 &= ~THELM_DESC_MASK;
+
+ if (is_hard_helmet(item))
+ item.plus2 |= (random2(8) << 8);
+ else
+ item.plus2 |= (random2(5) << 8);
+
+}
+
+bool is_helmet_type( const item_def &item, short val )
+{
+ if (item.base_type != OBJ_ARMOUR || get_armour_slot( item ) != EQ_HELMET)
+ return (false);
+
+ return (get_helmet_type( item ) == val);
+}
+
+//
+// Ego item functions:
+//
+bool set_item_ego_type( item_def &item, int item_type, int ego_type )
+{
+ if (item.base_type == item_type
+ && !is_random_artefact( item )
+ && !is_fixed_artefact( item ))
+ {
+ item.special = ego_type;
+ return (true);
+ }
+
+ return (false);
+}
+
+int get_weapon_brand( const item_def &item )
+{
+ // Weapon ego types are "brands", so we do the randart lookup here.
+
+ // Staves "brands" handled specially
+ if (item.base_type != OBJ_WEAPONS)
+ return (SPWPN_NORMAL);
+
+ if (is_fixed_artefact( item ))
+ {
+ switch (item.special)
+ {
+ case SPWPN_SWORD_OF_CEREBOV:
+ return (SPWPN_FLAMING);
+
+ case SPWPN_STAFF_OF_OLGREB:
+ return (SPWPN_VENOM);
+
+ case SPWPN_VAMPIRES_TOOTH:
+ return (SPWPN_VAMPIRICISM);
+
+ default:
+ return (SPWPN_NORMAL);
+ }
+ }
+ else if (is_random_artefact( item ))
+ {
+ return (randart_wpn_property( item, RAP_BRAND ));
+ }
+
+ return (item.special);
+}
+
+int get_ammo_brand( const item_def &item )
+{
+ // no artefact arrows yet -- bwr
+ if (item.base_type != OBJ_MISSILES || is_random_artefact( item ))
+ return (SPMSL_NORMAL);
+
+ return (item.special);
+}
+
+int get_armour_ego_type( const item_def &item )
+{
+ // artefact armours have no ego type, must look up powers separately
+ if (item.base_type != OBJ_ARMOUR
+ || (is_random_artefact( item ) && !is_unrandom_artefact( item )))
+ {
+ return (SPARM_NORMAL);
+ }
+
+ return (item.special);
+}
+
+//
+// Armour information and checking functions
+//
+bool hide2armour( item_def &item )
+{
+ if (item.base_type != OBJ_ARMOUR)
+ return (false);
+
+ switch (item.sub_type)
+ {
+ default:
+ return (false);
+
+ case ARM_DRAGON_HIDE:
+ item.sub_type = ARM_DRAGON_ARMOUR;
+ break;
+
+ case ARM_TROLL_HIDE:
+ item.sub_type = ARM_TROLL_LEATHER_ARMOUR;
+ break;
+
+ case ARM_ICE_DRAGON_HIDE:
+ item.sub_type = ARM_ICE_DRAGON_ARMOUR;
+ break;
+
+ case ARM_MOTTLED_DRAGON_HIDE:
+ item.sub_type = ARM_MOTTLED_DRAGON_ARMOUR;
+ break;
+
+ case ARM_STORM_DRAGON_HIDE:
+ item.sub_type = ARM_STORM_DRAGON_ARMOUR;
+ break;
+
+ case ARM_GOLD_DRAGON_HIDE:
+ item.sub_type = ARM_GOLD_DRAGON_ARMOUR;
+ break;
+
+ case ARM_SWAMP_DRAGON_HIDE:
+ item.sub_type = ARM_SWAMP_DRAGON_ARMOUR;
+ break;
+
+ case ARM_STEAM_DRAGON_HIDE:
+ item.sub_type = ARM_STEAM_DRAGON_ARMOUR;
+ break;
+ }
+
+ return (true);
+} // end hide2armour()
+
+// Return the enchantment limit of a piece of armour
+int armour_max_enchant( const item_def &item )
+{
+ ASSERT( item.base_type == OBJ_ARMOUR );
+
+ const int eq_slot = get_armour_slot( item );
+
+ int max_plus = MAX_SEC_ENCHANT;
+ if (eq_slot == EQ_BODY_ARMOUR || eq_slot == EQ_SHIELD)
+ max_plus = MAX_ARM_ENCHANT;
+
+ return (max_plus);
+}
+
+// doesn't include animal skin (only skins we can make and enchant)
+bool armour_is_hide( const item_def &item, bool inc_made )
+{
+ ASSERT( item.base_type == OBJ_ARMOUR );
+
+ switch (item.sub_type)
+ {
+ case ARM_TROLL_LEATHER_ARMOUR:
+ case ARM_DRAGON_ARMOUR:
+ case ARM_ICE_DRAGON_ARMOUR:
+ case ARM_STEAM_DRAGON_ARMOUR:
+ case ARM_MOTTLED_DRAGON_ARMOUR:
+ case ARM_STORM_DRAGON_ARMOUR:
+ case ARM_GOLD_DRAGON_ARMOUR:
+ case ARM_SWAMP_DRAGON_ARMOUR:
+ return (inc_made);
+
+ case ARM_TROLL_HIDE:
+ case ARM_DRAGON_HIDE:
+ case ARM_ICE_DRAGON_HIDE:
+ case ARM_STEAM_DRAGON_HIDE:
+ case ARM_MOTTLED_DRAGON_HIDE:
+ case ARM_STORM_DRAGON_HIDE:
+ case ARM_GOLD_DRAGON_HIDE:
+ case ARM_SWAMP_DRAGON_HIDE:
+ return (true);
+
+ default:
+ break;
+ }
+
+ return (false);
+}
+
+// used to distinguish shiny and embroidered
+bool armour_not_shiny( const item_def &item )
+{
+ ASSERT( item.base_type == OBJ_ARMOUR );
+
+ switch (item.sub_type)
+ {
+ case ARM_ROBE:
+ case ARM_CLOAK:
+ case ARM_GLOVES:
+ case ARM_BOOTS:
+ case ARM_NAGA_BARDING:
+ case ARM_CENTAUR_BARDING:
+ case ARM_CAP:
+ case ARM_LEATHER_ARMOUR:
+ case ARM_STUDDED_LEATHER_ARMOUR:
+ case ARM_ANIMAL_SKIN:
+ case ARM_TROLL_HIDE:
+ case ARM_TROLL_LEATHER_ARMOUR:
+ return (true);
+
+ case ARM_HELMET:
+ {
+ const int helmtype = get_helmet_type(item);
+ return (helmtype == THELM_CAP || helmtype == THELM_WIZARD_HAT);
+ }
+ default:
+ break;
+ }
+
+ return (false);
+}
+
+int armour_str_required( const item_def &arm )
+{
+ ASSERT (arm.base_type == OBJ_ARMOUR );
+
+ int ret = 0;
+
+ const equipment_type slot = get_armour_slot( arm );
+ const int mass = item_mass( arm );
+
+ switch (slot)
+ {
+ case EQ_BODY_ARMOUR:
+ ret = mass / 35;
+ break;
+
+ case EQ_SHIELD:
+ ret = mass / 15;
+ break;
+
+ default:
+ break;
+ }
+
+ return ((ret < STR_REQ_THRESHOLD) ? 0 : ret);
+}
+
+equipment_type get_armour_slot( const item_def &item )
+{
+ ASSERT( item.base_type == OBJ_ARMOUR );
+
+ return (Armour_prop[ Armour_index[item.sub_type] ].slot);
+}
+
+bool jewellery_is_amulet( const item_def &item )
+{
+ ASSERT( item.base_type == OBJ_JEWELLERY );
+
+ return (item.sub_type >= AMU_RAGE);
+}
+
+bool check_jewellery_size( const item_def &item, size_type size )
+{
+ ASSERT( item.base_type == OBJ_JEWELLERY );
+
+ // Currently assuming amulets are always wearable (only needs
+ // to be held over head or heart... giants can strap it on with
+ // a bit of binder twine). However, rings need to actually fit
+ // around the ring finger to work, and so the big cannot use them.
+ return (size <= SIZE_LARGE || jewellery_is_amulet( item ));
+}
+
+// Returns the basic light status of an armour, ignoring things like the
+// elven bonus... you probably want is_light_armour() most times.
+bool base_armour_is_light( const item_def &item )
+{
+ ASSERT( item.base_type == OBJ_ARMOUR );
+
+ return (Armour_prop[ Armour_index[item.sub_type] ].light);
+}
+
+// returns number of sizes off
+int fit_armour_size( const item_def &item, size_type size )
+{
+ ASSERT( item.base_type == OBJ_ARMOUR );
+
+ const size_type min = Armour_prop[ Armour_index[item.sub_type] ].fit_min;
+ const size_type max = Armour_prop[ Armour_index[item.sub_type] ].fit_max;
+
+ if (size < min)
+ return (min - size); // -'ve means levels too small
+ else if (size > max)
+ return (max - size); // +'ve means levels too large
+
+ return (0);
+}
+
+// returns true if armour fits size (shape needs additional verification)
+bool check_armour_size( const item_def &item, size_type size )
+{
+ ASSERT( item.base_type == OBJ_ARMOUR );
+
+ return (fit_armour_size( item, size ) == 0);
+}
+
+// Note that this function is used to check validity of equipment
+// coming out of transformations... so it shouldn't contain any
+// wield/unwield only checks like two-handed weapons and shield.
+bool check_armour_shape( const item_def &item, bool quiet )
+{
+ ASSERT( item.base_type == OBJ_ARMOUR );
+
+ const int slot = get_armour_slot( item );
+
+ if (!player_is_shapechanged())
+ {
+ switch (slot)
+ {
+ case EQ_BOOTS:
+ switch (you.species)
+ {
+ case SP_NAGA:
+ if (item.sub_type != ARM_NAGA_BARDING)
+ {
+ if (!quiet)
+ mpr( "You can't wear that!" );
+
+ return (false);
+ }
+ break;
+
+ case SP_CENTAUR:
+ if (item.sub_type != ARM_CENTAUR_BARDING)
+ {
+ if (!quiet)
+ mpr( "You can't wear that!" );
+
+ return (false);
+ }
+ break;
+
+ case SP_KENKU:
+ if (!quiet)
+ {
+ if (item.sub_type == ARM_BOOTS)
+ mpr( "Boots don't fit your feet!" );
+ else
+ mpr( "You can't wear barding!" );
+ }
+ return (false);
+
+ case SP_MERFOLK:
+ if (player_in_water() && item.sub_type == ARM_BOOTS)
+ {
+ if (!quiet)
+ mpr( "You don't currently have feet!" );
+
+ return (false);
+ }
+ // intentional fall-through
+ default:
+ if (item.sub_type == ARM_NAGA_BARDING
+ || item.sub_type == ARM_CENTAUR_BARDING)
+ {
+ if (!quiet)
+ mpr( "You can't wear barding!" );
+
+ return (false);
+ }
+
+ if (you.mutation[MUT_HOOVES] >= 2)
+ {
+ if (!quiet)
+ mpr( "You can't wear boots with hooves!" );
+
+ return (false);
+ }
+ break;
+ }
+ break;
+
+ case EQ_HELMET:
+ if (item.sub_type == ARM_CAP
+ || get_helmet_type(item) == THELM_CAP
+ || get_helmet_type(item) == THELM_WIZARD_HAT)
+ break;
+
+ if (you.species == SP_KENKU)
+ {
+ if (!quiet)
+ mpr( "That helmet does not fit your head!" );
+
+ return (false);
+ }
+
+ if (you.species == SP_MINOTAUR || you.mutation[MUT_HORNS])
+ {
+ if (!quiet)
+ mpr( "You can't wear that with your horns!" );
+
+ return (false);
+ }
+ break;
+
+ case EQ_GLOVES:
+ if (you.mutation[MUT_CLAWS] >= 3)
+ {
+ if (!quiet)
+ mpr( "You can't wear gloves with your huge claws!" );
+
+ return (false);
+ }
+ break;
+
+ case EQ_BODY_ARMOUR:
+ // Cannot swim in heavy armour
+ if (player_is_swimming() && !is_light_armour( item ))
+ {
+ if (!quiet)
+ mpr("You can't swim in that!");
+
+ return (false);
+ }
+
+ // Draconians are human-sized, but have wings that cause problems
+ // with most body armours (only very flexible fit allowed).
+ if (player_genus( GENPC_DRACONIAN )
+ && !check_armour_size( item, SIZE_BIG ))
+ {
+ if (!quiet)
+ mpr( "That armour doesn't fit your wings." );
+
+ return (false);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // Note: some transformation include all of the above as well
+ if (item.sub_type == ARM_NAGA_BARDING
+ || item.sub_type == ARM_CENTAUR_BARDING)
+ {
+ if (!quiet)
+ mpr( "You can't wear barding in your current form!" );
+
+ return (false);
+ }
+ }
+
+ // Note: This need to be checked after all the special cases
+ // above, and in addition to shapechanged or not. This is
+ // a simple check against the armour types that are forced off.
+
+ // FIXME FIXME FIXME
+ /*
+ if (!transform_can_equip_type( slot ))
+ {
+ if (!quiet)
+ mpr( "You can't wear that in your current form!" );
+
+ return (false);
+ }
+ */
+
+ return (true);
+}
+
+//
+// Weapon information and checking functions:
+//
+
+// Checks how rare a weapon is. Many of these have special routines for
+// placement, especially those with a rarity of zero. Chance is out of 10.
+int weapon_rarity( int w_type )
+{
+ switch (w_type)
+ {
+ case WPN_CLUB:
+ case WPN_DAGGER:
+ return (10);
+
+ case WPN_HAND_AXE:
+ case WPN_MACE:
+ case WPN_QUARTERSTAFF:
+ return (9);
+
+ case WPN_BOW:
+ case WPN_FLAIL:
+ case WPN_HAMMER:
+ case WPN_SABRE:
+ case WPN_SHORT_SWORD:
+ case WPN_SLING:
+ case WPN_SPEAR:
+ return (8);
+
+ case WPN_FALCHION:
+ case WPN_LONG_SWORD:
+ case WPN_MORNINGSTAR:
+ case WPN_WAR_AXE:
+ return (7);
+
+ case WPN_BATTLEAXE:
+ case WPN_CROSSBOW:
+ case WPN_GREAT_SWORD:
+ case WPN_SCIMITAR:
+ case WPN_TRIDENT:
+ return (6);
+
+ case WPN_GLAIVE:
+ case WPN_HALBERD:
+ case WPN_BLOWGUN:
+ return (5);
+
+ case WPN_BROAD_AXE:
+ case WPN_HAND_CROSSBOW:
+ case WPN_SPIKED_FLAIL:
+ case WPN_WHIP:
+ return (4);
+
+ case WPN_GREAT_MACE:
+ return (3);
+
+ case WPN_ANCUS:
+ case WPN_DIRE_FLAIL:
+ case WPN_SCYTHE:
+ case WPN_LONGBOW:
+ return (2);
+
+ case WPN_GIANT_CLUB:
+ case WPN_GIANT_SPIKED_CLUB:
+ case WPN_LOCHABER_AXE:
+ return (1);
+
+ case WPN_DOUBLE_SWORD:
+ case WPN_EVENINGSTAR:
+ case WPN_EXECUTIONERS_AXE:
+ case WPN_KATANA:
+ case WPN_LAJATANG:
+ case WPN_KNIFE:
+ case WPN_QUICK_BLADE:
+ case WPN_TRIPLE_SWORD:
+ case WPN_DEMON_TRIDENT:
+ case WPN_DEMON_WHIP:
+ case WPN_DEMON_BLADE:
+ case WPN_BLESSED_BLADE:
+ // zero value weapons must be placed specially -- see make_item() {dlb}
+ return (0);
+
+ default:
+ break;
+ }
+
+ return (0);
+} // end rare_weapon()
+
+int get_vorpal_type( const item_def &item )
+{
+ int ret = DVORP_NONE;
+
+ if (item.base_type == OBJ_WEAPONS)
+ ret = (Weapon_prop[ Weapon_index[item.sub_type] ].dam_type & DAMV_MASK);
+
+ return (ret);
+} // end vorpal_type()
+
+int get_damage_type( const item_def &item )
+{
+ int ret = DAM_BASH;
+
+ if (item.base_type == OBJ_WEAPONS)
+ ret = (Weapon_prop[ Weapon_index[item.sub_type] ].dam_type & DAM_MASK);
+
+ return (ret);
+} // end damage_type()
+
+bool does_damage_type( const item_def &item, int dam_type )
+{
+ return (get_damage_type( item ) & dam_type);
+} // end does_damage_type()
+
+
+hands_reqd_type hands_reqd(int base_type, int sub_type, size_type size)
+{
+ item_def item;
+ item.base_type = base_type;
+ item.sub_type = sub_type;
+ return hands_reqd(item, size);
+}
+
+// give hands required to wield weapon for a torso of "size"
+hands_reqd_type hands_reqd( const item_def &item, size_type size )
+{
+ int ret = HANDS_ONE;
+ int fit;
+ bool doub = false;
+
+ switch (item.base_type)
+ {
+ case OBJ_STAVES:
+ case OBJ_WEAPONS:
+ // Merging staff with magical staves for consistency... doing
+ // as a special case because we want to be very flexible with
+ // these useful objects (we want spriggans and ogre magi to
+ // be able to use them).
+ if (item.base_type == OBJ_STAVES || item.sub_type == WPN_QUARTERSTAFF)
+ {
+ if (size < SIZE_SMALL)
+ ret = HANDS_TWO;
+ else if (size > SIZE_LARGE)
+ ret = HANDS_ONE;
+ else
+ ret = HANDS_HALF;
+ break;
+ }
+
+ ret = Weapon_prop[ Weapon_index[item.sub_type] ].hands;
+
+ // size is the level where we can use one hand for one end
+ if (ret == HANDS_DOUBLE)
+ {
+ doub = true;
+ ret = HANDS_HALF;
+ }
+
+ // adjust handedness for size only for non-whip melee weapons
+ if (!is_range_weapon( item )
+ && item.sub_type != WPN_WHIP
+ && item.sub_type != WPN_DEMON_WHIP)
+ {
+ fit = cmp_weapon_size( item, size );
+
+ // Adjust handedness for non-medium races:
+ // (XX values don't matter, see fit_weapon_wieldable_size)
+ //
+ // Spriggan Kobold Human Ogre Big Giant
+ // Little 0 0 0 XX XX XX
+ // Small +1 0 0 -2 XX XX
+ // Medium XX +1 0 -1 -2 XX
+ // Large XX XX 0 0 -1 -2
+ // Big XX XX XX 0 0 -1
+ // Giant XX XX XX XX 0 0
+
+ // Note the stretching of double weapons for larger characters
+ // by one level since they tend to be larger weapons.
+ if (size < SIZE_MEDIUM && fit > 0)
+ ret += fit;
+ else if (size > SIZE_MEDIUM && fit < 0)
+ ret += (fit + doub);
+ }
+ break;
+
+ case OBJ_CORPSES: // unwieldy
+ ret = HANDS_TWO;
+ break;
+
+ case OBJ_ARMOUR: // barding and body armours are unwieldy
+ if (item.sub_type == ARM_NAGA_BARDING
+ || item.sub_type == ARM_CENTAUR_BARDING
+ || get_armour_slot( item ) == EQ_BODY_ARMOUR)
+ {
+ ret = HANDS_TWO;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (ret > HANDS_TWO)
+ ret = HANDS_TWO;
+ else if (ret < HANDS_ONE)
+ ret = HANDS_ONE;
+
+ return (static_cast< hands_reqd_type >( ret ));
+}
+
+bool is_double_ended( const item_def &item )
+{
+ if (item.base_type == OBJ_STAVES)
+ return (true);
+ else if (item.base_type != OBJ_WEAPONS)
+ return (false);
+
+ return (Weapon_prop[ Weapon_index[item.sub_type] ].hands == HANDS_DOUBLE);
+}
+
+int double_wpn_awkward_speed( const item_def &item )
+{
+ ASSERT( is_double_ended( item ) );
+
+ const int base = property( item, PWPN_SPEED );
+
+ return ((base * 30 + 10) / 20 + 2);
+}
+
+
+bool is_demonic( const item_def &item )
+{
+ if (item.base_type == OBJ_WEAPONS)
+ {
+ switch (item.sub_type)
+ {
+ case WPN_DEMON_BLADE:
+ case WPN_DEMON_WHIP:
+ case WPN_DEMON_TRIDENT:
+ return (true);
+
+ default:
+ break;
+ }
+ }
+
+ return (false);
+} // end is_demonic()
+
+int weapon_str_weight( const item_def &wpn )
+{
+ ASSERT (wpn.base_type == OBJ_WEAPONS || wpn.base_type == OBJ_STAVES);
+
+ if (wpn.base_type == OBJ_STAVES)
+ return (Weapon_prop[ Weapon_index[WPN_QUARTERSTAFF] ].str_weight);
+
+ return (Weapon_prop[ Weapon_index[wpn.sub_type] ].str_weight);
+}
+
+int weapon_dex_weight( const item_def &wpn )
+{
+ return (10 - weapon_str_weight( wpn ));
+}
+
+int weapon_impact_mass( const item_def &wpn )
+{
+ ASSERT (wpn.base_type == OBJ_WEAPONS || wpn.base_type == OBJ_STAVES);
+
+ return ((weapon_str_weight( wpn ) * item_mass( wpn ) + 5) / 10);
+}
+
+int weapon_str_required( const item_def &wpn, bool hand_half )
+{
+ ASSERT (wpn.base_type == OBJ_WEAPONS || wpn.base_type == OBJ_STAVES);
+
+ const int req = weapon_impact_mass( wpn ) / ((hand_half) ? 11 : 10);
+
+ return ((req < STR_REQ_THRESHOLD) ? 0 : req);
+}
+
+// returns melee skill of item
+skill_type weapon_skill( const item_def &item )
+{
+ if (item.base_type == OBJ_WEAPONS && !is_range_weapon( item ))
+ return (Weapon_prop[ Weapon_index[item.sub_type] ].skill);
+ else if (item.base_type == OBJ_STAVES)
+ return (SK_STAVES);
+
+ // this is used to mark that only fighting applies.
+ return (SK_FIGHTING);
+}
+
+// front function for the above when we don't have a physical item to check
+skill_type weapon_skill( int wclass, int wtype )
+{
+ item_def wpn;
+
+ wpn.base_type = wclass;
+ wpn.sub_type = wtype;
+
+ return (weapon_skill( wpn ));
+} // end weapon_skill()
+
+// returns range skill of the item
+skill_type range_skill( const item_def &item )
+{
+ if (item.base_type == OBJ_WEAPONS && is_range_weapon( item ))
+ return (Weapon_prop[ Weapon_index[item.sub_type] ].skill);
+ else if (item.base_type == OBJ_MISSILES && item.sub_type == MI_DART)
+ return (SK_DARTS);
+
+ return (SK_RANGED_COMBAT);
+}
+
+// front function for the above when we don't have a physical item to check
+skill_type range_skill( int wclass, int wtype )
+{
+ item_def wpn;
+
+ wpn.base_type = wclass;
+ wpn.sub_type = wtype;
+
+ return (range_skill( wpn ));
+} // end weapon_skill()
+
+
+// Calculate the bonus to melee EV for using "wpn", with "skill" and "dex"
+// to protect a body of size "body".
+int weapon_ev_bonus( const item_def &wpn, int skill, size_type body, int dex,
+ bool hide_hidden )
+{
+ ASSERT( wpn.base_type == OBJ_WEAPONS || wpn.base_type == OBJ_STAVES );
+
+ int ret = 0;
+
+ // Note: ret currently measured in halves (see skill factor)
+ if (wpn.sub_type == WPN_WHIP || wpn.sub_type == WPN_DEMON_WHIP)
+ ret = 3 + (dex / 5);
+ else if (weapon_skill( wpn ) == SK_POLEARMS)
+ ret = 2 + (dex / 5);
+
+ // weapons of reaching are naturally a bit longer/flexier
+ if (!hide_hidden || item_ident( wpn, ISFLAG_KNOW_TYPE ))
+ {
+ if (get_weapon_brand( wpn ) == SPWPN_REACHING)
+ ret += 1;
+ }
+
+ // only consider additional modifications if we have a positive base:
+ if (ret > 0)
+ {
+ // Size factors:
+ // - large characters can't cover their flanks as well
+ // - note that not all weapons are available to small characters
+ if (body > SIZE_LARGE)
+ ret -= (4 * (body - SIZE_LARGE) - 2);
+ else if (body < SIZE_MEDIUM)
+ ret += 1;
+
+ // apply skill (and dividing by 2)
+ ret = (ret * (skill + 10)) / 20;
+
+ // make sure things can't get too insane
+ if (ret > 8)
+ ret = 8 + (ret - 8) / 2;
+ }
+
+ // Note: this is always a bonus
+ return ((ret > 0) ? ret : 0);
+}
+
+static size_type weapon_size( const item_def &item )
+{
+ ASSERT (item.base_type == OBJ_WEAPONS || item.base_type == OBJ_STAVES);
+
+ if (item.base_type == OBJ_STAVES)
+ return (Weapon_prop[ Weapon_index[WPN_QUARTERSTAFF] ].fit_size);
+
+ return (Weapon_prop[ Weapon_index[item.sub_type] ].fit_size);
+}
+
+// returns number of sizes off
+int cmp_weapon_size( const item_def &item, size_type size )
+{
+ ASSERT( item.base_type == OBJ_WEAPONS || item.base_type == OBJ_STAVES );
+
+ return (weapon_size( item ) - size);
+}
+
+// Returns number of sizes away from being a usable weapon
+int fit_weapon_wieldable_size( const item_def &item, size_type size )
+{
+ ASSERT( item.base_type == OBJ_WEAPONS || item.base_type == OBJ_STAVES );
+
+ const int fit = cmp_weapon_size( item, size );
+
+ return ((fit < -2) ? fit + 2 : (fit > 1) ? fit - 1 : 0);
+}
+
+// Returns number of sizes away from being throwable... the window
+// is currently [size - 5, size - 1].
+int fit_item_throwable_size( const item_def &item, size_type size )
+{
+ int ret = item_size( item ) - size;
+
+ return ((ret >= 0) ? ret + 1 : (ret > -6) ? 0 : ret + 5);
+}
+
+// Returns true if weapon is usable as a tool
+// Note that we assume that tool usable >= wieldable
+bool check_weapon_tool_size( const item_def &item, size_type size )
+{
+ ASSERT( item.base_type == OBJ_WEAPONS || item.base_type == OBJ_STAVES );
+
+ // Staves are currently usable for everyone just to be nice.
+ if (item.base_type == OBJ_STAVES || item.sub_type == WPN_QUARTERSTAFF)
+ return (true);
+
+ const int fit = cmp_weapon_size( item, size );
+
+ return (fit >= -3 && fit <= 1);
+}
+
+// Returns true if weapon is usable as a weapon
+bool check_weapon_wieldable_size( const item_def &item, size_type size )
+{
+ ASSERT( item.base_type == OBJ_WEAPONS || item.base_type == OBJ_STAVES );
+
+ return (fit_weapon_wieldable_size( item, size ) == 0);
+}
+
+// Note that this function is used to check validity of equipment
+// coming out of transformations... so it shouldn't contain any
+// wield/unwield only checks like two-handed weapons and shield.
+// check_id is only used for descriptions, where we don't want to
+// give away any information the player doesn't have yet.
+bool check_weapon_shape( const item_def &item, bool quiet, bool check_id )
+{
+ const int brand = get_weapon_brand( item );
+
+ if ((!check_id || item_ident( item, ISFLAG_KNOW_TYPE ))
+ && ((item.base_type == OBJ_WEAPONS
+ && item.sub_type == WPN_BLESSED_BLADE)
+ || brand == SPWPN_HOLY_WRATH
+ || brand == SPWPN_DISRUPTION)
+ && (you.is_undead || you.species == SP_DEMONSPAWN))
+ {
+ if (!quiet)
+ mpr( "This weapon will not allow you to wield it." );
+
+ return (false);
+ }
+
+ // Note: this should always be done last, see check_armour_shape()
+ // FIXME FIXME FIXME
+ /*
+ if (!transform_can_equip_type( EQ_WEAPON ))
+ {
+ if (!quiet)
+ mpr( "You can't wield anything in your current form!" );
+
+ return (false);
+ }
+ */
+
+ return (true);
+}
+
+// Returns the you.inv[] index of our wielded weapon or -1 (no item, not wield)
+int get_inv_wielded( void )
+{
+ return (player_weapon_wielded() ? you.equip[EQ_WEAPON] : -1);
+}
+
+// Returns the you.inv[] index of our hand tool or -1 (no item, not usable)
+// Note that we don't count armour and such as "tools" here because
+// this function is used to judge if the item will sticky curse to
+// our hands.
+int get_inv_hand_tool( void )
+{
+ const int tool = you.equip[EQ_WEAPON];
+
+ // FIXME
+ /*
+ if (tool == -1 || !is_tool( you.inv[tool] ))
+ return (-1);
+
+ if (you.inv[tool].base_type == OBJ_WEAPONS
+ || you.inv[tool].base_type == OBJ_STAVES)
+ {
+ // assuring that bad "shape" weapons aren't in hand
+ ASSERT( check_weapon_shape( you.inv[tool], false ) );
+
+ if (!check_weapon_tool_size( you.inv[tool], player_size() ))
+ return (-1);
+ }
+ */
+
+ return (tool);
+}
+
+// Returns the you.inv[] index of the thing in our hand... this is provided
+// as a service to specify that both of the above are irrelevant.
+// Do not use this for low level functions dealing with wielding directly.
+int get_inv_in_hand( void )
+{
+ return (you.equip[EQ_WEAPON]);
+}
+
+//
+// Launcher and ammo functions:
+//
+missile_type fires_ammo_type( const item_def &item )
+{
+ if (item.base_type != OBJ_WEAPONS)
+ return (MI_NONE);
+
+ return (Weapon_prop[ Weapon_index[item.sub_type] ].ammo);
+}
+
+missile_type fires_ammo_type( weapon_type wtype )
+{
+ item_def wpn;
+ wpn.base_type = OBJ_WEAPONS;
+ wpn.sub_type = wtype;
+
+ return (fires_ammo_type(wpn));
+}
+
+bool is_range_weapon( const item_def &item )
+{
+ return (fires_ammo_type( item ) != MI_NONE);
+}
+
+bool is_range_weapon_type( weapon_type wtype )
+{
+ item_def wpn;
+
+ wpn.base_type = OBJ_WEAPONS;
+ wpn.sub_type = wtype;
+
+ return (is_range_weapon( wpn ));
+}
+
+const char * ammo_name( const item_def &bow )
+{
+ ASSERT( is_range_weapon( bow ) );
+
+ const int ammo = fires_ammo_type( bow );
+
+ return (Missile_prop[ Missile_index[ammo] ].name);
+}
+
+// returns true if item can be reasonably thrown without a launcher
+bool is_throwable( const item_def &wpn )
+{
+ if (wpn.base_type == OBJ_WEAPONS)
+ return (Weapon_prop[ Weapon_index[wpn.sub_type] ].throwable);
+ else if (wpn.base_type == OBJ_MISSILES)
+ return (Missile_prop[ Missile_index[wpn.sub_type] ].throwable);
+
+ return (false);
+}
+
+// FIXME
+#if 0
+// decide if "being" is launching or throwing "ammo"
+launch_retval is_launched( int being_id, const item_def &ammo, bool msg )
+{
+ ASSERT( being_id != MHITNOT );
+
+ launch_retval ret = LRET_FUMBLED;
+
+ const item_def * lnch = 0;
+ int fit = 0;
+
+ if (being_id == MHITYOU)
+ {
+ const int wpn = get_inv_wielded();
+ lnch = (wpn == -1) ? 0 : &you.inv[wpn];
+ fit = fit_item_throwable_size( ammo, player_size() );
+ }
+ else // monster case
+ {
+ const int wpn = menv[being_id].inv[MSLOT_WEAPON];
+ lnch = (wpn == NON_ITEM) ? 0 : &mitm[wpn];
+ fit = fit_item_throwable_size( ammo, mons_size( menv[being_id].type ) );
+ }
+
+ if (lnch
+ && lnch->base_type == OBJ_WEAPONS
+ && is_range_weapon( *lnch )
+ && ammo.base_type == OBJ_MISSILES
+ && ammo.sub_type == fires_ammo_type( *lnch ))
+ {
+ ret = LRET_LAUNCHED;
+ }
+ else if (is_throwable( ammo ))
+ {
+ if (fit == 0)
+ ret = LRET_THROWN;
+ else
+ {
+ ret = LRET_FUMBLED;
+
+ if (being_id == MHITYOU && msg)
+ {
+ mpr( MSGCH_WARN, "It's difficult to throw such a%s object.",
+ (fit > 0) ? " large" : (fit < 0) ? " small" : "n awkward" );
+ }
+ }
+ }
+
+ return (ret);
+}
+#endif
+
+//
+// Staff/rod functions:
+//
+bool item_is_rod( const item_def &item )
+{
+ return (item.base_type == OBJ_STAVES
+ && item.sub_type >= STAFF_SMITING && item.sub_type < STAFF_AIR);
+}
+
+bool item_is_staff( const item_def &item )
+{
+ // Isn't De Morgan's law wonderful. -- bwr
+ return (item.base_type == OBJ_STAVES
+ && (item.sub_type < STAFF_SMITING || item.sub_type >= STAFF_AIR));
+}
+
+//
+// Ring functions:
+//
+// Returns number of pluses on jewellery (always none for amulets yet).
+int ring_has_pluses( const item_def &item )
+{
+ ASSERT (item.base_type == OBJ_JEWELLERY);
+
+ switch (item.sub_type)
+ {
+ case RING_SLAYING:
+ return (2);
+
+ case RING_PROTECTION:
+ case RING_EVASION:
+ case RING_STRENGTH:
+ case RING_INTELLIGENCE:
+ case RING_DEXTERITY:
+ return (1);
+
+ default:
+ break;
+ }
+
+ return (0);
+}
+
+//
+// Food functions:
+//
+bool food_is_meat( const item_def &item )
+{
+ ASSERT( is_valid_item( item ) && item.base_type == OBJ_FOOD );
+
+ return (Food_prop[ Food_index[item.sub_type] ].carn_mod > 0);
+}
+
+bool food_is_veg( const item_def &item )
+{
+ ASSERT( is_valid_item( item ) && item.base_type == OBJ_FOOD );
+
+ return (Food_prop[ Food_index[item.sub_type] ].herb_mod > 0);
+}
+
+// returns food value for one turn of eating
+int food_value( const item_def &item )
+{
+ ASSERT( is_valid_item( item ) && item.base_type == OBJ_FOOD );
+
+ const int herb = you.mutation[MUT_HERBIVOROUS];
+
+ // XXX: this needs to be better merged with the mutation system
+ const int carn = (you.species == SP_KOBOLD || you.species == SP_GHOUL) ? 3
+ : you.mutation[MUT_CARNIVOROUS];
+
+ const food_def &food = Food_prop[ Food_index[item.sub_type] ];
+
+ int ret = food.value;
+
+ ret += (carn * food.carn_mod);
+ ret += (herb * food.herb_mod);
+
+ return ((ret > 0) ? div_rand_round( ret, food.turns ) : 0);
+}
+
+int food_turns( const item_def &item )
+{
+ ASSERT( is_valid_item( item ) && item.base_type == OBJ_FOOD );
+
+ return (Food_prop[ Food_index[item.sub_type] ].turns);
+}
+
+bool can_cut_meat( const item_def &item )
+{
+ return (does_damage_type( item, DAM_SLICE ));
+}
+
+// returns true if item counts as a tool for tool size comparisons and msgs
+bool is_tool( const item_def &item )
+{
+ // Currently using OBJ_WEAPONS instead of can_cut_meat() as almost
+ // any weapon might be an evocable artefact.
+ return (item.base_type == OBJ_WEAPONS
+ || item.base_type == OBJ_STAVES
+ || (item.base_type == OBJ_MISCELLANY
+ && item.sub_type != MISC_RUNE_OF_ZOT));
+}
+
+
+//
+// Generic item functions:
+//
+int property( const item_def &item, int prop_type )
+{
+ switch (item.base_type)
+ {
+ case OBJ_ARMOUR:
+ if (prop_type == PARM_AC)
+ return (Armour_prop[ Armour_index[item.sub_type] ].ac);
+ else if (prop_type == PARM_EVASION)
+ return (Armour_prop[ Armour_index[item.sub_type] ].ev);
+ break;
+
+ case OBJ_WEAPONS:
+ if (prop_type == PWPN_DAMAGE)
+ return (Weapon_prop[ Weapon_index[item.sub_type] ].dam);
+ else if (prop_type == PWPN_HIT)
+ return (Weapon_prop[ Weapon_index[item.sub_type] ].hit);
+ else if (prop_type == PWPN_SPEED)
+ return (Weapon_prop[ Weapon_index[item.sub_type] ].speed);
+ break;
+
+ case OBJ_MISSILES:
+ if (prop_type == PWPN_DAMAGE)
+ return (Missile_prop[ Missile_index[item.sub_type] ].dam);
+ break;
+
+ case OBJ_STAVES:
+ if (prop_type == PWPN_DAMAGE)
+ return (Weapon_prop[ Weapon_index[WPN_QUARTERSTAFF] ].dam);
+ else if (prop_type == PWPN_HIT)
+ return (Weapon_prop[ Weapon_index[WPN_QUARTERSTAFF] ].hit);
+ else if (prop_type == PWPN_SPEED)
+ return (Weapon_prop[ Weapon_index[WPN_QUARTERSTAFF] ].speed);
+ break;
+
+ default:
+ break;
+ }
+
+ return (0);
+}
+
+int item_mass( const item_def &item )
+{
+ int unit_mass = 0;
+
+ switch (item.base_type)
+ {
+ case OBJ_WEAPONS:
+ unit_mass = Weapon_prop[ Weapon_index[item.sub_type] ].mass;
+ break;
+
+ case OBJ_ARMOUR:
+ unit_mass = Armour_prop[ Armour_index[item.sub_type] ].mass;
+
+ if (get_equip_race( item ) == ISFLAG_ELVEN)
+ {
+ const int reduc = (unit_mass >= 25) ? unit_mass / 5 : 5;
+
+ // truncate to the nearest 5 and reduce the item mass:
+ unit_mass -= ((reduc / 5) * 5);
+ unit_mass = MAXIMUM( unit_mass, 5 );
+ }
+ break;
+
+ case OBJ_MISSILES:
+ unit_mass = Missile_prop[ Missile_index[item.sub_type] ].mass;
+ break;
+
+ case OBJ_FOOD:
+ unit_mass = Food_prop[ Food_index[item.sub_type] ].mass;
+ break;
+
+ case OBJ_WANDS:
+ unit_mass = 100;
+ break;
+
+ case OBJ_UNKNOWN_I:
+ unit_mass = 200; // labeled "books"
+ break;
+
+ case OBJ_SCROLLS:
+ unit_mass = 20;
+ break;
+
+ case OBJ_JEWELLERY:
+ unit_mass = 10;
+ break;
+
+ case OBJ_POTIONS:
+ unit_mass = 40;
+ break;
+
+ case OBJ_UNKNOWN_II:
+ unit_mass = 5; // labeled "gems"
+ break;
+
+ case OBJ_BOOKS:
+ unit_mass = 70;
+ break;
+
+ case OBJ_STAVES:
+ unit_mass = 130;
+ break;
+
+ case OBJ_ORBS:
+ unit_mass = 300;
+ break;
+
+ case OBJ_MISCELLANY:
+ switch (item.sub_type)
+ {
+ case MISC_BOTTLED_EFREET:
+ case MISC_CRYSTAL_BALL_OF_SEEING:
+ case MISC_CRYSTAL_BALL_OF_ENERGY:
+ case MISC_CRYSTAL_BALL_OF_FIXATION:
+ unit_mass = 150;
+ break;
+
+ default:
+ unit_mass = 100;
+ break;
+ }
+ break;
+
+ case OBJ_CORPSES:
+ unit_mass = mons_weight( item.plus );
+
+ if (item.sub_type == CORPSE_SKELETON)
+ unit_mass /= 10;
+ break;
+
+ default:
+ case OBJ_GOLD:
+ unit_mass = 0;
+ break;
+ }
+
+ return ((unit_mass > 0) ? unit_mass : 0);
+}
+
+// Note that this function, an item sizes in general aren't quite on the
+// same scale as PCs and monsters.
+size_type item_size( const item_def &item )
+{
+ int size = SIZE_TINY;
+
+ switch (item.base_type)
+ {
+ case OBJ_WEAPONS:
+ case OBJ_STAVES:
+ size = Weapon_prop[ Weapon_index[item.sub_type] ].fit_size - 1;
+ break;
+
+ case OBJ_ARMOUR:
+ size = SIZE_MEDIUM;
+ switch (item.sub_type)
+ {
+ case ARM_GLOVES:
+ case ARM_HELMET:
+ case ARM_CAP:
+ case ARM_BOOTS:
+ case ARM_BUCKLER:
+ // tiny armour
+ break;
+
+ case ARM_SHIELD:
+ size = SIZE_LITTLE;
+ break;
+
+ case ARM_LARGE_SHIELD:
+ size = SIZE_SMALL;
+ break;
+
+ default: // body armours and bardings
+ size = SIZE_MEDIUM;
+ break;
+ }
+ break;
+
+ case OBJ_MISSILES:
+ if (item.sub_type == MI_LARGE_ROCK)
+ size = SIZE_SMALL;
+ break;
+
+ case OBJ_MISCELLANY:
+ if (item.sub_type == MISC_PORTABLE_ALTAR_OF_NEMELEX)
+ {
+ size = SIZE_SMALL;
+ }
+ break;
+
+ case OBJ_CORPSES:
+ // FIXME
+ // size = mons_size( item.plus, PSIZE_BODY );
+ size = SIZE_SMALL;
+ break;
+
+ default: // sundry tiny items
+ break;
+ }
+
+ if (size < SIZE_TINY)
+ size = SIZE_TINY;
+ else if (size > SIZE_HUGE)
+ size = SIZE_HUGE;
+
+ return (static_cast<size_type>( size ));
+}
+
+// returns true if we might be interested in dumping the colour
+bool is_colourful_item( const item_def &item )
+{
+ bool ret = false;
+
+ switch (item.base_type)
+ {
+ case OBJ_ARMOUR:
+ if (item.sub_type == ARM_ROBE
+ || item.sub_type == ARM_CLOAK
+ || item.sub_type == ARM_CAP
+ || item.sub_type == ARM_NAGA_BARDING
+ || item.sub_type == ARM_CENTAUR_BARDING)
+ {
+ ret = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return (ret);
+}
+
+bool is_shield(const item_def &item)
+{
+ return item.base_type == OBJ_ARMOUR
+ && (item.sub_type == ARM_SHIELD
+ || item.sub_type == ARM_BUCKLER
+ || item.sub_type == ARM_LARGE_SHIELD);
+}
+
+// Returns true if the given item cannot be wielded with the given shield.
+// The currently equipped shield is used if no shield is passed in.
+bool is_shield_incompatible(const item_def &weapon, const item_def *shield)
+{
+ // If there's no shield, there's no problem.
+ if (!shield && !(shield = player_shield()))
+ return (false);
+
+ hands_reqd_type hand = hands_reqd(weapon, player_size());
+ return hand == HANDS_TWO
+ && !item_is_rod(weapon)
+ && !is_range_weapon(weapon);
+}
diff --git a/crawl-ref/source/itemprop.h b/crawl-ref/source/itemprop.h
new file mode 100644
index 0000000000..9e5428106e
--- /dev/null
+++ b/crawl-ref/source/itemprop.h
@@ -0,0 +1,148 @@
+/*
+ * File: itemname.cc
+ * Summary: Misc functions.
+ * Written by: Brent Ross
+ *
+ * Change History (most recent first):
+ *
+ * <1> -/--/-- BWR Created
+ */
+
+
+#ifndef ITEMPROP_H
+#define ITEMPROP_H
+
+#include "externs.h"
+
+void init_properties(void);
+
+// cursed:
+bool item_cursed( const item_def &item );
+bool item_known_cursed( const item_def &item );
+bool item_known_uncursed( const item_def &item );
+void do_curse_item( item_def &item );
+void do_uncurse_item( item_def &item );
+
+// ident:
+bool item_ident( const item_def &item, unsigned long flags );
+void set_ident_flags( item_def &item, unsigned long flags );
+void unset_ident_flags( item_def &item, unsigned long flags );
+
+// racial item and item descriptions:
+void set_equip_race( item_def &item, unsigned long flags );
+void set_equip_desc( item_def &item, unsigned long flags );
+unsigned long get_equip_race( const item_def &item );
+unsigned long get_equip_desc( const item_def &item );
+
+// helmet functions:
+void set_helmet_type( item_def &item, short flags );
+void set_helmet_desc( item_def &item, short flags );
+void set_helmet_random_desc( item_def &item );
+
+short get_helmet_type( const item_def &item );
+short get_helmet_desc( const item_def &item );
+
+bool is_helmet_type( const item_def &item, short val );
+
+// ego items:
+bool set_item_ego_type( item_def &item, int item_type, int ego_type );
+int get_weapon_brand( const item_def &item );
+int get_armour_ego_type( const item_def &item );
+int get_ammo_brand( const item_def &item );
+
+// armour functions:
+int armour_max_enchant( const item_def &item );
+bool armour_is_hide( const item_def &item, bool inc_made = false );
+bool armour_not_shiny( const item_def &item );
+int armour_str_required( const item_def &arm );
+
+equipment_type get_armour_slot( const item_def &item );
+
+bool jewellery_is_amulet( const item_def &item );
+bool check_jewellery_size( const item_def &item, size_type size );
+
+bool hide2armour( item_def &item );
+
+bool base_armour_is_light( const item_def &item );
+int fit_armour_size( const item_def &item, size_type size );
+bool check_armour_size( const item_def &item, size_type size );
+bool check_armour_shape( const item_def &item, bool quiet );
+
+// weapon functions:
+int weapon_rarity( int w_type );
+
+int cmp_weapon_size( const item_def &item, size_type size );
+bool check_weapon_tool_size( const item_def &item, size_type size );
+int fit_weapon_wieldable_size( const item_def &item, size_type size );
+bool check_weapon_wieldable_size( const item_def &item, size_type size );
+
+int fit_item_throwable_size( const item_def &item, size_type size );
+
+bool check_weapon_shape( const item_def &item, bool quiet, bool check_id = false );
+
+int weapon_ev_bonus( const item_def &wpn, int skill, size_type body, int dex,
+ bool hide_hidden = false );
+
+int get_inv_wielded( void );
+int get_inv_hand_tool( void );
+int get_inv_in_hand( void );
+
+hands_reqd_type hands_reqd( const item_def &item, size_type size );
+hands_reqd_type hands_reqd(int base_type, int sub_type, size_type size);
+bool is_double_ended( const item_def &item );
+
+int double_wpn_awkward_speed( const item_def &item );
+
+bool is_demonic( const item_def &item );
+
+int get_vorpal_type( const item_def &item );
+int get_damage_type( const item_def &item );
+bool does_damage_type( const item_def &item, int dam_type );
+
+int weapon_str_weight( const item_def &wpn );
+int weapon_dex_weight( const item_def &wpn );
+int weapon_impact_mass( const item_def &wpn );
+int weapon_str_required( const item_def &wpn, bool half );
+
+skill_type weapon_skill( const item_def &item );
+skill_type weapon_skill( int wclass, int wtype );
+
+skill_type range_skill( const item_def &item );
+skill_type range_skill( int wclass, int wtype );
+
+// launcher and ammo functions:
+bool is_range_weapon( const item_def &item );
+bool is_range_weapon_type( weapon_type wtype );
+missile_type fires_ammo_type( const item_def &item );
+missile_type fires_ammo_type( weapon_type wtype );
+const char * ammo_name( const item_def &bow );
+bool is_throwable( const item_def &wpn );
+launch_retval is_launched( int being_id, const item_def &ammo, bool msg = false );
+
+// staff/rod functions:
+bool item_is_rod( const item_def &item );
+bool item_is_staff( const item_def &item );
+
+// ring functions:
+int ring_has_pluses( const item_def &item );
+
+// food functions:
+bool food_is_meat( const item_def &item );
+bool food_is_veg( const item_def &item );
+int food_value( const item_def &item );
+int food_turns( const item_def &item );
+bool can_cut_meat( const item_def &item );
+
+// generic item property functions:
+bool is_tool( const item_def &item );
+int property( const item_def &item, int prop_type );
+int item_mass( const item_def &item );
+size_type item_size( const item_def &item );
+
+bool is_colourful_item( const item_def &item );
+
+bool is_shield(const item_def &item);
+bool is_shield_incompatible(const item_def &weapon,
+ const item_def *shield = NULL);
+
+#endif
diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc
index 5949668139..dfbacc206b 100644
--- a/crawl-ref/source/items.cc
+++ b/crawl-ref/source/items.cc
@@ -3,6 +3,8 @@
* Summary: Misc (mostly) inventory related functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <9> 7/08/01 MV Added messages for chunks/corpses rotting
@@ -40,6 +42,7 @@
#include "it_use2.h"
#include "item_use.h"
#include "itemname.h"
+#include "itemprop.h"
#include "misc.h"
#include "monplace.h"
#include "monstuff.h"
@@ -57,6 +60,11 @@
static void autopickup(void);
static bool is_stackable_item( const item_def &item );
+static bool invisible_to_player( const item_def& item );
+static void item_list_on_square( std::vector<const item_def*>& items,
+ int obj, bool force_squelch = false );
+static void autoinscribe_item( item_def& item );
+static void autoinscribe_items( void );
// Used to be called "unlink_items", but all it really does is make
// sure item coordinates are correct to the stack they're in. -- bwr
@@ -100,7 +108,7 @@ void link_items(void)
{
if (!is_valid_item(mitm[i]) || (mitm[i].x == 0 && mitm[i].y == 0))
{
- // item is not assigned, or is monster item. ignore.
+ // item is not assigned, or is monster item. ignore.
mitm[i].link = NON_ITEM;
continue;
}
@@ -178,9 +186,9 @@ int cull_items(void)
else if (is_unrandom_artefact( mitm[item] ))
{
// 9. unmark unrandart
- int x = find_unrandart_index(item);
- if (x >= 0)
- set_unrandart_exist(x, 0);
+ int z = find_unrandart_index(item);
+ if (z >= 0)
+ set_unrandart_exist(z, 0);
}
// POOF!
@@ -282,18 +290,7 @@ void init_item( int item )
if (item == NON_ITEM)
return;
- mitm[item].base_type = OBJ_UNASSIGNED;
- mitm[item].sub_type = 0;
- mitm[item].plus = 0;
- mitm[item].plus2 = 0;
- mitm[item].special = 0;
- mitm[item].quantity = 0;
- mitm[item].colour = 0;
- mitm[item].flags = 0;
-
- mitm[item].x = 0;
- mitm[item].y = 0;
- mitm[item].link = NON_ITEM;
+ mitm[item].clear();
}
// Returns an unused mitm slot, or NON_ITEM if none available.
@@ -465,14 +462,6 @@ void unlink_item( int dest )
#endif
} // end unlink_item()
-static void item_cleanup(item_def &item)
-{
- item.base_type = OBJ_UNASSIGNED;
- item.quantity = 0;
- item.orig_place = 0;
- item.orig_monnum = 0;
-}
-
void destroy_item( int dest )
{
// Don't destroy non-items, but this function may be called upon
@@ -483,7 +472,8 @@ void destroy_item( int dest )
unlink_item( dest );
- item_cleanup(mitm[dest]);
+ // paranoia, shouldn't be needed
+ mitm[dest].clear();
}
void destroy_item_stack( int x, int y )
@@ -517,18 +507,7 @@ void destroy_item_stack( int x, int y )
}
}
-
-/*
- * Takes keyin as an argument because it will only display a long list of items
- * if ; is pressed.
- */
-void item_check(char keyin)
-{
- char item_show[50][50];
- char temp_quant[10];
-
- int counter = 0;
- int counter_max = 0;
+static void describe_floor() {
const int grid = grd[you.x_pos][you.y_pos];
@@ -595,6 +574,8 @@ void item_check(char keyin)
break;
case DNGN_ENTER_ORCISH_MINES:
mpr("There is a staircase to the Orcish Mines here.");
+ mpr("Reaching the bottom shouldn't be too hard...");
+ mpr("But getting back might take some resources.");
break;
case DNGN_ENTER_HIVE:
mpr("There is a staircase to the Hive here.");
@@ -710,21 +691,74 @@ void item_check(char keyin)
}
}
}
+}
+
+static bool invisible_to_player( const item_def& item ) {
+ return strstr(item.inscription.c_str(), "=k") != 0;
+}
+
+static bool has_nonsquelched_items( int obj ) {
+ while ( obj != NON_ITEM ) {
+ if ( !invisible_to_player(mitm[obj]) )
+ return true;
+ obj = mitm[obj].link;
+ }
+ return false;
+}
+
+/* Fill items with the items on a square.
+ Squelched items (marked with =k) are ignored, unless
+ the square contains *only* squelched items, in which case they
+ are included. If force_squelch is true, squelched items are
+ never displayed.
+ */
+static void item_list_on_square( std::vector<const item_def*>& items,
+ int obj, bool force_squelch ) {
+
+ const bool have_nonsquelched = (force_squelch ||
+ has_nonsquelched_items(obj));
+
+ /* loop through the items */
+ while ( obj != NON_ITEM ) {
+ /* add them to the items list if they qualify */
+ if ( !have_nonsquelched || !invisible_to_player(mitm[obj]) )
+ items.push_back( &mitm[obj] );
+ obj = mitm[obj].link;
+ }
+}
+
+/*
+ * Takes keyin as an argument because it will only display a long list of items
+ * if ; is pressed.
+ */
+void item_check(char keyin)
+{
+ char item_show[50][50];
+ char temp_quant[10];
+
+ int counter = 0;
+ int counter_max = 0;
+
+ describe_floor();
if (igrd[you.x_pos][you.y_pos] == NON_ITEM && keyin == ';')
{
mpr("There are no items here.");
return;
}
-
+
+ autoinscribe_items();
autopickup();
origin_set(you.x_pos, you.y_pos);
- int objl = igrd[you.x_pos][you.y_pos];
- while (objl != NON_ITEM)
+ for ( int objl = igrd[you.x_pos][you.y_pos]; objl != NON_ITEM;
+ objl = mitm[objl].link )
{
+ if ( invisible_to_player(mitm[objl]) )
+ continue;
+
counter++;
if (counter > 45)
@@ -749,7 +783,6 @@ void item_check(char keyin)
strcpy(item_show[counter], str_pass);
}
- objl = mitm[objl].link;
}
counter_max = counter;
@@ -785,13 +818,25 @@ void item_check(char keyin)
mpr("There are several objects here.");
}
+void show_items()
+{
+ std::vector<const item_def*> items;
+ item_list_on_square( items, igrd[you.x_pos][you.y_pos], true );
+
+ if ( items.empty() )
+ mpr("There are no items here.");
+ else {
+ select_items( items, "Things that are here:", true );
+ redraw_screen();
+ }
+
+ describe_floor();
+}
void pickup_menu(int item_link)
{
- std::vector<item_def*> items;
-
- for (int i = item_link; i != NON_ITEM; i = mitm[i].link)
- items.push_back( &mitm[i] );
+ std::vector<const item_def*> items;
+ item_list_on_square( items, item_link, false );
std::vector<SelItem> selected =
select_items( items, "Select items to pick up" );
@@ -945,12 +990,7 @@ static std::string origin_monster_desc(const item_def &item)
static std::string origin_place_desc(const item_def &item)
{
- std::string place = branch_level_name(item.orig_place);
- if (place.length() && place != "Pandemonium")
- place[0] = tolower(place[0]);
- return (place.find("level") == 0?
- "on " + place
- : "in " + place);
+ return prep_branch_level_name(item.orig_place);
}
bool is_rune(const item_def &item)
@@ -1101,12 +1141,10 @@ bool pickup_single_item(int link, int qty)
return (true);
}
-void pickup(void)
+void pickup()
{
- int o = 0;
int m = 0;
- unsigned char keyin = 0;
- int next;
+ int keyin = 'x';
char str_pass[ ITEMNAME_SIZE ];
if (you.attribute[ATTR_TRANSFORMATION] == TRAN_AIR
@@ -1165,7 +1203,7 @@ void pickup(void)
}
}
- o = igrd[you.x_pos][you.y_pos];
+ int o = igrd[you.x_pos][you.y_pos];
if (o == NON_ITEM)
{
@@ -1173,49 +1211,41 @@ void pickup(void)
}
else if (mitm[o].link == NON_ITEM) // just one item?
{
+ // deliberately allowing the player to pick up
+ // a killed item here
pickup_single_item(o, mitm[o].quantity);
} // end of if items_here
else
- {
+ {
+ int next;
mpr("There are several objects here.");
-
- while (o != NON_ITEM)
+ const bool hide_squelched = has_nonsquelched_items(o);
+ while ( o != NON_ITEM )
{
+ // must save this because pickup can destroy the item
next = mitm[o].link;
+ if ( hide_squelched && invisible_to_player(mitm[o]) ) {
+ o = next;
+ continue;
+ }
+
if (keyin != 'a')
{
- strcpy(info, "Pick up ");
-
- if (mitm[o].base_type == OBJ_GOLD)
- {
- char st_prn[20];
- itoa(mitm[o].quantity, st_prn, 10);
- strcat(info, st_prn);
- strcat(info, " gold piece");
-
- if (mitm[o].quantity > 1)
- strcat(info, "s");
- }
- else
- {
- it_name(o, DESC_NOCAP_A, str_pass);
- strcat(info, str_pass);
- }
-
- strcat(info, "\? (y,n,a,*,q)");
+ char buf[ITEMNAME_SIZE];
+ item_name( mitm[o], DESC_NOCAP_A, buf );
+ snprintf( info, INFO_SIZE, "Pick up %s? (y/n/a/*?g,/q)", buf );
mpr( info, MSGCH_PROMPT );
-
keyin = get_ch();
}
- if (keyin == '*' || keyin == '?' || keyin == ',')
+ if (keyin == '*' || keyin == '?' || keyin == ',' || keyin == 'g')
{
pickup_menu(o);
break;
}
- if (keyin == 'q')
+ if (keyin == 'q' || keyin == ESCAPE)
break;
if (keyin == 'y' || keyin == 'a')
@@ -1234,7 +1264,7 @@ void pickup(void)
break;
}
}
-
+
o = next;
}
}
@@ -1299,8 +1329,8 @@ bool items_stack( const item_def &item1, const item_def &item2 )
// if either isn't identified and they look different. -- bwr
if (item1.base_type == OBJ_POTIONS
&& item1.special != item2.special
- && (item_not_ident( item1, ISFLAG_KNOW_TYPE )
- || item_not_ident( item2, ISFLAG_KNOW_TYPE )))
+ && (!item_ident( item1, ISFLAG_KNOW_TYPE )
+ || !item_ident( item2, ISFLAG_KNOW_TYPE )))
{
return (false);
}
@@ -1386,7 +1416,7 @@ int find_free_slot(const item_def &i)
// the player's inventory is full.
int move_item_to_player( int obj, int quant_got, bool quiet )
{
- int item_mass = 0;
+ int imass = 0;
int unit_mass = 0;
int retval = quant_got;
char brek = 0;
@@ -1409,21 +1439,21 @@ int move_item_to_player( int obj, int quant_got, bool quiet )
mpr(info);
}
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return (retval);
}
- unit_mass = mass_item( mitm[obj] );
+ unit_mass = item_mass( mitm[obj] );
if (quant_got > mitm[obj].quantity || quant_got <= 0)
quant_got = mitm[obj].quantity;
- item_mass = unit_mass * quant_got;
+ imass = unit_mass * quant_got;
brek = 0;
// multiply both constants * 10
- if ((int) you.burden + item_mass > carrying_capacity())
+ if ((int) you.burden + imass > carrying_capacity())
{
// calculate quantity we can actually pick up
int part = (carrying_capacity() - (int)you.burden) / unit_mass;
@@ -1457,7 +1487,7 @@ int move_item_to_player( int obj, int quant_got, bool quiet )
mpr(info);
}
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return (retval);
}
@@ -1486,6 +1516,10 @@ int move_item_to_player( int obj, int quant_got, bool quiet )
item.y = -1;
item.link = freeslot;
+ /*** HP CHANGE: do autoinscribe ***/
+ autoinscribe_item( item );
+
+
origin_freeze(item, you.x_pos, you.y_pos);
item.quantity = quant_got;
@@ -1506,7 +1540,7 @@ int move_item_to_player( int obj, int quant_got, bool quiet )
you.char_direction = DIR_ASCENDING;
}
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return (retval);
} // end move_item_to_player()
@@ -1658,6 +1692,9 @@ bool move_top_item( int src_x, int src_y, int dest_x, int dest_y )
//---------------------------------------------------------------
static void drop_gold(unsigned int amount)
{
+ const unsigned long BIGGEST_QUANT_VALUE =
+ ((1L << (sizeof(mitm[0].quantity)*8 - 1)) - 1000);
+
if (you.gold > 0)
{
if (amount > you.gold)
@@ -1674,10 +1711,17 @@ static void drop_gold(unsigned int amount)
{
if (mitm[i].base_type == OBJ_GOLD)
{
+ if ( mitm[i].quantity + amount > BIGGEST_QUANT_VALUE ) {
+ amount = BIGGEST_QUANT_VALUE - mitm[i].quantity;
+ snprintf(info, INFO_SIZE,
+ "But there's only room for %d.", amount);
+ mpr(info);
+
+ }
inc_mitm_item_quantity( i, amount );
you.gold -= amount;
you.redraw_gold = 1;
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return;
}
@@ -1692,9 +1736,17 @@ static void drop_gold(unsigned int amount)
mpr( "Too many items on this level, not dropping the gold." );
return;
}
+ if (amount > BIGGEST_QUANT_VALUE) {
+ amount = BIGGEST_QUANT_VALUE;
+ snprintf(info, INFO_SIZE,
+ "But there's only room for %d.", amount);
+ mpr(info);
+ }
mitm[i].base_type = OBJ_GOLD;
mitm[i].quantity = amount;
+ // [ds] #&^#@&#!
+ mitm[i].colour = YELLOW;
mitm[i].flags = 0;
move_item_to_grid( &i, you.x_pos, you.y_pos );
@@ -1702,7 +1754,7 @@ static void drop_gold(unsigned int amount)
you.gold -= amount;
you.redraw_gold = 1;
- you.turn_is_over = 1;
+ you.turn_is_over = true;
}
else
{
@@ -1728,7 +1780,15 @@ bool drop_item( int item_dropped, int quant_drop ) {
|| item_dropped == you.equip[EQ_RIGHT_RING]
|| item_dropped == you.equip[EQ_AMULET])
{
- mpr("You will have to take that off first.");
+ if (!Options.easy_unequip)
+ {
+ mpr("You will have to take that off first.");
+ return (false);
+ }
+
+ if (remove_ring( item_dropped, true ))
+ start_delay( DELAY_DROP_ITEM, 1, item_dropped, 1 );
+
return (false);
}
@@ -1744,7 +1804,7 @@ bool drop_item( int item_dropped, int quant_drop ) {
{
if (item_dropped == you.equip[i] && you.equip[i] != -1)
{
- if (!Options.easy_armour)
+ if (!Options.easy_unequip)
{
mpr("You will have to take that off first.");
}
@@ -1754,7 +1814,7 @@ bool drop_item( int item_dropped, int quant_drop ) {
if (takeoff_armour( item_dropped ))
{
start_delay( DELAY_DROP_ITEM, 1, item_dropped, 1 );
- you.turn_is_over = 0; // turn happens later
+ you.turn_is_over = false; // turn happens later
}
}
@@ -1765,6 +1825,8 @@ bool drop_item( int item_dropped, int quant_drop ) {
}
}
+ // [ds] easy_unequip does not apply to weapons.
+ //
// Unwield needs to be done before copy in order to clear things
// like temporary brands. -- bwr
if (item_dropped == you.equip[EQ_WEAPON])
@@ -1774,9 +1836,11 @@ bool drop_item( int item_dropped, int quant_drop ) {
canned_msg( MSG_EMPTY_HANDED );
}
- if (!copy_item_to_grid( you.inv[item_dropped],
- you.x_pos, you.y_pos, quant_drop, true ))
- {
+ const unsigned char my_grid = grd[you.x_pos][you.y_pos];
+
+ if ( !grid_destroys_items(my_grid) &&
+ !copy_item_to_grid( you.inv[item_dropped],
+ you.x_pos, you.y_pos, quant_drop, true )) {
mpr( "Too many items on this level, not dropping the item." );
return (false);
}
@@ -1785,20 +1849,51 @@ bool drop_item( int item_dropped, int quant_drop ) {
quant_name( you.inv[item_dropped], quant_drop, DESC_NOCAP_A, str_pass );
snprintf( info, INFO_SIZE, "You drop %s.", str_pass );
mpr(info);
+
+ if ( grid_destroys_items(my_grid) ) {
+ mprf(MSGCH_SOUND, grid_item_destruction_message(my_grid));
+ }
dec_inv_item_quantity( item_dropped, quant_drop );
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return (true);
}
+static std::string drop_menu_invstatus(const Menu *menu)
+{
+ char buf[100];
+ const int cap = carrying_capacity();
+
+ std::string s_newweight;
+ std::vector<MenuEntry*> se = menu->selected_entries();
+ if (!se.empty())
+ {
+ int newweight = you.burden;
+ for (int i = 0, size = se.size(); i < size; ++i)
+ {
+ const item_def *item = static_cast<item_def *>( se[i]->data );
+ newweight -= item_mass(*item) * se[i]->selected_qty;
+ }
-static std::string drop_menu_title( int menuflags, const std::string &oldt ) {
- std::string res = oldt;
- res.erase(0, res.find_first_not_of(" \n\t"));
- if (menuflags & MF_MULTISELECT)
+ snprintf(buf, sizeof buf, ">%d.%d", newweight / 10, newweight % 10);
+ s_newweight = buf;
+ }
+
+ snprintf(buf, sizeof buf, "(Inv: %d.%d%s/%d.%d aum)",
+ you.burden / 10, you.burden % 10,
+ s_newweight.c_str(),
+ cap / 10, cap % 10);
+ return (buf);
+}
+
+static std::string drop_menu_title(const Menu *menu, const std::string &oldt)
+{
+ std::string res = drop_menu_invstatus(menu) + " " + oldt;
+ if (menu->is_set( MF_MULTISELECT ))
res = "[Multidrop] " + res;
- return " " + res;
+
+ return (res);
}
int get_equip_slot(const item_def *item)
@@ -1823,13 +1918,13 @@ static std::string drop_selitem_text( const std::vector<MenuEntry*> *s )
char buf[130];
bool extraturns = false;
- if (!s->size())
+ if (s->empty())
return "";
for (int i = 0, size = s->size(); i < size; ++i)
{
const item_def *item = static_cast<item_def *>( (*s)[i]->data );
- int eq = get_equip_slot(item);
+ const int eq = get_equip_slot(item);
if (eq > EQ_WEAPON && eq < NUM_EQUIP)
{
extraturns = true;
@@ -1837,12 +1932,14 @@ static std::string drop_selitem_text( const std::vector<MenuEntry*> *s )
}
}
- snprintf( buf, sizeof buf, " (%lu%s turn%s)", (unsigned long) (s->size()),
- extraturns? "+" : "",
- s->size() > 1? "s" : "" );
+ snprintf( buf, sizeof buf, " (%lu%s turn%s)",
+ (unsigned long) (s->size()),
+ extraturns? "+" : "",
+ s->size() > 1? "s" : "" );
return buf;
}
+std::vector<SelItem> items_for_multidrop;
//---------------------------------------------------------------
//
// drop
@@ -1855,122 +1952,33 @@ void drop(void)
if (inv_count() < 1 && you.gold == 0)
{
canned_msg(MSG_NOTHING_CARRIED);
- you.activity = ACT_NONE;
return;
}
- static std::vector<SelItem> selected;
+ items_for_multidrop = prompt_invent_items( "Drop what?",
+ MT_DROP,
+ -1,
+ drop_menu_title,
+ true, true, '$',
+ &Options.drop_filter,
+ drop_selitem_text,
+ &items_for_multidrop );
- if (!you.activity || selected.empty())
- selected = prompt_invent_items( "Drop which item?", -1,
- drop_menu_title,
- true, true, '$',
- &Options.drop_filter,
- drop_selitem_text );
-
- if (selected.empty())
+ if (items_for_multidrop.empty())
{
canned_msg( MSG_OK );
- you.activity = ACT_NONE;
return;
}
- // Throw away invalid items; items usually go invalid because
- // of chunks rotting away.
- while (!selected.empty()
- // Don't look for gold in inventory
- && selected[0].slot != PROMPT_GOT_SPECIAL
- && !is_valid_item(you.inv[ selected[0].slot ]))
- selected.erase( selected.begin() );
-
- // Did the defunct item filter above deprive us of a drop target?
- if (!selected.empty())
- {
- drop_item( selected[0].slot, selected[0].quantity );
- // Forget the item we just dropped
- selected.erase( selected.begin() );
- }
-
- // If we still have items that want to be dropped, start the multiturn
- // activity
- you.activity = selected.empty()? ACT_NONE : ACT_MULTIDROP;
-} // end drop()
-
-//---------------------------------------------------------------
-//
-// shift_monster
-//
-// Moves a monster to approximately (x,y) and returns true
-// if monster was moved.
-//
-//---------------------------------------------------------------
-static bool shift_monster( struct monsters *mon, int x, int y )
-{
- bool found_move = false;
-
- int i, j;
- int tx, ty;
- int nx = 0, ny = 0;
-
- int count = 0;
-
- if (x == 0 && y == 0)
+ if ( items_for_multidrop.size() == 1 ) // only one item
{
- // try and find a random floor space some distance away
- for (i = 0; i < 50; i++)
- {
- tx = 5 + random2( GXM - 10 );
- ty = 5 + random2( GYM - 10 );
-
- int dist = grid_distance(x, y, tx, ty);
- if (grd[tx][ty] == DNGN_FLOOR && dist > 10)
- break;
- }
-
- if (i == 50)
- return (false);
+ drop_item( items_for_multidrop[0].slot,
+ items_for_multidrop[0].quantity );
+ items_for_multidrop.clear();
+ you.turn_is_over = true;
}
-
- for (i = -1; i <= 1; i++)
- {
- for (j = -1; j <= 1; j++)
- {
- tx = x + i;
- ty = y + j;
-
- if (tx < 5 || tx > GXM - 5 || ty < 5 || ty > GXM - 5)
- continue;
-
- // won't drop on anything but vanilla floor right now
- if (grd[tx][ty] != DNGN_FLOOR)
- continue;
-
- if (mgrd[tx][ty] != NON_MONSTER)
- continue;
-
- if (tx == you.x_pos && ty == you.y_pos)
- continue;
-
- count++;
- if (one_chance_in(count))
- {
- nx = tx;
- ny = ty;
- found_move = true;
- }
- }
- }
-
- if (found_move)
- {
- const int mon_index = mgrd[mon->x][mon->y];
- mgrd[mon->x][mon->y] = NON_MONSTER;
- mgrd[nx][ny] = mon_index;
- mon->x = nx;
- mon->y = ny;
- }
-
- return (found_move);
+ else
+ start_delay( DELAY_MULTIDROP, items_for_multidrop.size() );
}
//---------------------------------------------------------------
@@ -2616,9 +2624,9 @@ void handle_time( long time_delta )
int added_contamination = 0;
// Account for mutagenic radiation. Invis and haste will give the
- // player about .1 points per turn, mutagenic randarts will give
- // about 1.5 points on average, so they can corrupt the player
- // quite quickly. Wielding one for a short battle is OK, which is
+ // player about .1 points per turn, mutagenic randarts will give
+ // about 1.5 points on average, so they can corrupt the player
+ // quite quickly. Wielding one for a short battle is OK, which is
// as things should be. -- GDL
if (you.invis && random2(10) < 6)
added_contamination++;
@@ -2639,12 +2647,18 @@ void handle_time( long time_delta )
// only check for badness once every other turn
if (coinflip())
{
+ // [ds] Be less harsh with glow mutation; Brent and Mark Mackey note
+ // that the commented out random2(X) <= MC check was a bug. I've
+ // uncommented it but dropped the roll sharply from 150. (Brent used
+ // the original roll of 150 for 4.1.2, but I think players are
+ // sufficiently used to beta 26's unkindness that we can use a lower
+ // roll.)
if (you.magic_contamination >= 5
- /* && random2(150) <= you.magic_contamination */)
+ && random2(50) <= you.magic_contamination)
{
mpr("Your body shudders with the violent release of wild energies!", MSGCH_WARN);
- // for particularly violent releases, make a little boom
+ // for particularly violent releases, make a little boom
if (you.magic_contamination > 25 && one_chance_in(3))
{
struct bolt boom;
@@ -2657,9 +2671,10 @@ void handle_time( long time_delta )
boom.thrower = KILL_MISC;
boom.aux_source = "a magical explosion";
boom.beam_source = NON_MONSTER;
- boom.isBeam = false;
- boom.isTracer = false;
- strcpy(boom.beam_name, "magical storm");
+ boom.is_beam = false;
+ boom.is_tracer = false;
+ boom.is_explosion = true;
+ boom.name = "magical storm";
boom.ench_power = (you.magic_contamination * 5);
boom.ex_size = (you.magic_contamination / 15);
@@ -2669,13 +2684,13 @@ void handle_time( long time_delta )
explosion(boom);
}
- // we want to warp the player, not do good stuff!
+ // we want to warp the player, not do good stuff!
if (one_chance_in(5))
mutate(100);
else
give_bad_mutation(coinflip());
- // we're meaner now, what with explosions and whatnot, but
+ // we're meaner now, what with explosions and whatnot, but
// we dial down the contamination a little faster if its actually
// mutating you. -- GDL
contaminate_player( -(random2(you.magic_contamination / 4) + 1) );
@@ -2686,7 +2701,7 @@ void handle_time( long time_delta )
// and an appropriate other spell skill... is 1/20 too fast?
if (you.equip[EQ_WEAPON] != -1
&& you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_STAVES
- && item_not_ident( you.inv[you.equip[EQ_WEAPON]], ISFLAG_KNOW_TYPE )
+ && !item_ident( you.inv[you.equip[EQ_WEAPON]], ISFLAG_KNOW_TYPE )
&& one_chance_in(20))
{
int total_skill = you.skills[SK_SPELLCASTING];
@@ -2848,7 +2863,7 @@ void handle_time( long time_delta )
case SP_GHOUL: //likes it
temp_rand = random2(8);
mpr( ((temp_rand < 5) ? "You smell something rotten." :
- (temp_rand == 5) ? "Smell of rotting flesh makes you more hungry." :
+ (temp_rand == 5) ? "The smell of rotting flesh makes you hungry." :
(temp_rand == 6) ? "You smell decay. Yum-yum."
: "Wow! There is something tasty in your inventory."),
MSGCH_ROTTEN_MEAT );
@@ -2869,7 +2884,7 @@ void handle_time( long time_delta )
default:
temp_rand = random2(8);
mpr( ((temp_rand < 5) ? "You smell something rotten." :
- (temp_rand == 5) ? "Smell of rotting flesh makes you sick." :
+ (temp_rand == 5) ? "The smell of rotting flesh makes you sick." :
(temp_rand == 6) ? "You smell decay. Yuk..."
: "Ugh! There is something really disgusting in your inventory."),
MSGCH_ROTTEN_MEAT );
@@ -2880,7 +2895,7 @@ void handle_time( long time_delta )
// exercise armour *xor* stealth skill: {dlb}
if (!player_light_armour())
{
- if (random2(1000) <= mass_item( you.inv[you.equip[EQ_BODY_ARMOUR]] ))
+ if (random2(1000) <= item_mass( you.inv[you.equip[EQ_BODY_ARMOUR]] ))
{
return;
}
@@ -2897,7 +2912,7 @@ void handle_time( long time_delta )
return;
if (you.equip[EQ_BODY_ARMOUR] != -1
- && random2( mass_item( you.inv[you.equip[EQ_BODY_ARMOUR]] )) >= 100)
+ && random2( item_mass( you.inv[you.equip[EQ_BODY_ARMOUR]] )) >= 100)
{
return;
}
@@ -2909,7 +2924,23 @@ void handle_time( long time_delta )
return;
} // end handle_time()
-int autopickup_on = 1;
+static void autoinscribe_item( item_def& item )
+{
+ char name[ITEMNAME_SIZE];
+ item_name(item, DESC_INVENTORY, name, false);
+
+ std::string iname = name;
+
+ /* if there's an inscription already do nothing */
+ if ( item.inscription.size() > 0 )
+ return;
+
+ for ( unsigned i = 0; i < Options.autoinscriptions.size(); ++i ) {
+ if ( Options.autoinscriptions[i].first.matches(iname) ) {
+ item.inscription += Options.autoinscriptions[i].second;
+ }
+ }
+}
static bool is_banned(const item_def &item) {
static char name[ITEMNAME_SIZE];
@@ -2923,13 +2954,26 @@ static bool is_banned(const item_def &item) {
return false;
}
+static void autoinscribe_items()
+{
+ int o, next;
+ o = igrd[you.x_pos][you.y_pos];
+
+ while (o != NON_ITEM)
+ {
+ next = mitm[o].link;
+ autoinscribe_item( mitm[o] );
+ o = next;
+ }
+}
+
static void autopickup(void)
{
//David Loewenstern 6/99
int result, o, next;
bool did_pickup = false;
- if (autopickup_on == 0 || Options.autopickups == 0L)
+ if (!Options.autopickup_on || Options.autopickups == 0L)
return;
if (you.attribute[ATTR_TRANSFORMATION] == TRAN_AIR
@@ -2941,20 +2985,26 @@ static void autopickup(void)
if (player_is_levitating() && !wearing_amulet(AMU_CONTROLLED_FLIGHT))
return;
+ if ( Options.safe_autopickup && !i_feel_safe() )
+ return;
+
o = igrd[you.x_pos][you.y_pos];
while (o != NON_ITEM)
{
next = mitm[o].link;
- if ( ((mitm[o].flags & ISFLAG_THROWN) && Options.pickup_thrown) ||
+ if (
+ (strstr(mitm[o].inscription.c_str(), "=g") != 0) || (
+
+ ((mitm[o].flags & ISFLAG_THROWN) && Options.pickup_thrown) ||
( (Options.autopickups & (1L << mitm[o].base_type)
#ifdef CLUA_BINDINGS
|| clua.callbooleanfn(false, "ch_autopickup", "u", &mitm[o])
#endif
)
&& (Options.pickup_dropped || !(mitm[o].flags & ISFLAG_DROPPED))
- && !is_banned(mitm[o])))
+ && !is_banned(mitm[o]))))
{
mitm[o].flags &= ~(ISFLAG_THROWN | ISFLAG_DROPPED);
@@ -2982,7 +3032,7 @@ static void autopickup(void)
if (did_pickup)
{
- you.turn_is_over = 1;
+ you.turn_is_over = true;
start_delay( DELAY_AUTOPICKUP, 1 );
}
}
diff --git a/crawl-ref/source/items.h b/crawl-ref/source/items.h
index c4bca72527..53a779c2b9 100644
--- a/crawl-ref/source/items.h
+++ b/crawl-ref/source/items.h
@@ -3,6 +3,8 @@
* Summary: Misc (mostly) inventory related functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <2> 6/9/99 DML Autopickup
@@ -15,12 +17,6 @@
#include "externs.h"
-// used in acr.cc {dlb}:
-extern int autopickup_on;
-
-// used in initfile.cc {dlb}:
-extern long autopickups;
-
bool is_valid_item( const item_def &item );
bool dec_inv_item_quantity( int obj, int amount );
@@ -121,6 +117,8 @@ void handle_time( long time_delta );
* *********************************************************************** */
int inv_count(void);
+void show_items();
+
void cmd_destroy_item( void );
bool pickup_single_item(int link, int qty);
diff --git a/crawl-ref/source/lev-pand.cc b/crawl-ref/source/lev-pand.cc
index a2fadad876..b152da62d4 100644
--- a/crawl-ref/source/lev-pand.cc
+++ b/crawl-ref/source/lev-pand.cc
@@ -3,6 +3,8 @@
* Summary: Functions used in Pandemonium.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
diff --git a/crawl-ref/source/libdos.cc b/crawl-ref/source/libdos.cc
new file mode 100644
index 0000000000..4eb30860f0
--- /dev/null
+++ b/crawl-ref/source/libdos.cc
@@ -0,0 +1,21 @@
+/*
+ * File: libdos.cc
+ * Summary: Functions for DOS support.
+ * Written by: Darshan Shaligram
+ *
+ * Added for Crawl Reference by $Author: nlanza $ on $Date: 2006-09-26T03:22:57.300929Z $
+ */
+
+// Every .cc must include AppHdr or bad things happen.
+#include "AppHdr.h"
+#include <termios.h>
+
+void init_libdos()
+{
+ struct termios charmode;
+
+ tcgetattr (0, &charmode);
+ // Ignore Ctrl-C
+ charmode.c_lflag &= ~ISIG;
+ tcsetattr (0, TCSANOW, &charmode);
+}
diff --git a/crawl-ref/source/libdos.h b/crawl-ref/source/libdos.h
new file mode 100644
index 0000000000..647ce12b00
--- /dev/null
+++ b/crawl-ref/source/libdos.h
@@ -0,0 +1,6 @@
+#ifndef __LIBDOS_H__
+#define __LIBDOS_H__
+
+void init_libdos();
+
+#endif
diff --git a/crawl-ref/source/libemx.cc b/crawl-ref/source/libemx.cc
deleted file mode 100644
index 5634adbef8..0000000000
--- a/crawl-ref/source/libemx.cc
+++ /dev/null
@@ -1,233 +0,0 @@
-#include <stdio.h>
-#include <stdarg.h>
-#include <emx/syscalls.h>
-#include <sys/video.h>
-
-#include "libemx.h"
-
-
-static int cursor_start = 0, cursor_end = 0;
-static int gx = 0, gy = 0, gxx = 79, gyy = 24;
-static char buf[4096];
-
-
-
-
-void init_emx()
-{
- v_init();
- v_getctype(&cursor_start, &cursor_end);
-}
-
-
-
-
-void deinit_emx()
-{
- // nothing to do
-}
-
-
-
-
-void _setcursortype(int curstype)
-{
- if ( curstype == _NOCURSOR )
- v_hidecursor();
- else
- v_ctype(cursor_start, cursor_end);
-}
-
-
-
-
-void clrscr()
-{
- if ( (gx == 0) && (gy == 0) && (gxx == 79) && (gyy == 24) )
- {
- v_clear();
- v_gotoxy(0, 0);
- }
- else
- {
- for (int i = gy; i <= gyy; ++i)
- {
- v_gotoxy(gx, i);
- v_putn(' ', gxx - gx + 1);
- }
- v_gotoxy(gx, gy);
- }
-}
-
-
-
-
-void gotoxy(int x, int y)
-{
- v_gotoxy(x - 1 + gx, y - 1 + gy);
-}
-
-
-
-
-void textcolor(int c)
-{
- v_attrib(c);
-}
-
-
-
-
-static void cprintf_aux(const char *s)
-{
- char *ptr = buf;
-
- while (*s)
- {
- if ( *s == '\n' )
- {
- *ptr = 0;
- v_puts(buf);
- int x, y;
-
- v_getxy(&x, &y);
- if ( y != 24 )
- v_gotoxy(gx, y + 1);
- else
- v_putc('\n');
-
- ptr = buf;
- }
- else if ( *s != '\r' )
- *ptr++ = *s;
-
- ++s;
- }
-
- *ptr = 0;
- v_puts(buf);
-
-}
-
-void cprintf(const char *format, ...)
-{
- va_list argp;
- char buffer[4096]; // one could hope it's enough
-
- va_start( argp, format );
-
- vsprintf(buffer, format, argp);
- cprintf_aux(buffer);
-
- va_end(argp);
-}
-
-void puttext(int x, int y, int lx, int ly, unsigned const char *buf)
-{
- puttext(x, y, lx, ly, (const char *) buf);
-}
-
-
-
-
-void puttext(int x, int y, int lx, int ly, const char *buf)
-{
- int count = (lx - x + 1);
-
- for (int i = y - 1; i < ly; ++i)
- {
- v_putline(buf + 2 * count * i, x - 1, i, count);
- }
-}
-
-
-
-
-void gettext(int x, int y, int lx, int ly, unsigned char *buf)
-{
- gettext(x, y, lx, ly, (char *) buf);
-}
-
-
-
-
-void gettext(int x, int y, int lx, int ly, char *buf)
-{
- int count = (lx - x + 1);
-
- for (int i = y - 1; i < ly; ++i)
- {
- v_getline(buf + 2 * count * i, x - 1, i, count);
- }
-}
-
-
-
-
-void window(int x, int y, int lx, int ly)
-{
- gx = x - 1;
- gy = y - 1;
- gxx = lx - 1;
- gyy = ly - 1;
-}
-
-
-
-
-int wherex()
-{
- int x, y;
-
- v_getxy(&x, &y);
-
- return x + 1 - gx;
-}
-
-
-
-
-int wherey()
-{
- int x, y;
-
- v_getxy(&x, &y);
-
- return y + 1 - gy;
-}
-
-
-
-
-void putch(char c)
-{
- v_putc(c);
-}
-
-
-
-
-int kbhit()
-{
- return 0;
-}
-
-
-
-
-void delay(int ms)
-{
- __sleep2(ms);
-}
-
-
-
-
-void textbackground(int c)
-{
- if ( c != 0 )
- {
- fprintf(stderr, "bad background=%d", c);
- exit(1);
- }
-}
diff --git a/crawl-ref/source/libemx.h b/crawl-ref/source/libemx.h
deleted file mode 100644
index ac33612284..0000000000
--- a/crawl-ref/source/libemx.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef LIBEMX_H
-#define LIBEMX_H
-#ifndef __LIBEMX_C__
-
-
-#include <stdlib.h>
-#include <conio.h>
-
-#define itoa _itoa
-
-
-#define _NORMALCURSOR 1
-#define _NOCURSOR 0
-
-
-void init_emx();
-void deinit_emx();
-void _setcursortype(int curstype);
-void clrscr();
-void gotoxy(int x, int y);
-void textcolor(int c);
-void cprintf (const char *format, ...);
-
-void puttext(int x, int y, int lx, int ly, const char *buf);
-void puttext(int x, int y, int lx, int ly, unsigned const char *buf);
-void gettext(int x, int y, int lx, int ly, char *buf);
-void gettext(int x, int y, int lx, int ly, unsigned char *buf);
-void window(int x, int y, int lx, int ly);
-int wherex();
-int wherey();
-void putch(char c);
-int kbhit();
-void delay(int ms);
-void textbackground(int c);
-
-
-#endif // __LIBEMX_C__
-#endif
diff --git a/crawl-ref/source/libmac.cc b/crawl-ref/source/libmac.cc
deleted file mode 100644
index 35e2055344..0000000000
--- a/crawl-ref/source/libmac.cc
+++ /dev/null
@@ -1,2116 +0,0 @@
-/*
- * File: libmac.cc
- * Summary: Mac specific routines used by Crawl.
- * Written by: Jesse Jones (jesjones@mindspring.com)
- *
- * Modified for Crawl Reference by $Author$ on $Date$
- *
- * Change History (most recent first):
- *
- * <5> 5/25/02 JDJ Rewrote to use Carbon Events and Mach-O.
- * <4> 9/25/99 CDL linuxlib -> liblinux
- *
- * <3> 5/30/99 JDJ Quit only pops up save changes dialog if game_has_started is true.
- * <2> 4/24/99 JDJ HandleMenu calls save_game instead of returning a 'S'
- * character ('S' now prompts). kTermHeight is now initialized
- * to NUMBER_OF_LINES.
- * <2> 4/24/99 JDJ getstr only adds printable characters to the buffer.
- * <1> 3/23/99 JDJ Created
- */
-
-#include "AppHdr.h"
-#include "libmac.h"
-
-#if macintosh
-
-#include <cstdarg>
-#include <ctype.h>
-#include <string.h>
-#include <vector.h>
-
-#include <CarbonCore/StringCompare.h>
-#include <HIToolbox/CarbonEvents.h>
-#include <HIToolbox/Dialogs.h>
-
-#include "debug.h"
-#include "defines.h"
-#include "files.h"
-#include "MacString.h"
-#include "version.h"
-
-
-//-----------------------------------
-// Forward References
-//
-class CApplication;
-
-
-//-----------------------------------
-// Constants
-//
-const int kTermWidth = 80;
-const int kTermHeight = MAC_NUMBER_OF_LINES;
-
-const int kLeftArrowKey = 0x7B;
-const int kUpArrowKey = 0x7E;
-const int kRightArrowKey = 0x7C;
-const int kDownArrowKey = 0x7D;
-
-const int kNumPad0Key = 0x52;
-const int kNumPad1Key = 0x53;
-const int kNumPad2Key = 0x54;
-const int kNumPad3Key = 0x55;
-const int kNumPad4Key = 0x56;
-const int kNumPad5Key = 0x57;
-const int kNumPad6Key = 0x58;
-const int kNumPad7Key = 0x59;
-const int kNumPad8Key = 0x5B;
-const int kNumPad9Key = 0x5C;
-
-const int kNumPadMultKey = 0x43;
-const int kNumPadAddKey = 0x45;
-const int kNumPadSubKey = 0x4E;
-const int kNumPadDecimalKey = 0x41;
-const int kNumPadDivideKey = 0x4B;
-
-const char kEnterChar = 0x03;
-const short kEscapeKey = 0x35;
-const char kCheckMarkChar = 0x12;
-const char kNoMarkChar = 0x00;
-
-const short kSaveBtn = 1;
-const short kCancelBtn = 2;
-const short kDontSaveBtn = 3;
-
-const Rect kBigRect = {0, 0, 32000, 32000};
-
-const RGBColor kBlack = {0, 0, 0};
-const RGBColor kWhite = {65535, 65535, 65535};
-
-enum EAskSaveResult
-{
- kSaveChanges = 1,
- kCancelSave = 2,
- kDontSave = 3
-};
-
-
-//-----------------------------------
-// Variables
-//
-static CApplication* sApp = NULL;
-static CTabHandle sColors = NULL;
-
-static bool sInDialog = false;
-
-extern bool game_has_started;
-
-
-// ========================================================================
-// Internal Functions
-// ========================================================================
-
-//---------------------------------------------------------------
-//
-// CreateSpec
-//
-//---------------------------------------------------------------
-static EventTypeSpec CreateSpec(UInt32 c, UInt32 k)
-{
- EventTypeSpec spec;
-
- spec.eventClass = c;
- spec.eventKind = k;
-
- return spec;
-}
-
-
-//---------------------------------------------------------------
-//
-// DrawChar
-//
-//---------------------------------------------------------------
-inline void DrawChar(short x, short y, char ch)
-{
- MoveTo(x, y);
- DrawText(&ch, 0, 1);
-}
-
-
-//---------------------------------------------------------------
-//
-// ThrowIf
-//
-//---------------------------------------------------------------
-static void ThrowIf(bool predicate, const std::string& text)
-{
- if (predicate)
- throw std::runtime_error(text);
-}
-
-
-//---------------------------------------------------------------
-//
-// ThrowIfOSErr
-//
-//---------------------------------------------------------------
-static void ThrowIfOSErr(OSErr err, const std::string& text)
-{
- if (err != noErr)
- {
- char buffer[256];
- sprintf(buffer, "%s (%d)", text.c_str(), err);
-
- throw std::runtime_error(buffer);
- }
-}
-
-
-//---------------------------------------------------------------
-//
-// FlashButton
-//
-//---------------------------------------------------------------
-static void FlashButton(DialogPtr dialog, short item)
-{
- ASSERT(dialog != nil);
- ASSERT(item >= 1 && item <= CountDITL(dialog));
-
- ControlRef control;
- (void) GetDialogItemAsControl(dialog, item, &control);
-
- HiliteControl(control, 1);
-// QDAddRectToDirtyRegion(GetDialogPort(dialog), &kBigRect);
- QDFlushPortBuffer(GetDialogPort(dialog), NULL);
-
- unsigned long ticks;
- Delay(8, &ticks);
-
- HiliteControl(control, 0);
-// QDAddRectToDirtyRegion(GetDialogPort(dialog), &kBigRect);
- QDFlushPortBuffer(GetDialogPort(dialog), NULL);
-}
-
-
-//---------------------------------------------------------------
-//
-// WarnUser
-//
-// Pops up an error dialog.
-//
-//---------------------------------------------------------------
-static void WarnUser(const char* message)
-{
- int len = strlen(message);
- if (len > 250)
- len = 250;
-
- Str255 text;
- for (int i = 0; i < len; i++)
- text[i + 1] = message[i];
- text[0] = len;
-
- AlertStdAlertParamRec params;
- params.movable = true;
- params.helpButton = false;
- params.filterProc = NULL;
- params.defaultText = (StringPtr) -1L; // use default (ie "OK")
- params.cancelText = NULL;
- params.otherText = NULL;
- params.defaultButton = 1;
- params.cancelButton = 0;
- params.position = kWindowAlertPositionParentWindowScreen;
-
- short item;
- sInDialog = true;
- OSErr err = StandardAlert(kAlertCautionAlert, text, "\p", &params, &item);
- ASSERT(err == noErr); // seems kind of pointless to throw
- sInDialog = false;
-}
-
-
-//---------------------------------------------------------------
-//
-// SaveChangesFilter
-//
-//---------------------------------------------------------------
-static pascal Boolean SaveChangesFilter(DialogPtr dptr, EventRecord* event, short* item)
-{
- bool handled = false;
-
- if (event->what == keyDown)
- {
- char ch = (char) toupper((char) (event->message & charCodeMask));
- short key = (short) ((event->message & keyCodeMask) >> 8);
-
- if (ch == 'S')
- {
- *item = 1;
- handled = true;
- }
- else if (ch == 'D')
- {
- *item = 3;
- handled = true;
- }
- else if (ch == '\r' || ch == kEnterChar)
- {
- *item = 1;
- handled = true;
- }
- else if (key == kEscapeKey)
- {
- *item = 2;
- handled = true;
- }
-
- if (handled)
- FlashButton(dptr, *item);
- }
-
- return handled;
-}
-
-
-//---------------------------------------------------------------
-//
-// AskSaveChanges
-//
-//---------------------------------------------------------------
-static EAskSaveResult AskSaveChanges()
-{
-#if 1
- static ModalFilterUPP filterProc = NewModalFilterUPP(SaveChangesFilter);
-
- AlertStdAlertParamRec params;
- params.movable = true;
- params.helpButton = false;
- params.filterProc = filterProc;
- params.defaultText = "\pSave";
- params.cancelText = "\pCancel";
- params.otherText = "\pDon't Save";
- params.defaultButton = kSaveBtn;
- params.cancelButton = kCancelBtn;
- params.position = kWindowAlertPositionParentWindowScreen;
-
- short item = kSaveBtn;
- sInDialog = true;
- OSErr err = StandardAlert(kAlertStopAlert, "\pDo you want to save your game before quitting?", "\p", &params, &item);
- ASSERT(err == noErr); // seems kind of pointless to throw
- sInDialog = false;
-
- EAskSaveResult result;
- if (item == kSaveBtn)
- result = kSaveChanges;
- else if (item == kDontSaveBtn)
- result = kDontSave;
- else
- result = kCancelSave;
-
- return result;
-
-#else
- NavDialogOptions options;
- OSStatus err = NavGetDefaultDialogOptions(&options);
- ASSERT(err == noErr); // seems kind of pointless to throw
-
- NavAskSaveChangesResult reply = kSaveChanges;
- if (err == noErr)
- {
- std::string name = "foobar";
- UInt32 length = std::min(name.size(), sizeof(options.savedFileName) - 1);
- BlockMoveData(name.c_str(), options.savedFileName + 1, length);
- options.savedFileName[0] = length;
-
- err = NavAskSaveChanges(&options,
- action,
- &reply,
- NULL,
- 0UL);
- ASSERT(err == noErr); // seems kind of pointless to throw
- }
-
- return (EAskSaveResult) reply;
-#endif
-}
-
-
-//---------------------------------------------------------------
-//
-// ConvertColor
-//
-//---------------------------------------------------------------
-static RGBColor ConvertColor(int c)
-{
- ASSERT(c >= 0);
- ASSERT(c < 16);
-
- RGBColor color;
-
- if (c == BLACK)
- color = (**sColors).ctTable[15].rgb; // QD likes black and white swapped from DOS indices
-
- else if (c == WHITE)
- color = (**sColors).ctTable[0].rgb;
- else
- color = (**sColors).ctTable[c].rgb;
-
- return color;
-}
-
-#if __MWERKS__
-#pragma mark -
-#endif
-
-// ============================================================================
-// class CApplication
-// ============================================================================
-class CApplication {
-
-//-----------------------------------
-// Initialization/Destruction
-//
-public:
- ~CApplication();
- CApplication();
-
-//-----------------------------------
-// API
-//
-public:
- void Quit();
-
- char GetChar();
- // Block until a key is pressed.
-
- bool PeekChar();
- // Return true if a key event is on the event queue.
-
- void Clear();
- void SetCursor(int x, int y);
- Point GetCursor() const {return mCursor;}
- void SetChar(unsigned char ch);
- void Print(const char* buffer);
- void ShowCursor(bool show) {mShowCursor = show;}
-
- void SetForeColor(const RGBColor& color);
- void SetBackColor(const RGBColor& color);
-
- void SetFont(const unsigned char *name) {this->DoSetFont(name, mPointSize);}
- void SetFontSize(int size) {this->DoSetFont(mFontName, size);}
-
-//-----------------------------------
-// Internal Types
-//
-private:
- struct SCell {
- unsigned char ch;
- RGBColor color;
-
- SCell()
- {
- ch = ' ';
- color.red = color.green = color.blue = 65535;
- }
- };
-
- typedef vector<SCell> Line;
-
-//-----------------------------------
-// Internal API
-//
-private:
- void DoAbout();
- void DoClearToEOL();
- void DoDrawCell(const Rect& area, const SCell& cell);
- OSStatus DoEnableCommand(MenuRef menuH, MenuCommand command, MenuItemIndex index);
- OSStatus DoHandleCommand(MenuCommand command);
- void DoInitMenus();
- void DoInitWindows();
- char DoMungeChar(char inChar, UInt32 inKey, UInt32 modifiers) const;
- OSStatus DoOpenMenu(MenuRef menuH);
- void DoReadPrefs();
- void DoRender();
- void DoScroll();
- void DoSetChar(unsigned char ch);
- void DoSetFont(const unsigned char* name, int size);
- void DoWritePrefs();
-
- static pascal OSStatus DoKeyDown(EventHandlerCallRef handler, EventRef event, void* refCon);
- static pascal OSStatus DoMenuEvent(EventHandlerCallRef handler, EventRef event, void* refCon);
- static pascal OSErr DoQuit(const AppleEvent* event, AppleEvent* reply, SInt32 refCon);
- static pascal OSStatus DoWindowEvent(EventHandlerCallRef handler, EventRef event, void* refCon);
-
-//-----------------------------------
-// Member Data
-//
-private:
- WindowRef mWindow;
- vector<Line> mLines;
- char mChar;
-
- Point mCursor;
- bool mShowCursor;
-
- RGBColor mForeColor;
- RGBColor mBackColor;
-
- Str255 mFontName;
- int mPointSize;
- UInt32 mNumFonts;
- MenuRef mFontMenu;
-
- short mFontNum;
- int mAscent;
- int mCellHeight;
- int mCellWidth;
-};
-
-//---------------------------------------------------------------
-//
-// CApplication::~CApplication
-//
-//---------------------------------------------------------------
-CApplication::~CApplication()
-{
- this->DoWritePrefs();
-
- DisposeWindow(mWindow);
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::CApplication
-//
-//---------------------------------------------------------------
-CApplication::CApplication()
-{
- InitCursor();
-
- mCursor.h = 0;
- mCursor.v = 0;
- mShowCursor = false;
- mChar = 0;
-
- mNumFonts = 0;
- mFontName[0] = '\0';
- mFontNum = -2;
- mPointSize = 0;
- mAscent = 0;
- mCellHeight = 0;
- mCellWidth = 0;
- mFontMenu = NULL;
-
- mForeColor = kWhite;
- mBackColor = kBlack;
-
- try
- {
- // install a handler for the quit apple event
- OSStatus err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP(DoQuit), 0, false);
- ThrowIfOSErr(err, "Couldn't install the quit handler!");
-
- // install a custom key handler
- std::vector<EventTypeSpec> specs;
- specs.push_back(CreateSpec(kEventClassKeyboard, kEventRawKeyDown));
- specs.push_back(CreateSpec(kEventClassKeyboard, kEventRawKeyRepeat));
-
- err = InstallApplicationEventHandler(NewEventHandlerUPP(DoKeyDown), specs.size(), &specs[0], this, NULL);
- ThrowIfOSErr(err, "Couldn't install the key handler!");
-
- // create the window
- this->DoInitWindows();
-
- // init the menus
- this->DoInitMenus();
-
- // update some state
- this->DoReadPrefs();
-
- this->Clear();
-
- // show the window
- ShowWindow(mWindow);
- }
- catch (const std::exception& e)
- {
- WarnUser(e.what());
- ExitToShell();
- }
- catch (...)
- {
- WarnUser("Couldn't initialize the application.");
- ExitToShell();
- }
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::Quit
-//
-//---------------------------------------------------------------
-void CApplication::Quit()
-{
- if (game_has_started)
- {
- EAskSaveResult answer = AskSaveChanges();
-
- if (answer == kSaveChanges)
- {
- save_game(true);
- }
- else if (answer == kDontSave)
- {
- deinit_mac();
- ExitToShell();
- }
- }
- else
- {
- deinit_mac();
- ExitToShell();
- }
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::Clear
-//
-//---------------------------------------------------------------
-void CApplication::Clear()
-{
- mLines.resize(kTermHeight);
-
- for (int y = 0; y < mLines.size(); ++y)
- {
- Line& line = mLines[y];
- line.resize(kTermWidth);
-
- for (int x = 0; x < line.size(); ++x)
- {
- SCell& cell = line[x];
-
- cell.ch = ' ';
- cell.color = kWhite;
- }
- }
-
- mCursor.h = 0;
- mCursor.v = 0;
-
- (void) InvalWindowRect(mWindow, &kBigRect);
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::SetCursor
-//
-//---------------------------------------------------------------
-void CApplication::SetCursor(int x, int y)
-{
- ASSERT(x >= 0);
- ASSERT(x < kTermWidth);
- ASSERT(y >= 0);
- ASSERT(y < kTermHeight);
-
- if (x != mCursor.h || y != mCursor.v)
- {
- if (mShowCursor)
- {
- Rect area;
- area.top = mCursor.v * mCellHeight;
- area.bottom = area.top + mCellHeight;
- area.left = mCursor.h * mCellWidth;
- area.right = area.left + mCellWidth;
-
- (void) InvalWindowRect(mWindow, &area);
- }
-
- mCursor.h = x;
- mCursor.v = y;
-
- if (mShowCursor)
- {
- Rect area;
- area.top = mCursor.v * mCellHeight;
- area.bottom = area.top + mCellHeight;
- area.left = mCursor.h * mCellWidth;
- area.right = area.left + mCellWidth;
-
- (void) InvalWindowRect(mWindow, &area);
- }
- }
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::SetChar
-//
-//---------------------------------------------------------------
-void CApplication::SetChar(unsigned char ch)
-{
- ASSERT(ch != '\t');
- ASSERT(mLines.size() == kTermHeight);
-
- const int TABSIZE = 8;
-
- int x = mCursor.h; // this is from the ncurses source
- int y = mCursor.v;
-
- switch (ch) {
- case '\t':
- x += (TABSIZE - (x % TABSIZE));
-
- // Space-fill the tab on the bottom line so that we'll get the
- // "correct" cursor position.
- if (x < kTermWidth)
- {
- char blank = ' ';
-
- while (mCursor.h < x)
- this->DoSetChar(blank);
- break;
-
- }
- else
- {
- this->DoClearToEOL();
- if (++y >= kTermHeight)
- {
- x = kTermWidth - 1;
- y--;
- this->DoScroll();
- x = 0;
- }
- else
- x = 0;
- }
- break;
-
-#if 1
- case '\n':
- case '\r':
- this->DoClearToEOL();
- if (++y >= kTermHeight)
- {
- y--;
- this->DoScroll();
- }
- x = 0;
- break;
-
-#else
- case '\n':
- this->DoClearToEOL();
- if (++y >= kTermHeight)
- {
- y--;
- this->DoScroll();
- }
- /* FALLTHRU */
-
- case '\r':
- x = 0;
- break;
-#endif
-
- case '\b':
- if (x == 0)
- return;
- mCursor.h--;
- this->DoSetChar(' ');
- x--;
- break;
-
- case 159:
- case 176:
- case 177:
- case 220:
- case 239:
- case 240:
- case 247:
- case 249:
- case 250:
- case 206:
- case 254:
- this->DoSetChar(ch);
- return;
- break;
-
- default:
- if (ch == '\0')
- ch = ' ';
-
-// ASSERT(ch >= ' ');
-// ASSERT(ch <= '~');
-
- if (ch >= ' ' && ch <= '~')
- this->DoSetChar(ch);
- else
- this->DoSetChar('À');
- return;
- }
-
- mCursor.h = x;
- mCursor.v = y;
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::Print
-//
-//---------------------------------------------------------------
-void CApplication::Print(const char* buffer)
-{
- ASSERT(buffer != NULL);
-
- const char* p = buffer;
-
- while (*p != '\0')
- {
- char ch = *p++;
-
- this->SetChar(ch);
- }
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::SetForeColor
-//
-//---------------------------------------------------------------
-void CApplication::SetForeColor(const RGBColor & color)
-{
- if (color.red != mForeColor.red || color.green != mForeColor.green || color.blue != mForeColor.blue)
- {
- mForeColor = color;
-
- (void) InvalWindowRect(mWindow, &kBigRect);
- }
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::SetBackColor
-//
-//---------------------------------------------------------------
-void CApplication::SetBackColor(const RGBColor & color)
-{
- if (color.red != mBackColor.red || color.green != mBackColor.green || color.blue != mBackColor.blue)
- {
- mBackColor = color;
-
- (void) InvalWindowRect(mWindow, &kBigRect);
- }
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::GetChar
-//
-//---------------------------------------------------------------
-char CApplication::GetChar()
-{
- mChar = 0;
- RunApplicationEventLoop();
-
- (void) InvalWindowRect(mWindow, &kBigRect);
-
- return mChar;
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::PeekChar
-//
-//---------------------------------------------------------------
-bool CApplication::PeekChar()
-{
- EventTypeSpec specs[2];
- specs[0] = CreateSpec(kEventClassKeyboard, kEventRawKeyDown);
- specs[1] = CreateSpec(kEventClassKeyboard, kEventRawKeyRepeat);
-
- EventRef event = NULL;
- OSStatus err = ReceiveNextEvent(2, specs, kEventDurationNoWait, false, &event);
-
- return err == noErr;
-}
-
-#if __MWERKS__
-#pragma mark ~
-#endif
-
-//---------------------------------------------------------------
-//
-// CApplication::DoAbout
-//
-//---------------------------------------------------------------
-void CApplication::DoAbout()
-{
- AlertStdAlertParamRec params;
- params.movable = true;
- params.helpButton = false;
- params.filterProc = NULL;
- params.defaultText = (StringPtr) -1L; // use default (ie "OK") VERSION
- params.cancelText = NULL;
- params.otherText = NULL;
- params.defaultButton = 1;
- params.cancelButton = 0;
- params.position = kWindowAlertPositionParentWindowScreen;
-
- short item;
- sInDialog = true;
- OSErr err = StandardAlert(kAlertNoteAlert, "\p Crawl " VERSION, "\p© 1997-2002 by Linley Henzell\nMac Port by Jesse Jones", &params, &item);
- ASSERT(err == noErr); // seems kind of pointless to throw
- sInDialog = false;
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoClearToEOL
-//
-//---------------------------------------------------------------
-void CApplication::DoClearToEOL()
-{
- ASSERT(mCursor.h < kTermWidth);
- ASSERT(mCursor.v < kTermHeight);
-
- Line& line = mLines[mCursor.v];
- for (int x = mCursor.h; x < kTermWidth; ++x)
- {
- SCell& cell = line[x];
- cell.ch = ' ';
- }
-
- Rect area;
- area.top = mCursor.v * mCellHeight;
- area.bottom = area.top + mCellHeight;
- area.left = mCursor.h * mCellWidth;
- area.right = 16000;
-
- (void) InvalWindowRect(mWindow, &kBigRect);
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoDrawCell
-//
-//---------------------------------------------------------------
-void CApplication::DoDrawCell(const Rect& area, const SCell& cell)
-{
- RGBForeColor(&cell.color);
-
- switch (cell.ch) {
- case 159: // fountain
- DrawChar(area.left, area.top + mAscent, '´');
- break;
-
- case 177: // wall
- case 176:
- PaintRect(&area);
- break;
-
- case 247: // water/lava
- PaintRect(&area);
- break;
-
- case 249: // floor
- case 250: // undiscovered trap?
-// FillRect(&area, &qd.gray);
- DrawChar(area.left, area.top + mAscent, '.');
- break;
-
- case 206:
- case 254: // door
- {
- Rect temp = area;
- InsetRect(&temp, 2, 2);
- PaintRect(&temp);
- }
- break;
-
- case 220: // altar
- DrawChar(area.left, area.top + mAscent, 'Æ');
- break;
-
- case 239: // staircase to hell
- case 240: // branch staircase
- DrawChar(area.left, area.top + mAscent, '²');
- break;
-
- default:
- DrawChar(area.left, area.top + mAscent, cell.ch);
- }
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoEnableCommand
-//
-//---------------------------------------------------------------
-OSStatus CApplication::DoEnableCommand(MenuRef menuH, MenuCommand command, MenuItemIndex index)
-{
- OSStatus err = noErr;
-
- if (command == 'Abut')
- {
- EnableMenuItem(menuH, index);
- }
- else if (command == 'Save')
- {
- if (game_has_started)
- EnableMenuItem(menuH, index);
- else
- DisableMenuItem(menuH, index);
- }
- else if (command >= 'Size' && command <= 'Size'+128)
- {
- if (mPointSize == command - 'Size')
- SetItemMark(menuH, index, kCheckMarkChar);
- else
- SetItemMark(menuH, index, kNoMarkChar);
- }
- else if (command >= 'Font' && command <= 'Font'+128)
- {
- Str255 name;
- GetMenuItemText(menuH, index, name);
-
- if (EqualString(mFontName, name, true, true))
- SetItemMark(menuH, index, kCheckMarkChar);
- else
- SetItemMark(menuH, index, noMark);
- }
- else
- err = eventNotHandledErr;
-
- return err;
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoHandleCommand
-//
-//---------------------------------------------------------------
-OSStatus CApplication::DoHandleCommand(MenuCommand command)
-{
- OSStatus err = noErr;
-
- if (command == 'Abut')
- {
- this->DoAbout();
- }
- else if (command == 'Save')
- {
- save_game(false);
- }
- else if (command >= 'Size' && command <= 'Size'+128)
- {
- int size = command - 'Size';
-
- this->SetFontSize(size);
- }
- else if (command >= 'Font' && command <= 'Font'+128)
- {
- int index = command - 'Font';
-
- Str255 name;
- GetMenuItemText(mFontMenu, index, name);
-
- this->SetFont(name);
- }
- else if (command == kHICommandQuit)
- {
- this->Quit();
- }
- else
- err = eventNotHandledErr;
-
- return err;
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoInitMenus
-//
-//---------------------------------------------------------------
-void CApplication::DoInitMenus()
-{
- const int kFileMenu = 257;
- const int kFontMenu = 258;
- const int kSizeMenu = 259;
-
- // add the About menu item
- MenuRef menuH = NewMenu(0, "\pð");
-
- OSStatus err = InsertMenuItemTextWithCFString(menuH, MacString("About Crawl"), 0, kMenuItemAttrIgnoreMeta, 'Abut');
- ThrowIfOSErr(err, "Couldn't add the about menu item!");
-
- InsertMenu(menuH, 0);
-
- // create the File menu
- err = CreateNewMenu(kFileMenu, kMenuAttrAutoDisable, &menuH);
- ThrowIfOSErr(err, "Couldn't create the file menu!");
-
- err = SetMenuTitleWithCFString(menuH, MacString("File"));
- ThrowIfOSErr(err, "Couldn't set the file menu name!");
-
- InsertMenu(menuH, 0);
-
- // add the File menu items
- err = AppendMenuItemTextWithCFString(menuH, MacString("Save"), kMenuItemAttrIgnoreMeta, 'Save', NULL);
- ThrowIfOSErr(err, "Couldn't add the save menu item!");
-
- err = SetMenuItemCommandKey(menuH, 1, false, 'S');
- ThrowIfOSErr(err, "Couldn't set the save menu item's command key!");
-
- // create the Font menu
- err = CreateNewMenu(kFontMenu, kMenuAttrAutoDisable, &mFontMenu);
- ThrowIfOSErr(err, "Couldn't create the font menu!");
-
- err = CreateStandardFontMenu(mFontMenu, 0, 0, kNilOptions, &mNumFonts);
- ThrowIfOSErr(err, "Couldn't initialize the font menu!");
-
- err = SetMenuTitleWithCFString(mFontMenu, MacString("Font"));
- ThrowIfOSErr(err, "Couldn't set the font menu name!");
-
- UInt16 numItems = CountMenuItems(mFontMenu);
- for (UInt16 index = 1; index <= numItems; ++index)
- {
- // set the font for each menu item so we're WYSIWYG
- Str255 fontName;
- GetMenuItemText(mFontMenu, index, fontName);
-
- short fontNum;
- GetFNum(fontName, &fontNum);
-
- SetMenuItemFontID(mFontMenu, index, fontNum);
-
- // set the command id so we can process the items (CreateStandardFontMenu
- // leaves all of these at 0)
- err = SetMenuItemCommandID(mFontMenu, index, 'Font' + index);
- ThrowIfOSErr(err, "Couldn't set the font menu item's command ids!");
- }
-
- InsertMenu(mFontMenu, 0);
-
- // create the Size menu
- err = CreateNewMenu(kSizeMenu, kMenuAttrAutoDisable, &menuH);
- ThrowIfOSErr(err, "Couldn't create the size menu!");
-
- err = SetMenuTitleWithCFString(menuH, MacString("Size"));
- ThrowIfOSErr(err, "Couldn't set the size menu name!");
-
- InsertMenu(menuH, 0);
-
- // add the Size menu items
- const char* items[] = {"9", "10", "12", "16", "18", "20", "32", "48", "64", NULL};
- int sizes[] = {9, 10, 12, 16, 18, 20, 32, 48, 64};
- for (int i = 0; items[i] != NULL; ++i)
- {
- err = AppendMenuItemTextWithCFString(menuH, MacString(items[i]), kMenuItemAttrIgnoreMeta, 'Size' + sizes[i], NULL);
- ThrowIfOSErr(err, "Couldn't add a size menu item!");
- }
-
- // install a custom menu handler
- std::vector<EventTypeSpec> specs;
- specs.push_back(CreateSpec(kEventClassCommand, kEventCommandProcess));
- specs.push_back(CreateSpec(kEventClassCommand, kEventCommandUpdateStatus));
- specs.push_back(CreateSpec(kEventClassMenu, kEventMenuOpening));
-
- err = InstallApplicationEventHandler(NewEventHandlerUPP(DoMenuEvent), specs.size(), &specs[0], this, NULL);
- ThrowIfOSErr(err, "Couldn't install the menu handlers!");
-
- // draw the new menubar
- DrawMenuBar();
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoInitWindows
-//
-//---------------------------------------------------------------
-void CApplication::DoInitWindows()
-{
- // create the window
- Rect bounds = {32, 32, 64, 64}; // we position properly later
-
- WindowAttributes attrs = kWindowCollapseBoxAttribute | kWindowStandardHandlerAttribute;
- OSStatus err = CreateNewWindow(kDocumentWindowClass, attrs, &bounds, &mWindow);
- ThrowIfOSErr(err, "Couldn't create the window!");
-
- // install a custom window handler
- std::vector<EventTypeSpec> specs;
- specs.push_back(CreateSpec(kEventClassWindow, kEventWindowDrawContent));
-
- err = InstallWindowEventHandler(mWindow, NewEventHandlerUPP(DoWindowEvent), specs.size(), &specs[0], this, NULL);
- ThrowIfOSErr(err, "Couldn't install the window event handler!");
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoKeyDown [static]
-//
-//---------------------------------------------------------------
-pascal OSStatus CApplication::DoKeyDown(EventHandlerCallRef handler, EventRef event, void* refCon)
-{
- OSStatus err = eventNotHandledErr;
-
- if (!sInDialog)
- {
- CApplication* thisPtr = static_cast<CApplication*>(refCon);
-
- try
- {
- char ch;
- (void) GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(ch), NULL, &ch);
-
- UInt32 key;
- (void) GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(key), NULL, &key);
-
- UInt32 modifiers;
- (void) GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers);
-
- if ((modifiers & cmdKey) == 0)
- thisPtr->mChar = thisPtr->DoMungeChar(ch, key, modifiers);
-
- if (thisPtr->mChar != 0)
- QuitApplicationEventLoop();
-
- err = noErr;
- }
- catch (const std::exception& e)
- {
- DEBUGSTR((std::string("Couldn't complete the operation (") + e.what() + ").").c_str());
- err = eventNotHandledErr;
- }
- catch (...)
- {
- DEBUGSTR("Couldn't complete the operation.");
- err = eventNotHandledErr;
- }
- }
-
- return err;
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoMenuEvent [static]
-//
-//---------------------------------------------------------------
-pascal OSStatus CApplication::DoMenuEvent(EventHandlerCallRef handler, EventRef event, void* refCon)
-{
- OSStatus err = noErr;
- CApplication* thisPtr = static_cast<CApplication*>(refCon);
-
- UInt32 kind = GetEventKind(event);
- try
- {
- HICommand command;
-
- if (kind == kEventCommandUpdateStatus)
- {
- err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(command), NULL, &command);
- ThrowIfOSErr(err, "Couldn't get the direct object in DoMenuEvent");
-
- err = thisPtr->DoEnableCommand(command.menu.menuRef, command.commandID, command.menu.menuItemIndex);
- }
- else if (kind == kEventCommandProcess)
- {
- err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(command), NULL, &command);
- ThrowIfOSErr(err, "Couldn't get the direct object in DoMenuEvent");
-
- err = thisPtr->DoHandleCommand(command.commandID);
- }
- else if (kind == kEventMenuOpening)
- {
- Boolean firstTime;
- err = GetEventParameter(event, kEventParamMenuFirstOpen, typeBoolean, NULL, sizeof(firstTime), NULL, &firstTime);
- ThrowIfOSErr(err, "Couldn't get the first open flag in DoMenuEvent");
-
- if (firstTime) // only call the callbacks the first time we open the menu (during this drag)
- {
- MenuRef menuH;
- err = GetEventParameter(event, kEventParamDirectObject, typeMenuRef, NULL, sizeof(MenuRef), NULL, &menuH);
- ThrowIfOSErr(err, "Couldn't get the direct object in DoMenuEvent");
-
- err = thisPtr->DoOpenMenu(menuH);
- }
- }
- else
- err = eventNotHandledErr;
- }
- catch (const std::exception& e)
- {
- DEBUGSTR((std::string("Couldn't complete the operation (") + e.what() + ").").c_str());
- err = eventNotHandledErr;
- }
- catch (...)
- {
- DEBUGSTR("Couldn't complete the operation.");
- err = eventNotHandledErr;
- }
-
- if (kind == kEventCommandProcess)
- HiliteMenu(0);
-
- return err;
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoMungeChar
-//
-//---------------------------------------------------------------
-char CApplication::DoMungeChar(char ch, UInt32 key, UInt32 modifiers) const
-{
- switch (key) {
- case kNumPad1Key:
- if (modifiers & shiftKey)
- ch = 'B';
- else if (modifiers & controlKey)
- ch = 2;
- else
- ch = 'b';
- break;
-
- case kNumPad2Key:
- case kDownArrowKey:
- if (modifiers & shiftKey)
- ch = 'J';
- else if (modifiers & controlKey)
- ch = 10;
- else
- ch = 'j';
- break;
-
- case kNumPad3Key:
- if (modifiers & shiftKey)
- ch = 'N';
- else if (modifiers & controlKey)
- ch = 14;
- else
- ch = 'n';
- break;
-
- case kNumPad4Key:
- case kLeftArrowKey:
- if (modifiers & shiftKey)
- ch = 'H';
- else if (modifiers & controlKey)
- ch = 8;
- else
- ch = 'h';
- break;
-
- case kNumPad5Key:
- if (modifiers & shiftKey)
- ch = '5';
- else
- ch = '.';
- break;
-
- case kNumPad6Key:
- case kRightArrowKey:
- if (modifiers & shiftKey)
- ch = 'L';
- else if (modifiers & controlKey)
- ch = 12;
- else
- ch = 'l';
- break;
-
- case kNumPad7Key:
- if (modifiers & shiftKey)
- ch = 'Y';
- else if (modifiers & controlKey)
- ch = 25;
- else
- ch = 'y';
- break;
-
- case kNumPad8Key:
- case kUpArrowKey:
- if (modifiers & shiftKey)
- ch = 'K';
- else if (modifiers & controlKey)
- ch = 11;
- else
- ch = 'k';
- break;
-
- case kNumPad9Key:
- if (modifiers & shiftKey)
- ch = 'U';
- else if (modifiers & controlKey)
- ch = 21;
- else
- ch = 'u';
- break;
- }
-
- return ch;
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoOpenMenu
-//
-//---------------------------------------------------------------
-OSStatus CApplication::DoOpenMenu(MenuRef menuH)
-{
- // select the curret font
-
- return noErr;
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoQuit [static]
-//
-//---------------------------------------------------------------
-pascal OSErr CApplication::DoQuit(const AppleEvent* event, AppleEvent* reply, SInt32 refCon)
-{
- CApplication* thisPtr = reinterpret_cast<CApplication*>(refCon);
- thisPtr->Quit();
-
- return noErr;
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoReadPrefs
-//
-//---------------------------------------------------------------
-void CApplication::DoReadPrefs()
-{
- MacString appID("Crawl4");
-
- // window location
- Rect bounds;
-
- MacString name("window_x");
- Boolean existsX = false;
- bounds.left = CFPreferencesGetAppIntegerValue(name, appID, &existsX);
-
- name = MacString("window_y");
- Boolean existsY = false;
- bounds.top = CFPreferencesGetAppIntegerValue(name, appID, &existsY);
-
- if (existsX && existsY)
- {
- bounds.right = bounds.left + 32; // DoSetFont will reset the window dimensions
- bounds.bottom = bounds.top + 32;
-
- OSStatus err = SetWindowBounds(mWindow, kWindowStructureRgn, &bounds);
- ASSERT(err == noErr);
- }
- else
- {
- OSStatus err = RepositionWindow(mWindow, NULL, kWindowCenterOnMainScreen);
- ASSERT(err == noErr);
- }
-
- // mFontName
- name = MacString("font_name");
-
- CFTypeRef dataRef = CFPreferencesCopyAppValue(name, appID);
- if (dataRef != NULL && CFGetTypeID(dataRef) == CFStringGetTypeID())
- {
- MacString data(static_cast<CFStringRef>(dataRef));
-
- Str255 fontName;
- data.CopyTo(fontName, sizeof(fontName));
- CFRelease(dataRef);
-
- // mPointSize
- name = MacString("font_size");
- CFIndex fontSize = CFPreferencesGetAppIntegerValue(name, appID, NULL);
- if (fontSize > 0)
- this->DoSetFont(fontName, fontSize);
- else
- this->DoSetFont(fontName, 12);
- }
- else
- this->DoSetFont("\pMonaco", 12);
-
- // make sure the window isn't off-screen
- Rect area;
- OSStatus err = GetWindowGreatestAreaDevice(mWindow, kWindowStructureRgn, NULL, &area);
- if (err == noErr)
- {
- err = GetWindowBounds(mWindow, kWindowDragRgn, &bounds);
- if (err == noErr)
- {
- SectRect(&area, &bounds, &bounds);
-
- int pixels = (bounds.right - bounds.left)*(bounds.bottom - bounds.top);
- if (pixels < 64) // only move the window if there are fewer than 64 draggable pixels
- {
- err = ConstrainWindowToScreen(mWindow, kWindowStructureRgn, kWindowConstrainStandardOptions, NULL, NULL);
- ASSERT(err == noErr);
- }
- }
- }
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoRender
-//
-//---------------------------------------------------------------
-void CApplication::DoRender()
-{
- ASSERT(mLines.size() == kTermHeight);
-
- SetPortWindowPort(mWindow);
-
- TextFont(mFontNum);
- TextSize(mPointSize);
-
- RGBBackColor(&mBackColor);
- EraseRect(&kBigRect);
-
- Rect area;
- for (int y = 0; y < mLines.size(); ++y)
- {
- area.top = y*mCellHeight;
- area.bottom = area.top + mCellHeight;
- area.left = 0;
- area.right = area.left + mCellWidth;
-
- const Line& line = mLines[y];
- ASSERT(line.size() == kTermWidth);
-
- for (int x = 0; x < line.size(); ++x)
- {
- const SCell& cell = line[x];
-
- this->DoDrawCell(area, cell);
-
- if (x == mCursor.h && y == mCursor.v && mShowCursor)
- {
- ::RGBForeColor(&kWhite);
- ::MoveTo(area.left + 1, area.top + mAscent);
- ::Line(area.right - area.left - 2, 0);
- }
-
- area.left += mCellWidth;
- area.right += mCellWidth;
- }
- }
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoSetChar
-//
-//---------------------------------------------------------------
-void CApplication::DoSetChar(unsigned char ch)
-{
- ASSERT(mCursor.h < kTermWidth);
- ASSERT(mCursor.v < kTermHeight);
- ASSERT(mCursor.h >= 0);
- ASSERT(mCursor.v >= 0);
-
- int x = mCursor.h;
-
- Line& line = mLines[mCursor.v];
- ASSERT(line.size() == kTermWidth);
-
- SCell& cell = line[x++];
- cell.ch = ch;
- cell.color = mForeColor;
-
- Rect area;
- area.top = mCursor.v * mCellHeight;
- area.bottom = area.top + mCellHeight;
- area.left = mCursor.h * mCellWidth;
- area.right = area.left + mCellWidth;
-
- (void) InvalWindowRect(mWindow, &kBigRect);
-
- if (x >= kTermWidth)
- {
- if (++mCursor.v >= kTermHeight)
- {
- mCursor.v = kTermHeight - 1;
- mCursor.h = kTermWidth - 1;
- this->DoScroll();
- }
- x = 0;
- }
-
- mCursor.h = x;
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoScroll
-//
-//---------------------------------------------------------------
-void CApplication::DoScroll()
-{
- mLines.erase(mLines.begin());
-
- mLines.push_back(Line());
- mLines.back().resize(kTermWidth);
-
- (void) InvalWindowRect(mWindow, &kBigRect);
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoSetFont
-//
-//---------------------------------------------------------------
-void CApplication::DoSetFont(const unsigned char* name, int size)
-{
- ASSERT(name != NULL);
- ASSERT(size > 0);
-
- short fontNum;
- GetFNum(name, &fontNum);
-
- if (fontNum != mFontNum || size != mPointSize)
- {
- BlockMoveData(name, mFontName, name[0] + 1);
-
- mFontNum = fontNum;
- mPointSize = size;
-
- SetPortWindowPort(mWindow);
- TextFont(mFontNum);
- TextSize(mPointSize);
-
- FontInfo info;
- GetFontInfo(&info);
-
- mCellHeight = info.ascent + info.descent;
- mAscent = info.ascent;
-
- short width = StringWidth("\pMMMMM"); // widMax is usually much too wide so we'll compute this ourselves...
- mCellWidth = width/5 + 1;
-
- Rect bounds;
- bounds.top = 0;
- bounds.left = 0;
- bounds.bottom = mCellHeight * kTermHeight;
- bounds.right = mCellWidth * kTermWidth;
- SizeWindow(mWindow, bounds.right, bounds.bottom, false);
-
- (void) InvalWindowRect(mWindow, &kBigRect);
- }
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoWindowEvent [static]
-//
-//---------------------------------------------------------------
-pascal OSStatus CApplication::DoWindowEvent(EventHandlerCallRef handler, EventRef event, void* refCon)
-{
- OSStatus err = noErr;
- CApplication* thisPtr = static_cast<CApplication*>(refCon);
-
- try
- {
- WindowRef window = NULL;
- (void) GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(window), NULL, &window);
- ASSERT(window == thisPtr->mWindow);
-
- UInt32 kind = GetEventKind(event);
- switch (kind) {
-// case kEventWindowBoundsChanging:
-// thisPtr->DoConstrainWindow(event);
-// break;
-
- case kEventWindowDrawContent:
- thisPtr->DoRender();
- break;
-
-// case kEventWindowGetIdealSize:
-// case kEventWindowGetMaximumSize:
-// {
-// ::Point maxSize = thisPtr->OnGetMaxSize();
-// SetEventParameter(event, kEventParamDimensions, &maxSize);
-// }
-// break;
-
-// case kEventWindowGetMinimumSize:
-// {
-// ::Point minSize = thisPtr->OnGetMinSize();
-// SetEventParameter(event, kEventParamDimensions, &minSize);
-// }
-// break;
-
- default:
- err = eventNotHandledErr;
- }
- }
- catch (const std::exception& e)
- {
- DEBUGSTR((std::string("Couldn't complete the operation (") + e.what() + ").").c_str());
- err = eventNotHandledErr;
- }
- catch (...)
- {
- DEBUGSTR("Couldn't complete the operation.");
- err = eventNotHandledErr;
- }
-
- return err;
-}
-
-
-//---------------------------------------------------------------
-//
-// CApplication::DoWritePrefs , , mWindow->location
-//
-//---------------------------------------------------------------
-void CApplication::DoWritePrefs()
-{
- MacString appID("Crawl4");
-
- // mFontName
- MacString name("font_name");
- MacString data(mFontName);
- CFPreferencesSetAppValue(name, data, appID);
-
- // mPointSize
- name = MacString("font_size");
- data = MacString(mPointSize);
- CFPreferencesSetAppValue(name, data, appID);
-
- // window location
- Rect bounds;
- OSStatus err = GetWindowBounds(mWindow, kWindowStructureRgn, &bounds);
- if (err == noErr)
- {
- name = MacString("window_x");
- data = MacString(bounds.left);
- CFPreferencesSetAppValue(name, data, appID);
-
- name = MacString("window_y");
- data = MacString(bounds.top);
- CFPreferencesSetAppValue(name, data, appID);
- }
-
- // flush
- VERIFY(CFPreferencesAppSynchronize(appID));
-}
-
-#if __MWERKS__
-#pragma mark -
-#endif
-
-// ========================================================================
-// Non-ANSI Functions
-// ========================================================================
-
-//---------------------------------------------------------------
-//
-// stricmp
-//
-// Case insensitive string comparison (code is from MSL which
-// is why it looks so dorky).
-//
-//---------------------------------------------------------------
-int stricmp(const char* lhs, const char* rhs)
-{
- ASSERT(lhs != NULL);
- ASSERT(rhs != NULL);
-
- const unsigned char* p1 = (unsigned char*) lhs - 1;
- const unsigned char* p2 = (unsigned char*) rhs - 1;
- unsigned long c1, c2;
-
- while ((c1 = tolower(*++p1)) == (c2 = tolower(*++p2)))
- if (c1 == '\0')
- return (0);
-
- return c1 - c2;
-}
-
-
-//---------------------------------------------------------------
-//
-// strlwr
-//
-// In place conversion to lower case.
-//
-//---------------------------------------------------------------
-char* strlwr(char* str)
-{
- ASSERT(str != NULL);
-
- for (int i = 0; i < strlen(str); ++i)
- str[i] = tolower(str[i]);
-
- return str;
-}
-
-
-//---------------------------------------------------------------
-//
-// itoa
-//
-// Converts an integer to a string (after libunix.cc).
-//
-//---------------------------------------------------------------
-void itoa(int value, char* buffer, int radix)
-{
- ASSERT(buffer != NULL);
- ASSERT(radix == 10 || radix == 2);
-
- if (radix == 10)
- sprintf(buffer, "%i", value);
-
- if (radix == 2)
- { /* int to "binary string" */
- unsigned int bitmask = 32768;
- int ctr = 0;
- int startflag = 0;
-
- while (bitmask)
- {
- if (value & bitmask)
- {
- startflag = 1;
- sprintf(buffer + ctr, "1");
-
- }
- else
- {
- if (startflag)
- sprintf(buffer + ctr, "0");
- }
-
- bitmask = bitmask >> 1;
- if (startflag)
- ctr++;
- }
-
- if (!startflag) /* Special case if value == 0 */
- sprintf((buffer + ctr++), "0");
- buffer[ctr] = (char) NULL;
- }
-}
-
-#if __MWERKS__
-#pragma mark -
-#endif
-
-// ========================================================================
-// Curses(?) Functions
-// ========================================================================
-
-//---------------------------------------------------------------
-//
-// window
-//
-//---------------------------------------------------------------
-void window(int x, int y, int lx, int ly)
-{
- ASSERT(lx == kTermWidth); // window size is hard-coded
- ASSERT(ly == kTermHeight);
-
- gotoxy(x, y);
-}
-
-
-//---------------------------------------------------------------
-//
-// clrscr
-//
-//---------------------------------------------------------------
-void clrscr()
-{
- ASSERT(sApp != NULL);
-
- sApp->Clear();
-}
-
-
-//---------------------------------------------------------------
-//
-// textcolor
-//
-//---------------------------------------------------------------
-void textcolor(int c)
-{
- ASSERT(c >= 0);
- ASSERT(c < 16);
- ASSERT(sApp != NULL);
-
- RGBColor color = ConvertColor(c);
- sApp->SetForeColor(color);
-}
-
-
-//---------------------------------------------------------------
-//
-// textbackground
-//
-//---------------------------------------------------------------
-void textbackground(int c)
-{
- ASSERT(c >= 0);
- ASSERT(c < 16);
- ASSERT(sApp != NULL);
-
- RGBColor color = ConvertColor(c);
- sApp->SetBackColor(color);
-}
-
-
-//---------------------------------------------------------------
-//
-// gotoxy
-//
-//---------------------------------------------------------------
-void gotoxy(int x, int y)
-{
- ASSERT(x >= 1);
- ASSERT(y >= 1);
- ASSERT(sApp != NULL);
-
- sApp->SetCursor(x - 1, y - 1);
-}
-
-
-//---------------------------------------------------------------
-//
-// wherex
-//
-//---------------------------------------------------------------
-int wherex()
-{
- ASSERT(sApp != NULL);
-
- Point pos = sApp->GetCursor();
-
- return pos.h + 1;
-}
-
-
-//---------------------------------------------------------------
-//
-// wherey
-//
-//---------------------------------------------------------------
-int wherey()
-{
- ASSERT(sApp != NULL);
-
- Point pos = sApp->GetCursor();
-
- return pos.v + 1;
-}
-
-
-//---------------------------------------------------------------
-//
-// putch
-//
-//---------------------------------------------------------------
-void putch(char ch)
-{
- ASSERT(sApp != NULL);
-
- char buffer[2];
-
- buffer[0] = ch;
- buffer[1] = '\0';
-
- sApp->SetChar(ch);
-// sApp->Print(buffer);
-}
-
-
-//---------------------------------------------------------------
-//
-// cprintf
-//
-//---------------------------------------------------------------
-void cprintf(const char* format,...)
-{
- ASSERT(sApp != NULL);
-
- char buffer[2048];
-
- va_list argp;
-
- va_start(argp, format);
- vsprintf(buffer, format, argp);
- va_end(argp);
-
- sApp->Print(buffer);
-}
-
-
-//---------------------------------------------------------------
-//
-// kbhit
-//
-//---------------------------------------------------------------
-int kbhit()
-{
- return sApp->PeekChar();
-}
-
-
-//---------------------------------------------------------------
-//
-// getche
-//
-//---------------------------------------------------------------
-char getche()
-{
- char ch = getch();
-
- if (ch != '\r')
- putch(ch);
-
- return ch;
-}
-
-
-//---------------------------------------------------------------
-//
-// getstr
-//
-//---------------------------------------------------------------
-void getstr(char* buffer, int bufferSize)
-{
- ASSERT(buffer != NULL);
- ASSERT(bufferSize > 1);
-
- int index = 0;
-
- while (index < bufferSize - 1)
- {
- char ch = getche();
-
- if (ch == '\r')
- break;
- else if (ch == '\b' && index > 0)
- --index;
- else if (isprint(ch))
- buffer[index++] = ch;
- }
-
- buffer[index] = '\0';
-}
-
-
-//---------------------------------------------------------------
-//
-// _setcursortype
-//
-//---------------------------------------------------------------
-void _setcursortype(int curstype)
-{
- ASSERT(curstype == _NORMALCURSOR || curstype == _NOCURSOR);
- ASSERT(sApp != NULL);
-
- sApp->ShowCursor(curstype == _NORMALCURSOR);
-}
-
-
-//---------------------------------------------------------------
-//
-// getch
-//
-//---------------------------------------------------------------
-int getch()
-{
- ASSERT(sApp != NULL);
-
- return sApp->GetChar();
-}
-
-#if __MWERKS__
-#pragma mark -
-#endif
-
-// ========================================================================
-// Misc Functions
-// ========================================================================
-
-//---------------------------------------------------------------
-//
-// delay
-//
-//---------------------------------------------------------------
-void delay(int ms)
-{
- ASSERT(ms >= 0);
-
- usleep(1000*ms);
-}
-
-
-//---------------------------------------------------------------
-//
-// init_mac
-//
-//---------------------------------------------------------------
-void init_mac()
-{
- ASSERT(sApp == NULL);
-
- // Read in the color table
- sColors = GetCTable(256);
- if (sColors == NULL)
- {
- WarnUser("Couldn't load the colour table!");
- ExitToShell();
- }
-
- // Create the application object
- sApp = new CApplication;
-}
-
-
-//---------------------------------------------------------------
-//
-// deinit_mac
-//
-//---------------------------------------------------------------
-void deinit_mac()
-{
- delete sApp;
- sApp = NULL;
-}
-
-
-#endif // macintosh
diff --git a/crawl-ref/source/libmac.h b/crawl-ref/source/libmac.h
deleted file mode 100644
index 8b7e3903d6..0000000000
--- a/crawl-ref/source/libmac.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * File: libmac.h
- * Summary: Mac specific routines used by Crawl.
- * Written by: Jesse Jones
- *
- * Change History (most recent first):
- *
- * <2> 5/25/02 JDJ Updated for Mach-O targets
- * <1> 3/23/99 JDJ Created
- */
-
-#ifndef LIBMAC_H
-#define LIBMAC_H
-
-#if macintosh
-
-#ifdef _BSD_SIZE_T_ // $$$ is there a better way to test for OS X?
- #define OSX 1
-#else
- #define OS9 1
-#endif
-
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if OSX
- #include <unistd.h>
-#endif
-
-#define MAC_NUMBER_OF_LINES 30
-
-// constants
-const int _NORMALCURSOR = 1;
-const int _NOCURSOR = 0;
-
-
-// non-ANSI functions
-int stricmp(const char* lhs, const char* rhs);
-char* strlwr(char* str);
-void itoa(int n, char* buffer, int radix);
-
-#if !OSX
- inline void srandom(unsigned int seed)
- {
- srand(seed);
- }
-
- int open(const char* path, int openFlags, int permissions);
- int open(const char* path, int openFlags, int permissions, int mysteryFlags);
- int close(int desc);
- int read(int desc, void *buffer, unsigned int bytes);
- int write(int desc, const void *buffer, unsigned int bytes);
- int unlink(const char* path);
-#endif
-
-
-// curses(?) functions
-void clrscr();
-void gotoxy(int x, int y);
-void textcolor(int c);
-void cprintf(const char* format,...);
-
-void window(int x, int y, int lx, int ly);
-int wherex();
-int wherey();
-void putch(char c);
-int kbhit();
-
-char getche();
-int getch();
-void getstr(char* buffer, int bufferSize);
-
-void textbackground(int c);
-void _setcursortype(int curstype);
-
-
-// misc functions
-void delay(int ms);
-
-void init_mac();
-void deinit_mac();
-
-
-#endif // macintosh
-#endif // LIBMAC_H
diff --git a/crawl-ref/source/libunix.cc b/crawl-ref/source/libunix.cc
index 72441dfd3d..99605bea5f 100644
--- a/crawl-ref/source/libunix.cc
+++ b/crawl-ref/source/libunix.cc
@@ -63,15 +63,12 @@ static struct termios game_term;
#endif
// Character set variable
-int character_set = CHARACTER_SET;
+int Character_Set = CHARACTER_SET;
// Globals holding current text/backg. colors
short FG_COL = WHITE;
short BG_COL = BLACK;
-// a lookup table to convert keypresses to command enums
-static int key_to_command_table[KEY_MAX];
-
static unsigned int convert_to_curses_attr( int chattr )
{
switch (chattr & CHATTR_ATTRMASK)
@@ -150,10 +147,18 @@ static short translate_colour( short col )
}
}
+void set_altcharset( bool alt_on )
+{
+ Character_Set = ((alt_on) ? A_ALTCHARSET : 0);
+}
-static void setup_colour_pairs( void )
+bool get_altcharset( void )
{
+ return (Character_Set != 0);
+}
+static void setup_colour_pairs( void )
+{
short i, j;
for (i = 0; i < 8; i++)
@@ -192,8 +197,10 @@ static void termio_init()
int getch_ck() {
int c = getch();
switch (c) {
+ // [dshaligram] MacOS ncurses returns 127 for backspace.
+ case 127:
case KEY_BACKSPACE: return CK_BKSP;
- case KEY_DC: return CK_DELETE;
+ case KEY_DC: return CK_DELETE;
case KEY_HOME: return CK_HOME;
case KEY_PPAGE: return CK_PGUP;
case KEY_END: return CK_END;
@@ -206,188 +213,6 @@ int getch_ck() {
}
}
-void init_key_to_command()
-{
- int i;
-
- // initialize to "do nothing"
- for (i = 0; i < KEY_MAX; i++)
- {
- key_to_command_table[i] = CMD_NO_CMD;
- }
-
- // lower case
- key_to_command_table[(int) 'a'] = CMD_USE_ABILITY;
- key_to_command_table[(int) 'b'] = CMD_MOVE_DOWN_LEFT;
- key_to_command_table[(int) 'c'] = CMD_CLOSE_DOOR;
- key_to_command_table[(int) 'd'] = CMD_DROP;
- key_to_command_table[(int) 'e'] = CMD_EAT;
- key_to_command_table[(int) 'f'] = CMD_FIRE;
- key_to_command_table[(int) 'g'] = CMD_PICKUP;
- key_to_command_table[(int) 'h'] = CMD_MOVE_LEFT;
- key_to_command_table[(int) 'i'] = CMD_DISPLAY_INVENTORY;
- key_to_command_table[(int) 'j'] = CMD_MOVE_DOWN;
- key_to_command_table[(int) 'k'] = CMD_MOVE_UP;
- key_to_command_table[(int) 'l'] = CMD_MOVE_RIGHT;
- key_to_command_table[(int) 'm'] = CMD_DISPLAY_SKILLS;
- key_to_command_table[(int) 'n'] = CMD_MOVE_DOWN_RIGHT;
- key_to_command_table[(int) 'o'] = CMD_OPEN_DOOR;
- key_to_command_table[(int) 'p'] = CMD_PRAY;
- key_to_command_table[(int) 'q'] = CMD_QUAFF;
- key_to_command_table[(int) 'r'] = CMD_READ;
- key_to_command_table[(int) 's'] = CMD_SEARCH;
- key_to_command_table[(int) 't'] = CMD_THROW;
- key_to_command_table[(int) 'u'] = CMD_MOVE_UP_RIGHT;
- key_to_command_table[(int) 'v'] = CMD_EXAMINE_OBJECT;
- key_to_command_table[(int) 'w'] = CMD_WIELD_WEAPON;
- key_to_command_table[(int) 'x'] = CMD_LOOK_AROUND;
- key_to_command_table[(int) 'y'] = CMD_MOVE_UP_LEFT;
- key_to_command_table[(int) 'z'] = CMD_ZAP_WAND;
-
- // upper case
- key_to_command_table[(int) 'A'] = CMD_DISPLAY_MUTATIONS;
- key_to_command_table[(int) 'B'] = CMD_RUN_DOWN_LEFT;
- key_to_command_table[(int) 'C'] = CMD_EXPERIENCE_CHECK;
- key_to_command_table[(int) 'D'] = CMD_BUTCHER;
- key_to_command_table[(int) 'E'] = CMD_EVOKE;
- key_to_command_table[(int) 'F'] = CMD_NO_CMD;
- key_to_command_table[(int) 'G'] = CMD_NO_CMD;
- key_to_command_table[(int) 'H'] = CMD_RUN_LEFT;
- key_to_command_table[(int) 'I'] = CMD_OBSOLETE_INVOKE;
- key_to_command_table[(int) 'J'] = CMD_RUN_DOWN;
- key_to_command_table[(int) 'K'] = CMD_RUN_UP;
- key_to_command_table[(int) 'L'] = CMD_RUN_RIGHT;
- key_to_command_table[(int) 'M'] = CMD_MEMORISE_SPELL;
- key_to_command_table[(int) 'N'] = CMD_RUN_DOWN_RIGHT;
- key_to_command_table[(int) 'O'] = CMD_DISPLAY_OVERMAP;
- key_to_command_table[(int) 'P'] = CMD_WEAR_JEWELLERY;
- key_to_command_table[(int) 'Q'] = CMD_QUIT;
- key_to_command_table[(int) 'R'] = CMD_REMOVE_JEWELLERY;
- key_to_command_table[(int) 'S'] = CMD_SAVE_GAME;
- key_to_command_table[(int) 'T'] = CMD_REMOVE_ARMOUR;
- key_to_command_table[(int) 'U'] = CMD_RUN_UP_RIGHT;
- key_to_command_table[(int) 'V'] = CMD_GET_VERSION;
- key_to_command_table[(int) 'W'] = CMD_WEAR_ARMOUR;
- key_to_command_table[(int) 'X'] = CMD_DISPLAY_MAP;
- key_to_command_table[(int) 'Y'] = CMD_RUN_UP_LEFT;
- key_to_command_table[(int) 'Z'] = CMD_CAST_SPELL;
-
- // control
- key_to_command_table[ (int) CONTROL('A') ] = CMD_TOGGLE_AUTOPICKUP;
- key_to_command_table[ (int) CONTROL('B') ] = CMD_OPEN_DOOR_DOWN_LEFT;
- key_to_command_table[ (int) CONTROL('C') ] = CMD_CLEAR_MAP;
-
-#ifdef ALLOW_DESTROY_ITEM_COMMAND
- key_to_command_table[ (int) CONTROL('D') ] = CMD_DESTROY_ITEM;
-#else
- key_to_command_table[ (int) CONTROL('D') ] = CMD_NO_CMD;
-#endif
-
- key_to_command_table[ (int) CONTROL('E') ] = CMD_FORGET_STASH;
- key_to_command_table[ (int) CONTROL('F') ] = CMD_SEARCH_STASHES;
- key_to_command_table[ (int) CONTROL('G') ] = CMD_INTERLEVEL_TRAVEL;
- key_to_command_table[ (int) CONTROL('H') ] = CMD_OPEN_DOOR_LEFT;
- key_to_command_table[ (int) CONTROL('I') ] = CMD_NO_CMD;
- key_to_command_table[ (int) CONTROL('J') ] = CMD_OPEN_DOOR_DOWN;
- key_to_command_table[ (int) CONTROL('K') ] = CMD_OPEN_DOOR_UP;
- key_to_command_table[ (int) CONTROL('L') ] = CMD_OPEN_DOOR_RIGHT;
- key_to_command_table[ (int) CONTROL('M') ] = CMD_NO_CMD;
- key_to_command_table[ (int) CONTROL('N') ] = CMD_OPEN_DOOR_DOWN_RIGHT;
- key_to_command_table[ (int) CONTROL('O') ] = CMD_EXPLORE;
- key_to_command_table[ (int) CONTROL('P') ] = CMD_REPLAY_MESSAGES;
- key_to_command_table[ (int) CONTROL('Q') ] = CMD_NO_CMD;
- key_to_command_table[ (int) CONTROL('R') ] = CMD_REDRAW_SCREEN;
- key_to_command_table[ (int) CONTROL('S') ] = CMD_MARK_STASH;
- key_to_command_table[ (int) CONTROL('T') ] = CMD_NO_CMD;
- key_to_command_table[ (int) CONTROL('U') ] = CMD_OPEN_DOOR_UP_LEFT;
- key_to_command_table[ (int) CONTROL('V') ] = CMD_NO_CMD;
- key_to_command_table[ (int) CONTROL('W') ] = CMD_FIX_WAYPOINT;
- key_to_command_table[ (int) CONTROL('X') ] = CMD_SAVE_GAME_NOW;
- key_to_command_table[ (int) CONTROL('Y') ] = CMD_OPEN_DOOR_UP_RIGHT;
- key_to_command_table[ (int) CONTROL('Z') ] = CMD_SUSPEND_GAME;
-
- // other printables
- key_to_command_table[(int) '.'] = CMD_MOVE_NOWHERE;
- key_to_command_table[(int) '<'] = CMD_GO_UPSTAIRS;
- key_to_command_table[(int) '>'] = CMD_GO_DOWNSTAIRS;
- key_to_command_table[(int) '@'] = CMD_DISPLAY_CHARACTER_STATUS;
- key_to_command_table[(int) ','] = CMD_PICKUP;
- key_to_command_table[(int) ':'] = CMD_NO_CMD;
- key_to_command_table[(int) ';'] = CMD_INSPECT_FLOOR;
- key_to_command_table[(int) '!'] = CMD_SHOUT;
- key_to_command_table[(int) '^'] = CMD_DISPLAY_RELIGION;
- key_to_command_table[(int) '#'] = CMD_CHARACTER_DUMP;
- key_to_command_table[(int) '='] = CMD_ADJUST_INVENTORY;
- key_to_command_table[(int) '?'] = CMD_DISPLAY_COMMANDS;
- key_to_command_table[(int) '`'] = CMD_MACRO_ADD;
- key_to_command_table[(int) '~'] = CMD_MACRO_SAVE;
- key_to_command_table[(int) '&'] = CMD_WIZARD;
- key_to_command_table[(int) '"'] = CMD_LIST_JEWELLERY;
-
-
- // I'm making this both, because I'm tried of changing it
- // back to '[' (the character that represents armour on the map) -- bwr
- key_to_command_table[(int) '['] = CMD_LIST_ARMOUR;
- key_to_command_table[(int) ']'] = CMD_LIST_ARMOUR;
-
- // This one also ended up backwards this time, so it's also going on
- // both now -- should be ')'... the same character that's used to
- // represent weapons.
- key_to_command_table[(int) ')'] = CMD_LIST_WEAPONS;
- key_to_command_table[(int) '('] = CMD_LIST_WEAPONS;
-
- key_to_command_table[(int) '\\'] = CMD_DISPLAY_KNOWN_OBJECTS;
- key_to_command_table[(int) '\''] = CMD_WEAPON_SWAP;
-
- // digits
- key_to_command_table[(int) '0'] = CMD_NO_CMD;
- key_to_command_table[(int) '1'] = CMD_MOVE_DOWN_LEFT;
- key_to_command_table[(int) '2'] = CMD_MOVE_DOWN;
- key_to_command_table[(int) '3'] = CMD_MOVE_DOWN_RIGHT;
- key_to_command_table[(int) '4'] = CMD_MOVE_LEFT;
- key_to_command_table[(int) '5'] = CMD_REST;
- key_to_command_table[(int) '6'] = CMD_MOVE_RIGHT;
- key_to_command_table[(int) '7'] = CMD_MOVE_UP_LEFT;
- key_to_command_table[(int) '8'] = CMD_MOVE_UP;
- key_to_command_table[(int) '9'] = CMD_MOVE_UP_RIGHT;
-
- // keypad
- key_to_command_table[KEY_A1] = CMD_MOVE_UP_LEFT;
- key_to_command_table[KEY_A3] = CMD_MOVE_UP_RIGHT;
- key_to_command_table[KEY_C1] = CMD_MOVE_DOWN_LEFT;
- key_to_command_table[KEY_C3] = CMD_MOVE_DOWN_RIGHT;
-
- key_to_command_table[KEY_HOME] = CMD_MOVE_UP_LEFT;
- key_to_command_table[KEY_PPAGE] = CMD_MOVE_UP_RIGHT;
- key_to_command_table[KEY_END] = CMD_MOVE_DOWN_LEFT;
- key_to_command_table[KEY_NPAGE] = CMD_MOVE_DOWN_RIGHT;
-
- key_to_command_table[KEY_B2] = CMD_REST;
-
- key_to_command_table[KEY_UP] = CMD_MOVE_UP;
- key_to_command_table[KEY_DOWN] = CMD_MOVE_DOWN;
- key_to_command_table[KEY_LEFT] = CMD_MOVE_LEFT;
- key_to_command_table[KEY_RIGHT] = CMD_MOVE_RIGHT;
-
-
- // other odd things
- // key_to_command_table[ 263 ] = CMD_OPEN_DOOR_LEFT; // backspace
-
- // these are invalid keys, but to help kludge running
- // pass them through unmolested
- key_to_command_table[128] = 128;
- key_to_command_table[(int) '*'] = '*';
-}
-
-int key_to_command(int keyin)
-{
- bool is_userfunction(int key);
-
- if (is_userfunction(keyin))
- return keyin;
- return (key_to_command_table[keyin]);
-}
-
void unixcurses_startup( void )
{
termio_init();
@@ -424,12 +249,7 @@ void unixcurses_startup( void )
start_color();
setup_colour_pairs();
- init_key_to_command();
-
-#ifndef SOLARIS
- // These can cause some display problems under Solaris
scrollok(stdscr, TRUE);
-#endif
}
@@ -575,6 +395,11 @@ int get_number_of_lines_from_curses(void)
return (LINES);
}
+int get_number_of_cols_from_curses(void)
+{
+ return (COLS);
+}
+
void get_input_line_from_curses( char *const buff, int len )
{
echo();
@@ -605,9 +430,15 @@ inline unsigned get_brand(int col)
(col & COLFLAG_ITEM_HEAP)? Options.heap_brand :
(col & COLFLAG_WILLSTAB)? Options.stab_brand :
(col & COLFLAG_MAYSTAB)? Options.may_stab_brand :
+ (col & COLFLAG_REVERSE)? CHATTR_REVERSE :
CHATTR_NORMAL;
}
+void textattr(int col)
+{
+ textcolor(col);
+}
+
void textcolor(int col)
{
short fg, bg;
@@ -660,7 +491,7 @@ void textcolor(int col)
// figure out which colour pair we want
const int pair = (fg == 0 && bg == 0) ? 63 : (bg * 8 + fg);
- attrset( COLOR_PAIR(pair) | flags | character_set );
+ attrset( COLOR_PAIR(pair) | flags | Character_Set );
}
@@ -715,7 +546,7 @@ void textbackground(int col)
// figure out which colour pair we want
const int pair = (fg == 0 && bg == 0) ? 63 : (bg * 8 + fg);
- attrset( COLOR_PAIR(pair) | flags | character_set );
+ attrset( COLOR_PAIR(pair) | flags | Character_Set );
}
diff --git a/crawl-ref/source/libunix.h b/crawl-ref/source/libunix.h
index c416733666..d42454dadc 100644
--- a/crawl-ref/source/libunix.h
+++ b/crawl-ref/source/libunix.h
@@ -17,7 +17,6 @@ int cprintf(const char *format,...);
int gotoxy(int x, int y);
int itoa(int value, char *strptr, int radix);
int kbhit(void);
-int key_to_command(int);
int putch(unsigned char chr);
int stricmp(const char *str1, const char *str2);
int translate_keypad(int keyin);
@@ -28,15 +27,19 @@ void update_screen(void);
void clear_to_end_of_line(void);
void clear_to_end_of_screen(void);
int get_number_of_lines_from_curses(void);
+int get_number_of_cols_from_curses(void);
void get_input_line_from_curses( char *const buff, int len );
void _setcursortype(int curstype);
void delay(unsigned long time);
-void init_key_to_command();
void unixcurses_shutdown(void);
void unixcurses_startup(void);
void textbackground(int bg);
void textcolor(int col);
+void textattr(int col);
+
+void set_altcharset(bool alt_on);
+bool get_altcharset();
#ifndef _LIBUNIX_IMPLEMENTATION
/* Some stuff from curses, to remove compiling warnings.. */
diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc
index 734ae2dc0a..556365968e 100644
--- a/crawl-ref/source/libutil.cc
+++ b/crawl-ref/source/libutil.cc
@@ -13,6 +13,7 @@
#include "AppHdr.h"
#include "defines.h"
+#include "initfile.h"
#include "libutil.h"
#include "externs.h"
#include <stdio.h>
@@ -47,7 +48,7 @@
// the shell can do damage with.
bool shell_safe(const char *file)
{
- int match = strcspn(file, "`$*?|><");
+ int match = strcspn(file, "`$*?|><&\n");
return !(match >= 0 && file[match]);
}
@@ -59,7 +60,7 @@ void play_sound( const char *file )
sndPlaySound(file, SND_ASYNC | SND_NODEFAULT);
#elif defined(SOUND_PLAY_COMMAND)
char command[255];
- command[0] = '\0';
+ command[0] = 0;
if (file && *file && (strlen(file) + strlen(SOUND_PLAY_COMMAND) < 255)
&& shell_safe(file))
{
@@ -69,19 +70,68 @@ void play_sound( const char *file )
#endif
}
+void uppercase(std::string &s)
+{
+ /* yes, this is bad, but std::transform() has its own problems */
+ for (unsigned int i = 0; i < s.size(); ++i)
+ s[i] = toupper(s[i]);
+}
+
+void lowercase(std::string &s)
+{
+ for (unsigned int i = 0; i < s.size(); ++i)
+ s[i] = tolower(s[i]);
+}
+
+std::string replace_all(std::string s,
+ const std::string &tofind,
+ const std::string &replacement)
+{
+ std::string::size_type start = 0;
+ std::string::size_type found;
+
+ while ((found = s.find_first_of(tofind, start)) != std::string::npos)
+ {
+ s.replace( found, tofind.length(), replacement );
+ start = found + replacement.length();
+ }
+
+ return (s);
+}
+
+int count_occurrences(const std::string &text, const std::string &s)
+{
+ int nfound = 0;
+ std::string::size_type pos = 0;
+
+ while ((pos = text.find(s, pos)) != std::string::npos)
+ {
+ ++nfound;
+ pos += s.length();
+ }
+
+ return (nfound);
+}
+
void get_input_line( char *const buff, int len )
{
- buff[0] = '\0'; // just in case
+ buff[0] = 0; // just in case
#if defined(UNIX)
get_input_line_from_curses( buff, len ); // implemented in libunix.cc
-#elif defined(MAC) || defined(WIN32CONSOLE)
- getstr( buff, len ); // implemented in libmac.cc
+#elif defined(WIN32CONSOLE)
+ getstr( buff, len );
#else
+
+ // [dshaligram] Turn on the cursor for DOS.
+#ifdef DOS
+ _setcursortype(_NORMALCURSOR);
+#endif
+
fgets( buff, len, stdin ); // much safer than gets()
#endif
- buff[ len - 1 ] = '\0'; // just in case
+ buff[ len - 1 ] = 0; // just in case
// Removing white space from the end in order to get rid of any
// newlines or carriage returns that any of the above might have
@@ -92,17 +142,20 @@ void get_input_line( char *const buff, int len )
for (i = end - 1; i >= 0; i++)
{
if (isspace( buff[i] ))
- buff[i] = '\0';
+ buff[i] = 0;
else
break;
}
}
#ifdef DOS
-static int getch_ck() {
+static int getch_ck()
+{
int c = getch();
- if (!c) {
- switch (c = getch()) {
+ if (!c)
+ {
+ switch (c = getch())
+ {
case 'O': return CK_END;
case 'P': return CK_DOWN;
case 'I': return CK_PGUP;
@@ -128,8 +181,9 @@ static int getch_ck() {
// Hacky wrapper around getch() that returns CK_ codes for keys
// we want to use in cancelable_get_line() and menus.
-int c_getch() {
-#if defined(DOS) || defined(LINUX) || defined(WIN32CONSOLE)
+int c_getch()
+{
+#if defined(DOS) || defined(UNIX) || defined(WIN32CONSOLE)
return getch_ck();
#else
return getch();
@@ -144,7 +198,8 @@ int wrapcprintf( int wrapcol, const char *s, ... )
va_start(args, s);
// XXX: If snprintf isn't available, vsnprintf probably isn't, either.
- int len = vsnprintf(buf, sizeof buf, s, args), olen = len;
+ int len = vsnprintf(buf, sizeof buf, s, args);
+ int olen = len;
va_end(args);
char *run = buf;
@@ -157,7 +212,8 @@ int wrapcprintf( int wrapcol, const char *s, ... )
int avail = wrapcol - x + 1;
int c = 0;
- if (len > avail) {
+ if (len > avail)
+ {
c = run[avail];
run[avail] = 0;
}
@@ -173,195 +229,49 @@ int wrapcprintf( int wrapcol, const char *s, ... )
return (olen);
}
-#define WX(x) ( ((x) - 1) % maxcol + 1 )
-#define WY(x,y) ( (y) + ((x) - 1) / maxcol )
-#define WC(x,y) WX(x), WY(x,y)
-#define GOTOXY(x,y) gotoxy( WC(x,y) )
-bool cancelable_get_line( char *buf, int len, int maxcol,
- input_history *mh )
+int cancelable_get_line( char *buf, int len, int maxcol,
+ input_history *mh, int (*keyproc)(int &ch) )
{
- if (len <= 0) return false;
-
- buf[0] = 0;
-
- char *cur = buf;
- int start = wherex(), line = wherey();
- int length = 0, pos = 0;
+ line_reader reader(buf, len, maxcol);
+ reader.set_input_history(mh);
+ reader.set_keyproc(keyproc);
- if (mh)
- mh->go_end();
-
- for ( ; ; ) {
- int ch = c_getch();
-
- switch (ch) {
- case CK_ESCAPE:
- return false;
- case CK_UP:
- case CK_DOWN:
- {
- if (!mh)
- break;
- const std::string *text = ch == CK_UP? mh->prev() : mh->next();
- if (text)
- {
- int olen = length;
- length = text->length();
- if (length >= len)
- length = len - 1;
- memcpy(buf, text->c_str(), length);
- buf[length] = 0;
- GOTOXY(start, line);
-
- int clear = length < olen? olen - length : 0;
- wrapcprintf(maxcol, "%s%*s", buf, clear, "");
-
- pos = length;
- cur = buf + pos;
- GOTOXY(start + pos, line);
- }
- break;
- }
- case CK_ENTER:
- buf[length] = 0;
- if (mh && length)
- mh->new_input(buf);
- return true;
- case CONTROL('K'):
- {
- // Kill to end of line
- int erase = length - pos;
- if (erase)
- {
- length = pos;
- buf[length] = 0;
- wrapcprintf( maxcol, "%*s", erase, "" );
- GOTOXY(start + pos, line);
- }
- break;
- }
- case CK_DELETE:
- if (pos < length) {
- char *c = cur;
- while (c - buf < length) {
- *c = c[1];
- c++;
- }
- --length;
-
- GOTOXY( start + pos, line );
- buf[length] = 0;
- wrapcprintf( maxcol, "%s ", cur );
- GOTOXY( start + pos, line );
- }
- break;
- case CK_BKSP:
- if (pos) {
- --cur;
- char *c = cur;
- while (*c) {
- *c = c[1];
- c++;
- }
- --pos;
- --length;
-
- GOTOXY( start + pos, line );
- buf[length] = 0;
- wrapcprintf( maxcol, "%s ", cur );
- GOTOXY( start + pos, line );
- }
- break;
- case CK_LEFT:
- if (pos) {
- --pos;
- cur = buf + pos;
- GOTOXY( start + pos, line );
- }
- break;
- case CK_RIGHT:
- if (pos < length) {
- ++pos;
- cur = buf + pos;
- GOTOXY( start + pos, line );
- }
- break;
- case CK_HOME:
- case CONTROL('A'):
- pos = 0;
- cur = buf + pos;
- GOTOXY( start + pos, line );
- break;
- case CK_END:
- case CONTROL('E'):
- pos = length;
- cur = buf + pos;
- GOTOXY( start + pos, line );
- break;
- default:
- if (isprint(ch) && length < len - 1) {
- if (pos < length) {
- char *c = buf + length - 1;
- while (c >= cur) {
- c[1] = *c;
- c--;
- }
- }
- *cur++ = (char) ch;
- ++length;
- ++pos;
- putch(ch);
- if (pos < length) {
- buf[length] = 0;
- wrapcprintf( maxcol, "%s", cur );
- }
- GOTOXY(start + pos, line);
- }
- break;
- }
- }
+ return reader.read_line();
}
-#undef GOTOXY
-#undef WC
-#undef WX
-#undef WY
// also used with macros
std::string & trim_string( std::string &str )
{
- // OK, this is really annoying. Borland C++ seems to define
- // basic_string::erase to take iterators, and basic_string::remove
- // to take size_t or integer. This is ass-backwards compared to
- // nearly all other C++ compilers. Crap. (GDL)
- //
- // Borland 5.5 does this correctly now... leaving the old code
- // around for now in case anyone needs it. -- bwr
-// #ifdef __BCPLUSPLUS__
-// str.remove( 0, str.find_first_not_of( " \t\n\r" ) );
-// str.remove( str.find_last_not_of( " \t\n\r" ) + 1 );
-// #else
str.erase( 0, str.find_first_not_of( " \t\n\r" ) );
str.erase( str.find_last_not_of( " \t\n\r" ) + 1 );
-// #endif
return (str);
}
-std::vector<std::string> split_string(const char *sep, std::string s)
+std::vector<std::string> split_string(
+ const char *sep,
+ std::string s,
+ bool trim_segments,
+ bool accept_empty_segments)
{
std::vector<std::string> segments;
+ int separator_length = strlen(sep);
std::string::size_type pos;
- while ((pos = s.find(sep, 0)) != std::string::npos) {
- if (pos > 0)
+ while ((pos = s.find(sep, 0)) != std::string::npos)
+ {
+ if (pos > 0 || accept_empty_segments)
segments.push_back(s.substr(0, pos));
- s.erase(0, pos + 1);
+ s.erase(0, pos + separator_length);
}
if (s.length() > 0)
segments.push_back(s);
- for (int i = 0, count = segments.size(); i < count; ++i)
- trim_string(segments[i]);
+ if (trim_segments)
+ {
+ for (int i = 0, count = segments.size(); i < count; ++i)
+ trim_string(segments[i]);
+ }
return segments;
}
@@ -399,16 +309,23 @@ int snprintf( char *str, size_t size, const char *format, ... )
va_list argp;
va_start( argp, format );
- char buff[ 10 * size ]; // hopefully enough
+ char *buff = new char [ 10 * size ]; // hopefully enough
+ if (!buff)
+ {
+ fprintf(stderr, "Out of memory\n");
+ exit(1);
+ }
vsprintf( buff, format, argp );
strncpy( str, buff, size );
- str[ size - 1 ] = '\0';
+ str[ size - 1 ] = 0;
int ret = strlen( str );
if ((unsigned int) ret == size - 1 && strlen( buff ) >= size)
ret = -1;
+ delete [] buff;
+
va_end( argp );
return (ret);
@@ -419,7 +336,8 @@ int snprintf( char *str, size_t size, const char *format, ... )
///////////////////////////////////////////////////////////////////////
// Pattern matching
-inline int pm_lower(int ch, bool icase) {
+inline int pm_lower(int ch, bool icase)
+{
return icase? tolower(ch) : ch;
}
@@ -459,7 +377,8 @@ static bool glob_match( const char *pattern, const char *text, bool icase )
////////////////////////////////////////////////////////////////////
// Perl Compatible Regular Expressions
-void *compile_pattern(const char *pattern, bool icase) {
+void *compile_pattern(const char *pattern, bool icase)
+{
const char *error;
int erroffset;
int flags = icase? PCRE_CASELESS : 0;
@@ -470,7 +389,8 @@ void *compile_pattern(const char *pattern, bool icase) {
NULL);
}
-void free_compiled_pattern(void *cp) {
+void free_compiled_pattern(void *cp)
+{
if (cp)
pcre_free(cp);
}
@@ -494,7 +414,8 @@ bool pattern_match(void *compiled_pattern, const char *text, int length)
////////////////////////////////////////////////////////////////////
// POSIX regular expressions
-void *compile_pattern(const char *pattern, bool icase) {
+void *compile_pattern(const char *pattern, bool icase)
+{
regex_t *re = new regex_t;
if (!re)
return NULL;
@@ -504,15 +425,18 @@ void *compile_pattern(const char *pattern, bool icase) {
flags |= REG_ICASE;
int rc = regcomp(re, pattern, flags);
// Nonzero return code == failure
- if (rc) {
+ if (rc)
+ {
delete re;
return NULL;
}
return re;
}
-void free_compiled_pattern(void *cp) {
- if (cp) {
+void free_compiled_pattern(void *cp)
+{
+ if (cp)
+ {
regex_t *re = static_cast<regex_t *>( cp );
regfree(re);
delete re;
@@ -541,7 +465,8 @@ void *compile_pattern(const char *pattern, bool icase)
// If we're using simple globs, we need to box the pattern with '*'
std::string s = std::string("*") + pattern + "*";
glob_info *gi = new glob_info;
- if (gi) {
+ if (gi)
+ {
gi->s = s;
gi->ignore_case = icase;
}
@@ -563,113 +488,6 @@ bool pattern_match(void *compiled_pattern, const char *text, int length)
#endif
-
-////////////////////////////////////////////////////////////////////
-// formatted_string
-//
-
-formatted_string::formatted_string(const std::string &s)
- : ops()
-{
- ops.push_back( s );
-}
-
-formatted_string::operator std::string() const
-{
- std::string s;
- for (int i = 0, size = ops.size(); i < size; ++i)
- {
- if (ops[i] == FSOP_TEXT)
- s += ops[i].text;
- }
- return s;
-}
-
-inline void cap(int &i, int max)
-{
- if (i < 0 && -i <= max)
- i += max;
- if (i >= max)
- i = max - 1;
- if (i < 0)
- i = 0;
-}
-
-std::string formatted_string::tostring(int s, int e) const
-{
- std::string st;
-
- int size = ops.size();
- cap(s, size);
- cap(e, size);
-
- for (int i = s; i <= e && i < size; ++i)
- {
- if (ops[i] == FSOP_TEXT)
- st += ops[i].text;
- }
- return st;
-}
-
-void formatted_string::display(int s, int e) const
-{
- int size = ops.size();
- if (!size)
- return ;
-
- cap(s, size);
- cap(e, size);
-
- for (int i = s; i <= e && i < size; ++i)
- ops[i].display();
-}
-
-void formatted_string::gotoxy(int x, int y)
-{
- ops.push_back( fs_op(x, y) );
-}
-
-void formatted_string::textcolor(int color)
-{
- ops.push_back(color);
-}
-
-void formatted_string::cprintf(const char *s, ...)
-{
- char buf[1000];
- va_list args;
- va_start(args, s);
- vsnprintf(buf, sizeof buf, s, args);
- va_end(args);
-
- cprintf(std::string(buf));
-}
-
-void formatted_string::cprintf(const std::string &s)
-{
- ops.push_back(s);
-}
-
-void formatted_string::fs_op::display() const
-{
- switch (type)
- {
- case FSOP_CURSOR:
- {
- int cx = (x == -1? wherex() : x);
- int cy = (y == -1? wherey() : y);
- ::gotoxy(cx, cy);
- break;
- }
- case FSOP_COLOUR:
- ::textcolor(x);
- break;
- case FSOP_TEXT:
- ::cprintf("%s", text.c_str());
- break;
- }
-}
-
/////////////////////////////////////////////////////////////
// input_history
//
@@ -728,3 +546,270 @@ void input_history::clear()
history.clear();
go_end();
}
+
+/////////////////////////////////////////////////////////////////////////
+// line_reader
+
+line_reader::line_reader(char *buf, size_t sz, int wrap)
+ : buffer(buf), bufsz(sz), history(NULL), start_x(0),
+ start_y(0), keyfn(NULL), wrapcol(wrap), cur(NULL),
+ length(0), pos(-1)
+{
+}
+
+std::string line_reader::get_text() const
+{
+ return (buffer);
+}
+
+void line_reader::set_input_history(input_history *i)
+{
+ history = i;
+}
+
+void line_reader::set_keyproc(keyproc fn)
+{
+ keyfn = fn;
+}
+
+void line_reader::cursorto(int ncx)
+{
+ int x = (start_x + ncx - 1) % wrapcol + 1;
+ int y = start_y + (start_x + ncx - 1) / wrapcol;
+ ::gotoxy(x, y);
+}
+
+int line_reader::read_line(bool clear_previous)
+{
+ if (bufsz <= 0) return false;
+
+ cursor_control coff(true);
+
+ if (clear_previous)
+ *buffer = 0;
+
+ start_x = wherex();
+ start_y = wherey();
+
+ length = strlen(buffer);
+
+ // Remember the previous cursor position, if valid.
+ if (pos < 0 || pos > length)
+ pos = length;
+
+ cur = buffer + pos;
+
+ if (length)
+ wrapcprintf(wrapcol, "%s", buffer);
+
+ if (pos != length)
+ cursorto(pos);
+
+ if (history)
+ history->go_end();
+
+ for ( ; ; )
+ {
+ int ch = c_getch();
+
+ if (keyfn)
+ {
+ int whattodo = (*keyfn)(ch);
+ if (whattodo == 0)
+ {
+ buffer[length] = 0;
+ if (history && length)
+ history->new_input(buffer);
+ return (0);
+ }
+ else if (whattodo == -1)
+ {
+ buffer[length] = 0;
+ return (ch);
+ }
+ }
+
+ int ret = process_key(ch);
+ if (ret != -1)
+ return (ret);
+ }
+}
+
+void line_reader::backspace()
+{
+ if (pos)
+ {
+ --cur;
+ char *c = cur;
+ while (*c)
+ {
+ *c = c[1];
+ c++;
+ }
+ --pos;
+ --length;
+
+ cursorto(pos);
+ buffer[length] = 0;
+ wrapcprintf( wrapcol, "%s ", cur );
+ cursorto(pos);
+ }
+}
+
+bool line_reader::is_wordchar(int c)
+{
+ return isalnum(c) || c == '_' || c == '-';
+}
+
+void line_reader::killword()
+{
+ if (!pos || cur == buffer)
+ return;
+
+ bool foundwc = false;
+ while (pos)
+ {
+ if (is_wordchar(cur[-1]))
+ foundwc = true;
+ else if (foundwc)
+ break;
+
+ backspace();
+ }
+}
+
+int line_reader::process_key(int ch)
+{
+ switch (ch)
+ {
+ case CK_ESCAPE:
+ return (ch);
+ case CK_UP:
+ case CK_DOWN:
+ {
+ if (!history)
+ break;
+
+ const std::string *text =
+ ch == CK_UP? history->prev() : history->next();
+
+ if (text)
+ {
+ int olen = length;
+ length = text->length();
+ if (length >= (int) bufsz)
+ length = bufsz - 1;
+ memcpy(buffer, text->c_str(), length);
+ buffer[length] = 0;
+ cursorto(0);
+
+ int clear = length < olen? olen - length : 0;
+ wrapcprintf(wrapcol, "%s%*s", buffer, clear, "");
+
+ pos = length;
+ cur = buffer + pos;
+ cursorto(pos);
+ }
+ break;
+ }
+ case CK_ENTER:
+ buffer[length] = 0;
+ if (history && length)
+ history->new_input(buffer);
+ return (0);
+
+ case CONTROL('K'):
+ {
+ // Kill to end of line
+ int erase = length - pos;
+ if (erase)
+ {
+ length = pos;
+ buffer[length] = 0;
+ wrapcprintf( wrapcol, "%*s", erase, "" );
+ cursorto(pos);
+ }
+ break;
+ }
+ case CK_DELETE:
+ if (pos < length)
+ {
+ char *c = cur;
+ while (c - buffer < length)
+ {
+ *c = c[1];
+ c++;
+ }
+ --length;
+
+ cursorto(pos);
+ buffer[length] = 0;
+ wrapcprintf( wrapcol, "%s ", cur );
+ cursorto(pos);
+ }
+ break;
+
+ case CK_BKSP:
+ backspace();
+ break;
+
+ case CONTROL('W'):
+ killword();
+ break;
+
+ case CK_LEFT:
+ if (pos)
+ {
+ --pos;
+ cur = buffer + pos;
+ cursorto(pos);
+ }
+ break;
+ case CK_RIGHT:
+ if (pos < length)
+ {
+ ++pos;
+ cur = buffer + pos;
+ cursorto(pos);
+ }
+ break;
+ case CK_HOME:
+ case CONTROL('A'):
+ pos = 0;
+ cur = buffer + pos;
+ cursorto(pos);
+ break;
+ case CK_END:
+ case CONTROL('E'):
+ pos = length;
+ cur = buffer + pos;
+ cursorto(pos);
+ break;
+ default:
+ if (isprint(ch) && length < (int) bufsz - 1)
+ {
+ if (pos < length)
+ {
+ char *c = buffer + length - 1;
+ while (c >= cur)
+ {
+ c[1] = *c;
+ c--;
+ }
+ }
+ *cur++ = (char) ch;
+ ++length;
+ ++pos;
+ putch(ch);
+ if (pos < length)
+ {
+ buffer[length] = 0;
+ wrapcprintf( wrapcol, "%s", cur );
+ }
+ cursorto(pos);
+ }
+ break;
+ }
+
+ return (-1);
+}
diff --git a/crawl-ref/source/libutil.h b/crawl-ref/source/libutil.h
index 807d3f25a2..d05ef53bd4 100644
--- a/crawl-ref/source/libutil.h
+++ b/crawl-ref/source/libutil.h
@@ -2,6 +2,8 @@
* File: libutil.h
* Summary: System indepentant functions
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> 2001/Nov/01 BWR Created
@@ -11,9 +13,19 @@
#ifndef LIBUTIL_H
#define LIBUTIL_H
+#include "defines.h"
#include <string>
#include <vector>
+void lowercase(std::string &s);
+void uppercase(std::string &s);
+
+std::string replace_all(std::string s,
+ const std::string &tofind,
+ const std::string &replacement);
+
+int count_occurrences(const std::string &text, const std::string &searchfor);
+
// getch() that returns a consistent set of values for all platforms.
int c_getch();
@@ -28,12 +40,27 @@ void get_input_line( char *const buff, int len );
class input_history;
-// Returns true if user pressed Enter, false if user hit Escape.
-bool cancelable_get_line( char *buf, int len, int wrapcol = 80,
- input_history *mh = NULL );
+// In view.cc, declared here for default argument to cancelable_get_line()
+int get_number_of_cols(void);
+
+// Returns zero if user entered text and pressed Enter, otherwise returns the
+// key pressed that caused the exit, usually Escape.
+//
+// If keyproc is provided, it must return 1 for normal processing, 0 to exit
+// normally (pretend the user pressed Enter), or -1 to exit as if the user
+// pressed Escape
+int cancelable_get_line( char *buf,
+ int len,
+ int wrapcol = get_number_of_cols(),
+ input_history *mh = NULL,
+ int (*keyproc)(int &c) = NULL );
std::string & trim_string( std::string &str );
-std::vector<std::string> split_string(const char *sep, std::string s);
+std::vector<std::string> split_string(
+ const char *sep,
+ std::string s,
+ bool trim = true,
+ bool accept_empties = false);
#ifdef NEED_USLEEP
void usleep( unsigned long time );
@@ -48,7 +75,7 @@ enum KEYS
{
CK_ENTER = '\r',
CK_BKSP = 8,
- CK_ESCAPE = '\x1b',
+ CK_ESCAPE = ESCAPE,
// 128 is off-limits because it's the code that's used when running
CK_DELETE = 129,
@@ -97,6 +124,57 @@ enum KEYS
CK_CTRL_PGDN
};
+class cursor_control
+{
+public:
+ cursor_control(bool cs) : cstate(cs) {
+ _setcursortype(cs? _NORMALCURSOR : _NOCURSOR);
+ }
+ ~cursor_control() {
+ _setcursortype(cstate? _NOCURSOR : _NORMALCURSOR);
+ }
+private:
+ bool cstate;
+};
+
+// Reads lines of text; used internally by cancelable_get_line.
+class line_reader
+{
+public:
+ line_reader(char *buffer, size_t bufsz,
+ int wrap_col = get_number_of_cols());
+
+ typedef int (*keyproc)(int &key);
+
+ int read_line(bool clear_previous = true);
+
+ std::string get_text() const;
+
+ void set_input_history(input_history *ih);
+ void set_keyproc(keyproc fn);
+
+protected:
+ void cursorto(int newcpos);
+ int process_key(int ch);
+ void backspace();
+ void killword();
+
+ bool is_wordchar(int c);
+
+private:
+ char *buffer;
+ size_t bufsz;
+ input_history *history;
+ int start_x, start_y;
+ keyproc keyfn;
+ int wrapcol;
+
+ // These are subject to change during editing.
+ char *cur;
+ int length;
+ int pos;
+};
+
class base_pattern
{
public:
@@ -117,12 +195,13 @@ public:
text_pattern()
: pattern(), compiled_pattern(NULL),
- isvalid(false), ignore_case(false)
+ isvalid(false), ignore_case(false)
{
}
text_pattern(const text_pattern &tp)
- : pattern(tp.pattern),
+ : base_pattern(tp),
+ pattern(tp.pattern),
compiled_pattern(NULL),
isvalid(tp.isvalid),
ignore_case(tp.ignore_case)
diff --git a/crawl-ref/source/libw32c.cc b/crawl-ref/source/libw32c.cc
index 8426b82b53..60062c36ea 100644
--- a/crawl-ref/source/libw32c.cc
+++ b/crawl-ref/source/libw32c.cc
@@ -3,6 +3,8 @@
* Summary: Functions for windows32 console mode support
* Written by: Gordon Lipford
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <2> 8 Mar 2001 GDL Rewrite to use low level IO
@@ -62,10 +64,12 @@
// END -- WINDOWS INCLUDES
+#ifdef __MINGW32__
+#include <signal.h>
+#endif
+
#include <string.h>
-#ifdef __BCPLUSPLUS__
#include <stdio.h>
-#endif
#include "AppHdr.h"
#include "version.h"
#include "defines.h"
@@ -278,8 +282,7 @@ void bFlush(void)
xy.X = cx;
xy.Y = cy;
CLOCKIN
- if (SetConsoleCursorPosition(outbuf, xy) == 0)
- fputs("SetConsoleCursorPosition() failed!", stderr);
+ SetConsoleCursorPosition(outbuf, xy);
CLOCKOUT(2)
}
}
@@ -299,12 +302,12 @@ void setStringInput(bool value)
outmodes = 0;
}
- if ( SetConsoleMode( inbuf, inmodes ) == 0) {
+ if ( SetConsoleMode( inbuf, inmodes ) == 0) {
fputs("Error initialising console input mode.", stderr);
exit(0);
}
- if ( SetConsoleMode( outbuf, outmodes ) == 0) {
+ if ( SetConsoleMode( outbuf, outmodes ) == 0) {
fputs("Error initialising console output mode.", stderr);
exit(0);
}
@@ -327,6 +330,13 @@ static void init_colors(char *windowTitle)
// if not found, quit.
}
+#ifdef __MINGW32__
+static void install_sighandlers()
+{
+ signal(SIGINT, SIG_IGN);
+}
+#endif
+
void init_libw32c(void)
{
inbuf = GetStdHandle( STD_INPUT_HANDLE );
@@ -338,11 +348,15 @@ void init_libw32c(void)
}
GetConsoleTitle( oldTitle, 78 );
- SetConsoleTitle( "Crawl " VERSION );
+ SetConsoleTitle( CRAWL " " VERSION );
+
+#ifdef __MINGW32__
+ install_sighandlers();
+#endif
init_colors(oldTitle);
- // by default, set string input to false: use char-input only
+ // by default, set string input to false: use char-input only
setStringInput( false );
if (SetConsoleMode( outbuf, 0 ) == 0) {
fputs("Error initialising console output mode.", stderr);
@@ -410,8 +424,7 @@ void deinit_libw32c(void)
// only on input.
void _setcursortype(int curstype)
{
- UNUSED( curstype );
- ;
+ _setcursortype_internal(curstype);
}
@@ -423,13 +436,13 @@ void _setcursortype_internal(int curstype)
return;
cci.dwSize = 5;
- cci.bVisible = (bool)curstype;
+ cci.bVisible = curstype? TRUE : FALSE;
current_cursor = curstype;
CLOCKIN
SetConsoleCursorInfo( outbuf, &cci );
CLOCKOUT(1)
- // now, if we just changed from NOCURSOR to CURSOR,
+ // now, if we just changed from NOCURSOR to CURSOR,
// actually move screen cursor
if (current_cursor != _NOCURSOR)
gotoxy(cx+1, cy+1);
@@ -502,6 +515,11 @@ void gotoxy(int x, int y)
}
}
+void textattr(int c)
+{
+ textcolor(c);
+}
+
void textcolor(int c)
{
// change current color used to stamp chars
@@ -584,7 +602,7 @@ void putch(char c)
// translate virtual keys
#define VKEY_MAPPINGS 10
-static int vk_tr[4][VKEY_MAPPINGS] = // virtual key, unmodified, shifted, control
+static int vk_tr[4][VKEY_MAPPINGS] = // virtual key, unmodified, shifted, control
{
{ VK_END, VK_DOWN, VK_NEXT, VK_LEFT, VK_CLEAR, VK_RIGHT, VK_HOME, VK_UP, VK_PRIOR, VK_INSERT },
{ CK_END, CK_DOWN, CK_PGDN, CK_LEFT, CK_CLEAR, CK_RIGHT, CK_HOME, CK_UP, CK_PGUP , CK_INSERT },
@@ -696,9 +714,6 @@ int getch_ck(void)
return repeat_key;
}
- bool oldValue = current_cursor;
- _setcursortype_internal(_NORMALCURSOR);
-
while(1)
{
CLOCKIN
@@ -728,8 +743,6 @@ int getch_ck(void)
// DEBUG
//fprintf(foo, "getch() returning %02x (%c)\n", key, key);
- _setcursortype_internal(oldValue);
-
return key;
}
@@ -801,8 +814,8 @@ int getConsoleString(char *buf, int maxlen)
if (ReadConsole( inbuf, buf, (DWORD)(maxlen-1), &nread, NULL) == 0)
fputs("Error in ReadConsole()!", stderr);
- // terminate string, then strip CRLF, replace with \0
- buf[maxlen-1] = '\0';
+ // terminate string, then strip CRLF, replace with \0
+ buf[maxlen-1] = 0;
for (unsigned i=(nread<3 ? 0 : nread-3); i<nread; i++)
{
if (buf[i] == 0x0A || buf[i] == 0x0D)
diff --git a/crawl-ref/source/libw32c.h b/crawl-ref/source/libw32c.h
index 319efb02d8..3a818a71e9 100644
--- a/crawl-ref/source/libw32c.h
+++ b/crawl-ref/source/libw32c.h
@@ -1,3 +1,7 @@
+/*
+* Modified for Crawl Reference by $Author$ on $Date$
+*/
+
#ifndef LIBW32C_H
#define LIBW32C_H
@@ -21,6 +25,7 @@ void _setcursortype(int curstype);
void clrscr(void);
void gotoxy(int x, int y);
void textcolor(int c);
+void textattr(int c);
void cprintf( const char *format, ... );
// void cprintf(const char *s);
void setStringInput(bool value);
diff --git a/crawl-ref/source/lua/runrest.lua b/crawl-ref/source/lua/runrest.lua
index 6f5536506e..1432223389 100644
--- a/crawl-ref/source/lua/runrest.lua
+++ b/crawl-ref/source/lua/runrest.lua
@@ -32,6 +32,9 @@ chk_interrupt_activity.run = function (iname, cause, extra)
return false
end
+-- run no longer automatically implies rest as of 0.1.3.
+chk_interrupt_activity.rest = chk_interrupt_activity.run
+
function rr_handle_message(cause, extra)
local ch, mess = rr_split_channel(cause)
for _, m in ipairs(g_rr_ignored) do
diff --git a/crawl-ref/source/lua/safechunk.lua b/crawl-ref/source/lua/safechnk.lua
index cd0c9f036d..0fc5fe7c9d 100644
--- a/crawl-ref/source/lua/safechunk.lua
+++ b/crawl-ref/source/lua/safechnk.lua
@@ -22,7 +22,7 @@ function sc_safechunk(rot, race, mon)
end
if rot then
- if race ~= "Kobold" and race ~= "Troll" and not you.gourmand() then
+ if race ~= "Kobold" and race ~= "Troll" then
return false
end
end
diff --git a/crawl-ref/source/lua/stash.lua b/crawl-ref/source/lua/stash.lua
index 461a504cf3..640144743c 100644
--- a/crawl-ref/source/lua/stash.lua
+++ b/crawl-ref/source/lua/stash.lua
@@ -1,6 +1,6 @@
---------------------------------------------------------------------------
-- stash.lua
--- Annotates items for the stash-tracker.
+-- Annotates items for the stash-tracker's search.
--
-- To use this, add this line to your init.txt:
-- lua_file = lua/stash.lua
diff --git a/crawl-ref/source/lua/trapwalk.lua b/crawl-ref/source/lua/trapwalk.lua
new file mode 100644
index 0000000000..511860353c
--- /dev/null
+++ b/crawl-ref/source/lua/trapwalk.lua
@@ -0,0 +1,46 @@
+---------------------------------------------------------------------------
+-- trapwalk.lua: (requires base.lua)
+-- (Thanks to JPEG <erinacea@hotmail.de> for this script.)
+--
+-- Allows travel to cross traps provided you have sufficient HP to survive the
+-- trap.
+--
+-- To use this, add this line to your init.txt:
+-- lua_file = lua/trapwalk.lua
+-- and add
+-- trapwalk_safe_hp = dart:15, needle:25, spear:50
+-- or similar to your init.txt.
+--
+-- What it does:
+--
+-- * Normally autotravel automatically avoids all traps
+-- * This script allows you to customize at which hp what type of trap is
+-- regarded as safe for autotravel
+--
+-- IMPORTANT: trapwalk options must be defined *after* sourcing trapwalk.lua.
+---------------------------------------------------------------------------
+
+-- Travel will cross certain traps if you have more than safe_hp hp.
+
+function ch_cross_trap(trap)
+
+ if not options.trapwalk_safe_hp then
+ return false
+ end
+
+ local opt = options.trapwalk_safe_hp
+
+ local hpstr
+ _, _, hpstr = string.find(opt, trap .. "%s*:%s*(%d+)")
+
+ if not hpstr then
+ return false
+ end
+
+ local safe_hp = tonumber(hpstr)
+ local hp = you.hp()
+
+ -- finally compare current hp with safe limit
+ return hp >= safe_hp
+
+end
diff --git a/crawl-ref/source/machdr.h b/crawl-ref/source/machdr.h
deleted file mode 100644
index 5bad24eab7..0000000000
--- a/crawl-ref/source/machdr.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * File: MacHdr.h
- * Summary: OS specific stuff for inclusion into AppHdr.h.
- * Written by: Jesse Jones
- *
- * Copyright © 1999 Jesse Jones.
- *
- * Change History (most recent first):
- *
- * <1> 5/30/99 JDJ Created.
- */
-#ifndef MACHDR_H
-#define MACHDR_H
-
-#pragma check_header_flags on
-
-
-// ===================================================================================
-// MSL Defines
-// ===================================================================================
-#include <ansi_parms.h>
-
-#ifndef __dest_os
-#define __dest_os __mac_os
-#endif
-
-#ifndef __MSL_LONGLONG_SUPPORT__
-#define __MSL_LONGLONG_SUPPORT__
-#endif
-
-#ifndef MSIPL_DEF_EXPLICIT
-#define MSIPL_DEF_EXPLICIT // prevent explicit from being defined away
-#endif
-
-#if __MWERKS__ >= 0x2000
-#define MSIPL_TEMPL_NEWSPEC 1 // enable null_template
-#endif
-
-
-// ===================================================================================
-// Universal headers
-// ===================================================================================
-#define OLDROUTINENAMES 0
-#define OLDROUTINELOCATIONS 0
-
-#define STRICT_WINDOWS 0
-#define STRICT_CONTROLS 0
-#define STRICT_LISTS 0
-#define STRICT_MENUS 0
-
-#define USE_OLD_INPUT_SPROCKET_LABELS 0
-#define USE_OLD_ISPNEED_STRUCT 0
-
-#if 1
-// #include <ADSP.h>
-// #include <AEObjects.h>
-// #include <AEPackObject.h>
-// #include <AERegistry.h>
-// #include <AEUserTermTypes.h>
-// #include <AIFF.h>
-#include <Aliases.h>
-#include <AppleEvents.h>
-// #include <AppleGuide.h>
-// #include <AppleScript.h>
-// #include <AppleTalk.h>
-// #include <ASDebugging.h>
-// #include <ASRegistry.h>
-#include <Balloons.h>
-// #include <CMApplication.h>
-// #include <CMComponent.h>
-// #include <CodeFragments.h>
-#include <ColorPicker.h>
-// #include <CommResources.h>
-// #include <Components.h>
-#include <ConditionalMacros.h>
-// #include <Connections.h>
-// #include <ConnectionTools.h>
-#include <Controls.h>
-// #include <ControlStrip.h>
-// #include <CRMSerialDevices.h>
-// #include <CTBUtilities.h>
-// #include <CursorCtl.h>
-// #include <CursorDevices.h>
-// #include <DatabaseAccess.h>
-// #include <DeskBus.h>
-#include <Devices.h>
-#include <Dialogs.h>
-// #include <Dictionary.h>
-// #include <DisAsmLookup.h>
-// #include <Disassembler.h>
-#include <DiskInit.h>
-// #include <Disks.h>
-#include <Displays.h>
-#include <Drag.h>
-// #include <Editions.h>
-// #include <ENET.h>
-// #include <EPPC.h>
-// #include <ErrMgr.h>
-#include <Errors.h>
-#include <Events.h>
-// #include <fenv.h>
-#include <Files.h>
-// #include <FileTransfers.h>
-// #include <FileTransferTools.h>
-// #include <FileTypesAndCreators.h>
-#include <Finder.h>
-// #include <FixMath.h>
-#include <Folders.h>
-#include <Fonts.h>
-// #include <fp.h>
-// #include <FragLoad.h>
-// #include <FSM.h>
-#include <Gestalt.h>
-// #include <HyperXCmd.h>
-// #include <Icons.h>
-// #include <ImageCodec.h>
-// #include <ImageCompression.h>
-// #include <IntlResources.h>
-// #include <Language.h>
-// #include <Lists.h>
-#include <LowMem.h>
-// #include <MachineExceptions.h>
-// #include <MacTCP.h>
-// #include <MediaHandlers.h>
-#include <Memory.h>
-#include <Menus.h>
-// #include <MIDI.h>
-#include <MixedMode.h>
-// #include <Movies.h>
-// #include <MoviesFormat.h>
-// #include <Notification.h>
-// #include <OSA.h>
-// #include <OSAComp.h>
-// #include <OSAGeneric.h>
-#include <OSUtils.h>
-#include <Packages.h>
-#include <Palettes.h>
-// #include <PictUtil.h>
-// #include <PictUtils.h>
-#include <PLStringFuncs.h>
-// #include <Power.h>
-// #include <PPCToolbox.h>
-#include <Printing.h>
-#include <Processes.h>
-#include <QDOffscreen.h>
-#include <Quickdraw.h>
-#include <QuickdrawText.h>
-// #include <QuickTimeComponents.h>
-#include <Resources.h>
-// #include <Retrace.h>
-// #include <ROMDefs.h>
-#include <Scrap.h>
-// #include <Script.h>
-// #include <SCSI.h>
-#include <SegLoad.h>
-// #include <Serial.h>
-// #include <ShutDown.h>
-// #include <Slots.h>
-// #include <Sound.h>
-// #include <SoundComponents.h>
-// #include <SoundInput.h>
-// #include <Speech.h>
-#include <StandardFile.h>
-// #include <Start.h>
-#include <Strings.h>
-// #include <Terminals.h>
-// #include <TerminalTools.h>
-#include <TextEdit.h>
-// #include <TextServices.h>
-#include <TextUtils.h>
-// #include <Threads.h>
-// #include <Timer.h>
-#include <ToolUtils.h>
-// #include <Translation.h>
-// #include <TranslationExtensions.h>
-#include <Traps.h>
-// #include <TSMTE.h>
-#include <Types.h>
-// #include <Unmangler.h>
-// #include <Video.h>
-#include <Windows.h>
-// #include <WorldScript.h>
-#endif // PRECOMPILE_SYSTEM_HEADERS
-
-#endif
diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc
index 13838a947c..ed03525f9f 100644
--- a/crawl-ref/source/macro.cc
+++ b/crawl-ref/source/macro.cc
@@ -3,6 +3,8 @@
* Summary: Crude macro-capability
* Written by: Juho Snellman <jsnell@lyseo.edu.ouka.fi>
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <3> 6/25/02 JS Completely rewritten
@@ -553,11 +555,11 @@ int getch_with_command_macros( void )
keyseq keys = getch_mul();
// ... and add them into the buffer (apply keymaps)
macro_buf_add_long( keys );
+
+ // Apply longest matching macro at front of buffer:
+ macro_buf_apply_command_macro();
}
- // Apply longest matching macro at front of buffer:
- macro_buf_apply_command_macro();
-
return (macro_buf_get());
}
@@ -578,8 +580,7 @@ void macro_add_query( void )
KeymapContext keymc = KC_DEFAULT;
mesclr();
- mpr( "Command (m)acro or keymap [(k) default, (x) level-map or "
- "(t)argeting]? ", MSGCH_PROMPT );
+ mpr( "(m)acro, keymap [(k) default, (x) level-map or (t)argeting], (s)ave?", MSGCH_PROMPT );
input = getch();
if (input == 0)
input = getch();
@@ -602,7 +603,13 @@ void macro_add_query( void )
}
else if (input == 'm')
keymap = false;
- else
+ else if (input == 's')
+ {
+ mpr("Saving macros.");
+ macro_save();
+ return;
+ }
+ else
{
mpr( "Aborting." );
return;
diff --git a/crawl-ref/source/macro.h b/crawl-ref/source/macro.h
index dba3bafafe..f56edcf219 100644
--- a/crawl-ref/source/macro.h
+++ b/crawl-ref/source/macro.h
@@ -3,6 +3,8 @@
* Summary: Crude macro-capability
* Written by: Juho Snellman <jsnell@lyseo.edu.ouka.fi>
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <2> 6/25/02 JS Removed old cruft
diff --git a/crawl-ref/source/makefile b/crawl-ref/source/makefile
index 1f7dac1cb0..74adf5d88c 100644
--- a/crawl-ref/source/makefile
+++ b/crawl-ref/source/makefile
@@ -4,19 +4,20 @@
#Makefile chooser. Choose one:
-#MAKEFILE = makefile.lnx
-#MAKEFILE = makefile.sgi
+MAKEFILE = makefile.unix
#MAKEFILE = makefile.dos
-#MAKEFILE = makefile.emx
-#MAKEFILE = makefile.sol
-MAKEFILE = makefile.osx
+#MAKEFILE = makefile.osx
+#MAKEFILE = makefile.mgw
#jmf: number of concurrent jobs -- good value is (#_of_CPUs * 2) + 1
# cuts build time a lot on multi-cpu machines
#OTHER=-j2
all:
- $(MAKE) $(OTHER) -f $(MAKEFILE) EXTRA_FLAGS='-O2 -fno-strength-reduce'
+ $(MAKE) $(OTHER) -f $(MAKEFILE) EXTRA_FLAGS='-O3'
+
+profile:
+ $(MAKE) $(OTHER) -f $(MAKEFILE) EXTRA_FLAGS='-O3 -pg'
noopt:
$(MAKE) $(OTHER) -f $(MAKEFILE)
@@ -36,7 +37,15 @@ wizard:
# DEBUG mode includes WIZARD mode as well as copious debugging input
debug:
- $(MAKE) $(OTHER) -f $(MAKEFILE) debug EXTRA_FLAGS='-g -DFULLDEBUG -DWIZARD'
+ $(MAKE) $(OTHER) -f $(MAKEFILE) DEBUG_CRAWL=y debug EXTRA_FLAGS='-g -DFULLDEBUG -DWIZARD'
+
+# [dshaligram] The individual makefile need not necessarily support
+# package-source; only makefile.unix does at the moment.
+package-source:
+ $(MAKE) -f $(MAKEFILE) package-source
+
+prebuildyacc:
+ $(MAKE) -f $(MAKEFILE) prebuildyacc
# DO NOT DELETE THIS LINE -- $(MAKE) depend depends on it.
diff --git a/crawl-ref/source/makefile.bor b/crawl-ref/source/makefile.bor
deleted file mode 100644
index d90cf636d9..0000000000
--- a/crawl-ref/source/makefile.bor
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# Makefile for Borland C++ 5.5 free commandline tools
-#
-
-!include makefile.obj
-
-GAME = ..\crawl.exe
-
-all : $(GAME)
-
-.PHONY : clean
-.PHONY : debug
-.PHONY : noopt
-.PHONY : install
-.PHONY : wizard
-
-clean :
- $(DEL) *.o
-
-debug :
-
-noopt :
-
-install :
-
-wizard :
-
-#
-# Borland C++ tools
-#
-CC = bcc32
-LINK = ilink32
-DEL = del
-
-#
-# windows defines, including windows version to make sure code runs on
-# all windows systems
-#
-WIN32DEFINES = WIN32CONSOLE;NEED_SPRINTF;WINVER=0x0400;_WIN32_WINNT=0x0400;__BCPLUSPLUS__
-
-#
-# Options
-#
-LINKOPTS = -Tpe -ap -c -x /V4.0
-CFLAGS = -I. -D$(WIN32DEFINES) -4 -a -k- -Oc -OS -Oi -Ov -H- -P -c
-NICEFLAGS = -w-8004
-DEBUGFLAGS = -v -y
-
-$(GAME) : $(OBJECTS) libw32c.o
- $(LINK) $(LINKOPTS) c0x32.obj $?, $(GAME),, import32.lib cw32.lib
-
-.cc.o:
- $(CC) $(CFLAGS) $(NICEFLAGS) -o$*.o $<
diff --git a/crawl-ref/source/makefile.bsd b/crawl-ref/source/makefile.bsd
deleted file mode 100644
index 9e10d1ebf8..0000000000
--- a/crawl-ref/source/makefile.bsd
+++ /dev/null
@@ -1,64 +0,0 @@
-# -*- Makefile -*- for Dungeon Crawl (BSD)
-
-#
-# Modified for Crawl Reference by $Author$ on $Date$
-#
-
-GAME = crawl
-
-# this file contains a list of the libraries.
-# it will make a variable called OBJECTS that contains all the libraries
-include makefile.obj
-
-OBJECTS += libunix.o
-
-CXX = g++
-DELETE = rm -f
-COPY = cp
-OS_TYPE = BSD
-CFLAGS = -Wall -D$(OS_TYPE) $(EXTRA_FLAGS)
-LDFLAGS = -static -L/usr/lib
-MCHMOD = 711
-# INSTALLDIR = /usr/games
-INSTALLDIR = /tmp/CRAWLTEST/testdev
-LIB = -lncurses
-
-INCLUDES = -I/usr/include/ncurses
-
-all: $(GAME)
-
-install: $(GAME)
- $(COPY) $(GAME) ${INSTALLDIR}
- chmod ${MCHMOD} ${INSTALLDIR}/$(GAME)
-
-clean:
- $(DELETE) *.o
-
-distclean:
- $(DELETE) *.o
- $(DELETE) bones.*
- $(DELETE) morgue.txt
- $(DELETE) scores
- $(DELETE) $(GAME)
- $(DELETE) *.sav
- $(DELETE) core
- $(DELETE) *.0*
- $(DELETE) *.lab
-
-
-$(GAME): $(OBJECTS)
- ${CXX} ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(GAME) $(LIB)
- strip $(GAME)
- chmod ${MCHMOD} $(GAME)
-
-debug: $(OBJECTS)
- ${CXX} ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(GAME) $(LIB)
-
-profile: $(OBJECTS)
- ${CXX} -g -p ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(GAME) $(LIB)
-
-.cc.o:
- ${CXX} ${CFLAGS} -c $< ${INCLUDE}
-
-.h.cc:
- touch $@
diff --git a/crawl-ref/source/makefile.dos b/crawl-ref/source/makefile.dos
index 869d6f8745..f8e43f631f 100644
--- a/crawl-ref/source/makefile.dos
+++ b/crawl-ref/source/makefile.dos
@@ -1,4 +1,6 @@
# Make file for Dungeon Crawl (dos)
+#
+# Modified for Crawl Reference by $Author$ on $Date$
# this file contains a list of the libraries.
# it will make a variable called OBJECTS that contains all the libraries
@@ -10,18 +12,107 @@ CXX = gxx
DELETE = del
COPY = copy
OS_TYPE = DOS
-CFLAGS = -D$(OS_TYPE) $(EXTRA_FLAGS)
-LDFLAGS = -Bc:/djgpp/contrib/pdcurs22/lib
-INSTALLDIR = c:\games\crawl
+
+LIB =
+
+# If you don't have flex or bison, set DOYACC to N or empty.
+DOYACC := n
+LEX := flex
+YACC := bison -y
+
+INCLUDES := -Iutil -I.
+
+CFWARN := -Wall -Wwrite-strings -Wshadow -Werror -pedantic
+CFOTHERS := -D$(OS_TYPE) $(EXTRA_FLAGS) -fsigned-char -fstrict-aliasing
+
+CFLAGS := $(INCLUDES) $(CFWARN) $(CFOTHERS)
+YCFLAGS := $(INCLUDES) $(CFOTHERS)
+
+OBJECTS += libdos.o
+
+LDFLAGS =
# LIB = -lcurso -lpano
+UTIL = util/
+
+# DOS brain damage. What to do, what to do.
+YTABC := levcom~1.c
+YTABH := levcom~1.h
+
+ifeq ($(LEX),)
+DOYACC :=
+endif
+
+ifeq ($(YACC),)
+DOYACC :=
+endif
+
+OBJECTS := $(UTIL)levcomp.o $(UTIL)levtab.o $(UTIL)levlex.o $(OBJECTS)
+
+GAME_DEPENDS := $(OBJECTS)
+
+##########################################################################
+
all: $(APPNAME)
-install: $(APPNAME)
- $(COPY) $(APPNAME) ${INSTALLDIR}
+##########################################################################
+# The level compiler
+#
+
+# [dshaligram] A million plagues on djgpp make! It doesn't want to use a
+# generic rule for $(UTIL)%.cc; it always uses the .cc.o: rule instead.
+
+LINC :=
+
+# [ds] If we're using the prebuilt include, we can't copy it around because
+# djgpp copy mangles the name irreparably.
+ifneq ($(DOYACC),y)
+LINC += -I prebuilt
+endif
+
+$(UTIL)levcomp.o: $(UTIL)levcomp.cc
+ $(subst /,\,$(CXX) $(LINC) $(YCFLAGS) -o $@ -c $<)
+
+$(UTIL)levlex.o: $(UTIL)levlex.cc
+ $(subst /,\,$(CXX) $(LINC) $(YCFLAGS) -o $@ -c $<)
+
+$(UTIL)levtab.o: $(UTIL)levtab.cc
+ $(subst /,\,$(CXX) $(LINC) $(YCFLAGS) -o $@ -c $<)
+
+ifeq ($(DOYACC),y)
+
+$(UTIL)levtab.cc: $(UTIL)levcomp.ypp
+ $(subst /,\,cd $(UTIL))
+ $(YACC) -d -b levcomp levcomp.ypp
+ copy $(YTABC) levtab.cc
+ cd ..
+
+# djgpp flex must not have a space between -o and its parameter, or no business
+# will result.
+$(UTIL)levlex.cc: $(UTIL)levcomp.lpp
+ $(subst /,\,cd $(UTIL))
+ $(LEX) -olevlex.cc levcomp.lpp
+ cd ..
+
+else
+
+$(UTIL)levtab.cc: prebuilt/levcom~2.cc
+ $(subst /,\,$(COPY) $< $@)
+
+$(UTIL)levlex.cc: prebuilt/levcom~1.cc
+ $(subst /,\,$(COPY) $< $@)
+
+endif
+
+##########################################################################
clean:
$(DELETE) *.o
+ $(subst /,\,$(DELETE) $(UTIL)*.o)
+ $(subst /,\,$(DELETE) $(UTIL)*.exe)
+ $(subst /,\,$(DELETE) $(UTIL)levcom~1.*)
+ $(subst /,\,$(DELETE) $(UTIL)levtab.*)
+ $(subst /,\,$(DELETE) $(UTIL)levlex.*)
distclean:
$(DELETE) *.o
@@ -34,18 +125,18 @@ distclean:
$(DELETE) *.0*
$(DELETE) *.lab
-$(APPNAME): $(OBJECTS)
- ${CXX} ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
+$(APPNAME): $(GAME_DEPENDS)
+ ${CXX} ${LDFLAGS} $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
strip $(APPNAME)
-debug: $(OBJECTS)
- ${CXX} ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
+debug: $(GAME_DEPENDS)
+ ${CXX} ${LDFLAGS} $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
-profile: $(OBJECTS)
- ${CXX} -g -p ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
+profile: $(GAME_DEPENDS)
+ ${CXX} -g -p ${LDFLAGS} $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
.cc.o:
- ${CXX} ${CFLAGS} -c $< ${INCLUDE}
+ ${CXX} ${CFLAGS} -c $<
# I don't have touch for DOS, but if you do, you can put this back.
#
diff --git a/crawl-ref/source/makefile.emx b/crawl-ref/source/makefile.emx
deleted file mode 100644
index 13e99e47fe..0000000000
--- a/crawl-ref/source/makefile.emx
+++ /dev/null
@@ -1,53 +0,0 @@
-# Makefile for Dungeon Crawl (OS/2 EMX port)
-# 1998 (C) Alexey Guzeev, aga@russia.crosswinds.net
-# EMX is covered by GNU GPL
-# Dungeon Crawl is covered by Crawl GPL
-# OS/2 is a trademark of IBM Corp.
-# IBM is a trademark of IBM Corp.
-# :)
-
-# 1. make some directory, like \crawl
-# 2. make subdirectory for sources, \crawl\src
-# 3. put crawl sources in \crawl\src directory
-# 4. make directory \crawl\src current
-# 5. execute command 'dmake -B -r -f makefile.emx install'
-# 6. remove \crawl\src subdirectory with all contents
-# 7. delete \crawl\scoretable.exe - I don't know what it does :)
-# 8. run \crawl\crawl.exe & enjoy!
-
-
-CC = gcc
-CFLAGS = -Wall -O3 -MMD -Zmt -DUSE_EMX
-LIBS = -lvideo -lbsd
-AR = ar
-
-include makefile.obj
-
-OBJ = $(OBJECTS)
-
-
-all: crawl.exe scoretable.exe
-
-install: ..\crawl.exe ..\scoretable.exe
-
-crawl.a: $(OBJS)
- $(AR) r crawl.a $(OBJS)
-
-..\crawl.exe: crawl.exe
- +copy crawl.exe ..
- emxbind -s ..\crawl.exe
-
-..\scoretable.exe: scoretable.exe
- +copy scoretable.exe ..
- emxbind -s ..\scoretable.exe
-clean:
- +del *.o
-
-crawl.exe: crawl.a libemx.o
- $(CC) -o crawl.exe crawl.a libemx.o $(LIBS)
-
-scoretable.exe: scoretab.o libemx.o
- $(CC) -o scoretable.exe scoretab.o libemx.o $(LIBS)
-
-.cc.o:
- $(CC) $(CFLAGS) -c $*.cc
diff --git a/crawl-ref/source/makefile.lnx b/crawl-ref/source/makefile.lnx
deleted file mode 100644
index 8b8b8994fd..0000000000
--- a/crawl-ref/source/makefile.lnx
+++ /dev/null
@@ -1,68 +0,0 @@
-# -*- Makefile -*- for Dungeon Crawl (linux)
-
-#
-# Modified for Crawl Reference by $Author$ on $Date$
-#
-
-GAME = crawl
-
-# this file contains a list of the libraries.
-# it will make a variable called OBJECTS that contains all the libraries
-include makefile.obj
-
-OBJECTS += libunix.o
-
-CXX = g++
-DELETE = rm -f
-COPY = cp
-OS_TYPE = LINUX
-
-CFLAGS = -Wall -Wwrite-strings -fsigned-char \
- -g -D$(OS_TYPE) $(EXTRA_FLAGS)
-
-MCHMOD = 2755
-
-# [dshaligram] More common location than /opt/crawl/bin - this is from the
-# Debian patch.
-INSTALLDIR = /usr/games
-LIB = -lncurses
-
-# Include for Linux
-INCLUDES = -I/usr/include/ncurses
-
-all: $(GAME)
-
-install: $(GAME)
- $(COPY) $(GAME) ${INSTALLDIR}
- chmod ${MCHMOD} ${INSTALLDIR}/$(GAME)
-
-clean:
- $(DELETE) *.o
-
-distclean:
- $(DELETE) *.o
- $(DELETE) bones.*
- $(DELETE) morgue.txt
- $(DELETE) scores
- $(DELETE) $(GAME)
- $(DELETE) *.sav
- $(DELETE) core
- $(DELETE) *.0*
- $(DELETE) *.lab
-
-
-$(GAME): $(OBJECTS)
- ${CXX} ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(GAME) $(LIB)
- chmod ${MCHMOD} $(GAME)
-
-debug: $(OBJECTS)
- ${CXX} ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(GAME) $(LIB)
-
-profile: $(OBJECTS)
- ${CXX} -g -p ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(GAME) $(LIB)
-
-.cc.o:
- ${CXX} ${CFLAGS} -c $< ${INCLUDE}
-
-.h.cc:
- touch $@
diff --git a/crawl-ref/source/makefile.mgw b/crawl-ref/source/makefile.mgw
index 499d3e22d2..17a47f132c 100644
--- a/crawl-ref/source/makefile.mgw
+++ b/crawl-ref/source/makefile.mgw
@@ -1,51 +1,160 @@
-# Make file for Dungeon Crawl (dos)
+# Make file for Dungeon Crawl (Win32, MinGW)
-# this file contains a list of the libraries.
-# it will make a variable called OBJECTS that contains all the libraries
+# makefile.obj includes a list of object files needed to build Crawl.
include makefile.obj
+ifeq ($(DEBUG_CRAWL),)
+OPATH := rel
+else
+OPATH := dbg
+endif
+
# need .exe so make will find the right file
-APPNAME = crawl.exe
+APPNAME = $(OPATH)\crawl.exe
CXX = g++
-DELETE = rm
+DELETE = del
COPY = copy
OS_TYPE = WIN32CONSOLE
-CFLAGS = -Wall -Wwrite-strings -Wstrict-prototypes \
- -Wmissing-prototypes -Wmissing-declarations \
- -D$(OS_TYPE) $(EXTRA_FLAGS)
+
+INSTALLDIR := $(OPATH)
+
+LIB = -lwinmm -static
+
+CFWARN := -Wall -Wwrite-strings \
+ -Wshadow \
+ -Werror \
+ -pedantic
+
+INCLUDES := -Iutil -I.
+
+CFOTHERS := -fsigned-char \
+ -fstrict-aliasing \
+ -pedantic \
+ -D$(OS_TYPE) $(EXTRA_FLAGS) \
+ -DWINMM_PLAY_SOUNDS
+
+CFLAGS := $(INCLUDES) $(CFWARN) $(CFOTHERS)
+YCFLAGS := $(INCLUDES) $(CFOTHERS)
+
+OBJECTS := $(OBJECTS) libw32c.o
+
LDFLAGS =
-INSTALLDIR = .
+
#LIB = -lcurso -lpano
-LIB = -lwinmm -static -lpcre -lluacore -lluastd
+
+UTIL = util/
+
+# If you don't have flex or bison, set DOYACC to N or empty.
+DOYACC := n
+
+LEX := flex
+YACC := bison -y
+
+YTABC := levcomp.tab.c
+YTABH := levcomp.tab.h
+
+
+ifeq ($(LEX),)
+DOYACC :=
+endif
+
+ifeq ($(YACC),)
+DOYACC :=
+endif
+
+# Do the levcomp stuff first because that's the most likely to fail.
+OBJECTS := levcomp.tab.o levcomp.lex.o levcomp.o \
+ $(OBJECTS)
+
+OBJECTS := $(foreach file,$(OBJECTS),$(OPATH)/$(file))
+
+GAME_DEPENDS := prepare $(OBJECTS)
+
+##########################################################################
all: $(APPNAME)
+prepare:
+ if not exist $(OPATH) mkdir $(OPATH)
+
+##########################################################################
+# The level compiler
+#
+ifeq ($(DOYACC),y)
+
+# [ds] A plague on the broken copy command on Windoze.
+prebuildyacc: $(UTIL)levcomp.lex.cc $(UTIL)levcomp.tab.cc $(UTIL)levcomp.tab.h
+ $(subst /,\,for %%f in ($^) do $(COPY) %%f prebuilt)
+
+$(UTIL)levcomp.tab.cc: $(UTIL)levcomp.ypp
+ $(subst /,\, cd $(UTIL)) && $(YACC) -d -b levcomp levcomp.ypp
+ $(subst /,\, cd $(UTIL)) && move $(YTABC) levcomp.tab.cc
+
+$(UTIL)levcomp.lex.cc: $(UTIL)levcomp.lpp
+ $(subst /,\, cd $(UTIL) && $(LEX) -olevcomp.lex.cc levcomp.lpp)
+
+else
+
+$(UTIL)levcomp.tab.cc: prebuilt/levcomp.tab.cc
+ $(subst /,\,$(COPY) prebuilt/*.h $(UTIL))
+ $(subst /,\,$(COPY) $< $@)
+
+$(UTIL)levcomp.lex.cc: prebuilt/levcomp.lex.cc
+ $(subst /,\,$(COPY) $< $@)
+
+endif
+
+##########################################################################
+
install: $(APPNAME)
+ifneq ($(OPATH),$(INSTALLDIR))
$(COPY) $(APPNAME) ${INSTALLDIR}
+endif
+ mkdir $(INSTALLDIR)\dat 2>nul || echo "" >nul
+ copy dat\*.des $(INSTALLDIR)\dat
clean:
- $(DELETE) *.o
+ $(DELETE) $(OPATH)\*.o
+ $(subst /,\,$(DELETE) $(UTIL)*.o)
+ $(subst /,\,$(DELETE) $(UTIL)*.exe)
+ $(subst /,\,$(DELETE) $(UTIL)*.lex.cc)
+ $(subst /,\,$(DELETE) $(UTIL)*.tab.cc)
+ $(subst /,\,$(DELETE) $(UTIL)*.tab.h)
+ $(subst /,\,$(DELETE) $(UTIL)*.tab.c)
+ $(subst /,\,$(DELETE) *.ixx)
distclean:
- $(DELETE) *.o
+ $(DELETE) $(OPATH)\*.o
+ $(DELETE) *.o
$(DELETE) bones.*
+ $(DELETE) $(OPATH)\bones.*
$(DELETE) morgue.txt
+ $(DELETE) $(OPATH)\morgue.txt
$(DELETE) scores
- $(DELETE) $(APPNAME)
+ $(DELETE) $(OPATH)\scores
+ $(DELETE) crawl.exe
+ $(DELETE) $(subst /,\,$(APPNAME))
$(DELETE) *.sav
+ $(DELETE) $(OPATH)\*.sav
$(DELETE) core
+ $(DELETE) $(OPATH)\core
$(DELETE) *.0*
+ $(DELETE) $(OPATH)\*.0*
$(DELETE) *.lab
+ $(DELETE) $(OPATH)\*.lab
-$(APPNAME): $(OBJECTS) libw32c.o
- ${CXX} ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) libw32c.o -o $(APPNAME) $(LIB)
+$(APPNAME): $(GAME_DEPENDS)
+ ${CXX} ${LDFLAGS} $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
strip $(APPNAME)
-debug: $(OBJECTS)
- ${CXX} ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
+debug: $(GAME_DEPENDS)
+ ${CXX} ${LDFLAGS} $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
+
+profile: $(GAME_DEPENDS)
+ ${CXX} -g -p ${LDFLAGS} $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
-profile: $(OBJECTS)
- ${CXX} -g -p ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
+$(OPATH)/%.o: %.cc
+ ${CXX} ${CFLAGS} -o $@ -c $<
-.cc.o:
- ${CXX} ${CFLAGS} -c $< ${INCLUDE}
+$(OPATH)/%.o: $(UTIL)%.cc
+ $(CXX) $(YCFLAGS) -o $@ -c $<
diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj
index e15334a033..2b811f1c56 100644
--- a/crawl-ref/source/makefile.obj
+++ b/crawl-ref/source/makefile.obj
@@ -1,3 +1,5 @@
+# Modified for Crawl Reference by $Author$ on $Date$
+
OBJECTS = \
abl-show.o \
abyss.o \
@@ -24,10 +26,12 @@ it_use2.o \
it_use3.o \
item_use.o \
itemname.o \
+itemprop.o \
items.o \
lev-pand.o \
libutil.o \
macro.o \
+mapdef.o \
maps.o \
menu.o \
message.o \
@@ -40,6 +44,7 @@ mon-util.o \
mstuff2.o \
mutation.o \
newgame.o \
+notes.o \
ouch.o \
output.o \
overmap.o \
@@ -62,7 +67,6 @@ tags.o \
transfor.o \
travel.o \
view.o \
-wpn-misc.o \
Kills.o \
mt19937ar.o \
clua.o
diff --git a/crawl-ref/source/makefile.osx b/crawl-ref/source/makefile.osx
index 7cee7c3452..69c78b127e 100644
--- a/crawl-ref/source/makefile.osx
+++ b/crawl-ref/source/makefile.osx
@@ -4,58 +4,41 @@
# Modified for Crawl Reference by $Author$ on $Date$
#
-GAME = crawl
-
-# this file contains a list of the libraries.
-# it will make a variable called OBJECTS that contains all the libraries
-include makefile.obj
-
-OBJECTS += libunix.o
-
-CXX = g++
-DELETE = rm -f
-COPY = cp
-OS_TYPE = OSX
-
-CFLAGS = -Wall -Werror -D$(OS_TYPE) $(EXTRA_FLAGS)
-
-MCHMOD = 711
-INSTALLDIR = /tmp/CRAWLTEST/testdev
-LIB = -lncurses -lstdc++
+PROJECT = Crawl.xcodeproj
+GAME = Crawl
all: $(GAME)
-install: $(GAME)
- $(COPY) $(GAME) ${INSTALLDIR}
- ${MCHMOD} ${INSTALLDIR}/$(GAME)
+# Xcode handles dependencies, so install does _not_ have to depend on building.
+install:
+ xcodebuild -project $(PROJECT) -target $(GAME) -configuration Release install
clean:
- $(DELETE) *.o
-
-distclean:
- $(DELETE) *.o
- $(DELETE) bones.*
- $(DELETE) morgue.txt
- $(DELETE) scores
- $(DELETE) $(GAME)
- $(DELETE) *.sav
- $(DELETE) core
- $(DELETE) *.0*
- $(DELETE) *.lab
-
-
-$(GAME): $(OBJECTS)
- ${CXX} ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(GAME) $(LIB)
-
-debug: $(OBJECTS)
- ${CXX} ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(GAME) $(LIB)
-
-profile: $(OBJECTS)
- ${CXX} -g -p ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(GAME) $(LIB)
-
-.cc.o:
- ${CXX} ${CFLAGS} $(INCLUDES) -c $< ${INCLUDE}
-
-.h.cc:
- touch $@
-
+ xcodebuild -project $(PROJECT) -target $(GAME) -configuration Release clean
+ xcodebuild -project $(PROJECT) -target $(GAME) -configuration Debug clean
+ xcodebuild -project $(PROJECT) -target $(GAME) -configuration Wizard clean
+
+distclean: clean
+ rm -f bones.*
+ rm -f morgue.txt
+ rm -f scores
+ rm -f $(GAME)
+ rm -f *.sav
+ rm -f core
+ rm -f *.0*
+ rm -f *.lab
+
+$(GAME):
+ xcodebuild -project $(PROJECT) -target $(GAME) -configuration Release build
+
+debug:
+ xcodebuild -project $(PROJECT) -target $(GAME) -configuration Debug build
+
+wizard:
+ xcodebuild -project $(PROJECT) -target $(GAME) -configuration Wizard build
+
+devel:
+ xcodebuild -project $(PROJECT) -target $(GAME) -configuration Development build
+
+devclean:
+ xcodebuild -project $(PROJECT) -target $(GAME) -configuration Development clean
diff --git a/crawl-ref/source/makefile.sgi b/crawl-ref/source/makefile.sgi
deleted file mode 100644
index 67815feaae..0000000000
--- a/crawl-ref/source/makefile.sgi
+++ /dev/null
@@ -1,54 +0,0 @@
-# Make file for Dungeon Crawl (irix)
-
-APPNAME = crawl
-
-# this file contains a list of the libraries.
-# it will make a variable called OBJECTS that contains all the libraries
-include makefile.obj
-
-CXX = CC
-DELETE = rm -f
-COPY = cp
-OS_TYPE = LINUX
-CFLAGS = -Wall -D$(OS_TYPE) $(EXTRA_FLAGS)
-LDFLAGS = -L/usr/lib
-MCHMOD = 711
-INSTALLDIR = /usr/games
-LIB = -lncurses
-
-# Include for Linux
-INCLUDES = -I/usr/include/ncurses
-
-all: $(APPNAME)
-
-%.o: %.cc
- @echo hello
- @${CXX} ${CFLAGS} -c $< ${INCLUDE}
-
-install: $(APPNAME)
- $(COPY) $(APPNAME) ${INSTALLDIR}
- chmod ${MCHMOD} ${INSTALLDIR}/$(APPNAME)
-
-clean:
- $(DELETE) *.o
-
-distclean:
- $(DELETE) *.o
- $(DELETE) bones.*
- $(DELETE) morgue.txt
- $(DELETE) scores
- $(DELETE) $(APPNAME)
-
-$(APPNAME): $(OBJECTS)
- ${CXX} ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
- strip $(APPNAME)
- chmod ${MCHMOD} $(APPNAME)
-
-debug: $(OBJECTS)
- ${CXX} ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
-
-profile: $(OBJECTS)
- ${CXX} -g -p ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
-
-.h.cc:
- touch $@
diff --git a/crawl-ref/source/makefile.sol b/crawl-ref/source/makefile.sol
deleted file mode 100644
index e79d7e3a53..0000000000
--- a/crawl-ref/source/makefile.sol
+++ /dev/null
@@ -1,68 +0,0 @@
-# Make file for Dungeon Crawl (solaris)
-
-#
-# Modified for Crawl Reference by $Author$ on $Date$
-#
-
-APPNAME = crawl
-
-# this file contains a list of the libraries.
-# it will make a variable called OBJECTS that contains all the libraries
-include makefile.obj
-
-OBJECTS += libunix.o
-
-CXX = g++
-DELETE = rm -f
-COPY = cp
-GROUP = games
-MOVE = mv
-OS_TYPE = SOLARIS
-
-CFLAGS = -Wall -Wwrite-strings -Wstrict-prototypes \
- -Wmissing-prototypes -Wmissing-declarations \
- -g -D$(OS_TYPE) $(EXTRA_FLAGS)
-
-LDFLAGS = -static
-MCHMOD = 2755
-INSTALLDIR = /opt/local/newcrawl/bin
-LIB = -lcurses
-
-all: $(APPNAME)
-
-install: $(APPNAME)
- #strip $(APPNAME)
- $(MOVE) ${INSTALLDIR}/${APPNAME} ${INSTALLDIR}/${APPNAME}.old
- $(COPY) $(APPNAME) ${INSTALLDIR}
- chgrp ${GROUP} ${INSTALLDIR}/${APPNAME}
- chmod ${MCHMOD} ${INSTALLDIR}/$(APPNAME)
-
-clean:
- $(DELETE) *.o
-
-distclean:
- $(DELETE) *.o
- $(DELETE) bones.*
- $(DELETE) morgue.txt
- $(DELETE) scores
- $(DELETE) $(APPNAME)
- $(DELETE) *.sav
- $(DELETE) core
- $(DELETE) *.0*
- $(DELETE) *.lab
-
-
-$(APPNAME): $(OBJECTS)
- ${CXX} ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
-
-debug: $(OBJECTS)
- ${CXX} ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
-
-profile: $(OBJECTS)
- ${CXX} -g -p ${LDFLAGS} $(INCLUDES) $(CFLAGS) $(OBJECTS) -o $(APPNAME) $(LIB)
-
-.cc.o:
- ${CXX} ${CFLAGS} -c $< ${INCLUDE}
-
-.h.cc:
- touch $@
diff --git a/crawl-ref/source/makefile.unix b/crawl-ref/source/makefile.unix
new file mode 100644
index 0000000000..c656630acb
--- /dev/null
+++ b/crawl-ref/source/makefile.unix
@@ -0,0 +1,198 @@
+# -*- Makefile -*- for Dungeon Crawl (linux)
+
+#
+# Modified for Crawl Reference by $Author$ on $Date$
+#
+
+GAME = crawl
+
+# this file contains a list of the libraries.
+# it will make a variable called OBJECTS that contains all the libraries
+include makefile.obj
+
+OBJECTS += libunix.o
+
+CXX = g++
+DELETE = rm -f
+COPY = cp
+OS_TYPE = UNIX
+
+# Include path for curses or ncurses.
+INCLUDES = -I/usr/include/ncurses
+
+MCHMOD = 2755
+INSTALLDIR := /usr/games
+
+# If you're installing Crawl for multiple users, you *must* set this to a
+# valid path before building Crawl.
+DATADIR :=
+
+LIB = -lncurses
+
+INCLUDES := $(INCLUDES) -Iutil -I.
+
+CFWARN := -Wall -Wwrite-strings \
+ -Wshadow -pedantic
+
+CFOTHERS := -fsigned-char -g -D$(OS_TYPE) $(EXTRA_FLAGS)
+
+ifneq ($(DATADIR),)
+CFOTHERS += '-DDATA_DIR_PATH="$(DATADIR)"'
+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
+YACC := bison -y
+
+YTABC := levcomp.tab.c
+YTABH := levcomp.tab.h
+
+OBJECTS := $(UTIL)levcomp.tab.o $(UTIL)levcomp.lex.o $(UTIL)levcomp.o \
+ $(OBJECTS)
+
+ifeq ($(LEX),)
+DOYACC :=
+endif
+
+ifeq ($(YACC),)
+DOYACC :=
+endif
+
+GAME_DEPENDS := $(OBJECTS)
+SRC_PKG_BASE := stone_soup
+SRC_VERSION := $(shell egrep 'VERSION ".*"' version.h | \
+ egrep -o '[0-9]\.[0-9](\.[0-9])?')
+PKG_SRC_DIR := $(SRC_PKG_BASE)-$(SRC_VERSION)-src
+SRC_PKG_TAR := $(PKG_SRC_DIR).tbz2
+SRC_PKG_ZIP := $(PKG_SRC_DIR).zip
+
+PKG_TIDY_LIST := $(UTIL)*.o $(LEVCOMP) *.o \
+ $(UTIL)*.tab.cc $(UTIL)*.tab.h $(UTIL)*.lex.cc *.ixx
+PKG_EXCLUDES := $(PWD)/misc/src-pkg-excludes.lst
+
+##########################################################################
+
+all: $(GAME)
+
+##########################################################################
+# The level compiler
+#
+
+ifeq ($(DOYACC),y)
+
+prebuildyacc: $(UTIL)levcomp.tab.cc $(UTIL)levcomp.tab.h $(UTIL)levcomp.lex.cc
+ cp $^ prebuilt/
+
+$(UTIL)levcomp.tab.cc: $(UTIL)levcomp.ypp
+ cd $(UTIL) && $(YACC) -d -b levcomp levcomp.ypp \
+ && mv $(YTABC) levcomp.tab.cc
+
+$(UTIL)levcomp.lex.cc: $(UTIL)levcomp.lpp
+ cd $(UTIL) && $(LEX) -olevcomp.lex.cc levcomp.lpp
+
+else
+
+# Pull the level-compiler stuff up from prebuilt/
+
+$(UTIL)levcomp.tab.cc: prebuilt/levcomp.tab.cc
+ cp prebuilt/*.h $(UTIL)
+ cp $< $@
+
+
+$(UTIL)levcomp.lex.cc: prebuilt/levcomp.lex.cc
+ cp $< $@
+
+endif
+
+##########################################################################
+
+
+##########################################################################
+# The actual build targets
+#
+
+install: $(GAME)
+ $(COPY) $(GAME) ${INSTALLDIR}
+ chmod ${MCHMOD} ${INSTALLDIR}/$(GAME)
+ifeq ($(DATADIR),)
+ $(error DATADIR not set! Set DATADIR and run make clean install again)
+endif
+ mkdir -p $(DATADIR)/data
+ cp dat/*.des $(DATADIR)/data
+
+clean:
+ $(DELETE) *.o
+ $(DELETE) $(UTIL)*.o
+ $(DELETE) $(LEVCOMP)
+ $(DELETE) $(UTIL)*.tab.cc $(UTIL)*.tab.c $(UTIL)*.tab.h $(UTIL)*.lex.cc
+ $(DELETE) *.ixx
+
+distclean: clean
+ $(DELETE) bones.*
+ $(DELETE) morgue.txt
+ $(DELETE) scores
+ $(DELETE) $(GAME)
+ $(DELETE) *.sav
+ $(DELETE) core
+ $(DELETE) *.0*
+ $(DELETE) *.lab
+
+$(GAME): $(GAME_DEPENDS)
+ ${CXX} ${LDFLAGS} $(CFLAGS) $(OBJECTS) -o $(GAME) $(LIB)
+ chmod ${MCHMOD} $(GAME)
+
+debug: $(GAME_DEPENDS)
+ ${CXX} ${LDFLAGS} $(CFLAGS) $(OBJECTS) -o $(GAME) $(LIB)
+
+profile: $(GAME_DEPENDS)
+ ${CXX} -g -p ${LDFLAGS} $(CFLAGS) $(OBJECTS) -o $(GAME) $(LIB)
+
+.cc.o:
+ ${CXX} ${CFLAGS} -c $<
+
+# [ds] Note we don't use the standard CFLAGS here; that's intentional, most
+# flex/bison combos I've tried don't produce code that passes the warnings
+# test.
+$(UTIL)%.o: $(UTIL)%.cc
+ $(CXX) $(YCFLAGS) -o $@ -c $<
+
+.h.cc:
+ touch $@
+
+#############################################################################
+# Packaging a source tarball for release
+#
+
+# To package, you *must* have lex and yacc to generate the intermediates.
+ifeq ($(DOYACC),y)
+package-source: distclean prebuildyacc pkgtidy removeold vlink pkgtarbz2 pkgzip
+
+pkgtidy:
+ $(DELETE) $(PKG_TIDY_LIST)
+
+removeold:
+ if [ -f ../../$(SRC_PKG_TAR) ]; then $(DELETE) ../../$(SRC_PKG_TAR); fi
+ if [ -f ../../$(SRC_PKG_ZIP) ]; then $(DELETE) ../../$(SRC_PKG_ZIP); fi
+
+# [ds] Existing directory names could produce a bad package!
+vlink:
+ cd .. && WHERE=$$PWD && cd .. && \
+ ( [ -e $(PKG_SRC_DIR) ] || ln -sf $$WHERE $(PKG_SRC_DIR) )
+
+pkgtarbz2:
+ cd ../.. && tar -ch --bzip2 -f $(SRC_PKG_TAR) \
+ -X $(PKG_EXCLUDES) $(PKG_SRC_DIR)
+
+pkgzip:
+ cd ../.. && zip -rq $(SRC_PKG_ZIP) $(PKG_SRC_DIR) \
+ -x@$(PKG_EXCLUDES)
+
+endif
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
new file mode 100644
index 0000000000..84e48329d6
--- /dev/null
+++ b/crawl-ref/source/mapdef.cc
@@ -0,0 +1,412 @@
+#include <cstdarg>
+#include <cstdio>
+#include <cctype>
+
+#include "AppHdr.h"
+#include "libutil.h"
+#include "mapdef.h"
+#include "mon-util.h"
+#include "stuff.h"
+
+///////////////////////////////////////////////
+// level_range
+//
+
+level_range::level_range(int s, int d)
+ : shallowest(), deepest()
+{
+ set(s, d);
+}
+
+void level_range::set(int s, int d)
+{
+ shallowest = s;
+ deepest = d;
+ if (deepest == -1)
+ deepest = shallowest;
+}
+
+void level_range::reset()
+{
+ deepest = shallowest = -1;
+}
+
+bool level_range::contains(int x) const
+{
+ // [ds] The level ranges used by the game are zero-based, adjust for that.
+ ++x;
+ return (x >= shallowest && x <= deepest);
+}
+
+bool level_range::valid() const
+{
+ return (shallowest > 0 && deepest >= shallowest);
+}
+
+int level_range::span() const
+{
+ return (deepest - shallowest);
+}
+
+///////////////////////////////////////////////
+// map_lines
+//
+
+map_lines::map_lines() : lines(), map_width(0)
+{
+}
+
+map_lines::map_lines(int nlines, ...) : lines(), map_width(0)
+{
+ va_list args;
+ va_start(args, nlines);
+
+ for (int i = 0; i < nlines; ++i)
+ add_line( va_arg(args, const char *) );
+
+ va_end(args);
+}
+
+const std::vector<std::string> &map_lines::get_lines() const
+{
+ return (lines);
+}
+
+void map_lines::add_line(const std::string &s)
+{
+ lines.push_back(s);
+ if ((int) s.length() > map_width)
+ map_width = s.length();
+}
+
+int map_lines::width() const
+{
+ return map_width;
+}
+
+int map_lines::height() const
+{
+ return lines.size();
+}
+
+void map_lines::clear()
+{
+ lines.clear();
+ map_width = 0;
+}
+
+void map_lines::resolve(std::string &s, const std::string &fill)
+{
+ std::string::size_type pos;
+ while ((pos = s.find('?')) != std::string::npos)
+ s[pos] = fill[ random2(fill.length()) ];
+}
+
+void map_lines::resolve(const std::string &fillins)
+{
+ if (fillins.empty() || fillins.find('?') != std::string::npos)
+ return;
+
+ for (int i = 0, size = lines.size(); i < size; ++i)
+ resolve(lines[i], fillins);
+}
+
+void map_lines::normalise(char fillch)
+{
+ for (int i = 0, size = lines.size(); i < size; ++i)
+ {
+ std::string &s = lines[i];
+ if ((int) s.length() < map_width)
+ s += std::string( map_width - s.length(), fillch );
+ }
+}
+
+// Should never be attempted if the map has a defined orientation, or if one
+// of the dimensions is greater than the lesser of GXM,GYM.
+void map_lines::rotate(bool clockwise)
+{
+ std::vector<std::string> newlines;
+
+ // normalise() first for convenience.
+ normalise();
+
+ const int xs = clockwise? 0 : map_width - 1,
+ xe = clockwise? map_width : -1,
+ xi = clockwise? 1 : -1;
+
+ const int ys = clockwise? (int) lines.size() - 1 : 0,
+ ye = clockwise? -1 : (int) lines.size(),
+ yi = clockwise? -1 : 1;
+
+ for (int i = xs; i != xe; i += xi)
+ {
+ std::string line;
+
+ for (int j = ys; j != ye; j += yi)
+ line += lines[j][i];
+
+ newlines.push_back(line);
+ }
+
+ map_width = lines.size();
+ lines = newlines;
+}
+
+void map_lines::vmirror()
+{
+ const int size = lines.size();
+ const int midpoint = size / 2;
+
+ for (int i = 0; i < midpoint; ++i)
+ {
+ std::string temp = lines[i];
+ lines[i] = lines[size - 1 - i];
+ lines[size - 1 - i] = temp;
+ }
+}
+
+void map_lines::hmirror()
+{
+ const int midpoint = map_width / 2;
+ for (int i = 0, size = lines.size(); i < size; ++i)
+ {
+ std::string &s = lines[i];
+ for (int j = 0; j < midpoint; ++j)
+ {
+ int c = s[j];
+ s[j] = s[map_width - 1 - j];
+ s[map_width - 1 - j] = c;
+ }
+ }
+}
+
+///////////////////////////////////////////////
+// map_def
+//
+
+void map_def::init()
+{
+ name.clear();
+ tags.clear();
+ place.clear();
+ depth.reset();
+ orient = MAP_NONE;
+
+ // Base chance; this is not a percentage.
+ chance = 10;
+
+ // The map designer must explicitly disallow these if unwanted.
+ flags = MAPF_MIRROR_VERTICAL | MAPF_MIRROR_HORIZONTAL
+ | MAPF_ROTATE;
+
+ random_symbols.clear();
+
+ map.clear();
+ mons.clear();
+}
+
+bool map_def::is_minivault() const
+{
+ return (orient == MAP_NONE);
+}
+
+void map_def::hmirror()
+{
+ if (!(flags & MAPF_MIRROR_HORIZONTAL))
+ return;
+
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Mirroring %s horizontally.", name.c_str());
+#endif
+ map.hmirror();
+
+ switch (orient)
+ {
+ case MAP_EAST: orient = MAP_WEST; break;
+ case MAP_NORTHEAST: orient = MAP_NORTHWEST; break;
+ case MAP_SOUTHEAST: orient = MAP_SOUTHWEST; break;
+ case MAP_WEST: orient = MAP_EAST; break;
+ case MAP_NORTHWEST: orient = MAP_NORTHEAST; break;
+ case MAP_SOUTHWEST: orient = MAP_SOUTHEAST; break;
+ default: break;
+ }
+}
+
+void map_def::vmirror()
+{
+ if (!(flags & MAPF_MIRROR_VERTICAL))
+ return;
+
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Mirroring %s vertically.", name.c_str());
+#endif
+ map.vmirror();
+
+ switch (orient)
+ {
+ case MAP_NORTH: orient = MAP_SOUTH; break;
+ case MAP_NORTHEAST: orient = MAP_SOUTHEAST; break;
+ case MAP_NORTHWEST: orient = MAP_SOUTHWEST; break;
+
+ case MAP_SOUTH: orient = MAP_NORTH; break;
+ case MAP_SOUTHEAST: orient = MAP_NORTHEAST; break;
+ case MAP_SOUTHWEST: orient = MAP_NORTHWEST; break;
+ default: break;
+ }
+}
+
+void map_def::rotate(bool clock)
+{
+ if (!(flags & MAPF_ROTATE))
+ return;
+
+#define GMINM ((GXM) < (GYM)? (GXM) : (GYM))
+ // Make sure the largest dimension fits in the smaller map bound.
+ if (map.width() <= GMINM && map.height() <= GMINM)
+ {
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Rotating %s %sclockwise.",
+ name.c_str(),
+ !clock? "anti-" : "");
+#endif
+ map.rotate(clock);
+
+ // Orientation shifts for clockwise rotation:
+ const map_section_type clockrotate_orients[][2] = {
+ { MAP_NORTH, MAP_EAST },
+ { MAP_NORTHEAST, MAP_SOUTHEAST },
+ { MAP_EAST, MAP_SOUTH },
+ { MAP_SOUTHEAST, MAP_SOUTHWEST },
+ { MAP_SOUTH, MAP_WEST },
+ { MAP_SOUTHWEST, MAP_NORTHWEST },
+ { MAP_WEST, MAP_NORTH },
+ { MAP_NORTHWEST, MAP_NORTHEAST },
+ };
+ const int nrots = sizeof(clockrotate_orients)
+ / sizeof(*clockrotate_orients);
+
+ const int refindex = !clock;
+ for (int i = 0; i < nrots; ++i)
+ if (orient == clockrotate_orients[i][refindex])
+ {
+ orient = clockrotate_orients[i][!refindex];
+ break;
+ }
+ }
+}
+
+void map_def::normalise()
+{
+ // Minivaults are padded out with floor tiles, normal maps are
+ // padded out with rock walls.
+ map.normalise(is_minivault()? '.' : 'x');
+}
+
+void map_def::resolve()
+{
+ map.resolve( random_symbols );
+}
+
+void map_def::fixup()
+{
+ normalise();
+ resolve();
+}
+
+bool map_def::has_tag(const std::string &tagwanted) const
+{
+ return !tags.empty() && !tagwanted.empty()
+ && tags.find(" " + tagwanted + " ") != std::string::npos;
+}
+
+///////////////////////////////////////////////////////////////////
+// mons_list
+//
+
+mons_list::mons_list(int nids, ...) : mons_ids()
+{
+ va_list args;
+ va_start(args, nids);
+
+ for (int i = 0; i < nids; ++i)
+ mons_ids.push_back( va_arg(args, int) );
+
+ va_end(args);
+}
+
+mons_list::mons_list() : mons_ids()
+{
+}
+
+const std::vector<int> &mons_list::get_ids() const
+{
+ return (mons_ids);
+}
+
+void mons_list::clear()
+{
+ mons_ids.clear();
+}
+
+bool mons_list::add_mons(const std::string &s)
+{
+ const int mid = mons_by_name(s);
+ if (mid != MONS_PROGRAM_BUG)
+ mons_ids.push_back(mid);
+ return (mid != MONS_PROGRAM_BUG);
+}
+
+int mons_list::mons_by_name(std::string name) const
+{
+ lowercase(name);
+
+ name = replace_all( name, "_", " " );
+
+ // Special casery:
+ if (name == "pandemonium demon")
+ return (MONS_PANDEMONIUM_DEMON);
+
+ if (name == "random" || name == "random monster")
+ return (RANDOM_MONSTER);
+
+ if (name == "any demon" || name == "demon" || name == "random demon")
+ return (-100 - DEMON_RANDOM);
+
+ if (name == "any lesser demon"
+ || name == "lesser demon" || name == "random lesser demon")
+ return (-100 - DEMON_LESSER);
+
+ if (name == "any common demon"
+ || name == "common demon" || name == "random common demon")
+ return (-100 - DEMON_COMMON);
+
+ if (name == "any greater demon"
+ || name == "greater demon" || name == "random greater demon")
+ return (-100 - DEMON_GREATER);
+
+ if (name == "small zombie")
+ return (MONS_ZOMBIE_SMALL);
+ if (name == "large zombie")
+ return (MONS_ZOMBIE_LARGE);
+
+ if (name == "small skeleton")
+ return (MONS_SKELETON_SMALL);
+ if (name == "large skeleton")
+ return (MONS_SKELETON_LARGE);
+
+ if (name == "spectral thing")
+ return (MONS_SPECTRAL_THING);
+
+ if (name == "small simulacrum")
+ return (MONS_SIMULACRUM_SMALL);
+ if (name == "large simulacrum")
+ return (MONS_SIMULACRUM_LARGE);
+
+ if (name == "small abomination")
+ return (MONS_ABOMINATION_SMALL);
+
+ if (name == "large abomination")
+ return (MONS_ABOMINATION_LARGE);
+
+ return (get_monster_by_name(name, true));
+}
diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h
new file mode 100644
index 0000000000..9fc686ea94
--- /dev/null
+++ b/crawl-ref/source/mapdef.h
@@ -0,0 +1,167 @@
+/*
+ * mapdef.h:
+ * Header for map structures used by the level compiler.
+ *
+ * NOTE: When we refer to map, this could be a full map, filling an entire
+ * level or a minivault that occupies just a portion of the level.
+ */
+
+#ifndef __MAPDEF_H__
+#define __MAPDEF_H__
+
+#include <string>
+#include <vector>
+
+#include "enum.h"
+
+enum map_flags {
+ MAPF_PANDEMONIUM_VAULT = 0x01, // A pandemonium minivault.
+
+ MAPF_MIRROR_VERTICAL = 0x10, // The map may be mirrored vertically
+ MAPF_MIRROR_HORIZONTAL = 0x20, // may be mirrored horizontally.
+ MAPF_ROTATE = 0x40 // may be rotated
+};
+
+class level_range {
+public:
+ int shallowest, deepest;
+
+public:
+ level_range(int s = -1, int d = -1);
+
+ void set(int s, int d = -1);
+ void reset();
+ bool contains(int depth) const;
+
+ bool valid() const;
+ int span() const;
+};
+
+class map_lines {
+public:
+ map_lines();
+
+ // NULL-terminated list of map lines.
+ map_lines(int nlines, ...);
+
+ void add_line(const std::string &s);
+ void set_orientation(const std::string &s);
+
+ int width() const;
+ int height() const;
+
+ void resolve(const std::string &fillins);
+
+ // Make all lines the same length.
+ void normalise(char fillc = 'x');
+
+ // Rotate 90 degrees either clockwise or anticlockwise
+ void rotate(bool clockwise);
+ void hmirror();
+ void vmirror();
+
+ void clear();
+
+ const std::vector<std::string> &get_lines() const;
+
+private:
+ void resolve(std::string &s, const std::string &fill);
+
+private:
+ std::vector<std::string> lines;
+ int map_width;
+};
+
+class mons_list {
+public:
+ mons_list(int nids, ...);
+ mons_list();
+
+ void clear();
+ const std::vector<int> &get_ids() const;
+
+ // Returns false if the monster is unrecognised.
+ bool add_mons(const std::string &s);
+
+private:
+ int mons_by_name(std::string name) const;
+
+private:
+ std::vector<int> mons_ids;
+};
+
+// Not providing a constructor to make life easy for C-style initialisation.
+class map_def {
+public:
+ std::string name;
+ std::string tags;
+ std::string place;
+ level_range depth;
+ map_section_type orient;
+ int chance;
+ long flags;
+
+ map_lines map;
+ mons_list mons;
+
+ std::string random_symbols;
+
+public:
+ void init();
+
+ void hmirror();
+ void vmirror();
+ void rotate(bool clockwise);
+ void normalise();
+ void resolve();
+ void fixup();
+
+ bool is_minivault() const;
+ bool has_tag(const std::string &tag) const;
+};
+
+class monster_chance {
+public:
+ int mclass;
+ int level;
+ int rarity;
+};
+
+class level_def {
+public:
+ // The range of levels to which this def applies.
+ level_range range;
+
+ // Can be empty, in which case the default colours are applied.
+ std::string floor_colour, rock_colour;
+
+ std::string tags;
+
+ // The probability of requesting a random vault.
+ int p_vault;
+
+ // The probability of requesting a random minivault.
+ int p_minivault;
+
+ // If non-empty, any upstair will go straight to this level.
+ std::string upstair_targ, downstair_targ;
+
+ std::vector<monster_chance> monsters;
+};
+
+class dungeon_def {
+public:
+ std::string idstr;
+ int id;
+ std::string short_desc, full_desc;
+
+ std::vector<level_def> level_specs;
+
+public:
+ const level_def &specs(int subdepth);
+};
+
+std::string escape_string(std::string in, const std::string &toesc,
+ const std::string &escapewith);
+
+#endif
diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc
index 3e99b298e1..68d851c596 100644
--- a/crawl-ref/source/maps.cc
+++ b/crawl-ref/source/maps.cc
@@ -3,6 +3,8 @@
* Summary: Functions used to create vaults.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <2> 5/20/99 BWR Added stone lining to Zot vault,
@@ -13,112 +15,37 @@
#include "AppHdr.h"
#include "maps.h"
-#include <string.h>
-#include <stdlib.h>
+#include <cstring>
+#include <cstdlib>
+#include <errno.h>
+#include "dungeon.h"
#include "enum.h"
+#include "files.h"
#include "monplace.h"
+#include "mapdef.h"
#include "stuff.h"
+#include "levcomp.h"
-static char vault_1(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char vault_2(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char vault_3(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char vault_4(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char vault_5(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char vault_6(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char vault_7(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char vault_8(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char vault_9(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char vault_10(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-
-
-static char antaeus(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char asmodeus(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char beehive(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char box_level(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char castle_dis(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char elf_hall(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char ereshkigal(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char farm_and_country(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char fort_yaktaur(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char hall_of_Zot(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char hall_of_blades(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char gloorx_vloq(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-//static char mollusc(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char my_map(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char mnoleg(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char cerebov(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char orc_temple(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char lom_lobon(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char slime_pit(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char snake_pit(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char swamp(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char temple(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char tomb_1(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char tomb_2(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char tomb_3(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char vaults_vault(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char vestibule_map(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-
-
-static char minivault_1(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_2(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_3(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_4(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_5(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_6(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_7(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_8(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_9(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_10(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_11(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_12(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_13(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_14(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_15(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_16(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_17(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_18(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_19(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_20(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_21(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_22(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_23(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_24(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_25(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_26(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_27(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_28(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_29(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_30(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_31(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_32(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_33(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-
-//jmf: originals and slim wrappers to fit into don's non-switch
-static char minivault_34(char vgrid[81][81], FixedVector<int, 7>& mons_array, bool orientation);
-static char minivault_35(char vgrid[81][81], FixedVector<int, 7>& mons_array, bool orientation);
-static char minivault_34_a(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_34_b(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_35_a(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char minivault_35_b(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-
-static char rand_demon_1(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char rand_demon_2(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char rand_demon_3(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char rand_demon_4(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char rand_demon_5(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char rand_demon_6(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char rand_demon_7(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char rand_demon_8(char vgrid[81][81], FixedVector<int, 7>& mons_array);
-static char rand_demon_9(char vgrid[81][81], FixedVector<int, 7>& mons_array);
+static int write_vault(const map_def &mdef, map_type mt,
+ FixedVector<int,7> &marray,
+ vault_placement &);
+static int apply_vault_definition(
+ const map_def &def,
+ map_type map,
+ FixedVector<int,7> &marray,
+ vault_placement &);
+static void resolve_map(map_def &def);
+//////////////////////////////////////////////////////////////////////////
+// New style vault definitions
-/* ******************** BEGIN PUBLIC FUNCTIONS ******************* */
+static std::vector<map_def> vdefs;
+/* ******************** BEGIN PUBLIC FUNCTIONS ******************* */
// remember (!!!) - if a member of the monster array isn't specified
// within a vault subroutine, assume that it holds a random monster
@@ -127,3515 +54,282 @@ static char rand_demon_9(char vgrid[81][81], FixedVector<int, 7>& mons_array);
// make sure that vault_n, where n is a number, is a vault which can be put
// anywhere, while other vault names are for specific level ranges, etc.
-char vault_main( char vgrid[81][81], FixedVector<int, 7>& mons_array, int vault_force, int many_many )
-{
-
- int which_vault = 0;
- unsigned char vx, vy;
- char (*fnc_vault) (char[81][81], FixedVector<int, 7>&) = 0;
-
-// first, fill in entirely with walls and null-terminate {dlb}:
- for (vx = 0; vx < 80; vx++)
+int vault_main(
+ map_type vgrid,
+ FixedVector<int, 7>& mons_array,
+ vault_placement &place,
+ int which_vault,
+ int many_many )
+{
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Generating level: %s",
+ vdefs[which_vault].name.c_str());
+#endif
+
+ // first, fill in entirely with walls and null-terminate {dlb}:
+ for (int vx = 0; vx < MAP_SIDE; vx++)
{
- for (vy = 0; vy < 80; vy++)
+ for (int vy = 0; vy < MAP_SIDE; vy++)
vgrid[vx][vy] = 'x';
- vgrid[80][vx] = '\0';
- vgrid[vx][80] = '\0';
- }
-
- // next, select an appropriate vault to place {dlb}:
- for (;;)
- {
- which_vault = ( (vault_force == 100) ? random2(14) : vault_force );
-
- // endless loops result if forced vault cannot pass these tests {dlb}:
- if ( which_vault == 9 )
- {
- // if ( many_many > 23 || many_many > 12 )
- if (many_many > 12)
- break;
- }
- else if (which_vault == 11 || which_vault == 12)
- {
- if (many_many > 20)
- break;
- }
- else
- break;
+ vgrid[MAP_SIDE][vx] = 0;
+ vgrid[vx][MAP_SIDE] = 0;
}
- // then, determine which drawing routine to use {dlb}:
- fnc_vault = ( (which_vault == 0) ? vault_1 :
- (which_vault == 1) ? vault_2 :
- (which_vault == 2) ? vault_3 :
- (which_vault == 3) ? vault_4 :
- (which_vault == 4) ? vault_5 :
- (which_vault == 5) ? vault_6 :
- (which_vault == 6) ? vault_7 :
- (which_vault == 7) ? vault_8 :
- (which_vault == 8) ? vault_9 :
- (which_vault == 9) ? ( (many_many > 23) ? my_map : orc_temple ) :
- (which_vault == 10) ? vault_10 :
- (which_vault == 11) ? farm_and_country :
- (which_vault == 12) ? fort_yaktaur :
- (which_vault == 13) ? box_level :
-
- // the hell vaults:
- (which_vault == 50) ? vestibule_map :
- (which_vault == 51) ? castle_dis :
- (which_vault == 52) ? asmodeus :
- (which_vault == 53) ? antaeus :
- (which_vault == 54) ? ereshkigal :
-
- // the pandemonium big demonlord vaults:
- (which_vault == 60) ? mnoleg : // was nemelex
- (which_vault == 61) ? lom_lobon : // was sif muna
- (which_vault == 62) ? cerebov : // was okawaru
- (which_vault == 63) ? gloorx_vloq : // was kikubaaqudgha
-
- //(which_vault == 64) ? mollusc :
- (which_vault == 80) ? beehive :
- (which_vault == 81) ? slime_pit :
- (which_vault == 82) ? vaults_vault :
- (which_vault == 83) ? hall_of_blades :
- (which_vault == 84) ? hall_of_Zot :
- (which_vault == 85) ? temple :
- (which_vault == 86) ? snake_pit :
- (which_vault == 87) ? elf_hall :
- (which_vault == 88) ? tomb_1 :
- (which_vault == 89) ? tomb_2 :
- (which_vault == 90) ? tomb_3 :
- (which_vault == 91) ? swamp :
- (which_vault == 200) ? minivault_1 :
- (which_vault == 201) ? minivault_2 :
- (which_vault == 202) ? minivault_3 :
- (which_vault == 203) ? minivault_4 :
- (which_vault == 204) ? minivault_5 :
- (which_vault == 205) ? ( (many_many > 15) ? minivault_6 : minivault_1 ) :
- (which_vault == 206) ? ( (many_many > 10) ? minivault_7 : minivault_2 ) :
- (which_vault == 207) ? ( (many_many > 15) ? minivault_8 : minivault_3 ) :
- (which_vault == 208) ? ( (many_many > 15) ? minivault_9 : minivault_4 ) :
- (which_vault == 209) ? minivault_10 :
- (which_vault == 210) ? minivault_11 :
- (which_vault == 211) ? minivault_12 :
- (which_vault == 212) ? minivault_13 :
- (which_vault == 213) ? minivault_14 :
- (which_vault == 214) ? minivault_15 :
- (which_vault == 215) ? minivault_16 :
- (which_vault == 216) ? minivault_17 :
- (which_vault == 217) ? minivault_18 :
- (which_vault == 218) ? minivault_19 :
- (which_vault == 219) ? minivault_20 :
- (which_vault == 220) ? minivault_21 :
- (which_vault == 221) ? minivault_22 :
- (which_vault == 222) ? minivault_23 :
- (which_vault == 223) ? minivault_24 :
- (which_vault == 224) ? minivault_25 :
- (which_vault == 225) ? minivault_26 :
- (which_vault == 226) ? minivault_27 :
- (which_vault == 227) ? minivault_28 :
- (which_vault == 228) ? minivault_29 :
- (which_vault == 229) ? minivault_30 :
- (which_vault == 230) ? minivault_31 :
- (which_vault == 231) ? minivault_32 :
- (which_vault == 232) ? minivault_33 :
- (which_vault == 233) ? minivault_34_a :
- (which_vault == 234) ? minivault_34_b :
- (which_vault == 235) ? minivault_35_a :
- (which_vault == 236) ? minivault_35_b :
- (which_vault == 300) ? rand_demon_1 :
- (which_vault == 301) ? rand_demon_2 :
- (which_vault == 302) ? rand_demon_3 :
- (which_vault == 303) ? rand_demon_4 :
- (which_vault == 304) ? rand_demon_5 :
- (which_vault == 305) ? rand_demon_6 :
- (which_vault == 306) ? rand_demon_7 :
- (which_vault == 307) ? rand_demon_8 :
- (which_vault == 308) ? rand_demon_9
- : 0 ); // yep, NULL -- original behaviour {dlb}
-
// NB - a return value of zero is not handled well by dungeon.cc (but there it is) 10mar2000 {dlb}
- return ( (fnc_vault == 0) ? 0 : fnc_vault(vgrid, mons_array) );
+ return write_vault( vdefs[which_vault], vgrid, mons_array, place );
} // end vault_main()
-/* ********************* END PUBLIC FUNCTIONS ******************** */
-
-/*
- key:
- x - DNGN_ROCK_WALL
- X - DNGN_PERMAROCK_WALL -> should always be undiggable! -- bwr
- c - DNGN_STONE_WALL
- v - DNGN_METAL_WALL
- b - DNGN_GREEN_CRYSTAL_WALL
- a - DNGN_WAX_WALL
- . - DNGN_FLOOR
- + - DNGN_CLOSED_DOOR
- = - DNGN_SECRET_DOOR
- @ - entry point - must be on outside and on a particular side - see templates
- w - water
- l - lava
- >< - extra stairs - you can leave level by these but will never be placed on them from another level
- }{ - stairs 82/86 - You must be able to reach these from each other
- )( - stairs 83/87
- ][ - stairs 84/88
- I - orcish idol (does nothing)
- ^ - random trap
-
- A - Vestibule gateway (opened by Horn). Can also be put on other levels for colour, where it won't do anything.
- B - Altar. These are assigned specific types (eg of Zin etc) in dungeon.cc, in order.
- C - Random Altar.
- F - Typically a Granite Statue, but may be Orange or Silver (1 in 100)
- G - Granite statue (does nothing)
- H - orange crystal statue (attacks mind)
- S - Silver statue (summons demons). Avoid using (rare).
- T - Water fountain
- U - Magic fountain
- V - Permenantly dry fountain
-
- Statues can't be walked over and are only destroyed by disintegration
-
- $ - gold
- % - normal item
- * - higher level item (good)
- | - acquirement-level item (almost guaranteed excellent)
- O - place an appropriate rune here
- P - maybe place a rune here (50%)
- R - honeycomb (2/3) or royal jelly (1/3)
- Z - the Orb of Zot
-
- 0 - normal monster
- 9 - +5 depth monster
- 8 - (+2) * 2 depth monster (aargh!). Can get golden dragons and titans this way.
- 1-7 - monster array monster
- used to allocate specific monsters for a vault.
- is filled with RANDOM_MONSTER if monster not specified
-
- note that a lot of the vaults are in there mainly to add some interest to the
- scenery, and are not the lethal treasure-fests you find in Angband
- (not that there's anything wrong with that)
-
- Guidelines for creating new vault maps:
-
- Basically you can just let your creativity run wild. You do not have
- to place all of the stairs unless the level is full screen, in which
- case you must place all except the extra stairs (> and <). The <> stairs
- can be put anywhere and in any quantities but do not have to be there. Any
- of the other stairs which are not present in the vault will be randomly
- placed outside it. Also generally try to avoid rooms with no exit.
-
- You can use the templates below to build vaults, and remember to return the
- same number (this number is used in builder2.cc to determine where on the map
- the vault is located). The entry point '@' must be present (except
- full-screen vaults where it must not) and be on the same side of the vault
- as it is on the template, but can be anywhere along that side.
-
- You'll have to tell me the level range in which you want the vault to appear,
- so that I can code it into the vault management function. Unless you've
- placed specific monster types this will probably be unnecessary.
-
- I think that's all. Have fun!
-
- ps - remember to add one to the monster array value when placing monsters
- on each map (it is 1-7, not 0-6) {dlb}
- */
-
-static char vault_1(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // my first vault
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxxxxx....x........x........x.................................xxxxxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxxx|=8...x........+........x......x....x1...x2...x2...x3...x...xxxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxxx|x....x........x........x....................................xxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxxxxxxxxx+xxx+xxxxxxxxxxxxxx..................................xxxxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxx.......x.................+...................................8xxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxx.......x.................x..................................xxxxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxx.......+........3........xx+xx................................xxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxx.......x.................x...x..x....x1...x2...x2...x3...x...xxxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxx.......x.................x...x.............................xxxxxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxxx+xxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxx.........................x.S.x...xxxxxx..................|||||xxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxx....xxxxxxxxxxxxxxxxxx...x...x......xxxxxx..................||xxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxx....x...$$$$x****.999x...x...x.........xxxxxx.................xxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxx....+...$$$$x****....x...x...+............xxxxxx.........8....xxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxx....x...$$$$x****....+...x...x...............xxxxxx...........xxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxx....x...$$$$x****....x...x999x..................xxxxxx........xxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxx....xxxxxxxxxxxxxxxxxx...x...xxx...................xxxxxx.....xxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxx.........................x...xxxxxx...................xxxxxx..xxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxxxxxx+xxxxxxxx+xxxxxxx+xxxx...xxxxxx+xxxxxxxx+xxxxxxxx+xxxxxxx=xxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxx.........x.......x.......x...x.........x........x.............xxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxx.........x.......x.......x...x.........x........x.............xxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxx.........x.......x.......x...x.........x........x.............xxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxx....1....x...2...x...3...x...x....3....x....2...x......1......xxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxx.........x.......x.......x...x.........x........x.............xxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxx.........x.......x.......x...x.........x........x.............xxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxx.........x.......x.......x...x.........x........x.............xxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_SHAPESHIFTER;
- mons_array[1] = MONS_SHAPESHIFTER;
- mons_array[2] = MONS_GLOWING_SHAPESHIFTER;
-
- return MAP_NORTH;
-}
-
-
-static char vault_2(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // cell vault
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxcccccccccccccccccccccccccccccccc");
- strcpy(vgrid[7], "xxxxxxxxccw......^......w......^......wc");
- strcpy(vgrid[8], "xxxxxxxxcc.ccccccccccccc.ccccccccccccc.c");
- strcpy(vgrid[9], "xxxxxxxxcc.c....c.c....c.c....c.c....c.c");
- strcpy(vgrid[10], "xxxxxxxxcc.c.8..+.c....c.c....+.c..9.c.c");
- strcpy(vgrid[11], "xxxxxxxxcc.c....c.+..9.c.c.9..c.+....c.c");
- strcpy(vgrid[12], "xxxxxxxxcc.c....c.c....c.c....c.c....c.c");
- strcpy(vgrid[13], "xxxxxxxxcc.cccccc.cccccc.cccccc.cccccc.c");
- strcpy(vgrid[14], "xxxxxxxxcc^c....c.c....c.c....c.c....c.c");
- strcpy(vgrid[15], "xxxxxxxxcc.c....c.c....c.c....+.c....c.c");
- strcpy(vgrid[16], "xxxxxxxxcc.c8...+.+..8.c.c.8..c.+....c.c");
- strcpy(vgrid[17], "xxxxxxxxcc.c....c.c....c.c....c.c....c.c");
- strcpy(vgrid[18], "xxxxxxxxcc.cccccc.cccccc.cccccc.cccccc.c");
- strcpy(vgrid[19], "xxxxxxxxcc.c....c.c....c.c....c.c....c.c");
- strcpy(vgrid[20], "xxxxxxxxcc.c....+.c....c.c.0..c.c....c.c");
- strcpy(vgrid[21], "xxxxxxxxcc.c..9.c.+.8..c^c....+.+.0..c.c");
- strcpy(vgrid[22], "xxxxxxxxcc.c....c.c....c.c....c.c....c.c");
- strcpy(vgrid[23], "xxxxxxxxcc.cccccc.cccccc.cccccc.cccccc.c");
- strcpy(vgrid[24], "xxxxxxxxcc.c....c.c....c.c....c.c....c.c");
- strcpy(vgrid[25], "xxxxxxxxcc.c.0..+.+.0..c.c....+.+....c.c");
- strcpy(vgrid[26], "xxxxxxxxcc.c....c.c....c.c.0..c.c.8..c.c");
- strcpy(vgrid[27], "xxxxxxxxcc.cccccc.c....c.c....c.cccccc.c");
- strcpy(vgrid[28], "xxxxxxxxcc.c....c.cccccc.cccccc.c....c^c");
- strcpy(vgrid[29], "xxxxxxxxcc.c....c.c....c.c..9.+.+....c.c");
- strcpy(vgrid[30], "xxxxxxxxcc.c.0..+.+....c.c9...c.c.0..c.c");
- strcpy(vgrid[31], "xxxxxxxxcc.c....c.c.8..c.c....c.c....c.c");
- strcpy(vgrid[32], "xxxxxxxxcc.cccccc^cccccc.cccccc^cccccc.c");
- strcpy(vgrid[33], "xxxxxxxxccw.......Twwwwc.cwwwwT.......wc");
- strcpy(vgrid[34], "xxxxxxxxcccccccccccccccc.ccccccccccccccc");
- strcpy(vgrid[35], "xxxxxxxxxxxxxxxxxxxxxxxc@cxxxxxxxxxxxxxx");
-
- return MAP_NORTHWEST;
-}
-
-
-static char vault_3(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // little maze vault
- UNUSED( mons_array );
-
- for (unsigned char i = 0; i < 81; i++)
- strcpy(vgrid[i], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- strcat(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[7], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[8], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[9], "x900x..............x..........xxxxxxxxxx");
- strcat(vgrid[10], "x999x.xxxxxxxxxxxx.x.xxxxxxxx.xxxxxxxxxx");
- strcat(vgrid[11], "x000x.x............x.x......x.xxxxxxxxxx");
- strcat(vgrid[12], "xx.xx.xxxxxxxxxxxxxx.x.xxxx.x.xxxxxxxxxx");
- strcat(vgrid[13], "xx.x..............xx.x.88|x.x.xxxxxxxxxx");
- strcat(vgrid[14], "xx.x.x.xxxxxxxxxx.xx.xxxxxx.x.xxxxxxxxxx");
- strcat(vgrid[15], "xx.x.x.x........x...........x.xxxxxxxxxx");
- strcat(vgrid[16], "xx.x.x.x.xxxxxx.xxxxxxxxxxxxx.xxxxxxxxxx");
- strcat(vgrid[17], "xx.xxx.x.x$$$$x...............xxxxxxxxxx");
- strcat(vgrid[18], "xx.....x.x$$$$x.xxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[19], "xxxxxxxx.x$$$$x...............xxxxxxxxxx");
- strcat(vgrid[20], "x........x$$$$x.xxxxxxxxxxxxx.xxxxxxxxxx");
- strcat(vgrid[21], "x.xxxxxx.xxxx.x.............x.xxxxxxxxxx");
- strcat(vgrid[22], "x.xxxxxx.xxxx.xxxxxxxxxxxxx.x.xxxxxxxxxx");
- strcat(vgrid[23], "x.x.......xxx.x...........x.x.xxxxxxxxxx");
- strcat(vgrid[24], "x.x.xxxxx.....x.x.xxxxx...x.x.xxxxxxxxxx");
- strcat(vgrid[25], "x.x.x999xxxxxxx.x.x***x...x.x.xxxxxxxxxx");
- strcat(vgrid[26], "x.x.x889........x.x|||xxxxx.x.xxxxxxxxxx");
- strcat(vgrid[27], "x.x.x899x.xxxxx.x.x***xxxxx.x.xxxxxxxxxx");
- strcat(vgrid[28], "x.x.xxxxx.xxxxx.x.xx.xxxxxx.x.xxxxxxxxxx");
- strcat(vgrid[29], "x.x..........xx.x.xx........x.xxxxxxxxxx");
- strcat(vgrid[30], "x.xxxxxxx.xx.xx.x.xxxxx.xxxxx.xxxxxxxxxx");
- strcat(vgrid[31], "x.xxx000x.xx.xx.x.x$$$x.xxxxx.xxxxxxxxxx");
- strcat(vgrid[32], "x|||x000x.x$$$x.x.x$$$x%%x%%%.xxxxxxxxxx");
- strcat(vgrid[33], "x|||x000..x$8$x.x.x$$$x%%x%8%xxxxxxxxxxx");
- strcat(vgrid[34], "x|||xxxxxxx$$$x.x..$$$xxxx%%%xxxxxxxxxxx");
- strcat(vgrid[35], "xxxxxxxxxxxxxxx@xxxxxxxxxxxxxxxxxxxxxxxx");
-
- return MAP_NORTHEAST;
-}
-
-
-static char vault_4(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // thingy vault
- UNUSED( mons_array );
-
- for (unsigned char i = 0; i < 81; i++)
- strcpy(vgrid[i], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- strcpy(vgrid[36], "xxxxxxxxxxxxxxxxxxxxxxxxx@xxxxxxxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxxxxxxxxxxxxxxxxxx^xxxxxxxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxx");
- strcpy(vgrid[39], "xxxxxxxxxxxxxxxxxxxxxxx.....xxxxxxxxxxxx");
- strcpy(vgrid[40], "xxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxx");
- strcpy(vgrid[41], "xxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxx");
- strcpy(vgrid[42], "xxxxxxxxxxxxxxxxxxxxxxx.....xxxxxxxxxxxx");
- strcpy(vgrid[43], "xxxxxxxxxxxxxxxxxxxxx.........xxxxxxxxxx");
- strcpy(vgrid[44], "xxxxxxxxxxxxxxxxx......0...0......xxxxxx");
- strcpy(vgrid[45], "xxxxxxxxxxxxxx.......................xxx");
- strcpy(vgrid[46], "xxxxxxxxxxxxxx.........0...0.........xxx");
- strcpy(vgrid[47], "xxxxxxxxxxxxx8......0.........0......8xx");
- strcpy(vgrid[48], "xxxxxxxxxxxxxx.........0...0.........xxx");
- strcpy(vgrid[49], "xxxxxxxxxxxxxx.......................xxx");
- strcpy(vgrid[50], "xxxxxxxxxxxxxxx........0...0........xxxx");
- strcpy(vgrid[51], "xxxxxxxxxxxxxxxxxxxx...........xxxxxxxxx");
- strcpy(vgrid[52], "xxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxx");
- strcpy(vgrid[53], "xxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxx");
- strcpy(vgrid[54], "xxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxx");
- strcpy(vgrid[55], "xxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxx");
- strcpy(vgrid[56], "xxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxx");
- strcpy(vgrid[57], "xxxxxxxxxxxxxxxxxxxxxxx.....xxxxxxxxxxxx");
- strcpy(vgrid[58], "xxxxxxxxxxxxxxxxxx...............xxxxxxx");
- strcpy(vgrid[59], "xxxxxxxxxxxxxxxx8.................8xxxxx");
- strcpy(vgrid[60], "xxxxxxxxxxxxxxxxxxx.............xxxxxxxx");
- strcpy(vgrid[61], "xxxxxxxxxxxxxxxxxxxxxxxx999xxxxxxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- return MAP_SOUTHWEST;
-}
-
-static char vault_5(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // hourglass vault
- UNUSED( mons_array );
-
- for (unsigned char i = 0; i < 81; i++)
- strcpy(vgrid[i], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- strcat(vgrid[36], "xxxxxxxxxxxxxx@xxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[37], "xxxxxx.................xxxxxxxxxxxxxxxxx");
- strcat(vgrid[38], "xxxxx...................xxxxxxxxxxxxxxxx");
- strcat(vgrid[39], "xxxxx...................xxxxxxxxxxxxxxxx");
- strcat(vgrid[40], "xxxxxx.................xxxxxxxxxxxxxxxxx");
- strcat(vgrid[41], "xxxxxx.................xxxxxxxxxxxxxxxxx");
- strcat(vgrid[42], "xxxxxx.................xxxxxxxxxxxxxxxxx");
- strcat(vgrid[43], "xxxxxxx...............xxxxxxxxxxxxxxxxxx");
- strcat(vgrid[44], "xxxxxxx...............xxxxxxxxxxxxxxxxxx");
- strcat(vgrid[45], "xxxxxxxx.............xxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[46], "xxxxxxxxx.....8.....xxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[47], "xxxxxxxxxx...999...xxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[48], "xxxxxxxxxxxx00000xxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[49], "xxxxxxxxxxxxx===xxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[50], "xxxxxxxxxxxx.....xxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[51], "xxxxxxxxxx.........xxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[52], "xxxxxxxxx...........xxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[53], "xxxxxxxx......|......xxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[54], "xxxxxxx...............xxxxxxxxxxxxxxxxxx");
- strcat(vgrid[55], "xxxxxxx...............xxxxxxxxxxxxxxxxxx");
- strcat(vgrid[56], "xxxxxx........$........xxxxxxxxxxxxxxxxx");
- strcat(vgrid[57], "xxxxxx.......$$$.......xxxxxxxxxxxxxxxxx");
- strcat(vgrid[58], "xxxxxx....$$$$$$$$$....xxxxxxxxxxxxxxxxx");
- strcat(vgrid[59], "xxxxx$$$$$$$$$$$$$$$$$$$xxxxxxxxxxxxxxxx");
- strcat(vgrid[60], "xxxxx$$$$$$$$$$$$$$$$$$$xxxxxxxxxxxxxxxx");
- strcat(vgrid[61], "xxxxxx$$$$$$$$$$$$$$$$$xxxxxxxxxxxxxxxxx");
- strcat(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- return MAP_SOUTHEAST;
-}
-
-
-static char vault_6(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // a more Angbandy vault
- UNUSED( mons_array );
-
- for (unsigned char i = 0; i < 81; i++)
- strcpy(vgrid[i], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- strcat(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[6], "ccccccccccccccccccccccccccccccccxxxxxxxx");
- strcat(vgrid[7], "c*******cc..9...cc.+8c0c*c.c*c8cxxxxxxxx");
- strcat(vgrid[8], "c******cc..cc..cc..cc0c.c.c.c8ccxxxxxxxx");
- strcat(vgrid[9], "c*****cc..cc..cc..cc.c$c.c.c8c.cxxxxxxxx");
- strcat(vgrid[10], "c****cc9.cc..cc8.cc|c.c|c.c*c0ccxxxxxxxx");
- strcat(vgrid[11], "c***cc..cc..cc..cc.c.c.c.c.c.c$cxxxxxxxx");
- strcat(vgrid[12], "c**cc..cc8.cc..cc.c*c.c.c.c.c.ccxxxxxxxx");
- strcat(vgrid[13], "c+cc9.cc..cc..cc.c.c.c.c*c.c.c.cxxxxxxxx");
- strcat(vgrid[14], "c^c..cc..cc..cc.c$c.c.c.c.c.c*ccxxxxxxxx");
- strcat(vgrid[15], "c...cc..cc..cc.c.c.c9c$c.c.c.c9cxxxxxxxx");
- strcat(vgrid[16], "c..cc..cc..cc$c.c.c*c.c.c.c9c9ccxxxxxxxx");
- strcat(vgrid[17], "c.cc..cc..cc.c.c|c.c.c.c.c$c.c9cxxxxxxxx");
- strcat(vgrid[18], "ccc..cc..cc.c.c.c.c.c.c.c.c.cc+cxxxxxxxx");
- strcat(vgrid[19], "cc..cc..cc.c*c.c.c.c.c.c$c.cc..cxxxxxxxx");
- strcat(vgrid[20], "c0.cc..cc.c.c.c.c8c.c*c.c.cc0.ccxxxxxxxx");
- strcat(vgrid[21], "c.cc..cc*c.c.c.c.c$c.c.c.cc..cccxxxxxxxx");
- strcat(vgrid[22], "c^c..cc.c.c9c.c.c.c.c.c.cc..cc.cxxxxxxxx");
- strcat(vgrid[23], "c0..cc$c.c.c*c0c.c.c.c.cc..cc.0cxxxxxxxx");
- strcat(vgrid[24], "c..cc.c.c9c.c.c.c$c.c.cc.9cc...cxxxxxxxx");
- strcat(vgrid[25], "c.cc9c.c.c.c.c.c.c.c.cc..cc..c^cxxxxxxxx");
- strcat(vgrid[26], "ccc.c.c$c.c.c.c.c.c$cc..cc..cc^cxxxxxxxx");
- strcat(vgrid[27], "cc$c.c.c.c.c$c.c0c.cc..cc..cc..cxxxxxxxx");
- strcat(vgrid[28], "c.c.c.c.c.c.c.c.c.cc9.cc..cc..ccxxxxxxxx");
- strcat(vgrid[29], "cc.c8c.c.c$c.c.c.cc..cc..cc0.cccxxxxxxxx");
- strcat(vgrid[30], "c.c$c.c$c0c.c.c.cc..cc..cc..cc$cxxxxxxxx");
- strcat(vgrid[31], "cc.c.c.c.c.c*c.cc..cc..cc..cc$$cxxxxxxxx");
- strcat(vgrid[32], "c.c.c.c.c.c.c.cc..cc0.cc..cc$$$cxxxxxxxx");
- strcat(vgrid[33], "cc.c.c.c.c.c$cc..cc..cc..cc$$$$cxxxxxxxx");
- strcat(vgrid[34], "c.c.c.c.c.c.cc.8.^..cc....+$$$$cxxxxxxxx");
- strcat(vgrid[35], "cccc@cccccccccccccccccccccccccccxxxxxxxx");
-
- return MAP_NORTHEAST;
-}
-
-static char vault_7(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // four-leaf vault
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxxxxxx.........^..^.........xxxxx");
- strcpy(vgrid[8], "xxxxxxxxxxxx...xxxxxxxx..xxxxxxxx...xxxx");
- strcpy(vgrid[9], "xxxxxxxxxxx...xxxxxxxxx..xxxxxxxxx...xxx");
- strcpy(vgrid[10], "xxxxxxxxxx...xx$*....xx..xx....$$xx...xx");
- strcpy(vgrid[11], "xxxxxxxxx...xx$*$....xx..xx....$*$xx...x");
- strcpy(vgrid[12], "xxxxxxxxx..xx*$*$....xx..xx....*$$$xx..x");
- strcpy(vgrid[13], "xxxxxxxxx..xx$$$.00..xx..xx..00.*$*xx..x");
- strcpy(vgrid[14], "xxxxxxxxx..xx....09..xx..xx..90....xx..x");
- strcpy(vgrid[15], "xxxxxxxxx..xx......+xx....xx+......xx..x");
- strcpy(vgrid[16], "xxxxxxxxx..xx......x^......^x......xx..x");
- strcpy(vgrid[17], "xxxxxxxxx..xxxxxxxxx........xxxxxxxxx..x");
- strcpy(vgrid[18], "xxxxxxxxx..xxxxxxxx..........xxxxxxxx..x");
- strcpy(vgrid[19], "xxxxxxxxx..............TT..............x");
- strcpy(vgrid[20], "xxxxxxxxx..............TT..............x");
- strcpy(vgrid[21], "xxxxxxxxx..xxxxxxxx..........xxxxxxxx..x");
- strcpy(vgrid[22], "xxxxxxxxx..xxxxxxxxx........xxxxxxxxx..x");
- strcpy(vgrid[23], "xxxxxxxxx..xx......x^......^x......xx..x");
- strcpy(vgrid[24], "xxxxxxxxx..xx......+xx....xx+......xx..x");
- strcpy(vgrid[25], "xxxxxxxxx..xx....09..xx..xx..90....xx..x");
- strcpy(vgrid[26], "xxxxxxxxx..xx$$*.00..xx..xx..00.*$$xx..x");
- strcpy(vgrid[27], "xxxxxxxxx..xx*$*$....xx..xx....*$$*xx..x");
- strcpy(vgrid[28], "xxxxxxxxx...xx*$*....xx..xx....$$$xx...x");
- strcpy(vgrid[29], "xxxxxxxxxx...xx*$....xx..xx....*$xx...xx");
- strcpy(vgrid[30], "xxxxxxxxxxx...xxxxxxxxx..xxxxxxxxx...xxx");
- strcpy(vgrid[31], "xxxxxxxxxxxx...xxxxxxxx..xxxxxxxx...xxxx");
- strcpy(vgrid[32], "xxxxxxxxxxxxx..^................^..xxxxx");
- strcpy(vgrid[33], "xxxxxxxxxxxxxxxxxxxxxxx^^xxxxxxxxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxxxxxxxxxxxxxxxx++xxxxxxxxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxxxxxxxxxxxxxxxx@xxxxxxxxxxxxxxxx");
-
- return MAP_NORTHWEST;
-}
-
-static char vault_8(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // cross vault
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxxxxxxxxxxx............xxxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxxxxxxxx..................xxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxxxxxx......................xxxxx");
- strcpy(vgrid[10], "xxxxxxxxxxxx..........w..w..........xxxx");
- strcpy(vgrid[11], "xxxxxxxxxxx........wwww++wwww........xxx");
- strcpy(vgrid[12], "xxxxxxxxxxx......wwwvvv^^vvvwww......xxx");
- strcpy(vgrid[13], "xxxxxxxxxx......wwwwv.9..9.vwwww......xx");
- strcpy(vgrid[14], "xxxxxxxxxx.....wwwwwv......vwwwww.....xx");
- strcpy(vgrid[15], "xxxxxxxxxx....wwwwwvv......vvwwwww....xx");
- strcpy(vgrid[16], "xxxxxxxxx....wwwwwvv........vvwwwww....x");
- strcpy(vgrid[17], "xxxxxxxxx....wwvvvv....vv....vvvvww....x");
- strcpy(vgrid[18], "xxxxxxxxx...wwwv......vvvv......vwww...x");
- strcpy(vgrid[19], "xxxxxxxxx...wwwv....vv8vv8vv....vwww...x");
- strcpy(vgrid[20], "xxxxxxxxx..wwwwv...vvvv||vvvv...vwwww..x");
- strcpy(vgrid[21], "xxxxxxxxx^^wwwwv...vvvv||vvvv...vwwww^^x");
- strcpy(vgrid[22], "xxxxxxxxx..wwwwv....vv8vv8vv....vwwww..x");
- strcpy(vgrid[23], "xxxxxxxxx...wwwv......vvvv......vwww...x");
- strcpy(vgrid[24], "xxxxxxxxx...wwwvvvv....vv....vvvvwww...x");
- strcpy(vgrid[25], "xxxxxxxxx....wwwwwvv........vvwwwww....x");
- strcpy(vgrid[26], "xxxxxxxxxx...wwwwwwvv......vvwwwwww...xx");
- strcpy(vgrid[27], "xxxxxxxxxx....wwwwwwv......vwwwwww....xx");
- strcpy(vgrid[28], "xxxxxxxxxx.....wwwwwv......vwwwww.....xx");
- strcpy(vgrid[29], "xxxxxxxxxxx.....wwwwvvvvvvvvwwww.....xxx");
- strcpy(vgrid[30], "xxxxxxxxxxx.......wwwwwwwwwwww.......xxx");
- strcpy(vgrid[31], "xxxxxxxxxxxx.........wwwwww.........xxxx");
- strcpy(vgrid[32], "xxxxxxxxxxxxx.........^..^.........xxxxx");
- strcpy(vgrid[33], "xxxxxxxxxxxxxxx.......x++x.......xxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxxxxxxxxxxx...xx..xx...xxxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxxxxxxxxxxxxxxx..@.xxxxxxxxxxxxxx");
-
- return MAP_NORTHWEST;
-}
-
-
-static char vault_9(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // another thingy vault
- UNUSED( mons_array );
-
- for (unsigned char i = 0; i < 81; i++)
- strcpy(vgrid[i], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- strcat(vgrid[36], "xxxxxxxxxxxxxxx@xxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[37], "xxxxxxxxxxxxxxx^xxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[38], "xxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[39], "xx.....^...............^.....xxxxxxxxxxx");
- strcat(vgrid[40], "x..bb..xxxxxxxxxxxxxxxxx..bb..xxxxxxxxxx");
- strcat(vgrid[41], "x..b...xxxxxxxxxxxxxxxxx...b..xxxxxxxxxx");
- strcat(vgrid[42], "x...b..xxxxbbbbbbbbbxxxx..b...xxxxxxxxxx");
- strcat(vgrid[43], "x..bb..xxbbb.......bbbxx..bb..xxxxxxxxxx");
- strcat(vgrid[44], "x......xxb....9.9....bxx......xxxxxxxxxx");
- strcat(vgrid[45], "x..bb..xbb..%$$$$$%..bbx..bb..xxxxxxxxxx");
- strcat(vgrid[46], "x...b..xb..0%$***$%0..bx..b...xxxxxxxxxx");
- strcat(vgrid[47], "x..b...xb..0%$*H*$%0..bx...b..xxxxxxxxxx");
- strcat(vgrid[48], "x...b..xb..0%$***$%0..bx..b...xxxxxxxxxx");
- strcat(vgrid[49], "x..b...xb...%$$$$$%...bx...b..xxxxxxxxxx");
- strcat(vgrid[50], "x...b..xbb.900000009.bbx..b...xxxxxxxxxx");
- strcat(vgrid[51], "x..b...xxb...........bxx...b..xxxxxxxxxx");
- strcat(vgrid[52], "x..bb..xxbbb..9.9..bbbxx..bb..xxxxxxxxxx");
- strcat(vgrid[53], "x......xxxxbbbb.bbbbxxxx......xxxxxxxxxx");
- strcat(vgrid[54], "x..bb..xxxxxxxb=bxxxxxxx..bb..xxxxxxxxxx");
- strcat(vgrid[55], "x..b...xxxxxxxx=xxxxxxxx...b..xxxxxxxxxx");
- strcat(vgrid[56], "x...b..xxxxxxxx^xxxxxxxx..b...xxxxxxxxxx");
- strcat(vgrid[57], "x..b....xxxxxxx=xxxxxxx....b..xxxxxxxxxx");
- strcat(vgrid[58], "x...b...^.............^...b...xxxxxxxxxx");
- strcat(vgrid[59], "x..b....xxxxxxxxxxxxxxx....b..xxxxxxxxxx");
- strcat(vgrid[60], "x..bb..xxxxxxxxxxxxxxxxx..bb..xxxxxxxxxx");
- strcat(vgrid[61], "xx....xxxxxxxxxxxxxxxxxxx....xxxxxxxxxxx");
- strcat(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- return MAP_SOUTHEAST;
-}
-
-
-static char vault_10(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // impenetrable vault
- UNUSED( mons_array );
-
- for (unsigned char i = 0; i < 81; i++)
- strcpy(vgrid[i], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- strcat(vgrid[36], "..............@................xxxxxxxxx");
- strcat(vgrid[37], "...............................xxxxxxxxx");
- strcat(vgrid[38], "...............................xxxxxxxxx");
- strcat(vgrid[39], "...............................xxxxxxxxx");
- strcat(vgrid[40], "...............................xxxxxxxxx");
- strcat(vgrid[41], ".....cccccccccccccccc..........xxxxxxxxx");
- strcat(vgrid[42], ".....c[^...........9cc.........xxxxxxxxx");
- strcat(vgrid[43], ".....c^xxxxx=xxxxxx..cc........xxxxxxxxx");
- strcat(vgrid[44], ".....c.x9..^^^...9xx..cc.......xxxxxxxxx");
- strcat(vgrid[45], ".....c.x.xxx=xxxx..xx..cc......xxxxxxxxx");
- strcat(vgrid[46], ".....c.x^x$$$$$$xx..xx.9c......xxxxxxxxx");
- strcat(vgrid[47], ".....c.=^=$*|||*$xx..xx.c......xxxxxxxxx");
- strcat(vgrid[48], ".....c.x^xx$*|||*$xx.9x.c......xxxxxxxxx");
- strcat(vgrid[49], ".....c.x9.xx$*|||*$xx^x.c......xxxxxxxxx");
- strcat(vgrid[50], ".....c.xx..xx$*|||*$=^=.c......xxxxxxxxx");
- strcat(vgrid[51], ".....c9.xx..xx$$$$$$x^x.c......xxxxxxxxx");
- strcat(vgrid[52], ".....cc..xx..xxxx=xxx.x.c......xxxxxxxxx");
- strcat(vgrid[53], "......cc..xx9...^^^..9x.c......xxxxxxxxx");
- strcat(vgrid[54], ".......cc..xxxxxx=xxxxx^c......xxxxxxxxx");
- strcat(vgrid[55], "........cc9...........^]c......xxxxxxxxx");
- strcat(vgrid[56], ".........cccccccccccccccc......xxxxxxxxx");
- strcat(vgrid[57], "...............................xxxxxxxxx");
- strcat(vgrid[58], "...............................xxxxxxxxx");
- strcat(vgrid[59], "...............................xxxxxxxxx");
- strcat(vgrid[60], "...............................xxxxxxxxx");
- strcat(vgrid[61], "...............................xxxxxxxxx");
- strcat(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- return MAP_SOUTHEAST;
-}
-
-
-static char orc_temple(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
- for (unsigned char i = 0; i < 81; i++)
- strcpy(vgrid[i], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- strcpy(vgrid[36], "xxxxxxxxxxxxxxxxxxxxxxx@xxxxxxxxxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxx");
- strcpy(vgrid[39], "xxxxxxxxxxxxxxxxxxxxxx4.4xxxxxxxxxxxxxxx");
- strcpy(vgrid[40], "xxxxxxxxx**..........x414x..........**xx");
- strcpy(vgrid[41], "xxxxxxxxx**..........x4.4x..........**xx");
- strcpy(vgrid[42], "xxxxxxxxx............+...+....4.......xx");
- strcpy(vgrid[43], "xxxxxxxxx....4..4....x...x............xx");
- strcpy(vgrid[44], "xxxxxxxxx............x...x.......4....xx");
- strcpy(vgrid[45], "xxxxxxxxx............xx.xx............xx");
- strcpy(vgrid[46], "xxxxxxxxx...4......xxxx+xxxx......6...xx");
- strcpy(vgrid[47], "xxxxxxxxx........xxx.......xxx........xx");
- strcpy(vgrid[48], "xxxxxxxxxxx...xxxx..2.....2..xxxx...xxxx");
- strcpy(vgrid[49], "xxxxxxxxxxxx+xxxx.............xxxx+xxxxx");
- strcpy(vgrid[50], "xxxxxxxxxxx...xxx.............xxx...xxxx");
- strcpy(vgrid[51], "xxxxxxxxx......x...............x......xx");
- strcpy(vgrid[52], "xxxxxxxxx..4...x...2...I...2...x...5..xx");
- strcpy(vgrid[53], "xxxxxxxxx......x...............x......xx");
- strcpy(vgrid[54], "xxxxxxxxx...4..xx.............xx..5...xx");
- strcpy(vgrid[55], "xxxxxxxxx$......x....2...2....x......$xx");
- strcpy(vgrid[56], "xxxxxxxxx$6..5..xx.....3.....xx.5...7$xx");
- strcpy(vgrid[57], "xxxxxxxxx$$$.....xxx.......xxx.....$$$xx");
- strcpy(vgrid[58], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[59], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[60], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[61], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_ORC_WARLORD;
- mons_array[1] = MONS_ORC_PRIEST;
- mons_array[2] = MONS_ORC_HIGH_PRIEST;
- mons_array[3] = MONS_ORC_WARRIOR;
- mons_array[4] = MONS_ORC_WIZARD;
- mons_array[5] = MONS_ORC_KNIGHT;
- mons_array[6] = MONS_ORC_SORCERER;
-
- return MAP_SOUTHWEST;
-}
-
-static char my_map(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // by Matthew Ludivico
-
- for (unsigned char i = 0; i < 81; i++)
- strcpy(vgrid[i], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- strcpy(vgrid[36], "xxxxxxxxxx.@.xxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxxxxx..........................xx");
- strcpy(vgrid[39], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..xx");
- strcpy(vgrid[40], "xxxxxxxxx.^^..........................xx");
- strcpy(vgrid[41], "xxxxxxxxxx.^^xx+xxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[42], "xxxxxxxxxxx.^...11....xxxxxxxx..xxxxxxxx");
- strcpy(vgrid[43], "xxxxxxxxxxxx..x.1..6..xxx........xx..xxx");
- strcpy(vgrid[44], "xxxxxxxxxxxxx.xxxxxxxxx...vvvvv...x...xx");
- strcpy(vgrid[45], "xxxxxxxxx6..1...x.........+1..v.......xx");
- strcpy(vgrid[46], "xxxxxxxxx..1....x.........vvvvv........x");
- strcpy(vgrid[47], "xxxxxxxxx..5...xx......................x");
- strcpy(vgrid[48], "xxxxxxxxxxxxxx^++...........vvvvvvv....x");
- strcpy(vgrid[49], "xxxxxxxxxxxxxx^xx...xx=xx...vv$%$vvvvv.x");
- strcpy(vgrid[50], "xxxxxxxxxxxxxx^x...xxv1vxx...vvv*2...v.x");
- strcpy(vgrid[51], "xxxxxxxxxxxxxx^x..vvvv7.vvvv...vv.vv+v^x");
- strcpy(vgrid[52], "xxxxxxxxx..xxx^..vvvb....bvvv...vvv^...x");
- strcpy(vgrid[53], "xxxxxxxxx%%.xx..vvvvb....bvvvv.......xxx");
- strcpy(vgrid[54], "xxxxxxxxxx.....vvbbb......bbbvv.....xxxx");
- strcpy(vgrid[55], "xxxxxxxxxxx....vvb....66....bvvxxxxxxxxx");
- strcpy(vgrid[56], "xxxxxxxxxxxxxxvvvb..llllll..bvvvxxxxxxxx");
- strcpy(vgrid[57], "xxxxxxxxxvvvvvvvvb..ll45ll..bvvvvvvvvxxx");
- strcpy(vgrid[58], "xxxxxxxxxccc***+== .l3.2.l..cccccccccxxx");
- strcpy(vgrid[59], "xxxxxxxxxccc+cccbb....ll....c..$$$$+$*cx");
- strcpy(vgrid[60], "xxxxxxxxxcc|||cbb...3llll2...cc%*%*c$|cx");
- strcpy(vgrid[61], "xxxxxxxxxcccccccbbbbbbbbbbbccccccccccccx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_HELL_HOUND;
- mons_array[1] = MONS_NECROMANCER;
- mons_array[2] = MONS_WIZARD;
- mons_array[3] = MONS_ORANGE_DEMON;
- mons_array[4] = MONS_ROTTING_DEVIL;
- mons_array[5] = MONS_HELL_KNIGHT;
- mons_array[6] = MONS_GREAT_ORB_OF_EYES;
-
- return MAP_SOUTHWEST;
-}
-
-static char farm_and_country(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // by Matthew Ludivico (mll6@lehigh.edu)
-
- for (unsigned char i = 0; i < 81; i++)
- strcpy(vgrid[i], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxxxxxxxxxx..........................................xxxxxxxx}.xxxxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxxxxxxxxxxxx............xxxxxx....xxx.......xx...........xxxx..]xxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxxxxxxxx***x...........xxx..xxx............xxxx...........xx..xxxxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxxxxxxxx|*$=...xx.xxxxxxx....xxxxxxxxxx......xx................xxxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxxxxxxxxxxxx....xxxxxxxx......3..xxx.................x..........xxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxxxxxxxxxxx......x........x......xx.........w...................xxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxxxx)......xx...xxx.....xxx......x........www3....3.............xxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxxxxx=xxxxxxxxxxx...xxxxxxxxx..xxx.....wwwww....%%%.............xxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxxx......xxx.......xx.xxxx.x...xxxxxxxwwwwwww..5%%%..........xx.xxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxx.........x..xxxxxxxx.....x........3wwwwwwwww..%%%........xxx..xxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxx....5...xx..x.xxxxx.....xxx........wwwwwwwww..%%%..........xx.xxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxxxx.....xxx..xx..xx........xxxxxxxxxwwwwwwwww..............xxx.xxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxxx........x..x...............xx..xxxxwwwwwwwwwwwwww............xxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxx.............................x.....xxwwwwww3wwwwww............xxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxxxx...x...........5.....7...............ww.......ww.....44....xxxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxxwxx..xx.....622...2.26...6.2...22.6...62..2..226ww.....44xx...xxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxxwwxxxx......2....2.22....2..2...2.2.......22...2ww....xxxx..xxxxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxxwwwwxxx......2...2.2.2...2.22..2.22...22.2.2..22ww.....xxx....xxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxxwwwwwx....4..2...2...........22...277..2..2.2.22ww...........xxxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxxwwwwwxx....42..2....22.4..2..2...2.4..2.22..22.2ww............xxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxxwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww.wwwwwwwwwwwww..2.........xxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxxwwwwwxx.....62....2.26...62.2.2..26...6...22..26..............xxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxxwwwww.........................................................xxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxxwwwwwxx....222.2.22..2.7.......7..............................xxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxxwwwww...........ccccccc+ccccccc...ccc......cc+ccc...xxxxx.....xxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxxwwwwwxx.........c$$*.c$$5$+.5.c...+5c......c%%%%c......xxx3...xxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxxwwwwwx....2.....c$.c+cccccc.%.c...ccc......c%%%%c....xxxxx....xxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxxwwwwwx..........c..c..........c............cccccc......xxx....xxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxxwwxxxxxxx.......ccccc+ccccccccc.........................xx....xxxxxxxxx");
- strcpy(vgrid[36], "xxxxxxxxxwxx.....xxxx........c...c.................2...................xxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxxxx.........xxxx...........2....xxxx...........................xxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxx..............xxxx..........xxxx..x...........................xxxxxxxxx");
- strcpy(vgrid[39], "xxxxxxxxx.................xxxxx++xxxxx.....xx............xx...x........xxxxxxxxx");
- strcpy(vgrid[40], "xxxxxxxxx.....................c..c..........xxxxx..........xxxxx.......xxxxxxxxx");
- strcpy(vgrid[41], "xxxxxxxxx.......cccc..........c..c...cccc......xxx...........x.........xxxxxxxxx");
- strcpy(vgrid[42], "xxxxxxxxx.......c..c..........c++c...c..c........xxx.........x.........xxxxxxxxx");
- strcpy(vgrid[43], "xxxxxxxxx.......c..c..........c..c...c..c..........xxx.................xxxxxxxxx");
- strcpy(vgrid[44], "xxxxxxxxx....cccc++cccccccccccc++ccccc..ccccccc......xxx...............xxxxxxxxx");
- strcpy(vgrid[45], "xxxxxxxxx....c..........1.....................c........xxx.............xxxxxxxxx");
- strcpy(vgrid[46], "xxxxxxxxx.cccc.....w....w....%1.....w.....%...c..........xxx...........xxxxxxxxx");
- strcpy(vgrid[47], "xxxxxxxxx.c1.+....www..www..%%%....www...%%%1.c...........xxxxxxxxx....xxxxxxxxx");
- strcpy(vgrid[48], "xxxxxxxxx.cccc.....w....w....%......w.....%...c..................xxx...xxxxxxxxx");
- strcpy(vgrid[49], "xxxxxxxxx....c.......5........................c....................xxxxxxxxxxxxx");
- strcpy(vgrid[50], "xxxxxxxxx....ccc....%%%%%....cccccccccccccccccc........................xxxxxxxxx");
- strcpy(vgrid[51], "xxxxxxxxx......cc...........cc.........................................xxxxxxxxx");
- strcpy(vgrid[52], "xxxxxxxxx.......cccccc+cccccc..........................................xxxxxxxxx");
- strcpy(vgrid[53], "xxxxxxxxx........cc.......cc...........................................xxxxxxxxx");
- strcpy(vgrid[54], "xxxxxxxxx.........cc.....cc.....................cccccccccccccccccccccccxxxxxxxxx");
- strcpy(vgrid[55], "xxxxxxxxx..........ccc+ccc......................c......vvv.............xxxxxxxxx");
- strcpy(vgrid[56], "xxxxxxxxx..........ccc.c........................c......v5+...vvvvv.....xxxxxxxxx");
- strcpy(vgrid[57], "xxxxxxxxx..........ccc.c........................c......vvv...v.5.v.....xxxxxxxxx");
- strcpy(vgrid[58], "xxxxxxxxxccccccccccccc.ccc......................c............v..5v.....xxxxxxxxx");
- strcpy(vgrid[59], "xxxxxxxxx..........c.....cccccccccccccccccccccccccccc..........vv+vv...xxxxxxxxx");
- strcpy(vgrid[60], "xxxxxxxxx..........c............................+................5111..xxxxxxxxx");
- strcpy(vgrid[61], "xxxxxxxxx..........c.{([.c......................+................5.....xxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_DEATH_YAK;
- mons_array[1] = MONS_PLANT;
- mons_array[2] = MONS_GRIFFON;
- mons_array[3] = MONS_KILLER_BEE;
- mons_array[4] = MONS_OGRE;
- mons_array[5] = MONS_OKLOB_PLANT;
- mons_array[6] = MONS_WANDERING_MUSHROOM;
-
- return MAP_ENCOMPASS;
-}
-
-
-static char fort_yaktaur(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // by Matthew Ludivico (mll6@lehigh.edu)
-
- for (unsigned char i = 0; i < 81; i++)
- strcpy(vgrid[i], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- strcat(vgrid[36], ".........@....wwwwwwwwwwwwwwwwwxxxxxxxxx");
- strcat(vgrid[37], ".ccccc.......ww....wwww....wwwwxxxxxxxxx");
- strcat(vgrid[38], ".c$c%c......ww.ccccccccc.......xxxxxxxxx");
- strcat(vgrid[39], ".c+c+c......ww.c.%$....ccccccccxxxxxxxxx");
- strcat(vgrid[40], ".c...+......ww.c*.115..c$$+|*|cxxxxxxxxx");
- strcat(vgrid[41], ".c1..c.....ww..c...55+ccc+cxx=cxxxxxxxxx");
- strcat(vgrid[42], ".ccccc.....ww..ccccccc....c|=*cxxxxxxxxx");
- strcat(vgrid[43], "............ww.......c5...cxx=cxxxxxxxxx");
- strcat(vgrid[44], "....6.ccccc.ww.w...2.+51..c|1.cxxxxxxxxx"); // last 1 here was 7
- strcat(vgrid[45], "....63+...c..wwww..21+51..c2.2cxxxxxxxxx");
- strcat(vgrid[46], "....6.ccccc..wwwwww..c5...cc+ccxxxxxxxxx");
- strcat(vgrid[47], "............wwwwwww..c........cxxxxxxxxx");
- strcat(vgrid[48], "............wwwwwww..ccccccccccxxxxxxxxx");
- strcat(vgrid[49], "...........ww1w..www...........xxxxxxxxx");
- strcat(vgrid[50], ".......566.www.....www.........xxxxxxxxx");
- strcat(vgrid[51], ".........1ww....ccccc..........xxxxxxxxx");
- strcat(vgrid[52], ".....566.w......+...c..........xxxxxxxxx");
- strcat(vgrid[53], ".........www....ccccc..........xxxxxxxxx");
- strcat(vgrid[54], "...........ww............wwwwwwxxxxxxxxx");
- strcat(vgrid[55], ".......3....wwwww......www.....xxxxxxxxx");
- strcat(vgrid[56], "......666.......ww...www.......xxxxxxxxx");
- strcat(vgrid[57], ".....cc+cc.......wwwww.........xxxxxxxxx");
- strcat(vgrid[58], ".....c...c.....................xxxxxxxxx");
- strcat(vgrid[59], ".....ccccc.....................xxxxxxxxx");
- strcat(vgrid[60], "...............................xxxxxxxxx");
- strcat(vgrid[61], "...............................xxxxxxxxx");
- strcat(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_YAKTAUR;
- mons_array[1] = MONS_DEATH_YAK;
- mons_array[2] = MONS_MINOTAUR;
- mons_array[3] = RANDOM_MONSTER;
- mons_array[4] = MONS_YAK;
- mons_array[5] = MONS_GNOLL;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_SOUTHEAST;
-}
-
-
-static char box_level(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // by John Savard
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxx.................xx.............x...................^.........xxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxx.................xx...xxxxxx....x.xxxxxxx.xxxxxxxxxxxxxxxxxxx.xxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxx.................xx...xx.0......x.x........x......x.........x.xxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxx..$..............xx...xx........x.x........x.....%x.x..*..xxx.xxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxx......................xx........x.x........x.xxxxxx.x.....x...xxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxx......................xx....%...x.x........x.x......xxxxxxx.x.xxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxx.................xx...xx........x.x........x.x.xxxxxx.......x.xxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxx.................xx...xx........x.x..{.....x.x..............x.xxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxx.............0...xx...xxxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxxxxxxxx.xxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxx.................xx...........................................xxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxx}x.........................>=........xxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxx..................x...xxx.x.xxx+xxxxxxxxxxxxxxxx+xxxxx........xxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxx..xxxxxxxxxxxxxx..x...xxx.x.x0...x..0..............0.x........xxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxx..x............x..x...xxx.x.x....x...................x........xxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxx....xxxxxxxxx..x..x...xxx.x.x....x...................x......8*xxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxx..x.x....0..x..x..x...xxx...x...%x...................x......*|xxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxx..x.x..........x..x...xxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxx..x.x*......x..x..x..........x...........0...x...%............xxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxx..x.xxxxxxxxx..x..=..........x.xxxxxxxxxxxxx.x................xxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxx..x......0.....xxxxxxx.......x.x...x...x...x.x................xxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxx..xxxxxxxxxxxxxxxxxxxx..0....x...x.x.x.x.x.x.x......0.........xxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxx..........^.........xx.......x.x.x.x.x.x.x...+................xxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxxcccccccccccccccccc..xx.......x.x$x...x...xxxxx................xxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxxc...........9....c..xx.......x.x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxxc......c............xx.......x.x.x...x..0.....................xxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxxc.....|c............xx.......x.x.x.x.x........................xxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxxc...........9....c..xx.......x.x...x.x........................xxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxxcccccccccccccccccc..xx.......x.xxxxx.x........................xxxxxxxxx");
- strcpy(vgrid[36], "xxxxxxxxx....................xx.......x.x.....=....................*...xxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxx....................xx.......x.x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.......x.x.x...........................(xxxxxxxxx");
- strcpy(vgrid[39], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxx.x$x..xxxx.xxxxxxxxxxxxxxxxxxxx.xxxxxxxxx");
- strcpy(vgrid[40], "xxxxxxxxx...............................x.x..x.......................x.xxxxxxxxx");
- strcpy(vgrid[41], "xxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.x..x.xxxxxxxxxxxxx.........x.xxxxxxxxx");
- strcpy(vgrid[42], "xxxxxxxxx.............)xxx................x..x.xxxxxxxxxxxxx.........x.xxxxxxxxx");
- strcpy(vgrid[43], "xxxxxxxxx..............xxx.xxxxxxxxxxxxxxxx..x.xxxxxxxxxxxxx.........x.xxxxxxxxx");
- strcpy(vgrid[44], "xxxxxxxxx..............xxx...................x.x...........xxxxx+xxxxx.xxxxxxxxx");
- strcpy(vgrid[45], "xxxxxxxxx..............xxxxxxxxxxxxxxxxxxxxxxx.x..$........x.........x.xxxxxxxxx");
- strcpy(vgrid[46], "xxxxxxxxx......9.......xxxxxxxxxxxxxxxxxxxxxxx.x...........x........%x.xxxxxxxxx");
- strcpy(vgrid[47], "xxxxxxxxx..............xxxxxxxxxxxxxxxxxxxxxxx.x.0.........x0........x.xxxxxxxxx");
- strcpy(vgrid[48], "xxxxxxxxx..............xxxxxxxxxxxxxxxxxxxxxxx.x.......$...x.........x.xxxxxxxxx");
- strcpy(vgrid[49], "xxxxxxxxx..............xxxxxxxxxxxxxxxxxxxxxxx.x...........xxxxxxxxxxx.xxxxxxxxx");
- strcpy(vgrid[50], "xxxxxxxxx..............xxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxx.x...........xxxxxxxxx");
- strcpy(vgrid[51], "xxxxxxxxx..............xxxxxxxxxxxxxxxxxxxxxxx.............x...........xxxxxxxxx");
- strcpy(vgrid[52], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx+xxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[53], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[54], "xxxxxxxxx.xxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxx.xxxxxxx=xxxxxx.xxxxxx.xxxxxxxxx");
- strcpy(vgrid[55], "xxxxxxxxx.....xx.................xxxxxxxxxxx.......x........x.....x....xxxxxxxxx");
- strcpy(vgrid[56], "xxxxxxxxx....0xx.................xxxxxxxxxxx.%.....x.0......x...0.x....xxxxxxxxx");
- strcpy(vgrid[57], "xxxxxxxxx.....xx.9...............xxxxxxxxxxx.......x........x.%...x..$.xxxxxxxxx");
- strcpy(vgrid[58], "xxxxxxxxx.....xx.................xxxxxxxxxxx.......x........x.....x....xxxxxxxxx");
- strcpy(vgrid[59], "xxxxxxxxx.....xx.................xxxxxxxxxxx.......x........x.....x..0.xxxxxxxxx");
- strcpy(vgrid[60], "xxxxxxxxx....0xx.................xxxxxxxxxxx.......x$.......x.....x....xxxxxxxxx");
- strcpy(vgrid[61], "xxxxxxxxx]....xx................*xxxxxxxxxxx......[x........x.....x$...xxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- return MAP_ENCOMPASS;
-}
-
-
-static char vestibule_map(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // this is the vestibule
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxvvvvvvvxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..v.....v..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.....v.....v.....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxxxxxxxxxxxxxxxxxxxxx........v.....v........xxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxxxxxxxxxxxxxxxxxxx..........v..A..v..........xxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxxxxxxxxxxxxxxxxx............v.....v............xxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxxxxxxxxxxxxxxxx.............v.....v.............xxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxxxxxxxxxxxxxxx..............vvv+vvv..............xxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxxxxxxxxxxxxxx.....................................xxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxxxxxxxxxxxxx.......................................xxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxxxxxxxxxxxx.........................................xxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxxxxxxxxxxx...........................................xxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxxxxxxxxxx.............................................xxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxxxxxxxxx...............................................xxxxxxxxxxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxxxxxxxx.................................................xxxxxxxxxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxxxxxxx...................................................xxxxxxxxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxxxxxx.....................................................xxxxxxxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxxxxxx.....................................................xxxxxxxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxxxxx.......................................................xxxxxxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxxxxx.......................................................xxxxxxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxxxx.........................................................xxxxxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxxxx............................{............................xxxxxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxxxx.........................................................xxxxxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxxx...l.l.....................................................xxxxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxxx..l.l.l.l..................................................xxxxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxxx.l.l.l.l.l.................................................xxxxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxx.l.l.l.l.l...................................................xxxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxxl.l.l.l.l.l..................................................xxxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxx.l.l.l.A.l.l.................}1].............................=Axxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxxl.l.l.l.l.l.l.................)..............................xxxxxxxxxx");
- strcpy(vgrid[36], "xxxxxxxxx.l.l.l.l.l.l.................................................xxxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxxx.l.l.l.l.l.l...............................................xxxxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxxx..l.l.l.l..................................................xxxxxxxxxxx");
- strcpy(vgrid[39], "xxxxxxxxxx.....l.l...................................................xxxxxxxxxxx");
- strcpy(vgrid[40], "xxxxxxxxxxx......................[...........(......................xxxxxxxxxxxx");
- strcpy(vgrid[41], "xxxxxxxxxxx.........................................................xxxxxxxxxxxx");
- strcpy(vgrid[42], "xxxxxxxxxxx.........................................................xxxxxxxxxxxx");
- strcpy(vgrid[43], "xxxxxxxxxxxx.......................................................xxxxxxxxxxxxx");
- strcpy(vgrid[44], "xxxxxxxxxxxx.......................................................xxxxxxxxxxxxx");
- strcpy(vgrid[45], "xxxxxxxxxxxxx.....................................................xxxxxxxxxxxxxx");
- strcpy(vgrid[46], "xxxxxxxxxxxxx.....................................................xxxxxxxxxxxxxx");
- strcpy(vgrid[47], "xxxxxxxxxxxxxx...................................................xxxxxxxxxxxxxxx");
- strcpy(vgrid[48], "xxxxxxxxxxxxxxx....................wwwww........................xxxxxxxxxxxxxxxx");
- strcpy(vgrid[49], "xxxxxxxxxxxxxxxx..................wwwwwwww.....................xxxxxxxxxxxxxxxxx");
- strcpy(vgrid[50], "xxxxxxxxxxxxxxxxx..............wwwwwwwwwwwww..................xxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[51], "xxxxxxxxxxxxxxxxxx...........w..wwww..wwwww..w...............xxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[52], "xxxxxxxxxxxxxxxxxxx..........w...ww.....ww..wwwww...........xxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[53], "xxxxxxxxxxxxxxxxxxxx.........ww......ww....wwwwwwwww.......xxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[54], "xxxxxxxxxxxxxxxxxxxxx.........ww....wwww...wwwwwwwwww.....xxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[55], "xxxxxxxxxxxxxxxxxxxxxx.........ww....ww....wwwwwwwwwww...xxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[56], "xxxxxxxxxxxxxxxxxxxxxxx........wwww.......wwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[57], "xxxxxxxxxxxxxxxxxxxxxxxx......wwwwwww....wwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[58], "xxxxxxxxxxxxxxxxxxxxxxxxxx...wwwwwwwwwwAwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[59], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxwwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[60], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[61], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_GERYON;
- mons_array[1] = RANDOM_MONSTER;
- mons_array[2] = RANDOM_MONSTER;
- mons_array[3] = RANDOM_MONSTER;
- mons_array[4] = RANDOM_MONSTER;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_ENCOMPASS;
-}
-
-
-static char castle_dis(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // Dispater's castle - rest of level filled up with plan_4 (irregular city)
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxv..............................................................vxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxv..vvvvvvvvv........................................vvvvvvvvv..vxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxv..v3.....|v........................................v|.....2v..vxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxv..v.vv+vvvv.v.v.v.v.v.v.v.v.v..v.v.v.v.v.v.v.v.v.v.vvvv+vv.v..vxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxv..v.v.....vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv.....v.v..vxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxv..v|v.....+$$v$$+$$v||vvvvvvvvvvvvvvvvv$$$$v4.4.v$$v.....v|v..vxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxv..vvvv+vvvv$$+$$v$$+||v...............v$$$$+.4.4+$$v+vv+vvvv..vxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxv....vv.vvvvvvvvvvvvvvvv.v..v..v..v..v.v$$$$v4.4.v$$+||v.vv5...vxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxv...vvv................v...............vvvvvvvvvvvvvvvvv.vvv...vxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxv...5vv................+...............+.................vv....vxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxv...vvv+vvvvvvvvvvvvvvvv.v..v..v..v..v.vvvvvvvvvvvvvvvvv.vvv...vxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxv....vv..v.+$$$$$v.....v...............vvvvvvvvvvvvvvvvv.vv5...vxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxv...vvv..v.v$$$$$v.....v...............vv|$|$|vv|$|$|$vv.vvv...vxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxv...5vv..v.vvvvvvv.....vvvvv.......vvvvvv$|$|$++$|$|$|vv.vv....vxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxv...vvv..v...............v.vvvv+vvvvvvvvvvvvvvvvvvvvv+vv.vvv...vxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxv....vvv+v..........vvvvv.4vvv...vvvvvvvvvvvvvvvvvvvv+vv.vv5...vxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxv...vvv..v.v..v..v....2vvv+vv5...5vvvvvvv.4.4.vv.4.4.4vv.vvv...vxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxv...5vv.................vv|vvv...vvvvv.++4.4.4++4.4.4.vv.vv....vxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxv...vvv.................1vOvv5...5vvvv.vvvvvvvvvvvvvvvvv.vvv...vxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxv....vv.................vv|vvv...vvvvv.vvvvvvvvvvvvvvvvv.vv5...vxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxv...vvv.v..v..v..v....3vvv+vv5...5vvvv...................vvv...vxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxv...5vv.............vvvvv.4vvv...vvvvvvvvvvvvvvvvvvvvvvv.vv....vxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxv..vvvv+vvvv.............v.vv5...5vvvvvvvvvvvvvvvvvvvvvv+vvvv..vxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxv..v|v.....vvvvvvvvvvvvvvvvvvv...vvvvvvvvvvvvvvvvvvvv.....v|v..vxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxv..v.v.....vvvvvvvvvvvvvvvvvvvv+vvvvvvvvvvvvvvvvvvvvv.....v.v..vxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxv..v.vv+vvvv5.............5.........5..............5vvvv+vv.v..vxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxv..v2.....|v........................................v|.....3v..vxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxv..vvvvvvvvv........................................vvvvvvvvv..vxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxv............................{.[.(.............................vxxxxxxxx");
-
- mons_array[0] = MONS_DISPATER;
- mons_array[1] = MONS_FIEND;
- mons_array[2] = MONS_ICE_FIEND;
- mons_array[3] = MONS_IRON_DEVIL;
- mons_array[4] = MONS_METAL_GARGOYLE;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_NORTH_DIS;
-}
-
-
-static char asmodeus(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxx....xxxxxxxxxxxxxxx.xxxxxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxxxxxxxxxxxxxxxxxx............................xxxxxxxxxxxxxx..xxxxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxxxxxxxxxxxxxxxxxxx..............................xxxxxxxxxx....xxxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxxxxxxxxxxxxxx...xxx................................xxxxxx....xxxxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxxxxx.x.xxxxx.........................................xxx....xxxxxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxxxxx....xx.....................4......................xx...xxxxxxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxxxx......x......................llllllllllllll.........x..xxxxxxxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxxxx..xx..................lllllllllllllllllllllllll........xxxxxxxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxxx...xxx....0..........llllllllllllllllllllllllll........xx...xxxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxx....xxx.............llllllllllllllllllllllllllll..............xxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxxx....xx...........lllllllllllllllllllllllllllll...............xxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxxxxx..............llllllllllllllllllllllllllllll...2..xx...0...xxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxxxxxx...........lllllllllllllllllll.......llllll......xx......xxxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxxxxxxx.......llllllllllllllllll............llllll.............xxxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxxxxxxxx......lllllllll..........4.........4.lllllll..........xxxxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxxx...xx...ll3lllll......4...................llllllll......x.xxxxxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxx.......lllll.l................................llll.......xxxxxxxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxxx..4..llllll...cccccccc+c+c+c+c+c+c+c+c+c+c....lll......xxxxxxxxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxxxx..lllllll..4.c.....c....................c....llll.....xxxxxxxxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxxx...llllll.....c.V.V.+....0.....3.....0...c.....llll....x..xxxxxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxx...llllll...l..c.....c....................c....lllll........xxxxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxxx...lllll..ll..c..5..cccccccccccccccccccccc.4..llllll........xxxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxx...lllll..llll.c.....c...............c....c....lllllll.......xxxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxx...lllll..llll.c.V.V.c.......0.......c....c....lllllll.......xxxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxxx...lllll..lll.c.....+...............+....c...lllllll........xxxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxxxx..lllll...ll.cccccccccc....0.......c....c...llllllll........xxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxxx...lllll..4...c|$$||$$|c............c.0..c...llllllll........xxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxx...lllll.......c$$$$$$$$cccccccccccccc....c...lllllll.........xxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxx...lllll.......c$$|2|$$|c..0.........+....c...lllllll........xxxxxxxxxx");
- strcpy(vgrid[36], "xxxxxxxxxx.lllllll......c|$$$$$$$c........9...c....c....llllllll.....xxxxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxxx.lllllll......c$|$|$$|$c+ccccccccccccccccc....lllllll......xxxxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxxx..llllll......cccccccc+c.....9.......c.........llllll......x.xxxxxxxxx");
- strcpy(vgrid[39], "xxxxxxxxxx..lllllll.....c$$$$$$+3c.....8...3...c.....4...llllll........xxxxxxxxx");
- strcpy(vgrid[40], "xxxxxxxxxx..llllllll....c$$$$$$c.c.....9.......c..ll....llllll.........xxxxxxxxx");
- strcpy(vgrid[41], "xxxxxxxxxx...llllll..4..c$$2$$$c.ccccccccccccc+c.lll...lllllll...0....xxxxxxxxxx");
- strcpy(vgrid[42], "xxxxxxxxxxx..llllll.....c$$$$$$c..+............c.ll...lllllll..........xxxxxxxxx");
- strcpy(vgrid[43], "xxxxxxxxxxx..llllllll...ccccccccc+cccccccccccccc.....lllllll...........xxxxxxxxx");
- strcpy(vgrid[44], "xxxxxxxxxxxx..llllllll.........cc..........cc........lllllll.......x..xxxxxxxxxx");
- strcpy(vgrid[45], "xxxxxxxxxxxxx.llllllllll.......ccc.........cc......lllllllll.......xxxxxxxxxxxxx");
- strcpy(vgrid[46], "xxxxxxxxxx....lllllllllll...4...cc.....2.2.cc....llllllllll.4.......xxxxxxxxxxxx");
- strcpy(vgrid[47], "xxxxxxxxx....4.lllllllllllll....cccccccc+cccc..lllllllllll.....xx....xxxxxxxxxxx");
- strcpy(vgrid[48], "xxxxxxxxxx.....llllllllllllll...cccccccc+cccc..llllllllll......xx....xxxxxxxxxxx");
- strcpy(vgrid[49], "xxxxxxxxxxx.....lllllllllllllll..cc......cc...lllllllllll...........xxxxxxxxxxxx");
- strcpy(vgrid[50], "xxxxxxxxxxx.....llllllllllllll...ccO1....cc.4..lllllllll...........xxxxxxxxxxxxx");
- strcpy(vgrid[51], "xxxxxxxxxxxx.....lllllllllllll...cc......cc....lllllllll.......xx.xxxxxxxxxxxxxx");
- strcpy(vgrid[52], "xxxxxxxxxxxx.......llllllllllll..cccccccccc...lllllllll........xxxxxxxxxxxxxxxxx");
- strcpy(vgrid[53], "xxxxxxxxx.........llllllllllllll.cccccccccc.lllllllllll.......xxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[54], "xxxxxxxxxx....0...llllllllllllll............lllllllll....0....xxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[55], "xxxxxxxxxx.......4.lllllllllllllll..4....lllllllll...........xxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[56], "xxxxxxxxxxx..........llllllllllllll....lllllll....4.....x........xxxxxxxxxxxxxxx");
- strcpy(vgrid[57], "xxxxxxxxxxx...xx.........lllllllllllllllll...................xx{xxxxxxxxxxxxxxxx");
- strcpy(vgrid[58], "xxxxxxxxxxxxx..xx................lllllll.....................xxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[59], "xxxxxxxxxxxxxxxxx.........xxx.................xxxxxx......xxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[60], "xxxxxxxxxxxxxxxxxxx....xxxxxxxx...xxx......xxxxxxxxxx.......xxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[61], "xxxxxxxxxxxxxxxxxxxx(xxxxxxxxxxxx[xxxxx...xxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_ASMODEUS;
- mons_array[1] = MONS_FIEND;
- mons_array[2] = MONS_BALRUG;
- mons_array[3] = MONS_MOLTEN_GARGOYLE;
- mons_array[4] = MONS_SERPENT_OF_HELL;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_ENCOMPASS;
-}
-
-static char antaeus(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // bottom of Cocytus. This needs work
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxxxxxxxxxxxxxxxxxxxxx........................xxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxxxxxxxxxxxxxxxxxxxx..........................xxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxxxxxxxxxxxxxxxxxxx............................xxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxxxxxxxxxxxxxxxxxx..............................xxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxxxxxxxxxxxxxxxxx................................xxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxxxxxxxxxxxxxxxx....cccccccccccc..cccccccccccc....xxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxxxxxxxxxxxxxxx....ccccccccccccc2.ccccccccccccc....xxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxxxxxxxxxxxxxx....cc..........................cc....xxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxxxxxxxxxxxxx....cc............................cc....xxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxxxxxxxxxxxx....cc...wwwwwwwwwwwwwwwwwwwwwwww...cc....xxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxxxxxxxxxxx....cc...wwwwwwwwwwwwwwwwwwwwwwwwww...cc....xxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxxxxxxxxxx....cc...wwwwwwwwwwwwwwwwwwwwwwwwwwww...cc....xxxxxxxxxxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxxxxxxxxx....cc...ww.......3..........3.......ww...cc....xxxxxxxxxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxxxxxxxx....cc...ww............................ww...cc....xxxxxxxxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxxxxxxx....cc...ww....cccccccccccccccccccccc....ww...cc....xxxxxxxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxxxxxx....cc...ww....cccccccccccccccccccccccc....ww...cc....xxxxxxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxxxxx....cc...ww....cc......................cc....ww...cc....xxxxxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxxxx....cc...ww....cc...T................T...cc....ww...cc....xxxxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxxx....cc...ww....cc..........wwwwww..........cc....ww...cc....xxxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxx....cc...ww....cc.......wwwwwwwwwwwwww.......cc....ww...cc....xxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxx....cc...ww...cc.....wwwwwwwwwwwwwwwwwwww.....cc...ww...cc....xxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxx....cc..www..cc....wwwwwwwwwccccccwwwwwwwww....cc..www..cc....xxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxx....cc..www.cc....wwwwwwwwccc2O12cccwwwwwwww....cc.www..cc....xxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxx....cc..www.cc...wwwwwwwwcc2+....+2ccwwwwwwww...cc.www..cc....xxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxx....cc..www.cc...wwwwwwwwcc+cc++cc+ccwwwwwwww...cc.www..cc....xxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxx....cc..www..c..wwwwwwwwwc|||c..c$$$cwwwwwwwww..c..www..cc....xxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxx....cc..wwww.c.wwwwwwwwwwc|||c..c$$$cwwwwwwwwww.c.wwww..cc....xxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxx....cc..wwww.c.wwwwwwwwwwcc||c..c$$ccwwwwwwwwww.c.wwww..cc....xxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxx....cc..wwww.c.wwwwwwwwwwwcccc++ccccwwwwwwwwwww.c.wwww..cc....xxxxxxxxx");
- strcpy(vgrid[36], "xxxxxxxxx....cc..www..c..wwwwwwwwwwwwww..wwwwwwwwwwwwww..c..www..cc....xxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxx....cc..www.cc...wwwwwwwwwwwwwwwwwwwwwwwwwwww...cc.www..cc....xxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxx....cc..www.cc....wwwwwwwwwwwwwwwwwwwwwwwwwww...cc.www..cc....xxxxxxxxx");
- strcpy(vgrid[39], "xxxxxxxxx....cc..www.cc....wwwwwwwwwwwwwwwwwwwwwwwwww....cc.www..cc....xxxxxxxxx");
- strcpy(vgrid[40], "xxxxxxxxx....cc..www..cc....wwwwwwwwwwwwwwwwwwwwwwww....cc..www..cc....xxxxxxxxx");
- strcpy(vgrid[41], "xxxxxxxxx....cc...ww...cc.....wwwwwwwwwwwwwwwwwwww.....cc...ww...cc....xxxxxxxxx");
- strcpy(vgrid[42], "xxxxxxxxx....cc...ww....cc.......wwwwwwwwwwwwww.......cc....ww...cc....xxxxxxxxx");
- strcpy(vgrid[43], "xxxxxxxxxx....cc...ww....cc..........wwwwww..........cc....ww...cc....xxxxxxxxxx");
- strcpy(vgrid[44], "xxxxxxxxxxx....cc...ww....cc...T................T...cc....ww...cc....xxxxxxxxxxx");
- strcpy(vgrid[45], "xxxxxxxxxxxx....cc...ww....cc......................cc....ww...cc....xxxxxxxxxxxx");
- strcpy(vgrid[46], "xxxxxxxxxxxxx....cc...ww....ccccccccccc..ccccccccccc....ww...cc....xxxxxxxxxxxxx");
- strcpy(vgrid[47], "xxxxxxxxxxxxxx....cc...ww....cccccccccc2.cccccccccc....ww...cc....xxxxxxxxxxxxxx");
- strcpy(vgrid[48], "xxxxxxxxxxxxxxx....cc...ww............................ww...cc....xxxxxxxxxxxxxxx");
- strcpy(vgrid[49], "xxxxxxxxxxxxxxxx....cc...ww..........................ww...cc....xxxxxxxxxxxxxxxx");
- strcpy(vgrid[50], "xxxxxxxxxxxxxxxxx....cc...wwwwwwwwwwwww..wwwwwwwwwwwww...cc....xxxxxxxxxxxxxxxxx");
- strcpy(vgrid[51], "xxxxxxxxxxxxxxxxxx....cc...wwwwwwwwwwww..wwwwwwwwwwww...cc....xxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[52], "xxxxxxxxxxxxxxxxxxx....cc...wwwwwwwwwww..wwwwwwwwwww...cc....xxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[53], "xxxxxxxxxxxxxxxxxxxx....cc............................cc....xxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[54], "xxxxxxxxxxxxxxxxxxxxx....cc..........................cc....xxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[55], "xxxxxxxxxxxxxxxxxxxxxx....cccccccccccccccccccccccccccc....xxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[56], "xxxxxxxxxxxxxxxxxxxxxxx....cccccccccccccccccccccccccc....xxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[57], "xxxxxxxxxxxxxxxxxxxxxxxx................................xxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[58], "xxxxxxxxxxxxxxxxxxxxxxxxx..............................xxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[59], "xxxxxxxxxxxxxxxxxxxxxxxxxx............................xxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[60], "xxxxxxxxxxxxxxxxxxxxxxxxxxx..........{.(.[...........xxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[61], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_ANTAEUS;
- mons_array[1] = MONS_ICE_FIEND;
- mons_array[2] = MONS_ICE_DRAGON;
- mons_array[3] = RANDOM_MONSTER;
- mons_array[4] = RANDOM_MONSTER;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_ENCOMPASS;
-}
-
-
-static char ereshkigal(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // Tartarus
- // note that the tomb on the right isn't supposed to have any doors
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxx.................cccc..........ccc............................xxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxx.............ccccc..cccc.....ccc.cccc.........................xxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxx...........ccc.........ccccccc.....cc.........................xxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxx.........ccc.......2............V..cc.........................xxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxx........cc4........................cc...........xxxxxxxx......xxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxx........cc44xxx==xxx...............cc..........xx......xx.....xxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxx........ccxxx......xxx.......ccc++ccc.........xx........xx....xxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxx........cxx..........xxx.....ccc44ccc.........x..........x....xxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxx........cx............xx....cccc44cc.........xx..........xx...xxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxx.......ccx.G........G.xxx7ccc..c44c..........x.....|......x...xxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxx.......cxx............xxxcc..................x......7.....x...xxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxx......ccx..............xxc...................xx..........xx...xxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxx......ccx..G........G..xxc..x.........x.......x..........x....xxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxx......ccx..............xcc....................xx........xx....xxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxx.......cxx............xxc......................xx......xx.....xxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxx.......ccx.F........F.xcc.......................xxxxxxxx......xxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxx........cx............xc......................................xxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxx........cxx....17....xxc....x.........x.......................xxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxx........ccxxx......xxxcc......................................xxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxx........cccc=xxxxxx=cccc......................................xxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxx........cc||cccccccc||cc......................................xxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxx.........cc||||O|||||cc.......................................xxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxx..........cccccccccccc......x.........x............V..........xxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxx...........................................xxxxxxxxxxxxxxxx...xxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxx...........................................xxxxxxxxxxxxxxxx...xxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxx...........................................xx$$$$xxx|||||xx...xxxxxxxxx");
- strcpy(vgrid[36], "xxxxxxxxx.......V........V...........x.........x....xx$$$$xxx|||||xx...xxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxx...........................................xxxxxxxxxxxxxxxx...xxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxx...........................................xxxxxxxxxxxxxxxx...xxxxxxxxx");
- strcpy(vgrid[39], "xxxxxxxxx...........................................xx44444xx22222xx...xxxxxxxxx");
- strcpy(vgrid[40], "xxxxxxxxx.......xxxxxxxxx+xxxxxxxxx.................xx44444xx22222xx...xxxxxxxxx");
- strcpy(vgrid[41], "xxxxxxxxx.......x3.2..........3...x..x.........x..xxxxxxxxxxxxxxxxxx...xxxxxxxxx");
- strcpy(vgrid[42], "xxxxxxxxx.......x.x.x.x.x.x.x.x.x.x.................xxxxxxxxxxxxxxxx...xxxxxxxxx");
- strcpy(vgrid[43], "xxxxxxxxx.......x...2.3..4..5..4..x......................=.......xxx...xxxxxxxxx");
- strcpy(vgrid[44], "xxxxxxxxx.......xx.x.x.x.x.x.x.x.xx......................=.......xxx...xxxxxxxxx");
- strcpy(vgrid[45], "xxxxxxxxx.......x..65..3..6.6...5.x.................xxxxxxxxxxxxxxxx...xxxxxxxxx");
- strcpy(vgrid[46], "xxxxxxxxx.......x.x.x.x.x.x.x.x.x.x..x.........x..xxxxxxxxxxxxxxxxxx...xxxxxxxxx");
- strcpy(vgrid[47], "xxxxxxxxx.......x...4...3.....4...x.................xx.....xx555555x...xxxxxxxxx");
- strcpy(vgrid[48], "xxxxxxxxx.......xx=xxxxx.x.xxxxxxxx.................xx.....xx555555x...xxxxxxxxx");
- strcpy(vgrid[49], "xxxxxxxxx.......x$$$$$$x.25.x$$$||x.................xxxxxxxxxxxxxxxx...xxxxxxxxx");
- strcpy(vgrid[50], "xxxxxxxxx.......x$x$$x$xx.x.x$x$x|x.................xxxxxxxxxxxxxxxx...xxxxxxxxx");
- strcpy(vgrid[51], "xxxxxxxxx.......x||||||x.556=$$$||x..x.........x....xx$$xx56565xx$|x...xxxxxxxxx");
- strcpy(vgrid[52], "xxxxxxxxx.......xxxxxxxxxxxxxxxxxxx.................xx$$xx65656xx|7x...xxxxxxxxx");
- strcpy(vgrid[53], "xxxxxxxxx...........................................xxxxxxxxxxxxxxxx...xxxxxxxxx");
- strcpy(vgrid[54], "xxxxxxxxx...........................................xxxxxxxxxxxxxxxx...xxxxxxxxx");
- strcpy(vgrid[55], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[56], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[57], "xxxxxxxxx........(...........................................[.........xxxxxxxxx");
- strcpy(vgrid[58], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[59], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[60], "xxxxxxxxx..............................{...............................xxxxxxxxx");
- strcpy(vgrid[61], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_ERESHKIGAL;
- mons_array[1] = MONS_NECROPHAGE;
- mons_array[2] = MONS_WRAITH;
- mons_array[3] = MONS_SHADOW;
- mons_array[4] = MONS_ZOMBIE_SMALL;
- mons_array[5] = MONS_SKELETON_SMALL;
- mons_array[6] = MONS_SHADOW_FIEND;
-
- return MAP_ENCOMPASS;
-}
-
-
-static char mnoleg(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
-
- for (unsigned char i = 0; i < 81; i++)
- strcpy(vgrid[i], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- strcat(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[7], "x.................2............xxxxxxxxx");
- strcat(vgrid[8], "x.....2........................xxxxxxxxx");
- strcat(vgrid[9], "x..cccccccc...ccccccc..ccccccc.xxxxxxxxx");
- strcat(vgrid[10], "x..ccccccccc.2.ccccccc..cccccc.xxxxxxxxx");
- strcat(vgrid[11], "x..cccccccccc...ccccccc..ccccc.xxxxxxxxx");
- strcat(vgrid[12], "x..ccccccccccc.1.ccccccc..cccc.xxxxxxxxx");
- strcat(vgrid[13], "x2.cccccccccc.2..Occccccc2.ccc.xxxxxxxxx");
- strcat(vgrid[14], "x..ccccccccc.....ccccccccc..cc.xxxxxxxxx");
- strcat(vgrid[15], "x..cccccccc...c...ccccccccc..c.xxxxxxxxx");
- strcat(vgrid[16], "x..ccccccc...ccc...ccccccccc...xxxxxxxxx");
- strcat(vgrid[17], "x..cccccc...ccccc...ccccccccc..xxxxxxxxx");
- strcat(vgrid[18], "x..ccccc...ccccccc...ccccccccc.xxxxxxxxx");
- strcat(vgrid[19], "x..cccc...ccccccccc...ccccccc..xxxxxxxxx");
- strcat(vgrid[20], "x..ccc.2.ccccccccccc.2.ccccc...xxxxxxxxx");
- strcat(vgrid[21], "x..cc.....ccccccccccc...ccc....xxxxxxxxx");
- strcat(vgrid[22], "x..c...c...ccccccccccc...c.2...xxxxxxxxx");
- strcat(vgrid[23], "x.....ccc.2.ccccccccccc......c.xxxxxxxxx");
- strcat(vgrid[24], "x....ccccc...ccccccccccc....cc.xxxxxxxxx");
- strcat(vgrid[25], "x.2.ccccccc...ccccccccccc..ccc.xxxxxxxxx");
- strcat(vgrid[26], "x.................2.......cccc.xxxxxxxxx");
- strcat(vgrid[27], "x...c..ccccccc.ccccccc...ccccc.xxxxxxxxx");
- strcat(vgrid[28], "x..ccc......2c.c2cccc...cccccc.xxxxxxxxx");
- strcat(vgrid[29], "x.ccccc..ccc.c.c2ccc.2.ccccccc.xxxxxxxxx");
- strcat(vgrid[30], "x.cccccc..cc.c.c.cc...cccccccc.xxxxxxxxx");
- strcat(vgrid[31], "x.ccccccc..c.c.c.c...ccccccccc.xxxxxxxxx");
- strcat(vgrid[32], "x.cccccccc...c.c....cccccccccc.xxxxxxxxx");
- strcat(vgrid[33], "x.ccccccccc..c.c...ccccccccccc.xxxxxxxxx");
- strcat(vgrid[34], "x..............................xxxxxxxxx");
- strcat(vgrid[35], "xxxxxxxxxxxxxx@xxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_MNOLEG;
- mons_array[1] = MONS_NEQOXEC;
- mons_array[2] = RANDOM_MONSTER;
- mons_array[3] = RANDOM_MONSTER;
- mons_array[4] = RANDOM_MONSTER;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_NORTHEAST;
-}
-
-
-static char lom_lobon(char vgrid[81][81], FixedVector<int, 7>& mons_array)
+static int write_vault(const map_def &mdef, map_type map,
+ FixedVector<int, 7> &marray,
+ vault_placement &place)
{
+ place.map = &mdef;
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxxxxxxxxxxxxxxxxxxxxwwwwwwwwwwww.......wwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxxxxxxxxxxxxxxxwwwwwwwwwwwwbbbwwwwwww.......wwwwwwwxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxxxxxxxxxxxwwwwwwwwwwwwbbbbbbbbbbbwwwwww.........wwwwwwxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxxxxxxxxwwwwwwwwwwwwbbbbwwwwwwwwwbbbbwwwwww.........wwwwwwxxxxxxxxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxxxxxxwwwwwwwbbbbbbbbwwwwwwwwwwwwwwwbbbwwwww...........wwwwwxxxxxxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxxxxxwwwwwbbbb......bbbwwwwwwwwwwww...bbwwwww.............wwwxxxxxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxxxxxwwwbbb...........bbbwwwwww........bbwwwww.............wwxxxxxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxxxxwwwbb...............bbwwww..........bwwwwww.............wwxxxxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxxxxwwbb........1O.......bbww...........bbwwww..............wwxxxxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxxxwwwb...................bw......2......bwww.....U....2.....wwxxxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxxxwwbb...................bb.............bww.................wwxxxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxxxwwbb..3................bbb............bbw..............4..wwxxxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxxwwbbb...................b.b............4....................wwxxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxxwwbwbb.................bb.......U......4..........U..........wxxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxxwwbwwbb...............bb..b............bbw..............4.....xxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxxwwbbwwbbb...........bbb..bb............bwww...................xxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxxwwwbwwwwb..b..2..bbbb....b.............bwww...................xxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxxxwwbwwww...bbbbbbb.......bw.....3.....bbwwww...U.....3.......xxxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxxxwwbbww.................bbww........wwbwwwww.................xxxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxxxwwwbbw................bbwwwww....wwwbbwwww..................xxxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxxxwwwwbb...4...U........bwwwwwwwwwwwwbbwww....................xxxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxxxxwwwwbbb...........bbbbbwwwwwwwwwbbbwww....................xxxxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxxxxwwwwwwbbbb.....bbbbwwwbbbbwwwbbbbwwww....................xxxxxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxxxxwwwwwwwwwbbbbbbbwwwwwwwwwbbbbbwwwww......4.....4........xxxxxxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxxxxxwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww......................xxxxxxxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxxxxxwwwwwwwwwwwwwwwwwwwwwwwwwwwww.......................xxxxxxxxxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxxxxxxxwwwwwwwwwwwwwwwwwwwww........................xxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxxxxxxxxxxxxxxxxxxwwwwwww......................xxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...@.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_LOM_LOBON;
- mons_array[1] = MONS_GIANT_ORANGE_BRAIN;
- mons_array[2] = MONS_RAKSHASA;
- mons_array[3] = MONS_WIZARD;
- mons_array[4] = RANDOM_MONSTER;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_NORTH;
-}
-
-
-static char cerebov(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // you might not want to teleport too much on this level -
- // unless you can reliably teleport away again.
-
- for (unsigned char i = 0; i < 81; i++)
- strcpy(vgrid[i], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- strcat(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[7], "...............................xxxxxxxxx");
- strcat(vgrid[8], ".............vvvvv.............xxxxxxxxx");
- strcat(vgrid[9], ".............v$$$v.............xxxxxxxxx");
- strcat(vgrid[10], ".............v|||v.............xxxxxxxxx");
- strcat(vgrid[11], ".............v$$$v.............xxxxxxxxx");
- strcat(vgrid[12], ".vvvvv...vvvvvvvvvvvvv...vvvvv.xxxxxxxxx");
- strcat(vgrid[13], ".v|$|vvvvv...........vvvvv$|$v.xxxxxxxxx");
- strcat(vgrid[14], ".v$|$v.....vvvvvvvvv.....v|$|v.xxxxxxxxx");
- strcat(vgrid[15], ".v|$|v.vvvvvvvvOvvvvvvvv.v$|$v.xxxxxxxxx");
- strcat(vgrid[16], ".vvvvv.vvvvvv..3..vvvvvv.vvvvv.xxxxxxxxx");
- strcat(vgrid[17], "...v...vv.....vvv.....vv...v...xxxxxxxxx");
- strcat(vgrid[18], "...v.vvvv....vv1vv....vvvv.v...xxxxxxxxx");
- strcat(vgrid[19], "...v.vv......v...v......vv.v...xxxxxxxxx");
- strcat(vgrid[20], "...v.vvvv.............vvvv.v...xxxxxxxxx");
- strcat(vgrid[21], "...v...vv..2.......2..vv...v...xxxxxxxxx");
- strcat(vgrid[22], ".vvvvv.vv..2.......2..vv.vvvvv.xxxxxxxxx");
- strcat(vgrid[23], ".v|$|v.vv.............vv.v$|$v.xxxxxxxxx");
- strcat(vgrid[24], ".v|$|v.vv...vv...vv...vv.v$|$v.xxxxxxxxx");
- strcat(vgrid[25], ".v|$|v.vv...vv+++vv...vv.v$|$v.xxxxxxxxx");
- strcat(vgrid[26], ".vvvvv.vvvvvvv...vvvvvvv.vvvvv.xxxxxxxxx");
- strcat(vgrid[27], "....v..vvvvvvv...vvvvvvv..v....xxxxxxxxx");
- strcat(vgrid[28], "....vv...................vv....xxxxxxxxx");
- strcat(vgrid[29], ".....vv.vvvvv..2..vvvvv.vv.....xxxxxxxxx");
- strcat(vgrid[30], "......vvv|||v.....v$$$vvv......xxxxxxxxx");
- strcat(vgrid[31], "........v|$|vv...vv$|$v........xxxxxxxxx");
- strcat(vgrid[32], "........v|||v.....v$$$v........xxxxxxxxx");
- strcat(vgrid[33], "........vvvvv.....vvvvv........xxxxxxxxx");
- strcat(vgrid[34], "...............................xxxxxxxxx");
- strcat(vgrid[35], "...............@...............xxxxxxxxx");
-
- mons_array[0] = MONS_CEREBOV;
- mons_array[1] = MONS_BALRUG;
- mons_array[2] = MONS_PIT_FIEND;
- mons_array[3] = RANDOM_MONSTER;
- mons_array[4] = RANDOM_MONSTER;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_NORTHEAST;
-}
-
-
-static char gloorx_vloq(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
-
- for (unsigned char i = 0; i < 81; i++)
- strcpy(vgrid[i], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- strcpy(vgrid[36], "xxxxxxxxxxxxxxxxxxxxxxx@.xxxxxxxxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxx..............................x");
- strcpy(vgrid[38], "xxxxxxxxx..............................x");
- strcpy(vgrid[39], "xxxxxxxxx..............................x");
- strcpy(vgrid[40], "xxxxxxxxx.x.x.x.x.x.x.x..x.x.x.x.x.x.x.x");
- strcpy(vgrid[41], "xxxxxxxxx..............................x");
- strcpy(vgrid[42], "xxxxxxxxx.x.xxxx=xxxxxxxxxxxx=xxxxxx.x.x");
- strcpy(vgrid[43], "xxxxxxxxx...xx....................xx...x");
- strcpy(vgrid[44], "xxxxxxxxx.x.x..ccccc..4..4..ccccc..x.x.x");
- strcpy(vgrid[45], "xxxxxxxxx...x.cc.3............3.cc.x...x");
- strcpy(vgrid[46], "xxxxxxxxx.x.x.c..ccccc.cc.ccccc..c.x.x.x");
- strcpy(vgrid[47], "xxxxxxxxx...x.c.cc.....cc.....cc.c.x...x");
- strcpy(vgrid[48], "xxxxxxxxx.x.x.c.c.2...cccc...2.c.c.x.x.x");
- strcpy(vgrid[49], "xxxxxxxxx...x...c...ccc..ccc...c...=...x");
- strcpy(vgrid[50], "xxxxxxxxx.x.x.3.....2..1O..2.....3.x.x.x");
- strcpy(vgrid[51], "xxxxxxxxx...=...c...ccc..ccc...c...x...x");
- strcpy(vgrid[52], "xxxxxxxxx.x.x.c.c.2...cccc...2.c.c.x.x.x");
- strcpy(vgrid[53], "xxxxxxxxx...x.c.cc.....cc.....cc.c.x...x");
- strcpy(vgrid[54], "xxxxxxxxx.x.x.c..ccccc.cc.ccccc..c.x.x.x");
- strcpy(vgrid[55], "xxxxxxxxx...x.cc.3............3.cc.x...x");
- strcpy(vgrid[56], "xxxxxxxxx.x.x..ccccc..4..4..ccccc..=.x.x");
- strcpy(vgrid[57], "xxxxxxxxx...xx....................xx...x");
- strcpy(vgrid[58], "xxxxxxxxx.x.xxxx=xxxx=xxxxxxxx=xxxxx.x.x");
- strcpy(vgrid[59], "xxxxxxxxx..............................x");
- strcpy(vgrid[60], "xxxxxxxxx.x.x.x.x.x.x.x..x.x.x.x.x.x.x.x");
- strcpy(vgrid[61], "xxxxxxxxx..............................x");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_GLOORX_VLOQ;
- mons_array[1] = MONS_EXECUTIONER;
- mons_array[2] = MONS_DEMONIC_CRAWLER;
- mons_array[3] = MONS_SHADOW_DEMON;
- mons_array[4] = RANDOM_MONSTER;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_SOUTHWEST;
-}
-
-
-static char beehive(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxaaaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxxxxxxxxxxxxxxxaaaaaaaaaaaRaaaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxxxxxxxxxxaaaaaaaaaaRa2aaR1RaaRa2aaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxxxxxxxxxxxaaaaaaaaaaRa2a3R3aRaRaRaaaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxxxxxxxxxxxxxxaaaaRaRaRaaa3aaa3aRa.a.aaaaaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxxxxxxxxxaaaaaaRa.aRa2a2a2a2aRaRa.a.a3aaaaaaaaaaaaaaxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxxxxxx4aaaaaaaaa.aaRaRaa2aa2aaRaaa.aa3a33aaaaaaaaaa.44xxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxxxx.4aaaaaaa.222a3a.aaaRaaa.aaa.R3aa3a3aaaaaaaa.....4xxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxxx....aaaaaaa.aRa.a3aRaRa.a3a.a.a.a.aRa2aaaaaa....xxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxxxx...aaaaaa3a3a.a.a.a3aRa2aRa3a.a.aRaRa.aaaaa...xxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxxxxx...aa2aRa3a3a3aRa.a3a.a.a.a.a.a.a.a3a.aaa...xxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxxxxx...aaa.a.a.a2a.aaa.aRaRa2a.a2a3a.a2aaaa..T..xxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxxxx.....a2a.a2a.aRaaaaa3a.a.aaa3a3a3a3a.a.........xxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxxxx.4...aaRRaa.a2a.a3a3a3a.aaa.a.aRa.a.aa..4.......xxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxxx......a.a.aaa.a3a.a.a.a.aaa2a.a2a.a.aRaa.....4...xxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxxx.....aa3a2aaa.a.a.a3a3a3a3aRaaa.a2a.a2aa........xxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxxxx...aaaa.a2aRa.a.a2aaa.a.a.a.aaa.a.aaaa.....xxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxxxxx..aaa.a.a.a.a.a.a.aaa2a.a3a2a.a2aaa.....xxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxxxxxxx.aaaa3a.a2aRa.a.aaaRa.a.aa.a.aaa....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxxxxxxxx...aaaaRa.a3a3a.a.a.aaa.aa.aa....4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxxxxxx........aa.a2a.a.aaa2aa.aa.aaa....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxxxxxx....4.....a.a2a2a.a2a.a2a.......4.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxxxx.............a.a.a.a.a.a.....4....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxxx..............4..a.a.a......4...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxxx.................a.a.........xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxxxx........................xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxxxx.....4...T............xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[36], "xxxxxxxxxxx.......................xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxxxxx.........................xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxxxxx.................T.........xxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[39], "xxxxxxxxxxxx.......4.....................xxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[40], "xxxxxxxxxxx..............xx...............xxxxxx....xxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[41], "xxxxxxxxxxx............xxxxx........4......xxxx..4....xxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[42], "xxxxxxxxxxx..T..........xxx................xxxxx...T.xxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[43], "xxxxxxxxxxx............xxx........T.........xxx........xxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[44], "xxxxxxxxxxx....4........xx....................x..........xxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[45], "xxxxxxxxxx...............x.x...xxx...............xx.xxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[46], "xxxxxxxxxx.........4...........xxx..................xxxxxxxxxxxxxxxxxxaaaaaxxxxx");
- strcpy(vgrid[47], "xxxxxxxxx.....4.....................4......4...........4...xxxxxxxxxxaa5a5aaxxxx");
- strcpy(vgrid[48], "xxxxxxxxx.................................................wwwwwwwwxxxa5*|*5axxxx");
- strcpy(vgrid[49], "xxxxxxxxx............x...x...T.....xxxx.................wwwwwwwwwwwwxaa*|*aaxxxx");
- strcpy(vgrid[50], "xxxxxxxxxx.........xx.............xxxxx................wwwwwwwwwwwwwwxaa5aaxxxxx");
- strcpy(vgrid[51], "xxxxxxxxxxx.......x..................xxx....4..........wwwwwwwwwwwwwwwxa5axxxxxx");
- strcpy(vgrid[52], "xxxxxxxxxxx.....xxx...4...........................xxxx.4wwwwwwwwwwwwwwwa=axxxxxx");
- strcpy(vgrid[53], "xxxxxxxxxxxx..xxx.............xx....(.........xxxxxxxx....wwwwwwwwwwwwwwaaxxxxxx");
- strcpy(vgrid[54], "xxxxxxxxxxxxxxxx.............xxxx..................xxxx......wwwwwwwwwwxxxxxxxxx");
- strcpy(vgrid[55], "xxxxxxxxxxxxxxxxx....{..}..xxxxxx..]......xxx...........4.wwwwwwwwwwwwxxxxxxxxxx");
- strcpy(vgrid[56], "xxxxxxxxxxxxxxxxxxxx........xxx........xxxxxx....4....wwwwwwwwwwwwwwxxxxxxxxxxxx");
- strcpy(vgrid[57], "xxxxxxxxxxxxxxxxxxxxxxxxx..[.xxx........xxx)....wwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxx");
- strcpy(vgrid[58], "xxxxxxxxxxxxxxxxxxxxxxxxxxxx.........xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[59], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[60], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[61], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_QUEEN_BEE;
- mons_array[1] = MONS_KILLER_BEE;
- mons_array[2] = MONS_KILLER_BEE_LARVA;
- mons_array[3] = MONS_PLANT;
- mons_array[4] = MONS_YELLOW_WASP;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_ENCOMPASS;
-}
-
-
-static char vaults_vault(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // last level of the vaults -- dungeon.cc will change all these 'x's
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxxxx....xxxxxxxxxxxxxxxxxxxxxxxxxxx..xxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxx..x.........................x....xxxxxxxxxxxxxxxxxxxxxxxxxxx..xxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxx..x.xxxxxxxxxxx..xxxxxxxxxx.x....xxxxx.................xxxxx..xxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxx..x.x*.*.*.*.*x..x........x.x....xxx..........8..........xxx..xxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxx..x.x.*.*.*.*.x..x........x.x....xxx.....................xxx..xxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxx..x.x*.*.*.*.*x..x...||...x.x....xx......9........9.......xx..xxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxx..x.x.*.*.*.*.x..x...||...x.x....xx.......................xx..xxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxx..x.x*.*.*.*.*x..x...||...x.x....xx......xxxxxxxxxxx......xx..xxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxx..x.x.*.*.*.*.x..x........x.x....xx......x.........x......xx..xxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxx..x.x*.*.*.*.*+..+........x.x....xx....xxx..........xx....xx..xxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxx..x.x.*.*.*.*.xxxxxxxxxxxxx.x....xx.9..x....xxxxx....x..8.xx..xxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxx..x.xxxxxxxxxxx9998.........x....xx....x...xx$$$xx...x....xx..xxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxx..x...........899xxxxxxxxxx.x....xx....x..xx$***$xx..x....xx..xxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxx..x.xxxxxxxxxxx99x........x.x....xx....x..x$$*|*$$x..x....xx..xxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxx..x.x.....|...x88x.$$$$$$.x.x....xx..8.x..xx$***$xx..x....xx..xxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxx..x.x.|..|..|.x..x.$$$$$$.x.x....xx....x....x$$$xx...x..9.xx..xxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxx..x.x.........x..x.$$$$$$.x.x....xx....xxx..xxxxx..xxx....xx..xxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxx..x.x.|..|..|.x..x.$$$$$$.x.x....xx......x.........x......xx..xxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxx..x.x.........x..x.$$$$$$.x.x....xx......xxxxxxxxxxx......xx..xxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxx..x.x|..|..|..x..x.$$$$$$.x.x....xxx.....................xxx..xxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxx..x.x.........x..+........x.x....xxx......9.........9....xxx..xxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxx..x.xxxxxxxxx+x..xxxxxxxxxx.xx.11....xx................xxxxx..xxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxx..x...........x..x...........x1111...xxxxxxxxxxxxxxxxxxxxxxx..xxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxx..1....1..xxxxxxxxxxxxxxxxxxxxxxx..xxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxx..........................xx1..(}..1..........................xxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxx...........................11.[..{.11.........................xxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxx............................1..])..1..........................xxxxxxxxx");
- strcpy(vgrid[36], "xxxxxxxxx.............................1....1...........................xxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxx.....1111..x.xxx.xxxxxxxxxxxxxxxxxx..xxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxx..xx.x.x.x.x.x.x.x.x.x.x.x.....11..........................x..xxxxxxxxx");
- strcpy(vgrid[39], "xxxxxxxxx..x.x.x.x.x.x.x.x|x.x.x.x.x................................x..xxxxxxxxx");
- strcpy(vgrid[40], "xxxxxxxxx..xx.x|x.x.x.x.x.x.x.x.x.x.x.....x.........................x..xxxxxxxxx");
- strcpy(vgrid[41], "xxxxxxxxx..x.x.x.x.x.x.x.x9x.x.x.x.x.x..........8..........9........x..xxxxxxxxx");
- strcpy(vgrid[42], "xxxxxxxxx..xx.x.x.x.x.x.x.x.x.x.x.x.xx....x..9......................x..xxxxxxxxx");
- strcpy(vgrid[43], "xxxxxxxxx..x.x.x.x.x.x.x.x.x.x|x.x.x.x....x.........................x..xxxxxxxxx");
- strcpy(vgrid[44], "xxxxxxxxx..xx.x8x.x.x|x.x.x.x.x.x.x.xx....x..............9...9......x..xxxxxxxxx");
- strcpy(vgrid[45], "xxxxxxxxx..x.x.x.x.x9x.x.x.x.x.x.x.x.x...........8..................x..xxxxxxxxx");
- strcpy(vgrid[46], "xxxxxxxxx..xx.x.x.x.x.x.x.x.x.x.x.x.xx....x..9......................x..xxxxxxxxx");
- strcpy(vgrid[47], "xxxxxxxxx..x.x.x.x.x.x.x.x.x|x.x9x.x.x....x.........................x..xxxxxxxxx");
- strcpy(vgrid[48], "xxxxxxxxx..xx.x.x.x.x.x.x.x.x.x.x.x.xx....x...................9.....x..xxxxxxxxx");
- strcpy(vgrid[49], "xxxxxxxxx..x.x.x9x.x.x.x.x.x.x.x.x.x.x....x....9......8.............x..xxxxxxxxx");
- strcpy(vgrid[50], "xxxxxxxxx..xx.x.x.x.x.x.x9x.x.x.x.x.xx....x.........................x..xxxxxxxxx");
- strcpy(vgrid[51], "xxxxxxxxx..x.x.x.x.x.x.x.x.x.x.x.x.x.x....x.........................x..xxxxxxxxx");
- strcpy(vgrid[52], "xxxxxxxxx..xx.x.x.x.x.x.x.x.x.x.x.x.xx....x.......9......9..........x..xxxxxxxxx");
- strcpy(vgrid[53], "xxxxxxxxx..x.x.x.x.x.x.x.x.x.x8x.x.x.x....x.....................8...x..xxxxxxxxx");
- strcpy(vgrid[54], "xxxxxxxxx..xx.x8x.x.x.x.x.x.x.x.x.x.xx....x.....................||.|x..xxxxxxxxx");
- strcpy(vgrid[55], "xxxxxxxxx..x.x|x.x.x.x.x.x.x|x.x.x.x.x....x.....................|...x..xxxxxxxxx");
- strcpy(vgrid[56], "xxxxxxxxx..xx.x.x.x.x.x.x8x.x.x.x.x.xx....x......8..................x..xxxxxxxxx");
- strcpy(vgrid[57], "xxxxxxxxx..x.x.x.x.x.x.x.x.x.x.x.x.x.x....x..........8..8...8.....||x..xxxxxxxxx");
- strcpy(vgrid[58], "xxxxxxxxx..xO.x.x.x.x.x.x.x.x.x.x|x.xx....x.....................|.||x..xxxxxxxxx");
- strcpy(vgrid[59], "xxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxxxx....xxxxxxxxxxxxxxxxxxxxxxxxxxx..xxxxxxxxx");
- strcpy(vgrid[60], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[61], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_VAULT_GUARD;
- mons_array[1] = RANDOM_MONSTER;
- mons_array[2] = RANDOM_MONSTER;
- mons_array[3] = RANDOM_MONSTER;
- mons_array[4] = RANDOM_MONSTER;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_ENCOMPASS;
-}
-
-
-static char snake_pit(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // Hey, this looks a bit like a face ...
-
- for (unsigned char i = 0; i < 81; i++)
- strcpy(vgrid[i], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- strcpy(vgrid[36], "xxxxxxxxxxxxxxxxxxxxxxx..@.xxxxxxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxxxxxxxxxxxx.............xxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxxxxxxx....x.............x..xxxxx");
- strcpy(vgrid[39], "xxxxxxxxxxxx....2.x.............x.2..xxx");
- strcpy(vgrid[40], "xxxxxxxxxxx.....2.x....x.....x..x..3.xxx");
- strcpy(vgrid[41], "xxxxxxxxxxx.....22x.............xx.2..xx");
- strcpy(vgrid[42], "xxxxxxxxxxx.......xx..x........xx..3..xx");
- strcpy(vgrid[43], "xxxxxxxxxx.....x23.xx....T...xxx.44...xx");
- strcpy(vgrid[44], "xxxxxxxxxx......4.4.x.........x.333....x");
- strcpy(vgrid[45], "xxxxxxxxxx......3.x4...x.......4x4.....x");
- strcpy(vgrid[46], "xxxxxxxxxx.......3.......x.............x");
- strcpy(vgrid[47], "xxxxxxxxxx..c......3.........x.......c.x");
- strcpy(vgrid[48], "xxxxxxxxx...cc...................3..cc.x");
- strcpy(vgrid[49], "xxxxxxxxx...cc..........4.4.........cc.x");
- strcpy(vgrid[50], "xxxxxxxxx...cc...3...x........2.....cc.x");
- strcpy(vgrid[51], "xxxxxxxxx...cc.........1...1.......cc..x");
- strcpy(vgrid[52], "xxxxxxxxxx..cc.....1.....1.....1..ccc.xx");
- strcpy(vgrid[53], "xxxxxxxxxx...ccc..................cc..xx");
- strcpy(vgrid[54], "xxxxxxxxxx....cccc....3333333.....cc..xx");
- strcpy(vgrid[55], "xxxxxxxxxx.....ccccccc...........cc...xx");
- strcpy(vgrid[56], "xxxxxxxxxx........cccccccO...ccccc....xx");
- strcpy(vgrid[57], "xxxxxxxxxxx........cccccccccccccc....xxx");
- strcpy(vgrid[58], "xxxxxxxxxxx.........cccccccccccc.....xxx");
- strcpy(vgrid[59], "xxxxxxxxxxxxx.......................xxxx");
- strcpy(vgrid[60], "xxxxxxxxxxxxxxxx..................xxxxxx");
- strcpy(vgrid[61], "xxxxxxxxxxxxxxxxxxxxx.......xxxxxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_GREATER_NAGA;
- mons_array[1] = MONS_NAGA;
- mons_array[2] = MONS_NAGA_MAGE;
- mons_array[3] = MONS_NAGA_WARRIOR;
- mons_array[4] = RANDOM_MONSTER;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_SOUTHWEST;
-}
-
-
-static char elf_hall(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxxxxxxxxxxxcccccccccccccccccxxxxx");
- strcpy(vgrid[8], "xxxxxxxxxxxxxxxxxcc*|*|*|**|||||c$ccxxxx");
- strcpy(vgrid[9], "xxxxxxxxxxxxxxxxcc*$*|*|*|*|||||c$$ccxxx");
- strcpy(vgrid[10], "xxxxxxxxxxxxxxxcc*$|*$***$$|||||c|$$ccxx");
- strcpy(vgrid[11], "xxxxxxxxxxxxxxcc*$*|**ccccccccccc$$$$ccx");
- strcpy(vgrid[12], "xxxxxxxxxxxxxxc*|*$*$ccc.....2..c+$|$$cx");
- strcpy(vgrid[13], "xxxxxxxxxxxxxxc$*$*ccc...........c$$$$cx");
- strcpy(vgrid[14], "xxxxxxxxxxxxxxc||**cc...5.......4cc$|$cx");
- strcpy(vgrid[15], "xxxxxxxxxxxxxxc*$$cc........3..ccccccccx");
- strcpy(vgrid[16], "xxxxxxxxxxxxxxc$+ccc.....2....cc.....5cx");
- strcpy(vgrid[17], "xxxxxxxxxxxxxxc$c....5.......cc.......cx");
- strcpy(vgrid[18], "xxxxxxxxxxxxxxccc......5....cc..2....ccx");
- strcpy(vgrid[19], "xxxxxxxxxxxxxxxxc..........cc.......ccxx");
- strcpy(vgrid[20], "xxxxxxxxxxxxxxxcc..1..U..........4..ccxx");
- strcpy(vgrid[21], "xxxxxxxxxxxxxxcc.....................ccx");
- strcpy(vgrid[22], "xxxxxxxxxxxxxxc...........3...........cx");
- strcpy(vgrid[23], "xxxxxxxxxxxxxxc.......2.......3.......cx");
- strcpy(vgrid[24], "xxxxxxxxxxxxxxc..2................2..5cx");
- strcpy(vgrid[25], "xxxxxxxxxxxxxxc......x.........x......cx");
- strcpy(vgrid[26], "xxxxxxxxxxxxxxc.....xx.........xx.....cx");
- strcpy(vgrid[27], "xxxxxxxxxxxxxxc2...xxx....1....xxx.4..cx");
- strcpy(vgrid[28], "xxxxxxxxxxxxxxc..xxxx...........xxxx..cx");
- strcpy(vgrid[29], "xxxxxxxxxxxxxxc.xxx.....cc.cc.....xxx.cx");
- strcpy(vgrid[30], "xxxxxxxxxxxxxxc.x.....cccc.cccc.....x.cx");
- strcpy(vgrid[31], "xxxxxxxxxxxxxxc.3...cccxxc.cxxccc.3...cx");
- strcpy(vgrid[32], "xxxxxxxxxxxxxxc...cccxxxxc.cxxxxccc...cx");
- strcpy(vgrid[33], "xxxxxxxxxxxxxxc.cccxxxxxxc.cxxxxxxccc.cx");
- strcpy(vgrid[34], "xxxxxxxxxxxxxxcccxxxxxxxxc.cxxxxxxxxcccx");
- strcpy(vgrid[35], "xxxxxxxxxxxxxxxxxxxxxxxxxx@xxxxxxxxxxxxx");
-
- mons_array[0] = MONS_DEEP_ELF_HIGH_PRIEST;
- mons_array[1] = MONS_DEEP_ELF_DEMONOLOGIST;
- mons_array[2] = MONS_DEEP_ELF_ANNIHILATOR;
- mons_array[3] = MONS_DEEP_ELF_SORCERER;
- mons_array[4] = MONS_DEEP_ELF_DEATH_MAGE;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_NORTHWEST;
-}
-
-
-// Slime pit take is reduced pending an increase in difficulty
-// of this subdungeon. -- bwr
-static char slime_pit(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..xxxx.........xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx....................xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxxxxxxxxxxxxxxxxxxxxx......................xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxxxxxxxxxxxxxxxxxxx..........................x.xxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxxxxxxxxxxxxxxxxxxx............................xxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxxxxxxxxxxxxxxxxxx.............................xxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxxxxxxxxxxxxxxxxx.................................xxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxxxxxxxxxxxxxxxxx..................................xxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxxxxxxxxxxxxxxx....(................................xxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxxxxxxxxxxxxxxx......................................xxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxxxxxxxxxxxx..........................................xxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxxxxxxxxxxxx..........................................xxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxxxxxxxxxx............................................xxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxxxxxxxxxx............................................xxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxxxxxxx.....................ccc..ccc............]......xxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxxxxxxxx...................cccc2ccccc...................xxxxxxxxxxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxxxxxxx...................cc*cc..cc*cc....................xxxxxxxxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxxxxxxx..................cc***cc4c***cc..................xxxxxxxxxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxxxxxx..................cc*|*cc..cc*|*cc..................xxxxxxxxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxxxxxx.................cc*|P|*c4cc*|P|*cc.................xxxxxxxxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxxxxxx.................cc**|*cc..cc*|**cc....................xxxxxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxxxxx..................ccc**c|cc4c|c**ccc...................xxxxxxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxxxxx..................cccccccc..cccccccc....................xxxxxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxxxx...................c.4.c.4.1..4.c.4.c.....................xxxxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxxxx...................2.c.4.c..3.c.4.c.2.....................xxxxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxxxx..........)........cccccccc..cccccccc.....................xxxxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxxxx...................ccc**c|cc4c|c**ccc.....................xxxxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxxx....................cc**|*cc..cc*|**cc....................xxxxxxxxxxxx");
- strcpy(vgrid[36], "xxxxxxxxxx....................cc*|P|*c4cc*|P|*cc....................xxxxxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxxx.....................cc*|*cc..cc*|*cc....................xxxxxxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxxxx.....................cc***cc4c***cc.....................xxxxxxxxxxxxx");
- strcpy(vgrid[39], "xxxxxxxxxxxx.....................cc*cc..cc*cc......................xxxxxxxxxxxxx");
- strcpy(vgrid[40], "xxxxxxxxxxxxx.....................cccc2ccccc......................xxxxxxxxxxxxxx");
- strcpy(vgrid[41], "xxxxxxxxxxxxxx.....................ccc..ccc.......................xxxxxxxxxxxxxx");
- strcpy(vgrid[42], "xxxxxxxxxxxxxx...........................................[.........xxxxxxxxxxxxx");
- strcpy(vgrid[43], "xxxxxxxxxxxxx......................................................xxxxxxxxxxxxx");
- strcpy(vgrid[44], "xxxxxxxxxxxxx..............................................xxxxx...xxxxxxxxxxxxx");
- strcpy(vgrid[45], "xxxxxxxxxxxxxx...........................................xxxxxxxx.xxxxxxxxxxxxxx");
- strcpy(vgrid[46], "xxxxxxxxxxxxxx..........................................xxxxxxxxx.xxxxxxxxxxxxxx");
- strcpy(vgrid[47], "xxxxxxxxxxxxxxxx........................................xxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[48], "xxxxxxxxxxxxxxxx.........................................xxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[49], "xxxxxxxxxxxxxxxxxx.......................................xxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[50], "xxxxxxxxxxxxxxxxxxxx......................................xxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[51], "xxxxxxxxxxxxxxxxxxxx......................................xxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[52], "xxxxxxxxxxxxxxxxxxxxx.....................................xxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[53], "xxxxxxxxxxxxxxxxxxxxx.............................}......xxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[54], "xxxxxxxxxxxxxxxxxxxxxxx.................................xxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[55], "xxxxxxxxxxxxxxxxxxxxxxxx..............................xxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[56], "xxxxxxxxxxxxxxxxxxxxxxxxx..............................xxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[57], "xxxxxxxxxxxxxxxxxxxxxxxxxx............................xxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[58], "xxxxxxxxxxxxxxxxxxxxxxxxxxxx...........{........xxx..xxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[59], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx................xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[60], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.........xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[61], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_ROYAL_JELLY;
- mons_array[1] = MONS_ACID_BLOB;
- mons_array[2] = MONS_GREAT_ORB_OF_EYES;
- mons_array[3] = RANDOM_MONSTER;
- mons_array[4] = RANDOM_MONSTER;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_ENCOMPASS;
-
-}
-
-
-static char hall_of_blades(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxccc....cccc.cccc.cccc.cccc.cccc.cccc.cccc.cccc.cccc.cccc.....cccxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxcc......cc...cc...cc...cc...cc...cc...cc...cc...cc...cc.......ccxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxc..............................................................cxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxc..........c..............c..............c..............c......cxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxc.........ccc............ccc............ccc............ccc.....cxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxc........ccccc..........ccccc..........ccccc..........ccccc....cxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxc.........ccc............ccc............ccc...........ccccc....cxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxc..........c..............c..............c.............ccc.....cxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxc......................................................ccc.....cxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxc.......................................................c......cxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxc..............................................................cxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxc..............................................................cxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxc..............................................................cxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxc..............................................................cxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxc..............................................................cxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxc..............................................................cxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxc.......................................................c......cxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxc......................................................ccc.....cxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxc..........c..............c..............c.............ccc.....cxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxc.........ccc............ccc............ccc...........ccccc....cxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxc........ccccc..........ccccc..........ccccc..........ccccc....cxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxc.........ccc............ccc............ccc............ccc.....cxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxc..........c..............c..............c..............c......cxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxc..............................................................cxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxc.......cc...cc...cc...cc...cc...cc...cc...cc...cc...cc.......ccxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxcc.....cccc.cccc.cccc.cccc.cccc.cccc.cccc.cccc.cccc.cccc.....cccxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxccc...ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxcccc.............................cccccccccccccccccccccccccccccccxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxcccccccccccccccccccccccccccccc.@.cccccccccccccccccccccccccccccccxxxxxxxx");
-
- mons_array[0] = MONS_DANCING_WEAPON;
- mons_array[1] = RANDOM_MONSTER;
- mons_array[2] = RANDOM_MONSTER;
- mons_array[3] = RANDOM_MONSTER;
- mons_array[4] = RANDOM_MONSTER;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_NORTH;
-}
-
-
-static char hall_of_Zot(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxccccccccccccccccxxxxxxxxxxxxxxxxxxxxxxxccccccccccccccxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxxxxcccc..............ccccxxxxxxxxxxxxxxxxxcccc............ccccxxxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxxxcc....................cccxxxxxxxxxxxxxccc..................ccxxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxxcc...........3...........ccxxxxxxxxxxxcc...........3.........ccxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxxc..8......................cXXXXXXXXXXXc....................8..cxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxxc...................8.....XXX...1...XXX....8..................cxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxxcc........................XX..1...1..XX......................ccxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxxxcc.......................X1.........1X.....................ccxxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxxxxcc.....4....2..............1..Z..1............2....4.....ccxxxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxxxcc.......................X1.........1X.....................ccxxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxxcc........................XX..1...1..XX......................ccxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxxc...................8.....XXX...1...XXX....8..................cxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxxc...8.....................cXXXXXXXXXXXc...................8...cxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxxcc..........8............ccccccccccccccc..........8..........ccxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxxxcc....................ccccccccccccccccccc..................ccxxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxxxxcc................ccccccccccccccccccccccccc..............ccxxxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxxxxxccF111FcccccccccccccccccccccccccccccccccccccccccccF111Fccxxxxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxxxxcc................^^1.ccccccccccccccccc.1^^..............ccxxxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxxxcc.................cc1...ccccccccccccc...1cc...............ccxxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxxcc.............8.....ccc...ccccccccccc...ccc...8.............ccxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxxc....8................ccc...............ccc...........8...8...cxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxxc.......8.....8...8...cxcc.............ccxc...................cxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxxc.....................cxxc.............cxxc.......8...........cxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxxc.....................cxxcc.1...1...1.ccxxc............8....8.cxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxxc.......8....8.....8..cxxxc...........cxxxc....8..............cxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxxc.....................cxxcc...........ccxxc..........8........cxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxxcc...5...............ccxxc.............cxxcc..............8..ccxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxxxcc........8........ccxxcc.............ccxxcc....8....5.....ccxxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxxxxcc...............ccxxxc...............cxxxcc.............ccxxxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxxxxxcccccccccccccccccxxxxcccccccc@ccccccccxxxxcccccccccccccccxxxxxxxxxxx");
-
- mons_array[0] = MONS_ORB_GUARDIAN;
- mons_array[1] = MONS_KILLER_KLOWN;
- mons_array[2] = MONS_ELECTRIC_GOLEM;
- mons_array[3] = MONS_ORB_OF_FIRE;
- mons_array[4] = MONS_ANCIENT_LICH;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_NORTH;
-}
-
-
-static char temple(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // this is the ecumenical temple level
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxxxxxxxxxxxxxxxxxxxccccccccccccccccccccccccccxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxxxxxxxxxxxxxxxxxxcc............<............cxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxxxxxxxxxxxxxxxxxcc...........................cxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxxxxxxxxxxxxxxxxcc.............................cxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxxxxxxxxxxxxxxxcc...............................cxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxxxxxxxxxxxxxxcc.................................cxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxxxxxxxxxxxxxcc...................................cxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxxxxxxxxxxxxcc.....................................cxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxxxxxxxxxxxcc.......................................cxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxxxxxxxxxxcc.........................................cxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxxxxxxxxxcc...........................................cxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxxxxxxxxcc.............................................cxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxxxxxxxcc...............................................cxxxxxxxxxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxxxxxxcc.................................................cxxxxxxxxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxxxxxcc...................................................cxxxxxxxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxxxxcc..........................B..........................cxxxxxxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxxxcc.......................................................cxxxxxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxxcc.....................B.............B.....................cxxxxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxcc...........................................................cxxxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxc.............................................................cxxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxc.............................................................cxxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxc.................B.........................B.................cxxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxc..............................T..............................cxxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxc.............................................................cxxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxc.............................................................cxxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxc.............................................................cxxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxc.............................................................cxxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxc.............................................................cxxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxc..............B...............................B..............cxxxxxxxxx");
- strcpy(vgrid[36], "xxxxxxxxc(....................T.................T....................{cxxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxc.............................................................cxxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxc.............................................................cxxxxxxxxx");
- strcpy(vgrid[39], "xxxxxxxxc.............................................................cxxxxxxxxx");
- strcpy(vgrid[40], "xxxxxxxxc.............................................................cxxxxxxxxx");
- strcpy(vgrid[41], "xxxxxxxxc.............................................................cxxxxxxxxx");
- strcpy(vgrid[42], "xxxxxxxxc.............................................................cxxxxxxxxx");
- strcpy(vgrid[43], "xxxxxxxxc................B...........................B................cxxxxxxxxx");
- strcpy(vgrid[44], "xxxxxxxxcc...........................................................ccxxxxxxxxx");
- strcpy(vgrid[45], "xxxxxxxxxcc............................T............................ccxxxxxxxxxx");
- strcpy(vgrid[46], "xxxxxxxxxxcc.......................................................ccxxxxxxxxxxx");
- strcpy(vgrid[47], "xxxxxxxxxxxcc.....................................................ccxxxxxxxxxxxx");
- strcpy(vgrid[48], "xxxxxxxxxxxxcc...................................................ccxxxxxxxxxxxxx");
- strcpy(vgrid[49], "xxxxxxxxxxxxxcc.................................................ccxxxxxxxxxxxxxx");
- strcpy(vgrid[50], "xxxxxxxxxxxxxxcc...............B................B..............ccxxxxxxxxxxxxxxx");
- strcpy(vgrid[51], "xxxxxxxxxxxxxxxcc.............................................ccxxxxxxxxxxxxxxxx");
- strcpy(vgrid[52], "xxxxxxxxxxxxxxxxcc.....................B.....................ccxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[53], "xxxxxxxxxxxxxxxxxcc.........................................ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[54], "xxxxxxxxxxxxxxxxxxcc.......................................ccxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[55], "xxxxxxxxxxxxxxxxxxxcc.....................................ccxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[56], "xxxxxxxxxxxxxxxxxxxxcc...................................ccxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[57], "xxxxxxxxxxxxxxxxxxxxxcc.................................ccxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[58], "xxxxxxxxxxxxxxxxxxxxxxcc...............................ccxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[59], "xxxxxxxxxxxxxxxxxxxxxxxcc.............................ccxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[60], "xxxxxxxxxxxxxxxxxxxxxxxxcc...........................ccxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[61], "xxxxxxxxxxxxxxxxxxxxxxxxxcc............[............ccxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxcccccccccccccccccccccccccccxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- return MAP_ENCOMPASS;
-}
-
-
-static char tomb_1(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxx(.............................[..............................{xxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxx..........ccccccccccccccccccccccccccccccccccccccccccc.........xxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxx..........ccccccccccccccccccccccccccccccccccccccccccc.........xxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxx..........cc..........................^............cc.........xxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxx..........cc.........^....................^........cc.........xxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxx..........cc..ccccccccccccccccccccccccccccccccccc..cc.........xxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxx..........cc..c....^....^..c................c.^)c..cc.........xxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxx..........cc..c..ccccccccc.c..3.............c.^.c..cc.........xxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxx..........cc..c..c222c111c.c...............5c..^c..cc.........xxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxx..........cc..c..c2c222c.^.c......2.........+cccc..cc.........xxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxx..........cc..c..ccccccccccc..........3......5..c.^cc.........xxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxx..........cc..c.................................c..cc.........xxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxx..........cc..c..........................3......c..cc.........xxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxx..........cc^.cccccccccccccc.......2............c..cc.........xxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxx..........cc..c............c....................c..cc.........xxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxx..........cc..c............c.................3..c..cc.........xxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxx..........cc..c..cccccccc..c..........2.........c^5cc.........xxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxx..........cc..c..c.^.c11c..c....................c..cc.........xxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxx..........cc..c..c.c.c11c..c...3................c..cc.........xxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxx..........cc..c..c^c.11cc..c..............2.....c..cc.........xxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxx..........cc..c..c.cccccc..c.......2............c..cc.........xxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxx..........cc..c..c..^..^...c.................2..c..cc.........xxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxx..........cc5^c..ccccccccccc....................c..cc.........xxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxx..........cc..c.................................c..cc.........xxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxx..........cc..c.................................c..cc.........xxxxxxxxx");
- strcpy(vgrid[36], "xxxxxxxxx..........cc..cccccccccccccc..^.^..cccccccccccccc..cc.........xxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxx..........cc..c...........ccc+++++ccc........^..c.^cc.........xxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxx..........cc..c.^.....^...cc.2...2.cc......^....c..cc.........xxxxxxxxx");
- strcpy(vgrid[39], "xxxxxxxxx..........cc..c..ccccccc..cc.F...F.cc..ccccccc..c..cc.........xxxxxxxxx");
- strcpy(vgrid[40], "xxxxxxxxx..........cc..c..cc.322c..cc.......cc..c22..cc..c..cc.........xxxxxxxxx");
- strcpy(vgrid[41], "xxxxxxxxx..........cc..c..c].c22c..cc.......cc..c22c.}c^.c..cc.........xxxxxxxxx");
- strcpy(vgrid[42], "xxxxxxxxx..........cc..c..cccc..c.^cc.G...G.cc..c3.cccc..c..cc.........xxxxxxxxx");
- strcpy(vgrid[43], "xxxxxxxxx..........cc..c.....^..c..cc.......cc.^c........c..cc.........xxxxxxxxx");
- strcpy(vgrid[44], "xxxxxxxxx..........cc..c........c..cc.......cc..c....^...c..cc.........xxxxxxxxx");
- strcpy(vgrid[45], "xxxxxxxxx..........cc^.cccccccccc..cc.G...G.cc..cccccccccc.^cc.........xxxxxxxxx");
- strcpy(vgrid[46], "xxxxxxxxx..........cc......^.......cc.......cc..........^...cc.........xxxxxxxxx");
- strcpy(vgrid[47], "xxxxxxxxx..........cc...........^..cc.......cc.....^........cc.........xxxxxxxxx");
- strcpy(vgrid[48], "xxxxxxxxx..........cccccccccccccccccc.G...G.cccccccccccccccccc.........xxxxxxxxx");
- strcpy(vgrid[49], "xxxxxxxxx..........cccccccccccccccccc.......cccccccccccccccccc.........xxxxxxxxx");
- strcpy(vgrid[50], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[51], "xxxxxxxxx.............................G...G............................xxxxxxxxx");
- strcpy(vgrid[52], "xxxxxxxxx...........................4.......4..........................xxxxxxxxx");
- strcpy(vgrid[53], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[54], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[55], "xxxxxxxxx...........................4..V.V..4..........................xxxxxxxxx");
- strcpy(vgrid[56], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[57], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[58], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[59], "xxxxxxxxx...........................4.......4..........................xxxxxxxxx");
- strcpy(vgrid[60], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[61], "xxxxxxxxx..............................................................xxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_MUMMY;
- mons_array[1] = MONS_GUARDIAN_MUMMY;
- mons_array[2] = MONS_MUMMY_PRIEST;
- mons_array[3] = MONS_SPHINX;
- mons_array[4] = MONS_GREATER_MUMMY;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_ENCOMPASS;
-}
-
-
-static char tomb_2(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxxxxxxxxxxxxcc{...c......c.....3....c........c.......ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxxxxxxxxxxxxcc....c.....^c^........^c......2^c.......ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxxxxxxxxxxxxcc....c...2.^+..2.....2^+^..2....+.......ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxxxxxxxxxxxxcc.3.^c^.....c^.........c^2.....^c^......ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxxxxxxxxxxxxcc...^+^.....c..........c........c...2...ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxxxxxxxxxxxxccccc+ccccccccccccccccccccccccccccccc....ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxxxxxxxxxxxxcc..^.c.............................c....ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxxxxxxxxxxxxcc....c.............................c..3.ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxxxxxxxxxxxxcc....c..ccc4.................4ccc..c....ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxxxxxxxxxxxxcc....c..ccc...................ccc..c..2.ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxxxxxxxxxxxxcc....c..ccc.........1.........ccc..c)..}ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxxxxxxxxxxxxcc.3..c..ccc.....2.......2.....ccc..cccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxxxxxxxxxxxxcc....c.............................c....ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxxxxxxxxxxxxcc....c.............................c^2..ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxxxxxxxxxxxxcc....c........c...........c........+....ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxxxxxxxxxxxxcc]...c.............................c^2..ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxxxxxxxxxxxxccccccc.....3........(........3.....c....ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxxxxxxxxxxxxcc....c.............................c.^.^ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxxxxxxxxxxxxcc...^c........c...........c........ccc+cccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxxxxxxxxxxxxcc....+.............................c..^.ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxxxxxxxxxxxxcc...^c.............................c....ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxxxxxxxxxxxxcc....c..ccc.....2.......2.....ccc..c..2.ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[36], "xxxxxxxxxxxxxxxxxxxccccccc..ccc.........1.........ccc..c....ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxxxxxxxxxxxxcc....c..ccc...................ccc..c....ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxxxxxxxxxxxxcc...^+..ccc4.................4ccc..c2...ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[39], "xxxxxxxxxxxxxxxxxxxcc....c.............................c....ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[40], "xxxxxxxxxxxxxxxxxxxccccccc.............................c..2.ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[41], "xxxxxxxxxxxxxxxxxxxcc....c.............................ccc+cccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[42], "xxxxxxxxxxxxxxxxxxxcc....+cccc+ccccccccccccccc+ccccccccc.^.^ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[43], "xxxxxxxxxxxxxxxxxxxcc.1.^^.c.^..c............c^.......c.3...ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[44], "xxxxxxxxxxxxxxxxxxxcc...2..c.1..c.....1.1....c.....2..c.....ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[45], "xxxxxxxxxxxxxxxxxxxcc......c....c..1......1.^c..2.....c...2.ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[46], "xxxxxxxxxxxxxxxxxxxcc..3...c.1..c...1...1..1^+........c.....ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[47], "xxxxxxxxxxxxxxxxxxxcc......c....c[...........c.......3c.....ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[48], "xxxxxxxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[49], "xxxxxxxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[50], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[51], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[52], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[53], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[54], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[55], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[56], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[57], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[58], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[59], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[60], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[61], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_MUMMY;
- mons_array[1] = MONS_GUARDIAN_MUMMY;
- mons_array[2] = MONS_MUMMY_PRIEST;
- mons_array[3] = MONS_GREATER_MUMMY;
- mons_array[4] = RANDOM_MONSTER;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_ENCOMPASS;
-}
-
-
-static char tomb_3(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
-
- strcpy(vgrid[0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[1], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[2], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[3], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[4], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[5], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[6], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[7], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[8], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[9], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[10], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[11], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[12], "xxxxxxxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[13], "xxxxxxxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[14], "xxxxxxxxxxxxxxxxxxxccccccc.............................cccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[15], "xxxxxxxxxxxxxxxxxxxcccc...............cccccc..............ccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[16], "xxxxxxxxxxxxxxxxxxxccc...............cccccccc..............cccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[17], "xxxxxxxxxxxxxxxxxxxccc.......4......ccccO4cccc......4......cccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[18], "xxxxxxxxxxxxxxxxxxxccc............cccc......cccc...........cccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[19], "xxxxxxxxxxxxxxxxxxxcc............cccc........cccc...........ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[20], "xxxxxxxxxxxxxxxxxxxcc............cccc........cccc...........ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[21], "xxxxxxxxxxxxxxxxxxxcc...........cccc..444444..cccc..........ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[22], "xxxxxxxxxxxxxxxxxxxcc.......................................ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[23], "xxxxxxxxxxxxxxxxxxxcc.......................................ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[24], "xxxxxxxxxxxxxxxxxxxcc.................222222................ccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[25], "xxxxxxxxxxxxxxxxxxxccc................223322...............cccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[26], "xxxxxxxxxxxxxxxxxxxccc...3............223322............3..cccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[27], "xxxxxxxxxxxxxxxxxxxcccc...............222222..............ccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[28], "xxxxxxxxxxxxxxxxxxxcccc....2..........................2...ccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[29], "xxxxxxxxxxxxxxxxxxxcccccc....2......................2....cccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[30], "xxxxxxxxxxxxxxxxxxxcccccccc............................cccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[31], "xxxxxxxxxxxxxxxxxxxccccccccc+ccc..................ccc+ccccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[32], "xxxxxxxxxxxxxxxxxxxcccccccc....cc................cc....cccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[33], "xxxxxxxxxxxxxxxxxxxcccccc.......cc22222222222222cc......$cccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[34], "xxxxxxxxxxxxxxxxxxxcccc....^.....cc............cc..^.....$ccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[35], "xxxxxxxxxxxxxxxxxxxcccc.^.........cc..........cc.....^.^.$ccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[36], "xxxxxxxxxxxxxxxxxxxccc$...^...^..^.cc........cc..........$$cccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[37], "xxxxxxxxxxxxxxxxxxxccc$$$...........cc222222cc.^........$$$cccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[38], "xxxxxxxxxxxxxxxxxxxccc|$$$...........c......c.....^...$$$$$cccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[39], "xxxxxxxxxxxxxxxxxxxccc||$$$$...^.....c......c^......$$$$$$$cccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[40], "xxxxxxxxxxxxxxxxxxxccc|||||$$.....^..c......c......$$$$$$$$cccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[41], "xxxxxxxxxxxxxxxxxxxcccc|||||$........c......c...^.$$$$$$$$ccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[42], "xxxxxxxxxxxxxxxxxxxccccc||||$$..^....c......c.....$$$$$$$cccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[43], "xxxxxxxxxxxxxxxxxxxcccccc||||$.......c......c.....$$$$$$ccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[44], "xxxxxxxxxxxxxxxxxxxccccccc|||$$....^.c......c.^.^$$$$$$cccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[45], "xxxxxxxxxxxxxxxxxxxcccccccc|||$^....cc..{...cc...$$$$$ccccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[46], "xxxxxxxxxxxxxxxxxxxccccccccc||$.....cc...(..cc..$$$$$cccccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[47], "xxxxxxxxxxxxxxxxxxxcccccccccc|$...cccc..[...cccc$$$$ccccccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[48], "xxxxxxxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[49], "xxxxxxxxxxxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[50], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[51], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[52], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[53], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[54], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[55], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[56], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[57], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[58], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[59], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[60], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[61], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcpy(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_MUMMY;
- mons_array[1] = MONS_GUARDIAN_MUMMY;
- mons_array[2] = MONS_MUMMY_PRIEST;
- mons_array[3] = MONS_GREATER_MUMMY;
- mons_array[4] = RANDOM_MONSTER;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_ENCOMPASS;
-}
-
+ // Copy the map so we can monkey with it.
+ map_def def = mdef;
+ resolve_map(def);
-
-static char swamp(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // NB - most of the 'x's here will be set to water in dungeon.cc
-
- for (unsigned char i = 0; i < 81; i++)
- strcpy(vgrid[i], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- strcat(vgrid[36], "xxxxxxxxxxx@xxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[37], "xxxxxxxxxxx2xxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[38], "xxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[39], "xxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[40], "xxxxxxxxxx2x.xxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[41], "xxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[42], "xxxxxxxxxcc.ccxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[43], "xxxxxxxxcc...ccxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[44], "xxxxxxxcc3.2..ccxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[45], "xxxxxxcc.1.3.2.ccxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[46], "xxxxxccc....1.1cccxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[47], "xxxxxcc.1.32....ccxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[48], "xxxxxcc...3..1.3ccxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[49], "xxxxxcc2.1.3..2.ccxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[50], "xxxxxccc33..1..cccxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[51], "xxxxxxcccc3O3ccccxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[52], "xxxxxxxcccccccccxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[53], "xxxxxxxxcccccccxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[54], "xxxxxxxxxxcccxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[55], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[56], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[57], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[58], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[59], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[60], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[61], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[62], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[63], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[64], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[65], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[66], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[67], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[68], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
- strcat(vgrid[69], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-
- mons_array[0] = MONS_SWAMP_DRAGON;
- mons_array[1] = MONS_SWAMP_DRAKE;
- mons_array[2] = MONS_HYDRA;
- mons_array[3] = RANDOM_MONSTER;
- mons_array[4] = RANDOM_MONSTER;
- mons_array[5] = RANDOM_MONSTER;
- mons_array[6] = RANDOM_MONSTER;
-
- return MAP_SOUTHEAST;
-}
-
-
-/*
- NOTE: *Cannot* place 8,9 or 0 monsters in branch vaults which neither use the
- normal mons_level function or are around level 35, or generation will crash.
-
- Remember, minivaults are always sidewards
-*/
-
-static char minivault_1(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "..xxxx=xxx..");
- strcpy(vgrid[2], ".xx..x...xx.");
- strcpy(vgrid[3], ".x....x...x.");
- strcpy(vgrid[4], ".x...x....x.");
- strcpy(vgrid[5], ".xx.x*x.x.=.");
- strcpy(vgrid[6], ".=.x.x*x.xx.");
- strcpy(vgrid[7], ".x....x...x.");
- strcpy(vgrid[8], ".x...x....x.");
- strcpy(vgrid[9], ".xx...x..xx.");
- strcpy(vgrid[10], "..xxx=xxxx..");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-}
-
-
-static char minivault_2(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "..xxxx.xxxx.");
- strcpy(vgrid[2], "..xx.....xx.");
- strcpy(vgrid[3], "..x.......x.");
- strcpy(vgrid[4], "..x.......x.");
- strcpy(vgrid[5], "......C.....");
- strcpy(vgrid[6], "..x.......x.");
- strcpy(vgrid[7], "..x.......x.");
- strcpy(vgrid[8], "..xx.....xx.");
- strcpy(vgrid[9], "..xxxx.xxxx.");
- strcpy(vgrid[10], "............");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-}
-
-
-static char minivault_3(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".cccccccccc.");
- strcpy(vgrid[2], ".cccccccccc.");
- strcpy(vgrid[3], ".cBcBcBcBcc.");
- strcpy(vgrid[4], ".G.c.c.c.Bc.");
- strcpy(vgrid[5], ".........Bc.");
- strcpy(vgrid[6], ".........Bc.");
- strcpy(vgrid[7], ".G.c.c.c.Bc.");
- strcpy(vgrid[8], ".cBcBcBcBcc.");
- strcpy(vgrid[9], ".cccccccccc.");
- strcpy(vgrid[10], ".cccccccccc.");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-}
-
-
-static char minivault_4(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "....xwxx....");
- strcpy(vgrid[2], "..xxxwwxwx..");
- strcpy(vgrid[3], "..xwwwwwwx..");
- strcpy(vgrid[4], ".xwwxwwxwxx.");
- strcpy(vgrid[5], ".xwwwwwwwwx.");
- strcpy(vgrid[6], ".xwwxwwwxww.");
- strcpy(vgrid[7], ".xxwwwwwwxx.");
- strcpy(vgrid[8], "..wwwwxwwx..");
- strcpy(vgrid[9], "..xxxwwxxw..");
- strcpy(vgrid[10], "....xxww....");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
+ return apply_vault_definition(def, map, marray, place);
}
-
-static char minivault_5(char vgrid[81][81], FixedVector<int, 7>& mons_array)
+// Mirror the map if appropriate, resolve substitutable symbols (?),
+static void resolve_map(map_def &map)
{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".x.xxxxxxxx.");
- strcpy(vgrid[2], ".x.x......x.");
- strcpy(vgrid[3], ".x.x.xxxx.x.");
- strcpy(vgrid[4], ".x.x.x**x.x.");
- strcpy(vgrid[5], ".x.x.x**x.x.");
- strcpy(vgrid[6], ".x.x.xx.x.x.");
- strcpy(vgrid[7], ".x.x....x.x.");
- strcpy(vgrid[8], ".x.xxxxxx.x.");
- strcpy(vgrid[9], ".x........x.");
- strcpy(vgrid[10], ".xxxxxxxxxx.");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-}
-
-
-static char minivault_6(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // Wizard's laboratory
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".ccccccc+cc.");
- strcpy(vgrid[2], ".c........c.");
- strcpy(vgrid[3], ".c........c.");
- strcpy(vgrid[4], ".c..1.....c.");
- strcpy(vgrid[5], ".c........c.");
- strcpy(vgrid[6], ".cc+ccccccc.");
- strcpy(vgrid[7], ".c***c3232c.");
- strcpy(vgrid[8], ".c|**+2223c.");
- strcpy(vgrid[9], ".c||*c3322c.");
- strcpy(vgrid[10], ".cccccccccc.");
- strcpy(vgrid[11], "............");
-
- mons_array[0] = MONS_WIZARD;
- mons_array[1] = MONS_ABOMINATION_SMALL;
- mons_array[2] = MONS_ABOMINATION_LARGE;
-
- return MAP_NORTH;
-
-}
-
-
-static char minivault_7(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // beehive minivault
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "....aaaa....");
- strcpy(vgrid[2], "..a2a2aaaa..");
- strcpy(vgrid[3], "..aaRa3a2a..");
- strcpy(vgrid[4], ".aa2aRa2aaa.");
- strcpy(vgrid[5], ".a3aRa1aRa2.");
- strcpy(vgrid[6], ".aa3aRaRa2a.");
- strcpy(vgrid[7], ".aaa2a2a3aa.");
- strcpy(vgrid[8], "..a3aRa2aa..");
- strcpy(vgrid[9], "...aa2aa2a..");
- strcpy(vgrid[10], "....aaaa....");
- strcpy(vgrid[11], "............");
-
- mons_array[0] = MONS_QUEEN_BEE;
- mons_array[1] = MONS_KILLER_BEE;
- mons_array[2] = MONS_KILLER_BEE_LARVA;
-
- return MAP_NORTH;
-}
-
-
-static char minivault_8(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // lava pond
-
- strcpy(vgrid[0], "x.x.x.x.x.x.");
- strcpy(vgrid[1], ".c.c.c.c.c.x");
- strcpy(vgrid[2], "x...l1l...c.");
- strcpy(vgrid[3], ".c.llllll..x");
- strcpy(vgrid[4], "x.lllllll1c.");
- strcpy(vgrid[5], ".c.llFGll..x");
- strcpy(vgrid[6], "x..llGFll.c.");
- strcpy(vgrid[7], ".c1lllllll.x");
- strcpy(vgrid[8], "x..llllll.c.");
- strcpy(vgrid[9], ".c...l1l...x");
- strcpy(vgrid[10], "x.c.c.c.c.c.");
- strcpy(vgrid[11], ".x.x.x.x.x.x");
-
- mons_array[0] = MONS_MOLTEN_GARGOYLE;
-
- return MAP_NORTH;
-}
-
-
-static char minivault_9(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // evil zoo
- UNUSED( mons_array );
+ // Mirroring is possible for any map that does not explicitly forbid it.
+ // Note that mirroring also flips the orientation.
+ if (coinflip())
+ map.hmirror();
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".==========.");
- strcpy(vgrid[2], ".==========.");
- strcpy(vgrid[3], ".==========.");
- strcpy(vgrid[4], ".===8888===.");
- strcpy(vgrid[5], ".===8998===.");
- strcpy(vgrid[6], ".===8998===.");
- strcpy(vgrid[7], ".===8888===.");
- strcpy(vgrid[8], ".==========.");
- strcpy(vgrid[9], ".==========.");
- strcpy(vgrid[10], ".==========.");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
+ if (coinflip())
+ map.vmirror();
+ // The map may also refuse to be rotated.
+ if (coinflip())
+ map.rotate( coinflip() );
}
-
-static char minivault_10(char vgrid[81][81], FixedVector<int, 7>& mons_array)
+static void apply_monsters(
+ const map_def &def,
+ FixedVector<int,7> &marray)
{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".xxxx..xxxx.");
- strcpy(vgrid[2], ".x**x..x**x.");
- strcpy(vgrid[3], ".x**+..+**x.");
- strcpy(vgrid[4], ".xx+x..x+xx.");
- strcpy(vgrid[5], "............");
- strcpy(vgrid[6], "............");
- strcpy(vgrid[7], ".xx+x..x+xx.");
- strcpy(vgrid[8], ".x**+..+**x.");
- strcpy(vgrid[9], ".x**x..x**x.");
- strcpy(vgrid[10], ".xxxx..xxxx.");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-}
-
-
-static char minivault_11(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // multicoloured onion
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".+xxxxxxxx+.");
- strcpy(vgrid[2], ".x........x.");
- strcpy(vgrid[3], ".x.+cccc+.x.");
- strcpy(vgrid[4], ".x.c....c.x.");
- strcpy(vgrid[5], ".x.c.bb.c.x.");
- strcpy(vgrid[6], ".x.c.bb.c.x.");
- strcpy(vgrid[7], ".x.c....c.x.");
- strcpy(vgrid[8], ".x.+cccc+.x.");
- strcpy(vgrid[9], ".x........x.");
- strcpy(vgrid[10], ".+xxxxxxxx+.");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-}
-
-
-static char minivault_12(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // closed box minivault
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".xxxxxxxxxx.");
- strcpy(vgrid[2], ".x>9$9$9$<x.");
- strcpy(vgrid[3], ".x.$9$9$.$x.");
- strcpy(vgrid[4], ".x$.****$.x.");
- strcpy(vgrid[5], ".x.$*||*.$x.");
- strcpy(vgrid[6], ".x$.*||*$.x.");
- strcpy(vgrid[7], ".x.$****.$x.");
- strcpy(vgrid[8], ".x$9$9$9$.x.");
- strcpy(vgrid[9], ".x<$9$9$9>x.");
- strcpy(vgrid[10], ".xxxxxxxxxx.");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-}
-
-
-static char minivault_13(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // little trap spiral
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".xxxxxxxxxx.");
- strcpy(vgrid[2], ".=.^x..=.9x.");
- strcpy(vgrid[3], ".x.$=.^x..x.");
- strcpy(vgrid[4], ".xxxxxxxx=x.");
- strcpy(vgrid[5], ".x.8+|0x8.x.");
- strcpy(vgrid[6], ".x8$x.|x..x.");
- strcpy(vgrid[7], ".xx=xxxx=xx.");
- strcpy(vgrid[8], ".x.9=^.x..x.");
- strcpy(vgrid[9], ".x..x.^=9.x.");
- strcpy(vgrid[10], ".xxxxxxxxxx.");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-}
-
+ const std::vector<int> &mids = def.mons.get_ids();
+ size_t ndx = 0;
+ for (int i = 0, size = mids.size(); i < size; ++i)
+ {
+ int mid = mids[i];
+ if (mid < 0)
+ {
+ mid = -100 - mid;
+ if (mid == DEMON_RANDOM)
+ mid = random2(DEMON_RANDOM);
+ mid = summon_any_demon( mid );
+ }
-static char minivault_14(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // water cross
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".wwwww.wwww.");
- strcpy(vgrid[2], ".wwwww.wwww.");
- strcpy(vgrid[3], ".wwwww.wwww.");
- strcpy(vgrid[4], ".wwwww.wwww.");
- strcpy(vgrid[5], ".......wwww.");
- strcpy(vgrid[6], ".wwww.......");
- strcpy(vgrid[7], ".wwww.wwwww.");
- strcpy(vgrid[8], ".wwww.wwwww.");
- strcpy(vgrid[9], ".wwww.wwwww.");
- strcpy(vgrid[10], ".wwww.wwwww.");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
+ if (ndx < marray.size())
+ marray[ndx++] = mid;
+ }
}
-static char minivault_15(char vgrid[81][81], FixedVector<int, 7>& mons_array) /* lava pond */
+static void apply_vault_grid(const map_def &def, map_type map,
+ vault_placement &place)
{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "............");
- strcpy(vgrid[2], "....lll.....");
- strcpy(vgrid[3], "...vvlvv....");
- strcpy(vgrid[4], "..lv|*|vl...");
- strcpy(vgrid[5], "..ll*S*ll...");
- strcpy(vgrid[6], "..lv|*|vl...");
- strcpy(vgrid[7], "...vvlvv....");
- strcpy(vgrid[8], "....lll.....");
- strcpy(vgrid[9], "............");
- strcpy(vgrid[10], "............");
- strcpy(vgrid[11], "............");
-
- return 1;
-}
-
+ const map_lines &ml = def.map;
+ const int orient = def.orient;
+ const int width = ml.width();
+ const int height = ml.height();
-static char minivault_16(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // lava pond
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "............");
- strcpy(vgrid[2], "............");
- strcpy(vgrid[3], "............");
- strcpy(vgrid[4], "............");
- strcpy(vgrid[5], "............");
- strcpy(vgrid[6], "......S.....");
- strcpy(vgrid[7], "............");
- strcpy(vgrid[8], "............");
- strcpy(vgrid[9], "............");
- strcpy(vgrid[10], "............");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-}
+ int startx = 0, starty = 0;
+ if (orient == MAP_SOUTH || orient == MAP_SOUTHEAST
+ || orient == MAP_SOUTHWEST)
+ starty = GYM - height;
-static char minivault_17(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // lava pond
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "............");
- strcpy(vgrid[2], "............");
- strcpy(vgrid[3], "............");
- strcpy(vgrid[4], "............");
- strcpy(vgrid[5], ".....F......");
- strcpy(vgrid[6], "............");
- strcpy(vgrid[7], "............");
- strcpy(vgrid[8], "............");
- strcpy(vgrid[9], "............");
- strcpy(vgrid[10], "............");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-}
-
+ if (orient == MAP_EAST || orient == MAP_NORTHEAST
+ || orient == MAP_SOUTHEAST)
+ startx = GXM - width;
-static char minivault_18(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // lava pond
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "............");
- strcpy(vgrid[2], "............");
- strcpy(vgrid[3], "............");
- strcpy(vgrid[4], "............");
- strcpy(vgrid[5], ".....H......");
- strcpy(vgrid[6], "............");
- strcpy(vgrid[7], "............");
- strcpy(vgrid[8], "............");
- strcpy(vgrid[9], "............");
- strcpy(vgrid[10], "............");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-}
+ // Handle maps aligned along cardinals that are smaller than
+ // the corresponding map dimension.
+ if ((orient == MAP_NORTH || orient == MAP_SOUTH
+ || orient == MAP_ENCOMPASS)
+ && width < GXM)
+ startx = (GXM - width) / 2;
+ if ((orient == MAP_EAST || orient == MAP_WEST
+ || orient == MAP_ENCOMPASS)
+ && height < GYM)
+ starty = (GYM - height) / 2;
-static char minivault_19(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".xx......xx.");
- strcpy(vgrid[2], ".xxx....xxx.");
- strcpy(vgrid[3], "..xxx..xxx..");
- strcpy(vgrid[4], "...xxxxxx...");
- strcpy(vgrid[5], "....xxxx....");
- strcpy(vgrid[6], "....xxxx....");
- strcpy(vgrid[7], "...xxxxxx...");
- strcpy(vgrid[8], "..xxx..xxx..");
- strcpy(vgrid[9], ".xxx....xxx.");
- strcpy(vgrid[10], ".xx......xx.");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-}
+ const std::vector<std::string> &lines = ml.get_lines();
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Applying %s at (%d,%d), dimensions (%d,%d)",
+ def.name.c_str(), startx, starty, width, height);
+#endif
+ for (int y = starty; y < starty + height; ++y)
+ {
+ const std::string &s = lines[y - starty];
+ strncpy(&map[y][startx], s.c_str(), s.length());
+ }
-static char minivault_20(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // lava pond
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".xxxx..xxxx.");
- strcpy(vgrid[2], ".x........x.");
- strcpy(vgrid[3], ".x..xxxx..x.");
- strcpy(vgrid[4], ".x.x....x.x.");
- strcpy(vgrid[5], "...x.x9.x...");
- strcpy(vgrid[6], "...x.9x.x...");
- strcpy(vgrid[7], ".x.x....x.x.");
- strcpy(vgrid[8], ".x..xxxx..x.");
- strcpy(vgrid[9], ".x........x.");
- strcpy(vgrid[10], ".xxxx..xxxx.");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
+ place.x = startx;
+ place.y = starty;
+ place.width = width;
+ place.height = height;
}
-
-static char minivault_21(char vgrid[81][81], FixedVector<int, 7>& mons_array)
+static int apply_vault_definition(
+ const map_def &def,
+ map_type map,
+ FixedVector<int,7> &marray,
+ vault_placement &place)
{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".^xxxxxxxx^.");
- strcpy(vgrid[2], ".x........x.");
- strcpy(vgrid[3], ".x.cccccc.x.");
- strcpy(vgrid[4], ".x.c|..<c.x.");
- strcpy(vgrid[5], ".x.c.**.c.x.");
- strcpy(vgrid[6], ".x.c.**.c.x.");
- strcpy(vgrid[7], ".x.c>..|c.x.");
- strcpy(vgrid[8], ".x.cccccc.x.");
- strcpy(vgrid[9], ".x........x.");
- strcpy(vgrid[10], ".^xxxxxxxx^.");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
+ apply_monsters(def, marray);
+ apply_vault_grid(def, map, place);
+ int orient = def.orient;
+ if (orient == MAP_NONE)
+ orient = MAP_NORTH;
+ return (orient);
}
+///////////////////////////////////////////////////////////////////////////
+// Map lookups
-static char minivault_22(char vgrid[81][81], FixedVector<int, 7>& mons_array)
+// Returns a map for which PLACE: matches the given place.
+int random_map_for_place(const std::string &place, bool want_minivault)
{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".....xx.....");
- strcpy(vgrid[2], "...xxxxxx...");
- strcpy(vgrid[3], "..x^x..x^x..");
- strcpy(vgrid[4], "..xx.xx.xx..");
- strcpy(vgrid[5], ".xx.x$$x.xx.");
- strcpy(vgrid[6], ".xx.x$$x.xx.");
- strcpy(vgrid[7], "..xx.xx.xx..");
- strcpy(vgrid[8], "..x^x..x^x..");
- strcpy(vgrid[9], "...xxxxxx...");
- strcpy(vgrid[10], ".....xx.....");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-
-}
+ if (place.empty())
+ return (-1);
+ int mapindex = -1;
+ int rollsize = 0;
-static char minivault_23(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "x.x.x.x.x.x.");
- strcpy(vgrid[1], ".x.x.x.x.x.x");
- strcpy(vgrid[2], "x.x.x.x.x.x.");
- strcpy(vgrid[3], ".x.x.x.x.x.x");
- strcpy(vgrid[4], "x.x.x.x.x.x.");
- strcpy(vgrid[5], ".x.x.x.x.x.x");
- strcpy(vgrid[6], "x.x.x.x.x.x.");
- strcpy(vgrid[7], ".x.x.x.x.x.x");
- strcpy(vgrid[8], "x.x.x.x.x.x.");
- strcpy(vgrid[9], ".x.x.x.x.x.x");
- strcpy(vgrid[10], "x.x.x.x.x.x.");
- strcpy(vgrid[11], ".x.x.x.x.x.x");
-
- return MAP_NORTH;
-
-}
+ for (unsigned i = 0, size = vdefs.size(); i < size; ++i)
+ {
+ // We also accept tagged levels here.
+ if (vdefs[i].place == place
+ && vdefs[i].is_minivault() == want_minivault)
+ {
+ rollsize += vdefs[i].chance;
+ if (rollsize && random2(rollsize) < vdefs[i].chance)
+ mapindex = i;
+ }
+ }
-static char minivault_24(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "....xxxx....");
- strcpy(vgrid[2], "....xxxx....");
- strcpy(vgrid[3], "....xxxx....");
- strcpy(vgrid[4], ".xxxx.x.xxx.");
- strcpy(vgrid[5], ".xxx.x.xxxx.");
- strcpy(vgrid[6], ".xxxx.x.xxx.");
- strcpy(vgrid[7], ".xxx.x.xxxx.");
- strcpy(vgrid[8], "....xxxx....");
- strcpy(vgrid[9], "....xxxx....");
- strcpy(vgrid[10], "....xxxx....");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
+#ifdef DEBUG_DIAGNOSTICS
+ if (mapindex != -1)
+ mprf(MSGCH_DIAGNOSTICS, "Found map %s for %s",
+ vdefs[mapindex].name.c_str(), place.c_str());
+#endif
+ return (mapindex);
}
-
-static char minivault_25(char vgrid[81][81], FixedVector<int, 7>& mons_array)
+int find_map_named(const std::string &name)
{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".xx+xxxxxxx.");
- strcpy(vgrid[2], ".x........x.");
- strcpy(vgrid[3], ".x........+.");
- strcpy(vgrid[4], ".x........x.");
- strcpy(vgrid[5], ".x........x.");
- strcpy(vgrid[6], ".x........x.");
- strcpy(vgrid[7], ".x........x.");
- strcpy(vgrid[8], ".+........x.");
- strcpy(vgrid[9], ".x........x.");
- strcpy(vgrid[10], ".xxxxxxx+xx.");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-
-}
-
+ if (name.empty())
+ return (-1);
-static char minivault_26(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "c..........c");
- strcpy(vgrid[1], ".c...cc...c.");
- strcpy(vgrid[2], "..c..cc..c..");
- strcpy(vgrid[3], "...c....c...");
- strcpy(vgrid[4], "....c..c....");
- strcpy(vgrid[5], ".cc..cc..cc.");
- strcpy(vgrid[6], ".cc..cc..cc.");
- strcpy(vgrid[7], "....c..c....");
- strcpy(vgrid[8], "...c....c...");
- strcpy(vgrid[9], "..c..cc..c..");
- strcpy(vgrid[10], ".c...cc...c.");
- strcpy(vgrid[11], "c..........c");
-
- return MAP_NORTH;
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Looking for map named \"%s\"", name.c_str());
+#endif
+ for (unsigned i = 0, size = vdefs.size(); i < size; ++i)
+ if (vdefs[i].name == name)
+ return (i);
+ return (-1);
}
-
-static char minivault_27(char vgrid[81][81], FixedVector<int, 7>& mons_array)
+int random_map_for_depth(int depth, bool want_minivault)
{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".x.xxxxxxxx.");
- strcpy(vgrid[2], ".x........x.");
- strcpy(vgrid[3], ".xxxxxxxx.x.");
- strcpy(vgrid[4], ".x........x.");
- strcpy(vgrid[5], ".x.xxxxxxxx.");
- strcpy(vgrid[6], ".x........x.");
- strcpy(vgrid[7], ".xxxxxxxx.x.");
- strcpy(vgrid[8], ".x........x.");
- strcpy(vgrid[9], ".x.xxxxxxxx.");
- strcpy(vgrid[10], "............");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-
-}
+ int mapindex = -1;
+ int rollsize = 0;
+ for (unsigned i = 0, size = vdefs.size(); i < size; ++i)
+ if (vdefs[i].depth.contains(depth)
+ // Tagged levels cannot be selected by depth. This is
+ // the only thing preventing Pandemonium demon vaults from
+ // showing up in the main dungeon.
+ && vdefs[i].tags.empty()
+ && vdefs[i].is_minivault() == want_minivault)
+ {
+ rollsize += vdefs[i].chance;
-static char minivault_28(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".xxxx.xxxx..");
- strcpy(vgrid[2], ".x.......x..");
- strcpy(vgrid[3], ".x..999..x..");
- strcpy(vgrid[4], ".x.9...9.x..");
- strcpy(vgrid[5], "...9.I.9....");
- strcpy(vgrid[6], ".x.9...9.x..");
- strcpy(vgrid[7], ".x..999..x..");
- strcpy(vgrid[8], ".x.......x..");
- strcpy(vgrid[9], ".xxxx.xxxx..");
- strcpy(vgrid[10], "............");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
+ if (rollsize && random2(rollsize) < vdefs[i].chance)
+ mapindex = i;
+ }
+ return (mapindex);
}
-
-static char minivault_29(char vgrid[81][81], FixedVector<int, 7>& mons_array)
+int random_map_for_tag(const std::string &tag)
{
+ int mapindex = -1;
+ int rollsize = 0;
- strcpy(vgrid[0], ".3......3...");
- strcpy(vgrid[1], "...x.xx.x.2.");
- strcpy(vgrid[2], ".xxx2xxxxx..");
- strcpy(vgrid[3], ".xxxx42xxx2.");
- strcpy(vgrid[4], ".2xx243432x3");
- strcpy(vgrid[5], ".xx421424xx.");
- strcpy(vgrid[6], "3xx423242x..");
- strcpy(vgrid[7], ".x2x3243xxx.");
- strcpy(vgrid[8], ".x2xx42422x.");
- strcpy(vgrid[9], "..xxxxxxxx2.");
- strcpy(vgrid[10], "...x2xxxx3..");
- strcpy(vgrid[11], ".3.......33.");
-
- mons_array[0] = MONS_QUEEN_ANT;
- mons_array[1] = MONS_SOLDIER_ANT;
- mons_array[2] = MONS_GIANT_ANT;
- mons_array[3] = MONS_ANT_LARVA;
-
- return MAP_NORTH;
-
-}
-
-
-static char minivault_30(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // lava pond
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "............");
- strcpy(vgrid[2], "............");
- strcpy(vgrid[3], "............");
- strcpy(vgrid[4], "............");
- strcpy(vgrid[5], ".....T......");
- strcpy(vgrid[6], "............");
- strcpy(vgrid[7], "............");
- strcpy(vgrid[8], "............");
- strcpy(vgrid[9], "............");
- strcpy(vgrid[10], "............");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-
-}
-
-
-static char minivault_31(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // lava pond
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "............");
- strcpy(vgrid[2], "............");
- strcpy(vgrid[3], "............");
- strcpy(vgrid[4], "............");
- strcpy(vgrid[5], ".....T......");
- strcpy(vgrid[6], "............");
- strcpy(vgrid[7], "............");
- strcpy(vgrid[8], "............");
- strcpy(vgrid[9], "............");
- strcpy(vgrid[10], "............");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-
-}
-
-
-static char minivault_32(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // lava pond
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "............");
- strcpy(vgrid[2], "............");
- strcpy(vgrid[3], "............");
- strcpy(vgrid[4], "............");
- strcpy(vgrid[5], ".....U......");
- strcpy(vgrid[6], "............");
- strcpy(vgrid[7], "............");
- strcpy(vgrid[8], "............");
- strcpy(vgrid[9], "............");
- strcpy(vgrid[10], "............");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-
-}
-
-
-static char minivault_33(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // lava pond
- UNUSED( mons_array );
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "............");
- strcpy(vgrid[2], "............");
- strcpy(vgrid[3], "............");
- strcpy(vgrid[4], "............");
- strcpy(vgrid[5], ".....V......");
- strcpy(vgrid[6], "............");
- strcpy(vgrid[7], "............");
- strcpy(vgrid[8], "............");
- strcpy(vgrid[9], "............");
- strcpy(vgrid[10], "............");
- strcpy(vgrid[11], "............");
-
- return MAP_NORTH;
-
-}
-
-static char minivault_34(char vgrid[81][81], FixedVector<int, 7>& mons_array, bool orientation)
-{
- //jmf: multi-god temple thing
- UNUSED( mons_array );
- int i, di;
-
- if ( orientation )
- {
- i = 0;
- di = +1;
- }
- else
- {
- i = 11;
- di = -1;
- }
-
- for (int c=0; c <= 11; c++, i += di)
+ for (unsigned i = 0, size = vdefs.size(); i < size; ++i)
{
- strcpy(vgrid[i], "............");
- strcpy(vgrid[i], ".=xxxxxxxx=.");
- strcpy(vgrid[i], ".x9......9x.");
- strcpy(vgrid[i], ".xT......Tx.");
- strcpy(vgrid[i], ".x..C..C..x.");
- strcpy(vgrid[i], ".xT......Tx.");
- strcpy(vgrid[i], ".xxxxxxxxxx.");
- strcpy(vgrid[i], ".xxx$$$$xxx.");
- strcpy(vgrid[i], ".xx8....8xx.");
- strcpy(vgrid[i], "..xx....xx..");
- strcpy(vgrid[i], "...xG..Gx...");
- strcpy(vgrid[i], "............");
- }
-
- return MAP_NORTH;
-}
-
-static char minivault_34_a(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
- return minivault_34(vgrid, mons_array, true);
-}
-
-static char minivault_34_b(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
- return minivault_34(vgrid, mons_array, false);
-}
-
-static char minivault_35(char vgrid[81][81], FixedVector<int, 7>& mons_array, bool orientation)
-{
- UNUSED( mons_array );
- //jmf: another multi-god temple thing
- int i, di;
-
- if (orientation)
- {
- i = 0;
- di = +1;
- }
- else
- {
- i = 11;
- di = -1;
- }
+ if (vdefs[i].has_tag(tag))
+ {
+ rollsize += vdefs[i].chance;
- for (int c=0; c <= 11; c++, i += di)
- {
- strcpy(vgrid[i], "............");
- strcpy(vgrid[i], "..vvvvvvvv..");
- strcpy(vgrid[i], ".vv......vv.");
- strcpy(vgrid[i], ".v..x..x..v.");
- strcpy(vgrid[i], ".v.Cx..xC.v.");
- strcpy(vgrid[i], ".v..x..x..v.");
- strcpy(vgrid[i], ".vT8x..x8Tv.");
- strcpy(vgrid[i], ".vvvx==xvvv.");
- strcpy(vgrid[i], "...Gx99xG...");
- strcpy(vgrid[i], "...+*99*+...");
- strcpy(vgrid[i], "...GxxxxG...");
- strcpy(vgrid[i], "............");
+ if (rollsize && random2(rollsize) < vdefs[i].chance)
+ mapindex = i;
+ }
}
- return MAP_NORTH;
-}
-
-static char minivault_35_a(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
- return minivault_35(vgrid, mons_array, true);
-}
-
-static char minivault_35_b(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
- return minivault_35(vgrid, mons_array, false);
-}
-
-
-static char rand_demon_1(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".xx.xx.x.xx.");
- strcpy(vgrid[2], "..x.x..x.x..");
- strcpy(vgrid[3], "..x.x..x.x..");
- strcpy(vgrid[4], "..x.x..x.x..");
- strcpy(vgrid[5], "..x.x..x.x..");
- strcpy(vgrid[6], "..x.x1.x.x..");
- strcpy(vgrid[7], "..x.x..x.x..");
- strcpy(vgrid[8], "..x.x..x.x..");
- strcpy(vgrid[9], "..x.x..x.x..");
- strcpy(vgrid[10], ".xx.x.xx.xx.");
- strcpy(vgrid[11], "............");
-
- mons_array[0] = MONS_PANDEMONIUM_DEMON;
- mons_array[1] = RANDOM_MONSTER;
- mons_array[2] = RANDOM_MONSTER;
- mons_array[3] = RANDOM_MONSTER;
- mons_array[4] = RANDOM_MONSTER;
- mons_array[5] = RANDOM_MONSTER;
-
- return MAP_NORTH;
-}
-
-
-static char rand_demon_2(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".xxxxxxxx3x.");
- strcpy(vgrid[2], ".3.....xx.x.");
- strcpy(vgrid[3], ".xxxxxx4x.x.");
- strcpy(vgrid[4], ".xx4x..xx.x.");
- strcpy(vgrid[5], ".x.x.22.x.x.");
- strcpy(vgrid[6], ".x.x.12.x.x.");
- strcpy(vgrid[7], ".x.xx..x4xx.");
- strcpy(vgrid[8], ".x.x4xxxxxx.");
- strcpy(vgrid[9], ".x.xx.....3.");
- strcpy(vgrid[10], ".x3xxxxxxxx.");
- strcpy(vgrid[11], "............");
-
- mons_array[0] = MONS_PANDEMONIUM_DEMON;
- mons_array[1] = summon_any_demon(DEMON_GREATER);
- mons_array[2] = summon_any_demon(DEMON_COMMON);
- mons_array[3] = summon_any_demon(DEMON_COMMON);
- mons_array[4] = RANDOM_MONSTER;
- mons_array[5] = RANDOM_MONSTER;
-
- return MAP_NORTH;
-}
-
-
-static char rand_demon_3(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
+#ifdef DEBUG_DIAGNOSTICS
+ if (mapindex != -1)
+ mprf(MSGCH_DIAGNOSTICS, "Found map %s tagged '%s'",
+ vdefs[mapindex].name.c_str(), tag.c_str());
+ else
+ mprf(MSGCH_DIAGNOSTICS, "No map for tag '%s'", tag.c_str());
+#endif
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".x.x.x3x.x..");
- strcpy(vgrid[2], "..x.x3x3x.x.");
- strcpy(vgrid[3], ".x.x.x2x.x..");
- strcpy(vgrid[4], "..x3x2x2x3x.");
- strcpy(vgrid[5], ".x3x2x1x2x3.");
- strcpy(vgrid[6], "..x3x2x2x3x.");
- strcpy(vgrid[7], ".x.x.x2x3x..");
- strcpy(vgrid[8], "..x.x3x3x.x.");
- strcpy(vgrid[9], ".x.x.x3x.x..");
- strcpy(vgrid[10], "..x.x.x.x.x.");
- strcpy(vgrid[11], "............");
-
- mons_array[0] = MONS_PANDEMONIUM_DEMON;
- mons_array[1] = summon_any_demon(DEMON_COMMON);
- mons_array[2] = summon_any_demon(DEMON_COMMON);
-
- return MAP_NORTH;
+ return (mapindex);
}
+/////////////////////////////////////////////////////////////////////////////
+// Reading maps from .des files.
-static char rand_demon_4(char vgrid[81][81], FixedVector<int, 7>& mons_array)
+static void parse_maps(const std::string &s)
{
- //jmf: all 3s below were 1s -- may have been bug
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".xxxxxxxxx..");
- strcpy(vgrid[2], ".x$=*=3=|x..");
- strcpy(vgrid[3], ".xxxxxxx=x..");
- strcpy(vgrid[4], ".x2=3=2x|x..");
- strcpy(vgrid[5], ".x=xxxxx=x..");
- strcpy(vgrid[6], ".x3=*x1=Px..");
- strcpy(vgrid[7], ".x=x=xxxxx..");
- strcpy(vgrid[8], ".x*x2=3=2=..");
- strcpy(vgrid[9], ".xxxxxxxxx..");
- strcpy(vgrid[10], "............");
- strcpy(vgrid[11], "............");
-
- mons_array[0] = MONS_PANDEMONIUM_DEMON;
- mons_array[1] = summon_any_demon(random2(3));
- mons_array[2] = summon_any_demon(random2(3));
-
- return MAP_NORTH;
-
-}
-
-
-static char rand_demon_5(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{ // obviously possible to get stuck - too bad (should've come prepared)
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "...xxxxxx...");
- strcpy(vgrid[2], "..xx....xx..");
- strcpy(vgrid[3], ".xx......xx.");
- strcpy(vgrid[4], ".x..3232..x.");
- strcpy(vgrid[5], ".x..2|P3..x.");
- strcpy(vgrid[6], ".x..3P|2..x.");
- strcpy(vgrid[7], ".x..2123..x.");
- strcpy(vgrid[8], ".xx......xx.");
- strcpy(vgrid[9], "..xx....xx..");
- strcpy(vgrid[10], "...xxxxxx...");
- strcpy(vgrid[11], "............");
-
- mons_array[0] = MONS_PANDEMONIUM_DEMON;
- mons_array[1] = summon_any_demon(random2(3));
- mons_array[2] = summon_any_demon(random2(3));
-
- return MAP_NORTH;
-
-}
-
+ FILE *dat = fopen(s.c_str(), "r");
+ if (!dat)
+ {
+ fprintf(stderr, "Failed to open %s for reading: %d\n", s.c_str(),
+ errno);
+ exit(1);
+ }
-static char rand_demon_6(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
+ reset_map_parser();
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "............");
- strcpy(vgrid[2], "......2.....");
- strcpy(vgrid[3], "............");
- strcpy(vgrid[4], ".3..........");
- strcpy(vgrid[5], "..........2.");
- strcpy(vgrid[6], ".....1......");
- strcpy(vgrid[7], "............");
- strcpy(vgrid[8], "............");
- strcpy(vgrid[9], ".2.......3..");
- strcpy(vgrid[10], "............");
- strcpy(vgrid[11], "............");
-
- mons_array[0] = MONS_PANDEMONIUM_DEMON;
- mons_array[1] = summon_any_demon(random2(3));
- mons_array[2] = summon_any_demon(random2(3));
-
- return MAP_NORTH;
+ extern int yyparse(void);
+ extern FILE *yyin;
+ yyin = dat;
+ yyparse();
+ fclose(dat);
}
-
-static char rand_demon_7(char vgrid[81][81], FixedVector<int, 7>& mons_array)
+void read_maps()
{
-
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".xxx....xxx.");
- strcpy(vgrid[2], ".x|xx=xxx|x.");
- strcpy(vgrid[3], ".xx=....=xx.");
- strcpy(vgrid[4], "..x.x==x.x..");
- strcpy(vgrid[5], "..x.=12=.=..");
- strcpy(vgrid[6], "..=.=23=.x..");
- strcpy(vgrid[7], "..x.x==x.x..");
- strcpy(vgrid[8], ".xx=....=xx.");
- strcpy(vgrid[9], ".x|xxx=xx|x.");
- strcpy(vgrid[10], ".xxx....xxx.");
- strcpy(vgrid[11], "............");
-
- mons_array[0] = MONS_PANDEMONIUM_DEMON;
- mons_array[1] = summon_any_demon(random2(3));
- mons_array[2] = summon_any_demon(DEMON_GREATER);
-
- return MAP_NORTH;
-
+ parse_maps( lc_desfile = datafile_path( "splev.des" ) );
+ parse_maps( lc_desfile = datafile_path( "vaults.des" ) );
}
-
-static char rand_demon_8(char vgrid[81][81], FixedVector<int, 7>& mons_array)
+void add_parsed_map( const map_def &md )
{
+ map_def map = md;
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], "....xxxxxxx.");
- strcpy(vgrid[2], "..xxx....1x.");
- strcpy(vgrid[3], ".xx..2....x.");
- strcpy(vgrid[4], ".x........x.");
- strcpy(vgrid[5], ".xx.......x.");
- strcpy(vgrid[6], "..xx33..2.x.");
- strcpy(vgrid[7], "....33...xx.");
- strcpy(vgrid[8], ".....x...x..");
- strcpy(vgrid[9], "..F..xx.xx..");
- strcpy(vgrid[10], "......xxx...");
- strcpy(vgrid[11], "............");
-
- mons_array[0] = MONS_PANDEMONIUM_DEMON;
- mons_array[1] = summon_any_demon(DEMON_GREATER);
- mons_array[2] = summon_any_demon(random2(3));
-
- return MAP_NORTH;
-
+ map.fixup();
+ vdefs.push_back( map );
}
+//////////////////////////////////////////////////////////////////
+// map_lines
-static char rand_demon_9(char vgrid[81][81], FixedVector<int, 7>& mons_array)
-{
- strcpy(vgrid[0], "............");
- strcpy(vgrid[1], ".xxxxxxxxxx.");
- strcpy(vgrid[2], ".x2=3=3=3xx.");
- strcpy(vgrid[3], ".x=xxxxxx2x.");
- strcpy(vgrid[4], ".x3x^^^^x=x.");
- strcpy(vgrid[5], ".x=x^P^^x2x.");
- strcpy(vgrid[6], ".x3x^^1^x=x.");
- strcpy(vgrid[7], ".x=x^^^^x3x.");
- strcpy(vgrid[8], ".x2xxxx=x=x.");
- strcpy(vgrid[9], ".xx2=2=3x3x.");
- strcpy(vgrid[10], ".xxxxxxxx=x.");
- strcpy(vgrid[11], "............");
-
- mons_array[0] = MONS_PANDEMONIUM_DEMON;
- mons_array[1] = summon_any_demon(random2(3));
- mons_array[2] = summon_any_demon(DEMON_GREATER);
-
- return MAP_NORTH;
-
-}
diff --git a/crawl-ref/source/maps.h b/crawl-ref/source/maps.h
index e2ce11af80..7159448f85 100644
--- a/crawl-ref/source/maps.h
+++ b/crawl-ref/source/maps.h
@@ -13,13 +13,33 @@
#define MAPS_H
#include "FixVec.h"
+#include "dungeon.h"
+class map_def;
+struct vault_placement
+{
+ int x, y;
+ int width, height;
+ const map_def *map;
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: dungeon
- * *********************************************************************** */
-char vault_main(char vgrid[81][81], FixedVector<int, 7>& mons_array, int vault_force, int many_many);
+ vault_placement()
+ : x(-1), y(-1), width(0), height(0), map(NULL)
+ {
+ }
+};
+int vault_main(map_type vgrid,
+ FixedVector<int, 7>& mons_array,
+ vault_placement &vp,
+ int vault_force,
+ int many_many);
+
+int random_map_for_place(const std::string &place, bool mini = false);
+int find_map_named(const std::string &name);
+int random_map_for_depth(int depth, bool want_minivault = false);
+int random_map_for_tag(const std::string &tag);
+void add_parsed_map(const map_def &md);
+
+void read_maps();
#endif
diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc
index 0728980058..c804c5343b 100644
--- a/crawl-ref/source/menu.cc
+++ b/crawl-ref/source/menu.cc
@@ -1,23 +1,37 @@
+/*
+ * File: menu.cc
+ * Summary: Menus and associated malarkey.
+ * Written by: Darshan Shaligram
+ *
+ * Modified for Crawl Reference by $Author$ on $Date$
+ */
#include <cctype>
+#include "AppHdr.h"
#include "menu.h"
#include "macro.h"
#include "view.h"
+#include "initfile.h"
Menu::Menu( int _flags )
- : selitem_text(NULL),
+ : f_selitem(NULL),
+ f_drawitem(NULL),
+ f_keyfilter(NULL),
title(NULL),
flags(_flags),
first_entry(0),
y_offset(0),
pagesize(0),
+ max_pagesize(0),
+ more("-more-", true),
items(),
- sel(NULL),
+ sel(),
select_filter(),
highlighter(new MenuHighlighter),
num(-1),
lastch(0),
alive(false)
{
+ set_flags(flags);
}
Menu::~Menu()
@@ -28,6 +42,33 @@ Menu::~Menu()
delete highlighter;
}
+void Menu::clear()
+{
+ for (int i = 0, count = items.size(); i < count; ++i)
+ delete items[i];
+ items.clear();
+}
+
+void Menu::set_maxpagesize(int max)
+{
+ max_pagesize = max;
+}
+
+void Menu::set_flags(int new_flags, bool use_options)
+{
+ flags = new_flags;
+ if (use_options)
+ {
+ if (Options.easy_exit_menu)
+ flags |= MF_EASY_EXIT;
+ }
+}
+
+void Menu::set_more(const formatted_string &fs)
+{
+ more = fs;
+}
+
void Menu::set_highlighter( MenuHighlighter *mh )
{
if (highlighter != mh)
@@ -54,14 +95,17 @@ void Menu::reset()
first_entry = 0;
}
-std::vector<MenuEntry *> Menu::show()
+std::vector<MenuEntry *> Menu::show(bool reuse_selections)
{
- std::vector< MenuEntry * > selected;
-
- deselect_all(false);
+ if (reuse_selections)
+ get_selected(&sel);
+ else
+ deselect_all(false);
- // Lose lines for the title + room for more.
- pagesize = get_number_of_lines() - 2;
+ // Lose lines for the title + room for -more- line.
+ pagesize = get_number_of_lines() - !!title - 1;
+ if (max_pagesize > 0 && pagesize > max_pagesize)
+ pagesize = max_pagesize;
#ifdef DOS_TERM
char buffer[4600];
@@ -70,19 +114,18 @@ std::vector<MenuEntry *> Menu::show()
window(1, 1, 80, 25);
#endif
- do_menu( &selected );
+ do_menu();
#ifdef DOS_TERM
puttext(1, 1, 80, 25, buffer);
#endif
- return selected;
+ return (sel);
}
-void Menu::do_menu( std::vector<MenuEntry*> *selected )
+void Menu::do_menu()
{
- sel = selected;
- draw_menu( selected );
+ draw_menu();
alive = true;
while (alive)
@@ -96,71 +139,88 @@ void Menu::do_menu( std::vector<MenuEntry*> *selected )
bool Menu::is_set(int flag) const
{
- if (flag == MF_EASY_EXIT && Options.easy_exit_menu)
- return true;
return (flags & flag) == flag;
}
+int Menu::pre_process(int k)
+{
+ return (k);
+}
+
+int Menu::post_process(int k)
+{
+ return (k);
+}
+
bool Menu::process_key( int keyin )
{
if (items.size() == 0)
return false;
bool nav = false, repaint = false;
+
+ if (f_keyfilter)
+ keyin = (*f_keyfilter)(keyin);
+
+ keyin = pre_process(keyin);
+
switch (keyin)
{
- case CK_ENTER:
- return false;
- case CK_ESCAPE:
- sel->clear();
- lastch = keyin;
- return false;
- case ' ': case CK_PGDN: case '>': case '\'':
- nav = true;
- repaint = page_down();
- if (!repaint && flags && !is_set(MF_EASY_EXIT))
- {
- repaint = first_entry != 0;
- first_entry = 0;
- }
- break;
- case CK_PGUP: case '<': case ';':
- nav = true;
- repaint = page_up();
- break;
- case CK_UP:
- nav = true;
- repaint = line_up();
- break;
- case CK_DOWN:
- nav = true;
- repaint = line_down();
- break;
- default:
- lastch = keyin;
+ case 0:
+ return true;
+ case CK_ENTER:
+ return false;
+ case CK_ESCAPE:
+ sel.clear();
+ lastch = keyin;
+ return false;
+ case ' ': case CK_PGDN: case '>': case '\'':
+ nav = true;
+ repaint = page_down();
+ if (!repaint && !is_set(MF_EASY_EXIT) && !is_set(MF_NOWRAP))
+ {
+ repaint = first_entry != 0;
+ first_entry = 0;
+ }
+ break;
+ case CK_PGUP: case '<': case ';':
+ nav = true;
+ repaint = page_up();
+ break;
+ case CK_UP:
+ nav = true;
+ repaint = line_up();
+ break;
+ case CK_DOWN:
+ nav = true;
+ repaint = line_down();
+ break;
+ default:
+ keyin = post_process(keyin);
+ lastch = keyin;
- // If no selection at all is allowed, exit now.
- if (!(flags & (MF_SINGLESELECT | MF_MULTISELECT)))
- return false;
+ // If no selection at all is allowed, exit now.
+ if (!(flags & (MF_SINGLESELECT | MF_MULTISELECT)))
+ return false;
- if (!is_set(MF_NO_SELECT_QTY) && isdigit( keyin ))
- {
- if (num > 999)
- num = -1;
- num = (num == -1)? keyin - '0' :
- num * 10 + keyin - '0';
- }
-
- select_items( keyin, num );
- get_selected( sel );
- if (sel->size() == 1 && (flags & MF_SINGLESELECT))
- return false;
- draw_select_count( sel->size() );
+ if (!is_set(MF_NO_SELECT_QTY) && isdigit( keyin ))
+ {
+ if (num > 999)
+ num = -1;
+ num = (num == -1)? keyin - '0' :
+ num * 10 + keyin - '0';
+ }
+
+ select_items( keyin, num );
+ get_selected( &sel );
+ if (sel.size() == 1 && (flags & MF_SINGLESELECT))
+ return false;
+ draw_select_count( sel.size() );
- if (flags & MF_ANYPRINTABLE && !isdigit( keyin ))
- return false;
+ if (flags & MF_ANYPRINTABLE && !isdigit( keyin ))
+ return false;
- break;
+ break;
}
if (!isdigit( keyin ))
@@ -169,11 +229,11 @@ bool Menu::process_key( int keyin )
if (nav)
{
if (repaint)
- draw_menu( sel );
+ draw_menu();
// Easy exit should not kill the menu if there are selected items.
- else if (sel->empty() && (!flags || is_set(MF_EASY_EXIT)))
+ else if (sel.empty() && is_set(MF_EASY_EXIT))
{
- sel->clear();
+ sel.clear();
return false;
}
}
@@ -188,32 +248,32 @@ bool Menu::draw_title_suffix( const std::string &s, bool titlefirst )
draw_title();
int x = wherex();
- if (x > GXM || x < 1)
+ if (x > get_number_of_cols() || x < 1)
{
gotoxy(oldx, oldy);
return false;
}
- // Note: 1 <= x <= GXM; we have no fear of overflow.
- unsigned avail_width = GXM - x + 1;
+ // Note: 1 <= x <= get_number_of_cols(); we have no fear of overflow.
+ unsigned avail_width = get_number_of_cols() - x + 1;
std::string towrite = s.length() > avail_width? s.substr(0, avail_width) :
s.length() == avail_width? s :
s + std::string(avail_width - s.length(), ' ');
- cprintf(towrite.c_str());
+ cprintf("%s", towrite.c_str());
gotoxy( oldx, oldy );
return true;
}
-void Menu::draw_select_count( int count )
+void Menu::draw_select_count( int count, bool force )
{
- if (!is_set(MF_MULTISELECT))
+ if (!force && !is_set(MF_MULTISELECT))
return;
- if (selitem_text)
+ if (f_selitem)
{
- draw_title_suffix( selitem_text( sel ) );
+ draw_title_suffix( f_selitem( &sel ) );
}
else
{
@@ -226,6 +286,13 @@ void Menu::draw_select_count( int count )
}
}
+std::vector<MenuEntry*> Menu::selected_entries() const
+{
+ std::vector<MenuEntry*> selection;
+ get_selected(&selection);
+ return (selection);
+}
+
void Menu::get_selected( std::vector<MenuEntry*> *selected ) const
{
selected->clear();
@@ -257,7 +324,7 @@ bool Menu::is_hotkey(int i, int key)
items[i]->is_primary_hotkey(key)
: items[i]->is_hotkey(key);
- return is_set(MF_SELECT_ANY_PAGE)? ishotkey
+ return !is_set(MF_SELECT_BY_PAGE)? ishotkey
: ishotkey && i >= first_entry && i < end;
}
@@ -371,13 +438,13 @@ void Menu::select_index( int index, int qty )
}
}
-void Menu::draw_menu( std::vector< MenuEntry* > *selected )
+void Menu::draw_menu()
{
clrscr();
draw_title();
- draw_select_count( selected->size() );
- y_offset = 2;
+ draw_select_count( sel.size() );
+ y_offset = 1 + !!title;
int end = first_entry + pagesize;
if (end > (int) items.size()) end = items.size();
@@ -386,11 +453,10 @@ void Menu::draw_menu( std::vector< MenuEntry* > *selected )
{
draw_item( i );
}
- if (end < (int) items.size())
+ if (end < (int) items.size() || is_set(MF_ALWAYS_SHOW_MORE))
{
gotoxy( 1, y_offset + pagesize );
- textcolor( LIGHTGREY );
- cprintf("-more-");
+ more.display();
}
}
@@ -401,7 +467,7 @@ void Menu::update_title()
gotoxy(x, y);
}
-int Menu::item_colour(const MenuEntry *entry) const
+int Menu::item_colour(int, const MenuEntry *entry) const
{
int icol = -1;
if (highlighter)
@@ -415,18 +481,45 @@ void Menu::draw_title()
if (title)
{
gotoxy(1, 1);
- textcolor( item_colour(title) );
- cprintf( "%s", title->get_text().c_str() );
+ write_title();
}
}
+void Menu::write_title()
+{
+ textattr( item_colour(-1, title) );
+ cprintf("%s", title->get_text().c_str());
+
+ const int x = wherex(), y = wherey();
+ cprintf("%-*s", get_number_of_cols() - x, "");
+ gotoxy(x, y);
+}
+
+bool Menu::in_page(int index) const
+{
+ return (index >= first_entry && index < first_entry + pagesize);
+}
+
void Menu::draw_item( int index ) const
{
- if (index < first_entry || index >= first_entry + pagesize)
+ if (!in_page(index))
return;
-
gotoxy( 1, y_offset + index - first_entry );
- textcolor( item_colour(items[index]) );
+
+ draw_item(index, items[index]);
+}
+
+void Menu::draw_item(int index, const MenuEntry *me) const
+{
+ if (f_drawitem)
+ (*f_drawitem)(index, me);
+ else
+ draw_stock_item(index, me);
+}
+
+void Menu::draw_stock_item(int index, const MenuEntry *me) const
+{
+ textattr( item_colour(index, items[index]) );
cprintf( "%s", items[index]->get_text().c_str() );
}
@@ -481,6 +574,258 @@ bool Menu::line_up()
}
/////////////////////////////////////////////////////////////////
+// slider_menu
+
+slider_menu::slider_menu(int fl)
+ : Menu(fl), less(), starty(1), endy(get_number_of_lines()),
+ selected(0), search()
+{
+ less.textcolor(DARKGREY);
+ less.cprintf("<---- More");
+ more.clear();
+ more.textcolor(DARKGREY);
+ more.cprintf("More ---->");
+}
+
+void slider_menu::set_search(const std::string &s)
+{
+ search = s;
+}
+
+void slider_menu::set_limits(int y1, int y2)
+{
+ starty = y1;
+ endy = y2;
+}
+
+void slider_menu::select_search(const std::string &s)
+{
+ std::string srch = s;
+ tolower_string(srch);
+
+ for (int i = 0, size = items.size(); i < size; ++i)
+ {
+ std::string text = items[i]->get_text();
+ tolower_string(text);
+
+ std::string::size_type found = text.find(srch);
+ if (found != std::string::npos
+ && found == text.find_first_not_of(" "))
+ {
+ move_selection(i);
+ break;
+ }
+ }
+}
+
+int slider_menu::post_process(int key)
+{
+ select_search( search += key );
+ return (key);
+}
+
+bool slider_menu::process_key(int key)
+{
+ // Some of this key processing should really be in a user-passed-in function
+ // If we ever need to use slider_menu elsewhere, we should factor it out.
+ if (key == CK_ESCAPE || key == '\t')
+ {
+ int old = selected;
+ selected = -1;
+ draw_item(old);
+ sel.clear();
+ search.clear();
+ lastch = key;
+ return (false);
+ }
+
+ if (selected == 0 &&
+ (key == CK_UP || key == CK_PGUP || key == '<' || key == ';') &&
+ Menu::is_set(MF_EASY_EXIT))
+ {
+ int old = selected;
+ selected = -1;
+ draw_item(old);
+ search.clear();
+ return (false);
+ }
+
+ return Menu::process_key(key);
+}
+
+void slider_menu::display()
+{
+ // We lose two lines for each of the --More prompts
+ pagesize = endy - starty - 1 - !!title;
+ selected = -1;
+ draw_menu();
+}
+
+std::vector<MenuEntry *> slider_menu::show()
+{
+ cursor_control coff(false);
+
+ sel.clear();
+
+ // We lose two lines for each of the --More prompts
+ pagesize = endy - starty - 1 - !!title;
+
+ if (selected == -1)
+ selected = 0;
+
+ select_search(search);
+ do_menu();
+
+ if (selected >= 0 && selected <= (int) items.size())
+ sel.push_back(items[selected]);
+ return (sel);
+}
+
+const MenuEntry *slider_menu::selected_entry() const
+{
+ if (selected >= 0 && selected <= (int) items.size())
+ return (items[selected]);
+
+ return (NULL);
+}
+
+void slider_menu::draw_stock_item(int index, const MenuEntry *me) const
+{
+ Menu::draw_stock_item(index, me);
+ cprintf("%-*s", get_number_of_cols() - wherex() + 1, "");
+}
+
+int slider_menu::item_colour(int index, const MenuEntry *me) const
+{
+ int colour = Menu::item_colour(index, me);
+ if (index == selected && selected != -1)
+ {
+#if defined(WIN32CONSOLE) || defined(DOS)
+ colour = dos_brand(colour, CHATTR_REVERSE);
+#else
+ colour |= COLFLAG_REVERSE;
+#endif
+ }
+ return (colour);
+}
+
+void slider_menu::draw_menu()
+{
+ gotoxy(1, starty);
+ write_title();
+ y_offset = starty + !!title + 1;
+
+ int end = first_entry + pagesize;
+ if (end > (int) items.size()) end = items.size();
+
+ // We're using get_number_of_cols() - 1 because we want to avoid line wrap
+ // on DOS (the conio.h functions go batshit if that happens).
+ gotoxy(1, y_offset - 1);
+ if (first_entry > 0)
+ less.display();
+ else
+ {
+ textattr(LIGHTGREY);
+ cprintf("%-*s", get_number_of_cols() - 1, "");
+ }
+
+ for (int i = first_entry; i < end; ++i)
+ draw_item( i );
+
+ textattr(LIGHTGREY);
+ for (int i = end; i < first_entry + pagesize; ++i)
+ {
+ gotoxy(1, y_offset + i - first_entry);
+ cprintf("%-*s", get_number_of_cols() - 1, "");
+ }
+
+ gotoxy( 1, y_offset + pagesize );
+ if (end < (int) items.size() || is_set(MF_ALWAYS_SHOW_MORE))
+ more.display();
+ else
+ {
+ textattr(LIGHTGREY);
+ cprintf("%-*s", get_number_of_cols() - 1, "");
+ }
+}
+
+void slider_menu::select_items(int, int)
+{
+ // Ignored.
+}
+
+bool slider_menu::is_set(int flag) const
+{
+ if (flag == MF_EASY_EXIT)
+ return (false);
+ return Menu::is_set(flag);
+}
+
+bool slider_menu::fix_entry()
+{
+ if (selected < 0 || selected >= (int) items.size())
+ return (false);
+
+ const int oldfirst = first_entry;
+ if (selected < first_entry)
+ first_entry = selected;
+ else if (selected >= first_entry + pagesize)
+ {
+ first_entry = selected - pagesize + 1;
+ if (first_entry < 0)
+ first_entry = 0;
+ }
+
+ return (first_entry != oldfirst);
+}
+
+void slider_menu::new_selection(int nsel)
+{
+ if (nsel < 0)
+ nsel = 0;
+ if (nsel >= (int) items.size())
+ nsel = items.size() - 1;
+
+ const int old = selected;
+ selected = nsel;
+ if (old != selected && nsel >= first_entry && nsel < first_entry + pagesize)
+ {
+ draw_item(old);
+ draw_item(selected);
+ }
+}
+
+bool slider_menu::move_selection(int nsel)
+{
+ new_selection(nsel);
+ return fix_entry();
+}
+
+bool slider_menu::page_down()
+{
+ search.clear();
+ return move_selection( selected + pagesize );
+}
+
+bool slider_menu::page_up()
+{
+ search.clear();
+ return move_selection( selected - pagesize );
+}
+
+bool slider_menu::line_down()
+{
+ search.clear();
+ return move_selection( selected + 1 );
+}
+
+bool slider_menu::line_up()
+{
+ search.clear();
+ return move_selection( selected - 1 );
+}
+
+/////////////////////////////////////////////////////////////////
// Menu colouring
//
@@ -499,3 +844,364 @@ int MenuHighlighter::entry_colour(const MenuEntry *entry) const
{
return (::menu_colour(entry->get_text()));
}
+
+
+////////////////////////////////////////////////////////////////////
+// formatted_string
+//
+
+formatted_string::formatted_string(const std::string &s, bool init_style)
+ : ops()
+{
+ if (init_style)
+ ops.push_back(LIGHTGREY);
+ ops.push_back(s);
+}
+
+int formatted_string::get_colour(const std::string &tag)
+{
+ if (tag == "h")
+ return (YELLOW);
+
+ if (tag == "w")
+ return (WHITE);
+
+ const int colour = str_to_colour(tag);
+ return (colour != -1? colour : LIGHTGREY);
+}
+
+formatted_string formatted_string::parse_string(
+ const std::string &s,
+ bool eol_ends_format,
+ bool (*process)(const std::string &tag))
+{
+ // FIXME This is a lame mess, just good enough for the task on hand
+ // (keyboard help).
+ formatted_string fs;
+ std::string::size_type tag = std::string::npos;
+ std::string::size_type length = s.length();
+
+ std::string currs;
+ int curr_colour = LIGHTGREY;
+ bool masked = false;
+
+ for (tag = 0; tag < length; ++tag)
+ {
+ bool invert_colour = false;
+ std::string::size_type endpos = std::string::npos;
+
+ if (s[tag] != '<' || tag >= length - 2)
+ {
+ if (!masked)
+ currs += s[tag];
+ continue;
+ }
+
+ // Is this a << escape?
+ if (s[tag + 1] == '<')
+ {
+ if (!masked)
+ currs += s[tag];
+ tag++;
+ continue;
+ }
+
+ endpos = s.find('>', tag + 1);
+ // No closing >?
+ if (endpos == std::string::npos)
+ {
+ if (!masked)
+ currs += s[tag];
+ continue;
+ }
+
+ std::string tagtext = s.substr(tag + 1, endpos - tag - 1);
+ if (tagtext.empty() || tagtext == "/")
+ {
+ if (!masked)
+ currs += s[tag];
+ continue;
+ }
+
+ if (tagtext[0] == '/')
+ {
+ invert_colour = true;
+ tagtext = tagtext.substr(1);
+ tag++;
+ }
+
+ if (tagtext[0] == '?')
+ {
+ if (tagtext.length() == 1)
+ masked = false;
+ else if (process && !process(tagtext.substr(1)))
+ masked = true;
+
+ tag += tagtext.length() + 1;
+ continue;
+ }
+
+ const int new_colour = invert_colour? LIGHTGREY : get_colour(tagtext);
+ if (new_colour != curr_colour)
+ {
+ fs.cprintf(currs);
+ currs.clear();
+ fs.textcolor( curr_colour = new_colour );
+ }
+ tag += tagtext.length() + 1;
+ }
+ if (currs.length())
+ fs.cprintf(currs);
+
+ if (eol_ends_format && curr_colour != LIGHTGREY)
+ fs.textcolor(LIGHTGREY);
+
+ return (fs);
+}
+
+formatted_string::operator std::string() const
+{
+ std::string s;
+ for (unsigned i = 0, size = ops.size(); i < size; ++i)
+ {
+ if (ops[i] == FSOP_TEXT)
+ s += ops[i].text;
+ }
+ return (s);
+}
+
+const formatted_string &
+formatted_string::operator += (const formatted_string &other)
+{
+ ops.insert(ops.end(), other.ops.begin(), other.ops.end());
+ return (*this);
+}
+
+std::string::size_type formatted_string::length() const
+{
+ // Just add up the individual string lengths.
+ std::string::size_type len = 0;
+ for (unsigned i = 0, size = ops.size(); i < size; ++i)
+ if (ops[i] == FSOP_TEXT)
+ len += ops[i].text.length();
+ return (len);
+}
+
+inline void cap(int &i, int max)
+{
+ if (i < 0 && -i <= max)
+ i += max;
+ if (i >= max)
+ i = max - 1;
+ if (i < 0)
+ i = 0;
+}
+
+std::string formatted_string::tostring(int s, int e) const
+{
+ std::string st;
+
+ int size = ops.size();
+ cap(s, size);
+ cap(e, size);
+
+ for (int i = s; i <= e && i < size; ++i)
+ {
+ if (ops[i] == FSOP_TEXT)
+ st += ops[i].text;
+ }
+ return st;
+}
+
+void formatted_string::display(int s, int e) const
+{
+ int size = ops.size();
+ if (!size)
+ return ;
+
+ cap(s, size);
+ cap(e, size);
+
+ for (int i = s; i <= e && i < size; ++i)
+ ops[i].display();
+}
+
+void formatted_string::gotoxy(int x, int y)
+{
+ ops.push_back( fs_op(x, y) );
+}
+
+void formatted_string::movexy(int x, int y)
+{
+ ops.push_back( fs_op(x, y, true) );
+}
+
+void formatted_string::textcolor(int color)
+{
+ ops.push_back(color);
+}
+
+void formatted_string::clear()
+{
+ ops.clear();
+}
+
+void formatted_string::cprintf(const char *s, ...)
+{
+ char buf[1000];
+ va_list args;
+ va_start(args, s);
+ vsnprintf(buf, sizeof buf, s, args);
+ va_end(args);
+
+ cprintf(std::string(buf));
+}
+
+void formatted_string::cprintf(const std::string &s)
+{
+ ops.push_back(s);
+}
+
+void formatted_string::fs_op::display() const
+{
+ switch (type)
+ {
+ case FSOP_CURSOR:
+ {
+ int cx = x, cy = y;
+ if (relative)
+ {
+ cx += wherex();
+ cy += wherey();
+ }
+ else
+ {
+ if (cx == -1)
+ cx = wherex();
+ if (cy == -1)
+ cy = wherey();
+ }
+ ::gotoxy(cx, cy);
+ break;
+ }
+ case FSOP_COLOUR:
+ ::textattr(x);
+ break;
+ case FSOP_TEXT:
+ ::cprintf("%s", text.c_str());
+ break;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////
+// column_composer
+
+column_composer::column_composer(int cols, ...)
+ : ncols(cols), pagesize(0), columns()
+{
+ ASSERT(cols > 0);
+
+ va_list args;
+ va_start(args, cols);
+
+ columns.push_back( column(1) );
+ int lastcol = 1;
+ for (int i = 1; i < cols; ++i)
+ {
+ int nextcol = va_arg(args, int);
+ ASSERT(nextcol > lastcol);
+
+ lastcol = nextcol;
+ columns.push_back( column(nextcol) );
+ }
+
+ va_end(args);
+}
+
+void column_composer::set_pagesize(int ps)
+{
+ pagesize = ps;
+}
+
+void column_composer::clear()
+{
+ flines.clear();
+}
+
+void column_composer::add_formatted(
+ int ncol,
+ const std::string &s,
+ bool add_separator,
+ bool eol_ends_format,
+ bool (*tfilt)(const std::string &),
+ int margin)
+{
+ ASSERT(ncol >= 0 && ncol < (int) columns.size());
+
+ column &col = columns[ncol];
+ std::vector<std::string> segs = split_string("\n", s, false, true);
+
+ std::vector<formatted_string> newlines;
+ // Add a blank line if necessary. Blank lines will not
+ // be added at page boundaries.
+ if (add_separator && col.lines && !segs.empty()
+ && (!pagesize || col.lines % pagesize))
+ newlines.push_back(formatted_string());
+
+ for (unsigned i = 0, size = segs.size(); i < size; ++i)
+ {
+ newlines.push_back(
+ formatted_string::parse_string(
+ segs[i],
+ eol_ends_format,
+ tfilt));
+ }
+
+ strip_blank_lines(newlines);
+
+ compose_formatted_column(
+ newlines,
+ col.lines,
+ margin == -1? col.margin : margin);
+
+ col.lines += newlines.size();
+
+ strip_blank_lines(flines);
+}
+
+std::vector<formatted_string> column_composer::formatted_lines() const
+{
+ return (flines);
+}
+
+void column_composer::strip_blank_lines(std::vector<formatted_string> &fs) const
+{
+ for (int i = fs.size() - 1; i >= 0; --i)
+ {
+ if (fs[i].length() == 0)
+ fs.erase( fs.begin() + i );
+ else
+ break;
+ }
+}
+
+void column_composer::compose_formatted_column(
+ const std::vector<formatted_string> &lines,
+ int startline,
+ int margin)
+{
+ if (flines.size() < startline + lines.size())
+ flines.resize(startline + lines.size());
+
+ for (unsigned i = 0, size = lines.size(); i < size; ++i)
+ {
+ int f = i + startline;
+ if (margin > 1)
+ {
+ int xdelta = margin - flines[f].length() - 1;
+ if (xdelta > 0)
+ flines[f].cprintf("%-*s", xdelta, "");
+ }
+ flines[f] += lines[i];
+ }
+}
diff --git a/crawl-ref/source/menu.h b/crawl-ref/source/menu.h
index 05e4796383..441685e11a 100644
--- a/crawl-ref/source/menu.h
+++ b/crawl-ref/source/menu.h
@@ -5,6 +5,7 @@
#include <vector>
#include <algorithm>
#include "AppHdr.h"
+#include "externs.h"
#include "defines.h"
#include "libutil.h"
@@ -33,7 +34,8 @@ struct menu_letter
return *this;
}
- menu_letter operator ++ (int postfix)
+ // dummy postfix argument unnamed to stop gcc from complaining
+ menu_letter operator ++ (int)
{
menu_letter copy = *this;
this->operator++();
@@ -41,6 +43,77 @@ struct menu_letter
}
};
+class formatted_string
+{
+public:
+ formatted_string() : ops() { }
+ formatted_string(const std::string &s, bool init_style = false);
+
+ operator std::string() const;
+ void display(int start = 0, int end = -1) const;
+ std::string tostring(int start = 0, int end = -1) const;
+
+ void cprintf(const char *s, ...);
+ void cprintf(const std::string &s);
+ void gotoxy(int x, int y);
+ void movexy(int delta_x, int delta_y);
+ void textcolor(int color);
+
+ void clear();
+
+ std::string::size_type length() const;
+
+ const formatted_string &operator += (const formatted_string &other);
+
+public:
+ static formatted_string parse_string(
+ const std::string &s,
+ bool eol_ends_format = true,
+ bool (*process_tag)(const std::string &tag) = NULL );
+
+private:
+ enum fs_op_type
+ {
+ FSOP_COLOUR,
+ FSOP_CURSOR,
+ FSOP_TEXT
+ };
+
+ static int get_colour(const std::string &tag);
+
+private:
+ struct fs_op
+ {
+ fs_op_type type;
+ int x, y;
+ bool relative;
+ std::string text;
+
+ fs_op(int color)
+ : type(FSOP_COLOUR), x(color), y(-1), relative(false), text()
+ {
+ }
+
+ fs_op(int cx, int cy, bool rel = false)
+ : type(FSOP_CURSOR), x(cx), y(cy), relative(rel), text()
+ {
+ }
+
+ fs_op(const std::string &s)
+ : type(FSOP_TEXT), x(-1), y(-1), relative(false), text(s)
+ {
+ }
+
+ operator fs_op_type () const
+ {
+ return type;
+ }
+ void display() const;
+ };
+
+ std::vector<fs_op> ops;
+};
+
struct item_def;
struct MenuEntry
{
@@ -51,7 +124,7 @@ struct MenuEntry
MenuEntryLevel level;
void *data;
- MenuEntry( const std::string &txt = std::string(""),
+ MenuEntry( const std::string &txt = std::string(),
MenuEntryLevel lev = MEL_ITEM,
int qty = 0,
int hotk = 0 ) :
@@ -66,6 +139,10 @@ struct MenuEntry
}
virtual ~MenuEntry() { }
+ bool operator<( const MenuEntry& rhs ) const {
+ return text < rhs.text;
+ }
+
void add_hotkey( int key )
{
if (key && !is_hotkey(key))
@@ -91,8 +168,7 @@ struct MenuEntry
"%c - %s", hotkeys[0], text.c_str());
return std::string(buf);
}
- return std::string(level == MEL_SUBTITLE? " " :
- level == MEL_ITEM? "" : " ") + text;
+ return text;
}
virtual bool selected() const
@@ -118,15 +194,19 @@ public:
enum MenuFlag
{
- MF_NOSELECT = 0, // No selection is permitted
- MF_SINGLESELECT = 1, // Select just one item
- MF_MULTISELECT = 2, // Select multiple items
- MF_NO_SELECT_QTY = 4, // Disallow partial selections
- MF_ANYPRINTABLE = 8, // Any printable character is valid, and
- // closes the menu.
- MF_SELECT_ANY_PAGE = 16, // Allow selections to occur on any page.
-
- MF_EASY_EXIT = 64
+ MF_NOSELECT = 0x0000, // No selection is permitted
+ MF_SINGLESELECT = 0x0001, // Select just one item
+ MF_MULTISELECT = 0x0002, // Select multiple items
+ MF_NO_SELECT_QTY = 0x0004, // Disallow partial selections
+ MF_ANYPRINTABLE = 0x0008, // Any printable character is valid, and
+ // closes the menu.
+ MF_SELECT_BY_PAGE = 0x0010, // Allow selections to occur only on
+ // currently visible page.
+
+ MF_ALWAYS_SHOW_MORE = 0x0020, // Always show the -more- footer
+ MF_NOWRAP = 0x0040, // Paging past the end will not wrap back.
+
+ MF_EASY_EXIT = 0x1000
};
///////////////////////////////////////////////////////////////////////
@@ -142,18 +222,28 @@ public:
Menu( int flags = MF_MULTISELECT );
virtual ~Menu();
- void set_flags( int new_flags ) { this->flags = new_flags; }
+ // Remove all items from the Menu, leave title intact.
+ void clear();
+
+ // Sets menu flags to new_flags. If use_options is true, game options may
+ // override options.
+ void set_flags(int new_flags, bool use_options = true);
int get_flags() const { return flags; }
- bool is_set( int flag ) const;
+ virtual bool is_set( int flag ) const;
bool draw_title_suffix( const std::string &s, bool titlefirst = true );
void update_title();
+
+ // Sets a replacement for the --more-- string.
+ void set_more(const formatted_string &more);
void set_highlighter( MenuHighlighter *h );
void set_title( MenuEntry *e );
void add_entry( MenuEntry *entry );
void get_selected( std::vector<MenuEntry*> *sel ) const;
+ void set_maxpagesize(int max);
+
void set_select_filter( std::vector<text_pattern> filter )
{
select_filter = filter;
@@ -162,22 +252,31 @@ public:
unsigned char getkey() const { return lastch; }
void reset();
- std::vector<MenuEntry *> show();
+ std::vector<MenuEntry *> show(bool reuse_selections = false);
+ std::vector<MenuEntry *> selected_entries() const;
+
+ size_t item_count() const { return items.size(); }
public:
typedef std::string (*selitem_tfn)( const std::vector<MenuEntry*> *sel );
+ typedef void (*drawitem_tfn)(int index, const MenuEntry *me);
+ typedef int (*keyfilter_tfn)(int keyin);
- selitem_tfn selitem_text;
+ selitem_tfn f_selitem;
+ drawitem_tfn f_drawitem;
+ keyfilter_tfn f_keyfilter;
protected:
MenuEntry *title;
int flags;
int first_entry, y_offset;
- int pagesize;
+ int pagesize, max_pagesize;
+
+ formatted_string more;
std::vector<MenuEntry*> items;
- std::vector<MenuEntry*> *sel;
+ std::vector<MenuEntry*> sel;
std::vector<text_pattern> select_filter;
// Class that is queried to colour menu entries.
@@ -189,28 +288,122 @@ protected:
bool alive;
- void do_menu( std::vector<MenuEntry*> *selected );
- virtual void draw_select_count( int count );
- void draw_item( int index ) const;
+protected:
+ void do_menu();
+ virtual void draw_select_count(int count, bool force = false);
+ virtual void draw_item( int index ) const;
+ virtual void draw_item(int index, const MenuEntry *me) const;
+ virtual void draw_stock_item(int index, const MenuEntry *me) const;
+
virtual void draw_title();
- void draw_menu( std::vector<MenuEntry*> *selected );
- bool page_down();
- bool line_down();
- bool page_up();
- bool line_up();
+ virtual void write_title();
+ virtual void draw_menu();
+ virtual bool page_down();
+ virtual bool line_down();
+ virtual bool page_up();
+ virtual bool line_up();
+
+ virtual int pre_process(int key);
+ virtual int post_process(int key);
+
+ bool in_page(int index) const;
void deselect_all(bool update_view = true);
- void select_items( int key, int qty = -1 );
+ virtual void select_items( int key, int qty = -1 );
void select_index( int index, int qty = -1 );
bool is_hotkey(int index, int key );
bool is_selectable(int index) const;
- int item_colour(const MenuEntry *me) const;
+ virtual int item_colour(int index, const MenuEntry *me) const;
virtual bool process_key( int keyin );
};
+// Uses a sliding selector rather than hotkeyed selection.
+class slider_menu : public Menu
+{
+public:
+ // Multiselect would be awkward to implement.
+ slider_menu(int flags = MF_SINGLESELECT);
+ void display();
+ std::vector<MenuEntry *> show();
+
+ void set_search(const std::string &search);
+ void set_limits(int starty, int endy);
+ const MenuEntry *selected_entry() const;
+
+protected:
+ int item_colour(int index, const MenuEntry *me) const;
+ void draw_stock_item(int index, const MenuEntry *me) const;
+ void draw_menu();
+
+ void new_selection(int nsel);
+ bool move_selection(int nsel);
+
+ bool page_down();
+ bool line_down();
+ bool page_up();
+ bool line_up();
+
+ bool is_set(int flag) const;
+ void select_items( int key, int qty );
+ bool fix_entry();
+ bool process_key( int keyin );
+
+ int post_process(int key);
+
+ void select_search(const std::string &search);
+
+protected:
+ formatted_string less;
+ int starty, endy;
+ int selected;
+ std::string search;
+};
+
+// This is only tangentially related to menus, but what the heck.
+// Note, column margins start on 1, not 0.
+class column_composer
+{
+public:
+ // Number of columns and left margins for 2nd, 3rd, ... nth column.
+ column_composer(int ncols, ...);
+
+ void clear();
+ void add_formatted(int ncol,
+ const std::string &tagged_text,
+ bool add_separator = true,
+ bool eol_ends_format = true,
+ bool (*text_filter)(const std::string &tag) = NULL,
+ int margin = -1);
+
+ std::vector<formatted_string> formatted_lines() const;
+
+ void set_pagesize(int pagesize);
+
+private:
+ struct column;
+ void compose_formatted_column(
+ const std::vector<formatted_string> &lines,
+ int start_col,
+ int margin);
+ void strip_blank_lines(std::vector<formatted_string> &) const;
+
+private:
+ struct column
+ {
+ int margin;
+ int lines;
+
+ column(int marg = 1) : margin(marg), lines(0) { }
+ };
+
+ int ncols, pagesize;
+ std::vector<column> columns;
+ std::vector<formatted_string> flines;
+};
+
int menu_colour(const std::string &itemtext);
#endif
diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc
index 65faacbbd8..fee17318d6 100644
--- a/crawl-ref/source/message.cc
+++ b/crawl-ref/source/message.cc
@@ -16,7 +16,8 @@
#include "message.h"
#include "religion.h"
-#include <string.h>
+#include <cstdarg>
+#include <cstring>
#ifdef DOS
#include <conio.h>
@@ -26,11 +27,12 @@
#include "initfile.h"
#include "macro.h"
-#include "player.h"
+#include "delay.h"
#include "stuff.h"
#include "travel.h"
#include "view.h"
-
+#include "notes.h"
+#include "stash.h"
// circular buffer for keeping past messages
message_item Store_Message[ NUM_STORED_MESSAGES ]; // buffer of old messages
@@ -38,6 +40,19 @@ int Next_Message = 0; // end of messages
char Message_Line = 0; // line of next (previous?) message
+static bool suppress_messages = false;
+static void base_mpr(const char *inf, int channel, int param);
+
+no_messages::no_messages() : msuppressed(suppress_messages)
+{
+ suppress_messages = true;
+}
+
+no_messages::~no_messages()
+{
+ suppress_messages = msuppressed;
+}
+
static char god_message_altar_colour( char god )
{
int rnd;
@@ -103,9 +118,9 @@ static char channel_to_colour( int channel, int param )
{
case MSGCOL_PLAIN:
// note that if the plain channel is muted, then we're protecting
- // the player from having that spead to other other channels here.
+ // the player from having that spread to other channels here.
// The intent of plain is to give non-coloured messages, not to
- // supress them.
+ // suppress them.
if (Options.channels[ MSGCH_PLAIN ] >= MSGCOL_DEFAULT)
ret = LIGHTGREY;
else
@@ -117,6 +132,7 @@ static char channel_to_colour( int channel, int param )
switch (channel)
{
case MSGCH_GOD:
+ case MSGCH_PRAY:
ret = (Options.channels[ channel ] == MSGCOL_DEFAULT)
? god_colour( param )
: god_message_altar_colour( param );
@@ -167,7 +183,8 @@ static char channel_to_colour( int channel, int param )
break;
case MSGCH_DIAGNOSTICS:
- ret = DARKGREY; // makes is easier to ignore at times -- bwr
+ case MSGCH_MULTITURN_ACTION:
+ ret = DARKGREY; // makes it easier to ignore at times -- bwr
break;
case MSGCH_PLAIN:
@@ -215,14 +232,92 @@ static char channel_to_colour( int channel, int param )
#endif
+static void do_message_print( int channel, int param,
+ const char *format, va_list argp )
+{
+ char buff[200];
+ vsnprintf( buff, sizeof( buff ), format, argp );
+ buff[199] = 0;
+
+ mpr(buff, channel, param);
+}
+
+void mprf( int channel, const char *format, ... )
+{
+ va_list argp;
+ va_start( argp, format );
+ do_message_print( channel, 0, format, argp );
+ va_end( argp );
+}
+
+void mprf( const char *format, ... )
+{
+ va_list argp;
+ va_start( argp, format );
+ do_message_print( MSGCH_PLAIN, 0, format, argp );
+ va_end( argp );
+}
+
void mpr(const char *inf, int channel, int param)
{
- char info2[80];
+ char mbuf[400];
+ size_t i = 0;
+ const int stepsize = get_number_of_cols() - 1;
+ const size_t msglen = strlen(inf);
+ const int lookback_size = (stepsize < 12 ? 0 : 12);
+ // if a message is exactly STEPSIZE characters long,
+ // it should precisely fit in one line. The printing is thus
+ // from I to I + STEPSIZE - 1. Stop when I reaches MSGLEN.
+ while ( i < msglen || i == 0 )
+ {
+ strncpy( mbuf, inf + i, stepsize );
+ mbuf[stepsize] = 0;
+ // did the message break?
+ if ( i + stepsize < msglen )
+ {
+ // yes, find a nicer place to break it.
+ int lookback, where = 0;
+ for ( lookback = 0; lookback < lookback_size; ++lookback )
+ {
+ where = stepsize - 1 - lookback;
+ if ( where >= 0 && isspace(mbuf[where]) )
+ // aha!
+ break;
+ }
+
+ if ( lookback != lookback_size )
+ {
+ // found a good spot to break
+ mbuf[where] = 0;
+ i += where + 1; // skip past the space!
+ }
+ else
+ i += stepsize;
+ }
+ else
+ i += stepsize;
+ base_mpr( mbuf, channel, param );
+ }
+}
+
+static void base_mpr(const char *inf, int channel, int param)
+{
+ if (suppress_messages)
+ return;
int colour = channel_to_colour( channel, param );
if (colour == MSGCOL_MUTED)
return;
+ std::string imsg = inf;
+
+ for (unsigned i = 0; i < Options.note_messages.size(); ++i) {
+ if (Options.note_messages[i].matches(imsg)) {
+ take_note(Note(NOTE_MESSAGE, channel, param, inf));
+ break;
+ }
+ }
+
interrupt_activity( AI_MESSAGE, channel_to_str(channel) + ":" + inf );
// If you're travelling, only certain user-specified messages can break
@@ -230,9 +325,9 @@ void mpr(const char *inf, int channel, int param)
if (you.running < 0)
{
std::string message = inf;
- for (unsigned i = 0; i < Options.stop_travel.size(); ++i)
+ for (unsigned i = 0; i < Options.travel_stop_message.size(); ++i)
{
- if (Options.stop_travel[i].is_filtered( channel, message ))
+ if (Options.travel_stop_message[i].is_filtered( channel, message ))
{
stop_running();
break;
@@ -246,7 +341,7 @@ void mpr(const char *inf, int channel, int param)
for (unsigned i = 0; i < Options.sound_mappings.size(); i++)
{
// Maybe we should allow message channel matching as for
- // stop_travel?
+ // travel_stop_message?
if (Options.sound_mappings[i].pattern.matches(message))
{
play_sound(Options.sound_mappings[i].soundfile.c_str());
@@ -269,11 +364,8 @@ void mpr(const char *inf, int channel, int param)
more();
gotoxy( (Options.delay_message_clear) ? 2 : 1, Message_Line + 18 );
- strncpy(info2, inf, 78);
- info2[78] = 0;
-
textcolor( colour );
- cprintf(info2);
+ cprintf("%s", inf);
//
// reset colour
textcolor(LIGHTGREY);
@@ -491,7 +583,7 @@ void replay_messages(void)
#if DEBUG_DIAGNOSTICS
cprintf( "%d: %s", line, Store_Message[ line ].text.c_str() );
#else
- cprintf( Store_Message[ line ].text.c_str() );
+ cprintf( "%s", Store_Message[ line ].text.c_str() );
#endif
cprintf(EOL);
diff --git a/crawl-ref/source/message.h b/crawl-ref/source/message.h
index c7fe736ef1..584dc07554 100644
--- a/crawl-ref/source/message.h
+++ b/crawl-ref/source/message.h
@@ -3,6 +3,8 @@
* Summary: Functions used to print messages.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <2> 5/08/99 JDJ mpr takes a const char* instead of a char array.
@@ -53,6 +55,18 @@ void more(void);
* *********************************************************************** */
void mpr(const char *inf, int channel = MSGCH_PLAIN, int param = 0);
+// 4.1-style mpr, currently named mprf for minimal disruption.
+void mprf( int channel, const char *format, ... );
+void mprf( const char *format, ... );
+
+class no_messages
+{
+public:
+ no_messages();
+ ~no_messages();
+private:
+ bool msuppressed;
+};
// last updated 12may2000 {dlb}
/* ***********************************************************************
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index 705a8acadb..c0567ef369 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -3,6 +3,8 @@
* Summary: Misc functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <3> 11/14/99 cdl evade with random40(ev) vice random2(ev)
@@ -13,9 +15,10 @@
#include "AppHdr.h"
#include "misc.h"
+#include "notes.h"
#include <string.h>
-#if !(defined(__IBMCPP__) || defined(__BCPLUSPLUS__))
+#if !defined(__IBMCPP__)
#include <unistd.h>
#endif
@@ -45,6 +48,7 @@
#include "monplace.h"
#include "mon-util.h"
#include "monstuff.h"
+#include "notes.h"
#include "ouch.h"
#include "player.h"
#include "shopping.h"
@@ -57,6 +61,7 @@
#include "travel.h"
#include "view.h"
+extern FixedVector<char, 10> Visible_Statue; // defined in acr.cc
bool scramble(void);
bool trap_item(char base_type, char sub_type, char beam_x, char beam_y);
@@ -93,7 +98,7 @@ void turn_corpse_into_chunks( item_def &item )
mitm[o].plus2 = 0;
mitm[o].special = 0;
mitm[o].flags = 0;
- mitm[o].colour = mons_colour( mons_class );
+ mitm[o].colour = mons_class_colour( mons_class );
// these values cannot be set by a reasonable formula: {dlb}
switch (mons_class)
@@ -132,18 +137,92 @@ void turn_corpse_into_chunks( item_def &item )
}
} // end place_chunks()
+bool grid_is_wall( int grid )
+{
+ return (grid == DNGN_ROCK_WALL
+ || grid == DNGN_STONE_WALL
+ || grid == DNGN_METAL_WALL
+ || grid == DNGN_GREEN_CRYSTAL_WALL
+ || grid == DNGN_WAX_WALL
+ || grid == DNGN_PERMAROCK_WALL);
+}
+
+bool grid_is_opaque( int grid )
+{
+ return (grid < MINSEE && grid != DNGN_ORCISH_IDOL);
+}
+
+bool grid_is_solid( int grid )
+{
+ return (grid < MINMOVE);
+}
+
+bool grid_is_water( int grid )
+{
+ return (grid == DNGN_SHALLOW_WATER || grid == DNGN_DEEP_WATER);
+}
+
+bool grid_destroys_items( int grid )
+{
+ return (grid == DNGN_LAVA || grid == DNGN_DEEP_WATER);
+}
+
+// returns 0 is grid is not an altar, else it returns the GOD_* type
+god_type grid_altar_god( unsigned char grid )
+{
+ if (grid >= DNGN_ALTAR_ZIN && grid <= DNGN_ALTAR_ELYVILON)
+ return (static_cast<god_type>( grid - DNGN_ALTAR_ZIN + 1 ));
+
+ return (GOD_NO_GOD);
+}
+
+bool grid_is_branch_stairs( unsigned char grid )
+{
+ return ((grid >= DNGN_ENTER_ORCISH_MINES && grid <= DNGN_ENTER_RESERVED_4)
+ || (grid >= DNGN_ENTER_DIS && grid <= DNGN_ENTER_TARTARUS));
+}
+
+int grid_secret_door_appearance( int gx, int gy )
+{
+ int ret = DNGN_FLOOR;
+
+ for (int dx = -1; dx <= 1; dx++)
+ {
+ for (int dy = -1; dy <= 1; dy++)
+ {
+ // only considering orthogonal grids
+ if ((abs(dx) + abs(dy)) % 2 == 0)
+ continue;
+
+ const int targ = grd[gx + dx][gy + dy];
+
+ if (!grid_is_wall( targ ))
+ continue;
+
+ if (ret == DNGN_FLOOR)
+ ret = targ;
+ else if (ret != targ)
+ ret = ((ret < targ) ? ret : targ);
+ }
+ }
+
+ return ((ret == DNGN_FLOOR) ? DNGN_ROCK_WALL
+ : ret);
+}
+
+const char *grid_item_destruction_message( unsigned char grid )
+{
+ return grid == DNGN_DEEP_WATER? "You hear a splash."
+ : grid == DNGN_LAVA ? "You hear a sizzling splash."
+ : "You hear an empty echo.";
+}
+
void search_around(void)
{
char srx = 0;
char sry = 0;
int i;
- // Never if doing something else... this prevents a slight asymetry
- // where using autopickup was giving free searches in comparison to
- // not using autopickup. -- bwr
- if (you_are_delayed())
- return;
-
for (srx = you.x_pos - 1; srx < you.x_pos + 2; srx++)
{
for (sry = you.y_pos - 1; sry < you.y_pos + 2; sry++)
@@ -218,7 +297,7 @@ void in_a_cloud(void)
hurted /= (1 + resist * resist);
ouch( hurted, cl, KILLED_BY_CLOUD, "flame" );
}
- scrolls_burn(7, OBJ_SCROLLS);
+ expose_player_to_element(BEAM_FIRE, 7);
break;
case CLOUD_STINK:
@@ -269,7 +348,7 @@ void in_a_cloud(void)
hurted /= (1 + resist * resist);
ouch( hurted, cl, KILLED_BY_CLOUD, "freezing vapour" );
}
- scrolls_burn(7, OBJ_POTIONS);
+ expose_player_to_element(BEAM_COLD, 7);
break;
case CLOUD_POISON:
@@ -298,13 +377,7 @@ void in_a_cloud(void)
case CLOUD_STEAM:
case CLOUD_STEAM_MON:
mpr("You are engulfed in a cloud of scalding steam!");
- if (you.species == SP_PALE_DRACONIAN && you.experience_level > 5)
- {
- mpr("It doesn't seem to affect you.");
- return;
- }
-
- if (player_equip( EQ_BODY_ARMOUR, ARM_STEAM_DRAGON_ARMOUR ))
+ if (player_res_steam() > 0)
{
mpr("It doesn't seem to affect you.");
return;
@@ -343,6 +416,27 @@ void in_a_cloud(void)
return;
} // end in_a_cloud()
+void curare_hits_player(int agent, int degree)
+{
+ const bool res_poison = player_res_poison();
+
+ poison_player(degree);
+
+ if (!player_res_asphyx())
+ {
+ int hurted = roll_dice(2, 6);
+ // Note that the hurtage is halved by poison resistance.
+ if (res_poison)
+ hurted /= 2;
+
+ if (hurted)
+ {
+ mpr("You feel difficulty breathing.");
+ ouch( hurted, agent, KILLED_BY_CURARE, "curare-induced apnoea" );
+ }
+ potion_effect(POT_SLOWING, 2 + random2(4 + degree));
+ }
+}
void merfolk_start_swimming(void)
{
@@ -409,14 +503,14 @@ void up_stairs(void)
ouch( roll_dice( 3 + you.burden_state, 5 ), 0,
KILLED_BY_FALLING_DOWN_STAIRS );
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return;
}
if (you.burden_state == BS_OVERLOADED)
{
mpr("You are carrying too much to climb upwards.");
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return;
}
@@ -533,7 +627,7 @@ void up_stairs(void)
load(stair_taken, LOAD_ENTER_LEVEL, was_a_labyrinth, old_level, old_where);
- you.turn_is_over = 1;
+ you.turn_is_over = true;
save_game(false);
@@ -703,7 +797,6 @@ void down_stairs( bool remove_stairs, int old_level, bool force )
if (collect_travel_data)
old_level_info.update();
-
if (you.level_type == LEVEL_PANDEMONIUM
&& stair_find == DNGN_TRANSIT_PANDEMONIUM)
{
@@ -836,41 +929,21 @@ void down_stairs( bool remove_stairs, int old_level, bool force )
you.level_type = LEVEL_PANDEMONIUM;
}
- if (you.level_type == LEVEL_LABYRINTH || you.level_type == LEVEL_ABYSS
- || you.level_type == LEVEL_PANDEMONIUM)
+ // When going downstairs into a special level, delete any previous
+ // instances of it
+ if (you.level_type == LEVEL_LABYRINTH ||
+ you.level_type == LEVEL_ABYSS ||
+ you.level_type == LEVEL_PANDEMONIUM)
{
- char glorpstr[kFileNameSize];
- char del_file[kFileNameSize];
- int sysg;
-
-#ifdef SAVE_DIR_PATH
- snprintf( glorpstr, sizeof(glorpstr),
- SAVE_DIR_PATH "%s%d", you.your_name, (int) getuid() );
-#else
- strncpy(glorpstr, you.your_name, kFileNameLen);
-
- // glorpstr [strlen(glorpstr)] = 0;
- // This is broken. Length is not valid yet! We have to check if we got
- // a trailing NULL; if not, write one:
- /* is name 6 chars or more? */
- if (strlen(you.your_name) > kFileNameLen - 1)
- glorpstr[kFileNameLen] = '\0';
-#endif
-
- strcpy(del_file, glorpstr);
- strcat(del_file, ".lab");
-
-#ifdef DOS
- strupr(del_file);
-#endif
- sysg = unlink(del_file);
-
+ std::string lname = make_filename(you.your_name, you.your_level,
+ you.where_are_you,
+ true, false );
#if DEBUG_DIAGNOSTICS
- strcpy( info, "Deleting: " );
- strcat( info, del_file );
+ snprintf( info, INFO_SIZE, "Deleting: %s", lname.c_str() );
mpr( info, MSGCH_DIAGNOSTICS );
more();
#endif
+ unlink(lname.c_str());
}
if (stair_find == DNGN_EXIT_ABYSS || stair_find == DNGN_EXIT_PANDEMONIUM)
@@ -993,7 +1066,7 @@ void down_stairs( bool remove_stairs, int old_level, bool force )
break;
}
- you.turn_is_over = 1;
+ you.turn_is_over = true;
save_game(false);
@@ -1065,6 +1138,7 @@ void new_level(void)
env.floor_colour = LIGHTGREY;
env.rock_colour = BROWN;
+ take_note(Note(NOTE_DUNGEON_LEVEL_CHANGE));
if (you.level_type == LEVEL_PANDEMONIUM)
{
cprintf("- Pandemonium ");
@@ -1240,7 +1314,7 @@ static void dart_trap( bool trap_known, int trapped, struct bolt &pbolt,
if (random2(10) < 2 || (trap_known && !one_chance_in(4)))
{
snprintf( info, INFO_SIZE, "You avoid triggering a%s trap.",
- pbolt.beam_name );
+ pbolt.name.c_str() );
mpr(info);
return;
}
@@ -1248,9 +1322,9 @@ static void dart_trap( bool trap_known, int trapped, struct bolt &pbolt,
if (you.equip[EQ_SHIELD] != -1 && one_chance_in(3))
exercise( SK_SHIELDS, 1 );
- snprintf( info, INFO_SIZE, "A%s shoots out and ", pbolt.beam_name );
+ snprintf( info, INFO_SIZE, "A%s shoots out and ", pbolt.name.c_str() );
- if (random2( 50 + 10 * you.shield_blocks * you.shield_blocks )
+ if (random2( 20 + 5 * you.shield_blocks * you.shield_blocks )
< player_shield_class())
{
you.shield_blocks++;
@@ -1280,7 +1354,7 @@ static void dart_trap( bool trap_known, int trapped, struct bolt &pbolt,
damage_taken -= random2( player_AC() + 1 );
if (damage_taken > 0)
- ouch( damage_taken, 0, KILLED_BY_TRAP, pbolt.beam_name );
+ ouch( damage_taken, 0, KILLED_BY_TRAP, pbolt.name.c_str() );
}
else
{
@@ -1351,37 +1425,37 @@ void handle_traps(char trt, int i, bool trap_known)
switch (trt)
{
case TRAP_DART:
- strcpy(beam.beam_name, " dart");
+ beam.name = " dart";
beam.damage = dice_def( 1, 4 + (you.your_level / 2) );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_NEEDLE:
- strcpy(beam.beam_name, " needle");
+ beam.name = " needle";
beam.damage = dice_def( 1, 0 );
dart_trap(trap_known, i, beam, true);
break;
case TRAP_ARROW:
- strcpy(beam.beam_name, "n arrow");
+ beam.name = "n arrow";
beam.damage = dice_def( 1, 7 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_BOLT:
- strcpy(beam.beam_name, " bolt");
+ beam.name = " bolt";
beam.damage = dice_def( 1, 13 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_SPEAR:
- strcpy(beam.beam_name, " spear");
+ beam.name = " spear";
beam.damage = dice_def( 1, 10 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_AXE:
- strcpy(beam.beam_name, "n axe");
+ beam.name = "n axe";
beam.damage = dice_def( 1, 15 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
@@ -1462,7 +1536,7 @@ void disarm_trap( struct dist &disa )
{
mpr("You failed to disarm the trap.");
- you.turn_is_over = 1;
+ you.turn_is_over = true;
if (random2(you.dex) > 5 + random2(5 + you.your_level))
exercise(SK_TRAPS_DOORS, 1 + random2(you.your_level / 5));
@@ -1499,7 +1573,7 @@ void disarm_trap( struct dist &disa )
grd[you.x_pos + disa.dx][you.y_pos + disa.dy] = DNGN_FLOOR;
env.trap[i].type = TRAP_UNASSIGNED;
- you.turn_is_over = 1;
+ you.turn_is_over = true;
// reduced from 5 + random2(5)
exercise(SK_TRAPS_DOORS, 1 + random2(5) + (you.your_level / 5));
@@ -1604,7 +1678,9 @@ void weird_writing(char stringy[40])
} // end weird_writing()
// must be a better name than 'place' for the first parameter {dlb}
-void fall_into_a_pool(bool place, unsigned char terrain)
+// returns true if we manage to scramble free.
+bool fall_into_a_pool( int entry_x, int entry_y, bool allow_shift,
+ unsigned char terrain )
{
bool escape = false;
FixedVector< char, 2 > empty;
@@ -1613,7 +1689,7 @@ void fall_into_a_pool(bool place, unsigned char terrain)
{
// These can happen when we enter deep water directly -- bwr
merfolk_start_swimming();
- return;
+ return (false);
}
strcpy(info, "You fall into the ");
@@ -1635,67 +1711,73 @@ void fall_into_a_pool(bool place, unsigned char terrain)
if (resist <= 0)
{
mpr( "The lava burns you to a cinder!" );
- ouch( -9999, 0, KILLED_BY_LAVA );
+ ouch( INSTANT_DEATH, 0, KILLED_BY_LAVA );
}
else
{
// should boost # of bangs per damage in the future {dlb}
mpr( "The lava burns you!" );
- ouch( (10 + random2avg(100, 2)) / resist, 0, KILLED_BY_LAVA );
+ ouch( (10 + roll_dice(2,50)) / resist, 0, KILLED_BY_LAVA );
}
- if (you.duration[DUR_CONDENSATION_SHIELD] > 0)
- {
- mpr("Your icy shield dissipates!", MSGCH_DURATION);
- you.duration[DUR_CONDENSATION_SHIELD] = 0;
- you.redraw_armour_class = 1;
- }
+ expose_player_to_element( BEAM_LAVA, 14 );
}
// a distinction between stepping and falling from you.levitation
// prevents stepping into a thin stream of lava to get to the other side.
if (scramble())
{
- if (place)
+ if (allow_shift)
{
- if (empty_surrounds(you.x_pos, you.y_pos, DNGN_FLOOR, false, empty))
+ if (empty_surrounds( you.x_pos, you.y_pos, DNGN_FLOOR, 1,
+ false, empty ))
{
- you.x_pos = empty[0];
- you.y_pos = empty[1];
escape = true;
}
else
+ {
escape = false;
+ }
}
else
- escape = true;
+ {
+ // back out the way we came in, if possible
+ if (grid_distance( you.x_pos, you.y_pos, entry_x, entry_y ) == 1
+ && (entry_x != empty[0] || entry_y != empty[1]))
+ {
+ escape = true;
+ empty[0] = entry_x;
+ empty[1] = entry_y;
+ }
+ else // zero or two or more squares away, with no way back
+ {
+ escape = false;
+ }
+ }
}
else
{
- // that is, don't display following when fall from levitating
- if (!place)
- mpr("You try to escape, but your burden drags you down!");
+ mpr("You try to escape, but your burden drags you down!");
}
- if (escape)
+ if (escape && move_player_to_grid( empty[0], empty[1], false, false, true ))
{
mpr("You manage to scramble free!");
if (terrain == DNGN_LAVA)
- scrolls_burn(10, OBJ_SCROLLS);
+ expose_player_to_element( BEAM_LAVA, 14 );
- return;
+ return (true);
}
mpr("You drown...");
if (terrain == DNGN_LAVA)
- ouch(-9999, 0, KILLED_BY_LAVA);
+ ouch( INSTANT_DEATH, 0, KILLED_BY_LAVA );
else if (terrain == DNGN_DEEP_WATER)
- ouch(-9999, 0, KILLED_BY_WATER);
+ ouch( INSTANT_DEATH, 0, KILLED_BY_WATER );
- // Okay, so you don't trigger a trap when you scramble onto it.
- //I really can't be bothered right now.
+ return (false);
} // end fall_into_a_pool()
bool scramble(void)
@@ -1823,6 +1905,9 @@ bool trap_item(char base_type, char sub_type, char beam_x, char beam_y)
else
{
set_item_ego_type( item, OBJ_MISSILES, SPMSL_NORMAL );
+
+ if (sub_type == MI_ARROW)
+ item.colour = BROWN;
}
}
else
@@ -1888,3 +1973,224 @@ int trap_at_xy(int which_x, int which_y)
// no idea how well this will be handled elsewhere: {dlb}
return (-1);
} // end trap_at_xy()
+
+bool i_feel_safe()
+{
+ /* This is probably unnecessary, but I'm not sure that
+ you're always at least 9 away from a wall */
+ int ystart = you.y_pos - 9, xstart = you.x_pos - 9;
+ int yend = you.y_pos + 9, xend = you.x_pos + 9;
+ if ( xstart < 0 ) xstart = 0;
+ if ( ystart < 0 ) ystart = 0;
+ if ( xend >= GXM ) xend = 0;
+ if ( ystart >= GYM ) yend = 0;
+
+ /* statue check */
+ if (you.visible_statue[STATUE_SILVER] ||
+ you.visible_statue[STATUE_ORANGE_CRYSTAL] )
+ return false;
+
+ /* monster check */
+ for ( int y = ystart; y < yend; ++y ) {
+ for ( int x = xstart; x < xend; ++x ) {
+ /* if you can see a nonfriendly monster then you feel
+ unsafe */
+ if ( see_grid(x,y) ) {
+ const unsigned char targ_monst = mgrd[x][y];
+ if ( targ_monst != NON_MONSTER ) {
+ struct monsters *mon = &menv[targ_monst];
+ if ( !mons_friendly(mon) &&
+ player_monster_visible(mon) &&
+ !mons_is_mimic(mon->type) &&
+ (!Options.safe_zero_exp ||
+ !mons_class_flag( mon->type, M_NO_EXP_GAIN ))) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
+// Do not attempt to use level_id if level_type != LEVEL_DUNGEON
+std::string short_place_name(level_id id)
+{
+ return short_place_name(
+ get_packed_place(id.branch, id.depth, LEVEL_DUNGEON));
+}
+
+unsigned short get_packed_place( unsigned char branch, int subdepth,
+ char level_type )
+{
+ unsigned short place = (unsigned short)
+ ( (branch << 8) | (subdepth & 0xFF) );
+ if (level_type == LEVEL_ABYSS || level_type == LEVEL_PANDEMONIUM
+ || level_type == LEVEL_LABYRINTH)
+ place = (unsigned short) ( (level_type << 8) | 0xFF );
+ return place;
+}
+
+unsigned short get_packed_place()
+{
+ return get_packed_place( you.where_are_you,
+ subdungeon_depth(you.where_are_you, you.your_level),
+ you.level_type );
+}
+
+std::string place_name( unsigned short place, bool long_name,
+ bool include_number ) {
+
+ unsigned char branch = (unsigned char) ((place >> 8) & 0xFF);
+ int lev = place & 0xFF;
+
+ std::string result;
+ if (lev == 0xFF)
+ {
+ switch (branch)
+ {
+ case LEVEL_ABYSS:
+ return ( long_name ? "The Abyss" : "Abyss" );
+ case LEVEL_PANDEMONIUM:
+ return ( long_name ? "Pandemonium" : "Pan" );
+ case LEVEL_LABYRINTH:
+ return ( long_name ? "a Labyrinth" : "Lab" );
+ default:
+ return ( long_name ? "Buggy Badlands" : "Bug" );
+ }
+ }
+ else
+ {
+ switch (branch)
+ {
+ case BRANCH_VESTIBULE_OF_HELL:
+ return ( long_name ? "The Vestibule of Hell" : "Hell" );
+ case BRANCH_HALL_OF_BLADES:
+ return ( long_name ? "The Hall of Blades" : "Blade" );
+ case BRANCH_ECUMENICAL_TEMPLE:
+ return ( long_name ? "The Ecumenical Temple" : "Temple" );
+ case BRANCH_DIS:
+ result = ( long_name ? "The Iron City of Dis" : "Dis");
+ break;
+ case BRANCH_GEHENNA:
+ result = ( long_name ? "Gehenna" : "Geh" );
+ break;
+ case BRANCH_COCYTUS:
+ result = ( long_name ? "Cocytus" : "Coc" );
+ break;
+ case BRANCH_TARTARUS:
+ result = ( long_name ? "Tartarus" : "Tar" );
+ break;
+ case BRANCH_ORCISH_MINES:
+ result = ( long_name ? "The Orcish Mines" : "Orc" );
+ break;
+ case BRANCH_HIVE:
+ result = ( long_name ? "The Hive" : "Hive" );
+ break;
+ case BRANCH_LAIR:
+ result = ( long_name ? "The Lair" : "Lair" );
+ break;
+ case BRANCH_SLIME_PITS:
+ result = ( long_name ? "The Slime Pits" : "Slime" );
+ break;
+ case BRANCH_VAULTS:
+ result = ( long_name ? "The Vaults" : "Vault" );
+ break;
+ case BRANCH_CRYPT:
+ result = ( long_name ? "The Crypt" : "Crypt" );
+ break;
+ case BRANCH_HALL_OF_ZOT:
+ result = ( long_name ? "The Hall of Zot" : "Zot" );
+ break;
+ case BRANCH_SNAKE_PIT:
+ result = ( long_name ? "The Snake Pit" : "Snake" );
+ break;
+ case BRANCH_ELVEN_HALLS:
+ result = ( long_name ? "The Elven Halls" : "Elf" );
+ break;
+ case BRANCH_TOMB:
+ result = ( long_name ? "The Tomb" : "Tomb" );
+ break;
+ case BRANCH_SWAMP:
+ result = ( long_name ? "The Swamp" : "Swamp" );
+ break;
+ default:
+ result = ( long_name ? "The Dungeon" : "D" );
+ break;
+ }
+ }
+
+ if ( include_number ) {
+ char buf[200];
+ if ( long_name ) {
+ // decapitalize 'the'
+ if ( result.find("The") == 0 )
+ result[0] = 't';
+ snprintf( buf, sizeof buf, "Level %d of %s",
+ lev, result.c_str() );
+ }
+ else if (lev) {
+ snprintf( buf, sizeof buf, "%s:%d",
+ result.c_str(), lev );
+ }
+ else {
+ snprintf( buf, sizeof buf, "%s:$",
+ result.c_str() );
+ }
+ result = buf;
+ }
+ return result;
+}
+
+// Takes a packed 'place' and returns a compact stringified place name.
+// XXX: This is done in several other places; a unified function to
+// describe places would be nice.
+std::string short_place_name(unsigned short place)
+{
+ return place_name( place, false, true );
+}
+
+// Prepositional form of branch level name. For example, "in the
+// Abyss" or "on level 3 of the Main Dungeon".
+std::string prep_branch_level_name(unsigned short packed_place)
+{
+ std::string place = place_name( packed_place, true, true );
+ if (place.length() && place != "Pandemonium")
+ place[0] = tolower(place[0]);
+ return (place.find("level") == 0?
+ "on " + place
+ : "in " + place);
+}
+
+// Use current branch and depth
+std::string prep_branch_level_name()
+{
+ return prep_branch_level_name( get_packed_place() );
+}
+
+int absdungeon_depth(unsigned char branch, int subdepth)
+{
+ int realdepth = subdepth - 1;
+
+ if (branch >= BRANCH_ORCISH_MINES && branch <= BRANCH_SWAMP)
+ realdepth = subdepth + you.branch_stairs[branch - 10];
+
+ if (branch >= BRANCH_DIS && branch <= BRANCH_THE_PIT)
+ realdepth = subdepth + 26;
+
+ return realdepth;
+}
+
+int subdungeon_depth(unsigned char branch, int depth)
+{
+ int curr_subdungeon_level = depth + 1;
+
+ if (branch >= BRANCH_DIS && branch <= BRANCH_THE_PIT)
+ curr_subdungeon_level = depth - 26;
+
+ if (branch >= BRANCH_ORCISH_MINES && branch <= BRANCH_SWAMP)
+ curr_subdungeon_level = depth
+ - you.branch_stairs[branch - 10];
+
+ return curr_subdungeon_level;
+}
diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h
index 7a754ffdd0..a11d043940 100644
--- a/crawl-ref/source/misc.h
+++ b/crawl-ref/source/misc.h
@@ -3,6 +3,8 @@
* Summary: Misc functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -14,6 +16,7 @@
#include "externs.h"
+#include "travel.h"
// last updated 08jan2001 {gdl}
/* ***********************************************************************
@@ -54,7 +57,8 @@ void down_stairs(bool remove_stairs, int old_level, bool force = false);
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
-void fall_into_a_pool(bool place, unsigned char grype);
+bool fall_into_a_pool( int entry_x, int entry_y, bool allow_shift,
+ unsigned char terrain );
// last updated 12may2000 {dlb}
@@ -131,5 +135,45 @@ void weird_writing(char stringy[40]);
* *********************************************************************** */
unsigned char trap_category(unsigned char trap_type);
+bool grid_is_wall(int grid);
+bool grid_is_opaque(int grid);
+bool grid_is_solid(int grid);
+bool grid_is_water(int grid);
+god_type grid_altar_god( unsigned char grid );
+bool grid_is_branch_stairs( unsigned char grid );
+int grid_secret_door_appearance( int gx, int gy );
+bool grid_destroys_items( int grid );
+
+const char *grid_item_destruction_message( unsigned char grid );
+
+void curare_hits_player(int agent, int degree);
+
+bool i_feel_safe();
+
+//////////////////////////////////////////////////////////////////////
+// Places and names
+//
+unsigned short get_packed_place();
+
+unsigned short get_packed_place( unsigned char branch, int subdepth,
+ char level_type );
+
+std::string short_place_name(unsigned short place);
+std::string short_place_name(level_id id);
+std::string place_name( unsigned short place, bool long_name = false,
+ bool include_number = true );
+
+// Prepositional form of branch level name. For example, "in the
+// Abyss" or "on level 3 of the Main Dungeon".
+std::string prep_branch_level_name(unsigned short packed_place);
+std::string prep_branch_level_name();
+
+// Get displayable depth in the current branch, given the absolute
+// depth.
+int subdungeon_depth(unsigned char branch, int depth);
+
+// Get absolute depth given the displayable depth in the branch.
+int absdungeon_depth(unsigned char branch, int subdepth);
+//////////////////////////////////////////////////////////////////////
#endif
diff --git a/crawl-ref/source/misc/header b/crawl-ref/source/misc/header
index 9f91952461..b49c13f3ad 100644
--- a/crawl-ref/source/misc/header
+++ b/crawl-ref/source/misc/header
@@ -3,6 +3,8 @@
* Summary:
* Written by:
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> --/--/-- --- Created
diff --git a/crawl-ref/source/misc/src-pkg-excludes.lst b/crawl-ref/source/misc/src-pkg-excludes.lst
new file mode 100644
index 0000000000..1d28c6f19f
--- /dev/null
+++ b/crawl-ref/source/misc/src-pkg-excludes.lst
@@ -0,0 +1,3 @@
+,svn
+**/.svn/*
+.*
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index 8580b8758b..47f443f951 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -1,6 +1,12 @@
+/*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ */
+
#ifndef MONDATA_H
#define MONDATA_H
+#include "enum.h"
+
/*
This whole file was very generously condensed from its initial ugly form
by Wladimir van der Laan ($pellbinder).
@@ -104,7 +110,8 @@
{
MONS_PROGRAM_BUG, 'B', LIGHTRED, "program bug",
M_NO_EXP_GAIN,
- 0, 10, MONS_PROGRAM_BUG, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 0, 10, MONS_PROGRAM_BUG, MONS_PROGRAM_BUG, MH_NATURAL, -3,
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
0, 0, 0, 0, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -115,8 +122,9 @@
// real monsters begin here {dlb}:
{
MONS_GIANT_ANT, 'a', DARKGREY, "giant ant",
- M_ED_POISON,
- 700, 10, MONS_GIANT_ANT, MH_NATURAL, -3,
+ M_NO_FLAGS,
+ MR_VUL_POISON,
+ 700, 10, MONS_GIANT_ANT, MONS_GIANT_ANT, MH_NATURAL, -3,
{ 8, 0, 0, 0 },
{ 3, 3, 5, 0 },
4, 10, 12, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_SILENT, I_INSECT,
@@ -127,7 +135,8 @@
{
MONS_GIANT_BAT, 'b', DARKGREY, "giant bat",
M_FLIES | M_SEE_INVIS | M_WARM_BLOOD,
- 150, 4, MONS_GIANT_BAT, MH_NATURAL, -1,
+ MR_NO_FLAGS,
+ 150, 4, MONS_GIANT_BAT, MONS_GIANT_BAT, MH_NATURAL, -1,
{ 1, 0, 0, 0 },
{ 1, 2, 3, 0 },
1, 14, 30, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_SILENT, I_ANIMAL,
@@ -138,7 +147,8 @@
{
MONS_CENTAUR, 'c', BROWN, "centaur",
M_WARM_BLOOD,
- 1500, 10, MONS_CENTAUR, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 1500, 10, MONS_CENTAUR, MONS_CENTAUR, MH_NATURAL, -3,
{ 10, 0, 0, 0 },
{ 4, 3, 5, 0 },
3, 7, 15, 7, MST_NO_SPELLS, CE_CLEAN, Z_BIG, S_SHOUT, I_NORMAL,
@@ -148,8 +158,9 @@
{
MONS_RED_DEVIL, '4', RED, "red devil",
- M_RES_POISON | M_RES_HELLFIRE | M_ED_COLD | M_FLIES,
- 0, 10, MONS_RED_DEVIL, MH_DEMONIC, -7,
+ M_FLIES | M_EVIL,
+ MR_RES_POISON | MR_RES_HELLFIRE | MR_VUL_COLD,
+ 0, 10, MONS_RED_DEVIL, MONS_RED_DEVIL, MH_DEMONIC, -7,
{ 18, 0, 0, 0 },
{ 5, 3, 5, 0 },
10, 10, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -159,8 +170,9 @@
{
MONS_ETTIN, 'C', BROWN, "ettin",
- M_WARM_BLOOD,
- 0, 10, MONS_ETTIN, MH_NATURAL, -3,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 0, 10, MONS_HILL_GIANT, MONS_ETTIN, MH_NATURAL, -3,
{ 18, 12, 0, 0 },
{ 7, 3, 5, 0 },
3, 4, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_BIG, S_SHOUT2, I_NORMAL,
@@ -170,8 +182,9 @@
{
MONS_FUNGUS, 'f', LIGHTGREY, "fungus",
- M_NO_EXP_GAIN | M_RES_POISON,
- 0, 10, MONS_FUNGUS, MH_PLANT, 5000,
+ M_NO_EXP_GAIN,
+ MR_RES_POISON,
+ 0, 10, MONS_PLANT, MONS_FUNGUS, MH_PLANT, MAG_IMMUNE,
{ 0, 0, 0, 0 },
{ 8, 3, 5, 0 },
1, 0, 0, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -181,8 +194,9 @@
{
MONS_GOBLIN, 'g', LIGHTGREY, "goblin",
- M_WARM_BLOOD,
- 400, 10, MONS_GOBLIN, MH_NATURAL, -1,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 400, 10, MONS_GOBLIN, MONS_GOBLIN, MH_NATURAL, -1,
{ 4, 0, 0, 0 },
{ 1, 2, 4, 0 },
0, 12, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -193,7 +207,8 @@
{
MONS_HOUND, 'h', BROWN, "hound",
M_SEE_INVIS | M_WARM_BLOOD,
- 300, 10, MONS_HOUND, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 300, 10, MONS_HOUND, MONS_HOUND, MH_NATURAL, -3,
{ 6, 0, 0, 0 },
{ 3, 3, 5, 0 },
2, 13, 15, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_BARK, I_ANIMAL,
@@ -204,8 +219,9 @@
// note: these things regenerate
{
MONS_IMP, '5', RED, "imp",
- M_RES_POISON | M_RES_HELLFIRE | M_ED_COLD | M_FLIES | M_SEE_INVIS | M_SPEAKS,
- 0, 13, MONS_IMP, MH_DEMONIC, -9,
+ M_FLIES | M_SEE_INVIS | M_SPEAKS | M_EVIL | M_SPECIAL_ABILITY,
+ MR_RES_POISON | MR_RES_HELLFIRE | MR_VUL_COLD,
+ 0, 13, MONS_IMP, MONS_IMP, MH_DEMONIC, -9,
{ 4, 0, 0, 0 },
{ 3, 3, 3, 0 },
3, 14, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SHOUT, I_HIGH,
@@ -216,7 +232,8 @@
{
MONS_JACKAL, 'j', YELLOW, "jackal",
M_WARM_BLOOD,
- 200, 10, MONS_JACKAL, MH_NATURAL, -1,
+ MR_NO_FLAGS,
+ 200, 10, MONS_HOUND, MONS_JACKAL, MH_NATURAL, -1,
{ 3, 0, 0, 0 },
{ 1, 3, 5, 0 },
2, 12, 14, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_BARK, I_ANIMAL,
@@ -226,8 +243,9 @@
{
MONS_KILLER_BEE, 'k', YELLOW, "killer bee",
- M_ED_POISON | M_FLIES,
- 150, 11, MONS_KILLER_BEE, MH_NATURAL, -3,
+ M_FLIES,
+ MR_VUL_POISON,
+ 150, 11, MONS_KILLER_BEE, MONS_KILLER_BEE, MH_NATURAL, -3,
{ 10, 0, 0, 0 },
{ 3, 3, 5, 0 },
2, 18, 20, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_BUZZ, I_INSECT,
@@ -237,8 +255,9 @@
{
MONS_KILLER_BEE_LARVA, 'w', LIGHTGREY, "killer bee larva",
- M_ED_POISON | M_NO_SKELETON,
- 150, 5, MONS_KILLER_BEE_LARVA, MH_NATURAL, -3,
+ M_NO_SKELETON,
+ MR_VUL_POISON,
+ 150, 5, MONS_KILLER_BEE_LARVA, MONS_KILLER_BEE_LARVA, MH_NATURAL, -3,
{ 3, 0, 0, 0 },
{ 1, 3, 5, 0 },
1, 5, 5, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_SILENT, I_INSECT,
@@ -248,8 +267,9 @@
{
MONS_MANTICORE, 'm', BROWN, "manticore",
- M_WARM_BLOOD,
- 1800, 10, MONS_MANTICORE, MH_NATURAL, -3,
+ M_WARM_BLOOD | M_SPECIAL_ABILITY,
+ MR_NO_FLAGS,
+ 1800, 10, MONS_MANTICORE, MONS_MANTICORE, MH_NATURAL, -3,
{ 14, 8, 8, 0 },
{ 9, 3, 5, 0 },
5, 7, 7, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_BIG, S_SILENT, I_NORMAL,
@@ -260,8 +280,9 @@
// this thing doesn't have nr. 13 for nothing, has it? ($pellbinder)
{
MONS_NECROPHAGE, 'n', DARKGREY, "necrophage",
- M_RES_POISON | M_RES_COLD,
- 500, 10, MONS_NECROPHAGE, MH_UNDEAD, -5,
+ M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 500, 10, MONS_GHOUL, MONS_NECROPHAGE, MH_UNDEAD, -5,
{ 8, 0, 0, 0 },
{ 5, 3, 5, 0 },
2, 10, 10, 7, MST_NO_SPELLS, CE_HCL, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -271,8 +292,9 @@
{
MONS_ORC, 'o', LIGHTRED, "orc",
- M_WARM_BLOOD,
- 600, 10, MONS_ORC, MH_NATURAL, -3,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 600, 10, MONS_ORC, MONS_ORC, MH_NATURAL, -3,
{ 5, 0, 0, 0 },
{ 1, 4, 6, 0 },
0, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -284,8 +306,9 @@
// dangerous, but still come out at 200+ XP
{
MONS_PHANTOM, 'p', BLUE, "phantom",
- M_RES_POISON | M_RES_COLD,
- 0, 5, MONS_PHANTOM, MH_UNDEAD, -4,
+ M_EVIL | M_SPECIAL_ABILITY,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 5, MONS_PHANTOM, MONS_PHANTOM, MH_UNDEAD, -4,
{ 10, 0, 0, 0 },
{ 7, 3, 5, 0 },
3, 13, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -295,8 +318,9 @@
{
MONS_QUASIT, 'q', LIGHTGREY, "quasit",
- M_RES_POISON | M_RES_FIRE | M_RES_COLD,
- 0, 10, MONS_QUASIT, MH_DEMONIC, 50,
+ M_EVIL,
+ MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD,
+ 0, 10, MONS_QUASIT, MONS_QUASIT, MH_DEMONIC, 50,
{ 3, 2, 2, 0 },
{ 3, 2, 6, 0 },
5, 17, 15, 7, MST_NO_SPELLS, CE_POISONOUS, Z_NOZOMBIE, S_SILENT, I_INSECT,
@@ -307,7 +331,8 @@
{
MONS_RAT, 'r', BROWN, "rat",
M_WARM_BLOOD,
- 200, 10, MONS_RAT, MH_NATURAL, -1,
+ MR_NO_FLAGS,
+ 200, 10, MONS_RAT, MONS_RAT, MH_NATURAL, -1,
{ 3, 0, 0, 0 },
{ 1, 1, 3, 0 },
1, 10, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_SILENT, I_ANIMAL,
@@ -317,8 +342,9 @@
{
MONS_SCORPION, 's', DARKGREY, "scorpion",
- M_ED_POISON,
- 500, 10, MONS_SCORPION, MH_NATURAL, -3,
+ M_NO_FLAGS,
+ MR_VUL_POISON,
+ 500, 10, MONS_SCORPION, MONS_SCORPION, MH_NATURAL, -3,
{ 10, 0, 0, 0 },
{ 3, 3, 5, 0 },
5, 10, 10, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_SILENT, I_INSECT,
@@ -331,8 +357,9 @@
// not until it can be reimplemented safely {dlb}
{
MONS_TUNNELING_WORM, 't', LIGHTRED, "tunneling worm",
- M_RES_POISON,
- 0, 10, 19, MH_NATURAL, 5000,
+ M_NO_FLAGS,
+ MR_RES_POISON,
+ 0, 10, 19, MH_NATURAL, MAG_IMMUNE,
{ 50, 0, 0, 0 },
{ 10, 5, 5, 0 },
3, 3, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_REPTILE,
@@ -344,7 +371,8 @@
{
MONS_UGLY_THING, 'u', BROWN, "ugly thing",
M_WARM_BLOOD | M_AMPHIBIOUS,
- 600, 10, MONS_UGLY_THING, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 600, 10, MONS_UGLY_THING, MONS_UGLY_THING, MH_NATURAL, -3,
{ 12, 0, 0, 0 },
{ 8, 3, 5, 0 },
3, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -354,8 +382,9 @@
{
MONS_FIRE_VORTEX, 'v', RED, "fire vortex",
- M_RES_POISON | M_RES_FIRE | M_ED_COLD | M_RES_ELEC | M_LEVITATE | M_CONFUSED,
- 0, 5, MONS_FIRE_VORTEX, MH_NONLIVING, 5000,
+ M_LEVITATE | M_CONFUSED,
+ MR_RES_POISON | MR_RES_FIRE | MR_VUL_COLD | MR_RES_ELEC,
+ 0, 5, MONS_FIRE_VORTEX, MONS_FIRE_VORTEX, MH_NONLIVING, MAG_IMMUNE,
{ 30, 0, 0, 0 },
{ 3, 3, 5, 0 },
0, 5, 15, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -366,7 +395,8 @@
{
MONS_WORM, 'w', LIGHTRED, "worm",
M_NO_SKELETON,
- 350, 4, MONS_WORM, MH_NATURAL, -2,
+ MR_NO_FLAGS,
+ 350, 4, MONS_WORM, MONS_WORM, MH_NATURAL, -2,
{ 12, 0, 0, 0 },
{ 5, 3, 5, 0 },
1, 5, 6, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_SILENT, I_INSECT,
@@ -377,8 +407,9 @@
// random
{
MONS_ABOMINATION_SMALL, 'x', BLACK, "abomination",
- M_NO_FLAGS,
- 0, 10, MONS_ABOMINATION_SMALL, MH_DEMONIC, -5,
+ M_EVIL,
+ MR_NO_FLAGS,
+ 0, 10, MONS_ABOMINATION_SMALL, MONS_ABOMINATION_SMALL, MH_DEMONIC, -5,
{ 23, 0, 0, 0 },
{ 6, 2, 5, 0 },
0, 0, 0, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -388,8 +419,9 @@
{
MONS_YELLOW_WASP, 'y', YELLOW, "yellow wasp",
- M_ED_POISON | M_FLIES,
- 220, 12, MONS_YELLOW_WASP, MH_NATURAL, -3,
+ M_FLIES,
+ MR_VUL_POISON,
+ 220, 12, MONS_YELLOW_WASP, MONS_YELLOW_WASP, MH_NATURAL, -3,
{ 13, 0, 0, 0 },
{ 4, 3, 5, 0 },
5, 14, 15, 7, MST_NO_SPELLS, CE_POISONOUS, Z_NOZOMBIE, S_SILENT, I_INSECT,
@@ -400,8 +432,9 @@
// small zombie
{
MONS_ZOMBIE_SMALL, 'z', BROWN, "",
- M_RES_POISON | M_RES_COLD,
- 0, 6, MONS_ZOMBIE_SMALL, MH_UNDEAD, -1,
+ M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 6, MONS_ZOMBIE_SMALL, MONS_ZOMBIE_SMALL, MH_UNDEAD, -1,
{ 10, 0, 0, 0 },
{ 1, 5, 5, 0 },
0, 4, 5, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -411,8 +444,9 @@
{
MONS_ANGEL, 'A', WHITE, "Angel",
- M_RES_POISON | M_FLIES | M_RES_ELEC | M_SPELLCASTER,
- 0, 10, MONS_ANGEL, MH_HOLY, -8,
+ M_FLIES | M_SPELLCASTER,
+ MR_RES_POISON | MR_RES_ELEC,
+ 0, 10, MONS_ANGEL, MONS_ANGEL, MH_HOLY, -8,
{ 20, 0, 0, 0 },
{ 9, 3, 5, 0 },
10, 10, 10, 7, MST_ANGEL, CE_NOCORPSE, Z_NOZOMBIE, S_SHOUT, I_HIGH,
@@ -422,8 +456,9 @@
{
MONS_GIANT_BEETLE, 'B', DARKGREY, "giant beetle",
- M_ED_POISON,
- 1000, 10, MONS_GIANT_BEETLE, MH_NATURAL, -3,
+ M_NO_FLAGS,
+ MR_VUL_POISON,
+ 1000, 10, MONS_GIANT_BEETLE, MONS_GIANT_BEETLE, MH_NATURAL, -3,
{ 20, 0, 0, 0 },
{ 5, 7, 6, 0 },
10, 3, 5, 7, MST_NO_SPELLS, CE_POISONOUS, Z_BIG, S_SILENT, I_INSECT,
@@ -433,8 +468,9 @@
{
MONS_CYCLOPS, 'C', BROWN, "cyclops",
- M_WARM_BLOOD,
- 2500, 10, MONS_CYCLOPS, MH_NATURAL, -3,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 2500, 10, MONS_HILL_GIANT, MONS_CYCLOPS, MH_NATURAL, -3,
{ 35, 0, 0, 0 },
{ 9, 3, 5, 0 },
5, 3, 7, 7, MST_NO_SPELLS, CE_CLEAN, Z_BIG, S_SHOUT, I_NORMAL,
@@ -444,8 +480,9 @@
{
MONS_DRAGON, 'D', GREEN, "dragon",
- M_RES_POISON | M_RES_FIRE | M_ED_COLD | M_FLIES, //jmf: warm blood?
- 2200, 12, MONS_DRAGON, MH_NATURAL, -4,
+ M_FLIES | M_SPECIAL_ABILITY, //jmf: warm blood?
+ MR_RES_POISON | MR_RES_FIRE | MR_VUL_COLD,
+ 2200, 12, MONS_DRAGON, MONS_DRAGON, MH_NATURAL, -4,
{ 20, 13, 13, 0 },
{ 12, 5, 5, 0 },
10, 8, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_BIG, S_SILENT, I_NORMAL,
@@ -457,8 +494,9 @@
// that they wield two weapons... I'm raising their xp modifier. -- bwr
{
MONS_TWO_HEADED_OGRE, 'O', LIGHTRED, "two-headed ogre",
- M_WARM_BLOOD,
- 1500, 15, MONS_TWO_HEADED_OGRE, MH_NATURAL, -4,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 1500, 15, MONS_OGRE, MONS_TWO_HEADED_OGRE, MH_NATURAL, -4,
{ 17, 13, 0, 0 },
{ 6, 3, 5, 0 },
1, 4, 8, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_BIG, S_SHOUT2, I_NORMAL,
@@ -468,8 +506,9 @@
{
MONS_FIEND, '1', LIGHTRED, "Fiend", //jmf: was RED, like Balrog
- M_RES_POISON | M_RES_HELLFIRE | M_ED_COLD | M_FLIES | M_SEE_INVIS,
- 0, 18, MONS_FIEND, MH_DEMONIC, -12,
+ M_FLIES | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_HELLFIRE | MR_VUL_COLD,
+ 0, 18, MONS_FIEND, MONS_FIEND, MH_DEMONIC, -12,
{ 25, 15, 15, 0 },
{ 18, 3, 5, 0 },
15, 6, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_ROAR, I_HIGH,
@@ -479,8 +518,9 @@
{
MONS_GIANT_SPORE, 'G', GREEN, "giant spore",
- M_RES_POISON | M_LEVITATE,
- 0, 10, MONS_GIANT_SPORE, MH_NATURAL, -3,
+ M_LEVITATE,
+ MR_RES_POISON | MR_RES_ASPHYX,
+ 0, 10, MONS_PLANT, MONS_GIANT_SPORE, MH_NATURAL, -3,
{ 1, 0, 0, 0 },
{ 1, 0, 0, 1 },
0, 10, 15, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -490,8 +530,9 @@
{
MONS_HOBGOBLIN, 'g', BROWN, "hobgoblin",
- M_WARM_BLOOD,
- 500, 10, MONS_HOBGOBLIN, MH_NATURAL, -1,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 500, 10, MONS_GOBLIN, MONS_HOBGOBLIN, MH_NATURAL, -1,
{ 5, 0, 0, 0 },
{ 1, 4, 5, 0 },
2, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -501,8 +542,9 @@
{
MONS_ICE_BEAST, 'I', WHITE, "ice beast",
- M_RES_POISON | M_ED_FIRE | M_RES_COLD,
- 0, 12, MONS_ICE_BEAST, MH_NATURAL, -3,
+ M_NO_FLAGS,
+ MR_RES_POISON | MR_RES_ASPHYX | MR_VUL_FIRE | MR_RES_COLD,
+ 0, 12, MONS_ICE_BEAST, MONS_ICE_BEAST, MH_NATURAL, -3,
{ 5, 0, 0, 0 },
{ 5, 3, 5, 0 },
5, 10, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_ANIMAL_LIKE,
@@ -512,8 +554,9 @@
{
MONS_JELLY, 'J', LIGHTRED, "jelly",
- M_RES_POISON | M_SEE_INVIS | M_SPLITS | M_AMPHIBIOUS,
- 0, 13, MONS_JELLY, MH_NATURAL, -3,
+ M_SEE_INVIS | M_SPLITS | M_AMPHIBIOUS,
+ MR_RES_POISON | MR_RES_ASPHYX,
+ 0, 13, MONS_JELLY, MONS_JELLY, MH_NATURAL, -3,
{ 8, 0, 0, 0 },
{ 3, 5, 5, 0 },
0, 2, 9, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -524,7 +567,8 @@
{
MONS_KOBOLD, 'K', BROWN, "kobold",
M_WARM_BLOOD,
- 400, 10, MONS_KOBOLD, MH_NATURAL, -1,
+ MR_NO_FLAGS,
+ 400, 10, MONS_KOBOLD, MONS_KOBOLD, MH_NATURAL, -1,
{ 4, 0, 0, 0 },
{ 1, 2, 3, 0 },
2, 12, 10, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -534,8 +578,9 @@
{
MONS_LICH, 'L', WHITE, "lich",
- M_RES_POISON | M_RES_COLD | M_RES_ELEC | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS,
- 0, 16, MONS_LICH, MH_UNDEAD, -11,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD | MR_RES_ELEC,
+ 0, 16, MONS_LICH, MONS_LICH, MH_UNDEAD, -11,
{ 15, 0, 0, 0 },
{ 20, 2, 4, 0 },
10, 10, 10, 7, MST_LICH_I, CE_NOCORPSE, Z_NOZOMBIE, S_SHOUT, I_HIGH,
@@ -545,8 +590,9 @@
{
MONS_MUMMY, 'M', WHITE, "mummy",
- M_RES_POISON | M_ED_FIRE | M_RES_COLD,
- 0, 10, MONS_MUMMY, MH_UNDEAD, -5,
+ M_EVIL,
+ MR_RES_POISON | MR_VUL_FIRE | MR_RES_COLD,
+ 0, 10, MONS_MUMMY, MONS_MUMMY, MH_UNDEAD, -5,
{ 20, 0, 0, 0 },
{ 3, 5, 3, 0 },
3, 6, 6, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_ANIMAL,
@@ -556,8 +602,9 @@
{
MONS_GUARDIAN_NAGA, 'N', LIGHTGREEN, "guardian naga",
- M_RES_POISON | M_SPELLCASTER | M_SEE_INVIS | M_ACTUAL_SPELLS | M_WARM_BLOOD,
- 350, 10, MONS_GUARDIAN_NAGA, MH_NATURAL, -6,
+ M_SPELLCASTER | M_SEE_INVIS | M_ACTUAL_SPELLS | M_WARM_BLOOD,
+ MR_RES_POISON,
+ 350, 10, MONS_NAGA, MONS_GUARDIAN_NAGA, MH_NATURAL, -6,
{ 19, 0, 0, 0 },
{ 8, 3, 5, 0 },
6, 14, 15, 7, MST_GUARDIAN_NAGA, CE_MUTAGEN_RANDOM, Z_SMALL, S_SHOUT, I_HIGH,
@@ -567,8 +614,9 @@
{
MONS_OGRE, 'O', BROWN, "ogre",
- M_WARM_BLOOD,
- 1300, 10, MONS_OGRE, MH_NATURAL, -3,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 1300, 10, MONS_OGRE, MONS_OGRE, MH_NATURAL, -3,
{ 17, 0, 0, 0 },
{ 5, 3, 5, 0 },
1, 6, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_BIG, S_SHOUT, I_NORMAL,
@@ -579,7 +627,8 @@
{
MONS_PLANT, 'P', GREEN, "plant",
M_NO_EXP_GAIN,
- 0, 10, MONS_PLANT, MH_PLANT, 5000,
+ MR_NO_FLAGS,
+ 0, 10, MONS_PLANT, MONS_PLANT, MH_PLANT, MAG_IMMUNE,
{ 0, 0, 0, 0 },
{ 10, 3, 5, 0 },
10, 0, 0, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -589,8 +638,9 @@
{
MONS_QUEEN_BEE, 'Q', YELLOW, "queen bee",
- M_ED_POISON | M_FLIES,
- 200, 14, MONS_QUEEN_BEE, MH_NATURAL, -3,
+ M_FLIES,
+ MR_VUL_POISON,
+ 200, 14, MONS_KILLER_BEE, MONS_QUEEN_BEE, MH_NATURAL, -3,
{ 20, 0, 0, 0 },
{ 7, 3, 5, 0 },
10, 10, 10, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_SILENT, I_INSECT,
@@ -600,8 +650,9 @@
{
MONS_RAKSHASA, 'R', YELLOW, "rakshasa",
- M_RES_POISON | M_SPELLCASTER | M_SEE_INVIS,
- 0, 15, MONS_RAKSHASA, MH_NATURAL, -10,
+ M_SPELLCASTER | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON,
+ 0, 15, MONS_RAKSHASA, MONS_RAKSHASA, MH_NATURAL, -10,
{ 20, 0, 0, 0 },
{ 10, 3, 5, 0 },
10, 14, 10, 7, MST_RAKSHASA, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_HIGH,
@@ -612,7 +663,8 @@
{
MONS_SNAKE, 'S', GREEN, "snake",
M_COLD_BLOOD | M_AMPHIBIOUS,
- 200, 10, MONS_SNAKE, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 200, 10, MONS_SNAKE, MONS_SNAKE, MH_NATURAL, -3,
{ 5, 0, 0, 0 },
{ 2, 3, 5, 0 },
1, 15, 13, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_SILENT, I_REPTILE,
@@ -622,8 +674,9 @@
{
MONS_TROLL, 'T', BROWN, "troll",
- M_WARM_BLOOD,
- 1500, 10, MONS_TROLL, MH_NATURAL, -3,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 1500, 10, MONS_TROLL, MONS_TROLL, MH_NATURAL, -3,
{ 20, 15, 15, 0 },
{ 7, 3, 5, 0 },
3, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_BIG, S_SHOUT, I_NORMAL,
@@ -633,8 +686,9 @@
{
MONS_UNSEEN_HORROR, 'x', MAGENTA, "unseen horror",
- M_LEVITATE | M_SEE_INVIS | M_RES_ELEC | M_INVIS,
- 0, 12, MONS_UNSEEN_HORROR, MH_NATURAL, -3,
+ M_LEVITATE | M_SEE_INVIS | M_INVIS,
+ MR_RES_ELEC,
+ 0, 12, MONS_UNSEEN_HORROR, MONS_UNSEEN_HORROR, MH_NATURAL, -3,
{ 12, 0, 0, 0 },
{ 7, 3, 5, 0 },
5, 10, 30, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_ANIMAL_LIKE,
@@ -644,8 +698,9 @@
{
MONS_VAMPIRE, 'V', RED, "vampire",
- M_RES_POISON | M_RES_COLD | M_SPELLCASTER | M_SEE_INVIS,
- 0, 11, MONS_VAMPIRE, MH_UNDEAD, -6,
+ M_SPELLCASTER | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 11, MONS_VAMPIRE, MONS_VAMPIRE, MH_UNDEAD, -6,
{ 22, 0, 0, 0 },
{ 6, 3, 5, 0 },
10, 10, 10, 7, MST_VAMPIRE, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -655,8 +710,9 @@
{
MONS_WRAITH, 'W', DARKGREY, "wraith",
- M_RES_POISON | M_RES_COLD | M_LEVITATE | M_SEE_INVIS,
- 0, 11, MONS_WRAITH, MH_UNDEAD, -7,
+ M_LEVITATE | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 11, MONS_WRAITH, MONS_WRAITH, MH_UNDEAD, -7,
{ 13, 0, 0, 0 },
{ 6, 3, 5, 0 },
10, 10, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -667,8 +723,9 @@
// Large abom: (the previous one was small)
{
MONS_ABOMINATION_LARGE, 'X', BLACK, "abomination",
- M_NO_FLAGS,
- 0, 10, MONS_ABOMINATION_LARGE, MH_DEMONIC, -7,
+ M_EVIL,
+ MR_NO_FLAGS,
+ 0, 10, MONS_ABOMINATION_SMALL, MONS_ABOMINATION_LARGE, MH_DEMONIC, -7,
{ 40, 0, 0, 0 },
{ 11, 2, 5, 0 },
0, 0, 0, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -678,8 +735,9 @@
{
MONS_YAK, 'Y', BROWN, "yak",
- M_WARM_BLOOD,
- 1200, 10, MONS_YAK, MH_NATURAL, -3,
+ M_WARM_BLOOD,
+ MR_NO_FLAGS,
+ 1200, 10, MONS_YAK, MONS_YAK, MH_NATURAL, -3,
{ 18, 0, 0, 0 },
{ 7, 3, 5, 0 },
4, 7, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_BIG, S_BELLOW, I_ANIMAL,
@@ -690,8 +748,9 @@
// big zombie
{
MONS_ZOMBIE_LARGE, 'Z', BROWN, "",
- M_RES_POISON | M_RES_COLD,
- 0, 6, MONS_ZOMBIE_LARGE, MH_UNDEAD, -1,
+ M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 6, MONS_ZOMBIE_SMALL, MONS_ZOMBIE_LARGE, MH_UNDEAD, -1,
{ 23, 0, 0, 0 },
{ 6, 3, 5, 0 },
8, 5, 5, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -701,8 +760,9 @@
{
MONS_ORC_WARRIOR, 'o', YELLOW, "orc warrior",
- M_WARM_BLOOD,
- 0, 10, MONS_ORC, MH_NATURAL, -3,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 0, 10, MONS_ORC, MONS_ORC, MH_NATURAL, -3,
{ 20, 0, 0, 0 },
{ 4, 4, 6, 0 },
0, 13, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -712,8 +772,9 @@
{
MONS_KOBOLD_DEMONOLOGIST, 'K', MAGENTA, "kobold demonologist",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD,
- 0, 10, MONS_KOBOLD, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 0, 10, MONS_KOBOLD, MONS_KOBOLD, MH_NATURAL, -5,
{ 4, 0, 0, 0 },
{ 4, 3, 5, 0 },
2, 13, 10, 7, MST_KOBOLD_DEMONOLOGIST, CE_POISONOUS, Z_NOZOMBIE, S_SHOUT, I_NORMAL,
@@ -723,8 +784,9 @@
{
MONS_ORC_WIZARD, 'o', MAGENTA, "orc wizard",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD,
- 0, 10, MONS_ORC, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 0, 10, MONS_ORC, MONS_ORC, MH_NATURAL, -5,
{ 5, 0, 0, 0 },
{ 3, 3, 4, 0 },
1, 12, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -734,8 +796,9 @@
{
MONS_ORC_KNIGHT, 'o', LIGHTCYAN, "orc knight",
- M_WARM_BLOOD,
- 0, 10, MONS_ORC, MH_NATURAL, -3,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 0, 10, MONS_ORC, MONS_ORC, MH_NATURAL, -3,
{ 25, 0, 0, 0 },
{ 9, 4, 7, 0 },
2, 13, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -748,8 +811,9 @@
// not until it can be reimplemented safely {dlb}
{
MONS_WORM_TAIL, '~', LIGHTRED, "worm tail",
- M_NO_EXP_GAIN | M_RES_POISON,
- 0, 10, 56, MH_NATURAL, 5000,
+ M_NO_EXP_GAIN,
+ MR_RES_POISON,
+ 0, 10, 56, MH_NATURAL, MAG_IMMUNE,
{ 0, 0, 0, 0 },
{ 10, 5, 5, 0 },
3, 3, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -760,8 +824,9 @@
{
MONS_WYVERN, 'D', LIGHTRED, "wyvern",
- M_NO_FLAGS, //jmf: warm blood?
- 2000, 10, MONS_WYVERN, MH_NATURAL, -3,
+ M_NO_FLAGS, //jmf: warm blood?
+ MR_NO_FLAGS,
+ 2000, 10, MONS_WYVERN, MONS_WYVERN, MH_NATURAL, -3,
{ 20, 0, 0, 0 },
{ 5, 3, 5, 0 },
5, 10, 15, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_SILENT, I_ANIMAL,
@@ -771,8 +836,9 @@
{
MONS_BIG_KOBOLD, 'K', RED, "big kobold",
- M_WARM_BLOOD,
- 0, 10, MONS_BIG_KOBOLD, MH_NATURAL, -3,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 0, 10, MONS_KOBOLD, MONS_BIG_KOBOLD, MH_NATURAL, -3,
{ 7, 0, 0, 0 },
{ 5, 3, 5, 0 },
3, 12, 10, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_SILENT, I_NORMAL,
@@ -783,7 +849,8 @@
{
MONS_GIANT_EYEBALL, 'G', WHITE, "giant eyeball",
M_NO_SKELETON | M_LEVITATE,
- 400, 10, MONS_GIANT_EYEBALL, MH_NATURAL, -3,
+ MR_RES_ASPHYX,
+ 400, 10, MONS_GIANT_EYEBALL, MONS_GIANT_EYEBALL, MH_NATURAL, -3,
{ 0, 0, 0, 0 },
{ 3, 3, 5, 0 },
0, 1, 3, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_SILENT, I_PLANT,
@@ -793,8 +860,9 @@
{
MONS_WIGHT, 'W', LIGHTGREY, "wight",
- M_RES_POISON | M_RES_COLD,
- 0, 10, MONS_WIGHT, MH_UNDEAD, -4,
+ M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 10, MONS_WRAITH, MONS_WIGHT, MH_UNDEAD, -4,
{ 8, 0, 0, 0 },
{ 3, 3, 5, 0 },
4, 10, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -804,8 +872,9 @@
{
MONS_OKLOB_PLANT, 'P', GREEN, "oklob plant",
- M_RES_POISON,
- 0, 10, MONS_OKLOB_PLANT, MH_PLANT, -3,
+ M_SPECIAL_ABILITY,
+ MR_RES_POISON,
+ 0, 10, MONS_PLANT, MONS_OKLOB_PLANT, MH_PLANT, -3,
{ 0, 0, 0, 0 },
{ 10, 3, 5, 0 },
10, 0, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -815,8 +884,9 @@
{
MONS_WOLF_SPIDER, 's', BROWN, "wolf spider",
- M_ED_POISON,
- 800, 10, MONS_WOLF_SPIDER, MH_NATURAL, -3,
+ M_NO_FLAGS,
+ MR_VUL_POISON,
+ 800, 10, MONS_WOLF_SPIDER, MONS_WOLF_SPIDER, MH_NATURAL, -3,
{ 20, 0, 0, 0 },
{ 8, 3, 5, 0 },
3, 10, 15, 7, MST_NO_SPELLS, CE_POISONOUS, Z_BIG, S_SILENT, I_INSECT,
@@ -826,8 +896,9 @@
{
MONS_SHADOW, ' ', BLACK, "shadow",
- M_RES_POISON | M_RES_COLD | M_SEE_INVIS,
- 0, 10, MONS_SHADOW, MH_UNDEAD, -5,
+ M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 10, MONS_WRAITH, MONS_SHADOW, MH_UNDEAD, -5,
{ 5, 0, 0, 0 },
{ 3, 3, 5, 0 },
12, 10, 10, 7, BLACK, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_ANIMAL,
@@ -837,8 +908,9 @@
{
MONS_HUNGRY_GHOST, 'p', GREEN, "hungry ghost",
- M_RES_POISON | M_RES_COLD | M_SEE_INVIS | M_FLIES,
- 0, 10, MONS_HUNGRY_GHOST, MH_UNDEAD, -4,
+ M_SEE_INVIS | M_FLIES | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 10, MONS_PHANTOM, MONS_HUNGRY_GHOST, MH_UNDEAD, -4,
{ 5, 0, 0, 0 },
{ 7, 3, 5, 0 },
0, 17, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -849,7 +921,8 @@
{
MONS_EYE_OF_DRAINING, 'G', LIGHTGREY, "eye of draining",
M_NO_SKELETON | M_LEVITATE | M_SEE_INVIS,
- 400, 10, MONS_EYE_OF_DRAINING, MH_NATURAL, 5000,
+ MR_RES_ASPHYX,
+ 400, 10, MONS_GIANT_EYEBALL, MONS_EYE_OF_DRAINING, MH_NATURAL, MAG_IMMUNE,
{ 0, 0, 0, 0 },
{ 7, 3, 5, 0 },
3, 1, 5, 7, MST_NO_SPELLS, CE_MUTAGEN_RANDOM, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -859,8 +932,9 @@
{
MONS_BUTTERFLY, 'b', BLACK, "butterfly",
- M_FLIES | M_ED_POISON | M_CONFUSED,
- 150, 10, MONS_BUTTERFLY, MH_NATURAL, -3,
+ M_FLIES | M_CONFUSED,
+ MR_VUL_POISON | MR_RES_ASPHYX,
+ 150, 10, MONS_BUTTERFLY, MONS_BUTTERFLY, MH_NATURAL, -3,
{ 0, 0, 0, 0 },
{ 1, 3, 5, 0 },
0, 25, 25, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_SILENT, I_INSECT,
@@ -870,8 +944,9 @@
{
MONS_WANDERING_MUSHROOM, 'f', BROWN, "wandering mushroom",
- M_RES_POISON,
- 0, 10, MONS_WANDERING_MUSHROOM, MH_PLANT, -3,
+ M_NO_FLAGS,
+ MR_RES_POISON,
+ 0, 10, MONS_PLANT, MONS_WANDERING_MUSHROOM, MH_PLANT, -3,
{ 20, 0, 0, 0 },
{ 8, 3, 5, 0 },
5, 0, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -881,8 +956,9 @@
{
MONS_EFREET, 'E', RED, "efreet",
- M_RES_POISON | M_RES_FIRE | M_ED_COLD | M_SPELLCASTER | M_LEVITATE,
- 0, 12, MONS_EFREET, MH_DEMONIC, -3,
+ M_SPELLCASTER | M_LEVITATE | M_EVIL,
+ MR_RES_POISON | MR_RES_FIRE | MR_VUL_COLD,
+ 0, 12, MONS_EFREET, MONS_EFREET, MH_DEMONIC, -3,
{ 12, 0, 0, 0 },
{ 7, 3, 5, 0 },
10, 5, 10, 7, MST_EFREET, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_HIGH,
@@ -893,7 +969,8 @@
{
MONS_BRAIN_WORM, 'w', LIGHTMAGENTA, "brain worm",
M_SPELLCASTER,
- 150, 10, MONS_BRAIN_WORM, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 150, 10, MONS_WORM, MONS_BRAIN_WORM, MH_NATURAL, -3,
{ 0, 0, 0, 0 },
{ 5, 3, 3, 0 },
1, 5, 10, 7, MST_BRAIN_WORM, CE_POISONOUS, Z_SMALL, S_SILENT, I_REPTILE,
@@ -904,7 +981,8 @@
{
MONS_GIANT_ORANGE_BRAIN, 'G', LIGHTRED, "giant orange brain",
M_NO_SKELETON | M_SPELLCASTER | M_LEVITATE | M_SEE_INVIS,
- 1000, 13, MONS_GIANT_ORANGE_BRAIN, MH_NATURAL, -8,
+ MR_RES_ASPHYX,
+ 1000, 13, MONS_GIANT_ORANGE_BRAIN, MONS_GIANT_ORANGE_BRAIN, MH_NATURAL, -8,
{ 0, 0, 0, 0 },
{ 10, 3, 5, 0 },
2, 4, 10, 7, MST_GIANT_ORANGE_BRAIN, CE_MUTAGEN_RANDOM, Z_NOZOMBIE, S_SILENT, I_HIGH,
@@ -914,8 +992,9 @@
{
MONS_BOULDER_BEETLE, 'B', LIGHTGREY, "boulder beetle",
- M_ED_POISON,
- 2500, 10, MONS_BOULDER_BEETLE, MH_NATURAL, -3,
+ M_NO_FLAGS,
+ MR_VUL_POISON,
+ 2500, 10, MONS_GIANT_BEETLE, MONS_BOULDER_BEETLE, MH_NATURAL, -3,
{ 35, 0, 0, 0 },
{ 9, 3, 5, 0 },
20, 2, 3, 7, MST_NO_SPELLS, CE_POISONOUS, Z_BIG, S_SILENT, I_INSECT,
@@ -925,8 +1004,9 @@
{
MONS_FLYING_SKULL, 'z', WHITE, "flying skull",
- M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_RES_ELEC | M_LEVITATE,
- 0, 10, MONS_FLYING_SKULL, MH_UNDEAD, -3,
+ M_LEVITATE,
+ MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 10, MONS_SKELETON_SMALL, MONS_FLYING_SKULL, MH_UNDEAD, -3,
{ 7, 0, 0, 0 },
{ 2, 3, 5, 0 },
10, 17, 15, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SCREAM, I_ANIMAL,
@@ -936,8 +1016,9 @@
{
MONS_HELL_HOUND, 'h', DARKGREY, "hell hound",
- M_RES_POISON | M_RES_HELLFIRE | M_ED_COLD | M_SEE_INVIS,
- 0, 10, MONS_HELL_HOUND, MH_DEMONIC, -3,
+ M_SEE_INVIS | M_EVIL | M_SPECIAL_ABILITY,
+ MR_RES_POISON | MR_RES_HELLFIRE | MR_VUL_COLD,
+ 0, 10, MONS_HOUND, MONS_HELL_HOUND, MH_DEMONIC, -3,
{ 13, 0, 0, 0 },
{ 5, 3, 5, 0 },
6, 13, 15, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_BARK, I_NORMAL,
@@ -948,7 +1029,8 @@
{
MONS_MINOTAUR, 'm', LIGHTRED, "minotaur",
M_WARM_BLOOD,
- 1500, 10, MONS_MINOTAUR, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 1500, 10, MONS_MINOTAUR, MONS_MINOTAUR, MH_NATURAL, -3,
{ 35, 0, 0, 0 },
{ 13, 3, 5, 0 },
5, 7, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_BIG, S_BELLOW, I_NORMAL,
@@ -958,8 +1040,9 @@
{
MONS_ICE_DRAGON, 'D', WHITE, "ice dragon",
- M_RES_POISON | M_ED_FIRE | M_RES_COLD | M_FLIES,
- 2200, 10, MONS_ICE_DRAGON, MH_NATURAL, -3,
+ M_FLIES | M_SPECIAL_ABILITY,
+ MR_RES_POISON | MR_VUL_FIRE | MR_RES_COLD,
+ 2200, 10, MONS_DRAGON, MONS_ICE_DRAGON, MH_NATURAL, -3,
{ 17, 17, 17, 0 },
{ 12, 5, 5, 0 },
10, 8, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_BIG, S_SILENT, I_NORMAL,
@@ -969,8 +1052,9 @@
{
MONS_SLIME_CREATURE, 'J', GREEN, "slime creature",
- M_RES_POISON | M_AMPHIBIOUS,
- 0, 5, MONS_SLIME_CREATURE, MH_NATURAL, -3,
+ M_AMPHIBIOUS,
+ MR_RES_POISON,
+ 0, 5, MONS_SLIME_CREATURE, MONS_SLIME_CREATURE, MH_NATURAL, -3,
{ 22, 0, 0, 0 },
{ 11, 3, 5, 0 },
1, 4, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -980,8 +1064,9 @@
{
MONS_FREEZING_WRAITH, 'W', LIGHTBLUE, "freezing wraith",
- M_RES_POISON | M_ED_FIRE | M_RES_COLD | M_LEVITATE | M_SEE_INVIS,
- 0, 10, MONS_FREEZING_WRAITH, MH_UNDEAD, -4,
+ M_LEVITATE | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_VUL_FIRE | MR_RES_COLD,
+ 0, 10, MONS_WRAITH, MONS_FREEZING_WRAITH, MH_UNDEAD, -4,
{ 19, 0, 0, 0 },
{ 8, 3, 5, 0 },
12, 10, 8, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -992,8 +1077,9 @@
// fake R - conjured by the R's illusion spell.
{
MONS_RAKSHASA_FAKE, 'R', YELLOW, "rakshasa",
- M_RES_POISON,
- 0, 10, MONS_RAKSHASA_FAKE, MH_NATURAL, 5000,
+ M_EVIL,
+ MR_RES_POISON,
+ 0, 10, MONS_RAKSHASA_FAKE, MONS_RAKSHASA_FAKE, MH_NATURAL, MAG_IMMUNE,
{ 0, 0, 0, 0 },
{ 1, 0, 0, 1 },
0, 30, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_ROAR, I_PLANT,
@@ -1003,8 +1089,9 @@
{
MONS_GREAT_ORB_OF_EYES, 'G', LIGHTGREEN, "great orb of eyes",
- M_NO_SKELETON | M_RES_POISON | M_SPELLCASTER | M_LEVITATE | M_SEE_INVIS,
- 900, 13, MONS_GREAT_ORB_OF_EYES, MH_NATURAL, 5000,
+ M_NO_SKELETON | M_SPELLCASTER | M_LEVITATE | M_SEE_INVIS,
+ MR_RES_POISON,
+ 900, 13, MONS_GIANT_EYEBALL, MONS_GREAT_ORB_OF_EYES, MH_NATURAL, MAG_IMMUNE,
{ 20, 0, 0, 0 },
{ 12, 3, 5, 0 },
10, 3, 10, 7, MST_GREAT_ORB_OF_EYES, CE_MUTAGEN_RANDOM, Z_NOZOMBIE, S_SILENT, I_HIGH,
@@ -1013,20 +1100,22 @@
,
{
- MONS_HELLION, '3', BLACK, "hellion",
- M_RES_POISON | M_RES_HELLFIRE | M_ED_COLD | M_SPELLCASTER | M_ON_FIRE,
- 0, 11, MONS_HELLION, MH_DEMONIC, -7,
+ MONS_HELLION, '3', EC_FIRE, "hellion",
+ M_SPELLCASTER | M_EVIL,
+ MR_RES_POISON | MR_RES_HELLFIRE | MR_VUL_COLD,
+ 0, 11, MONS_HELLION, MONS_HELLION, MH_DEMONIC, -7,
{ 10, 0, 0, 0 },
{ 7, 3, 5, 0 },
- 5, 10, 13, 7, RED, CE_NOCORPSE, Z_NOZOMBIE, S_SCREAM, I_HIGH,
+ 5, 10, 13, 7, MST_BURNING_DEVIL, CE_NOCORPSE, Z_NOZOMBIE, S_SCREAM, I_HIGH,
MONUSE_OPEN_DOORS
}
,
{
MONS_ROTTING_DEVIL, '4', GREEN, "rotting devil",
- M_RES_POISON | M_RES_COLD,
- 0, 10, MONS_ROTTING_DEVIL, MH_DEMONIC, -7,
+ M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 10, MONS_ROTTING_DEVIL, MONS_ROTTING_DEVIL, MH_DEMONIC, -7,
{ 8, 0, 0, 0 },
{ 5, 3, 5, 0 },
2, 10, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_HIGH,
@@ -1036,8 +1125,9 @@
{
MONS_TORMENTOR, '3', YELLOW, "tormentor",
- M_RES_POISON | M_RES_FIRE | M_SPELLCASTER | M_FLIES | M_SPEAKS,
- 0, 10, MONS_TORMENTOR, MH_DEMONIC, -6,
+ M_SPELLCASTER | M_FLIES | M_SPEAKS | M_EVIL,
+ MR_RES_POISON | MR_RES_FIRE,
+ 0, 10, MONS_TORMENTOR, MONS_TORMENTOR, MH_DEMONIC, -6,
{ 8, 8, 0, 0 },
{ 7, 3, 5, 0 },
12, 12, 13, 7, MST_TORMENTOR, CE_NOCORPSE, Z_NOZOMBIE, S_ROAR, I_HIGH,
@@ -1047,8 +1137,9 @@
{
MONS_REAPER, '2', LIGHTGREY, "reaper",
- M_RES_POISON | M_RES_COLD | M_SEE_INVIS,
- 0, 10, MONS_REAPER, MH_DEMONIC, 5000,
+ M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 10, MONS_REAPER, MONS_REAPER, MH_DEMONIC, MAG_IMMUNE,
{ 32, 0, 0, 0 },
{ 8, 3, 5, 0 },
15, 10, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_HIGH,
@@ -1058,8 +1149,9 @@
{
MONS_SOUL_EATER, '2', DARKGREY, "soul eater",
- M_RES_POISON | M_RES_COLD | M_LEVITATE | M_SEE_INVIS,
- 0, 12, MONS_SOUL_EATER, MH_DEMONIC, -10,
+ M_LEVITATE | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 12, MONS_SOUL_EATER, MONS_SOUL_EATER, MH_DEMONIC, -10,
{ 25, 0, 0, 0 },
{ 11, 3, 5, 0 },
18, 10, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_HIGH,
@@ -1069,8 +1161,9 @@
{
MONS_HAIRY_DEVIL, '4', LIGHTRED, "hairy devil",
- M_RES_POISON,
- 0, 10, MONS_HAIRY_DEVIL, MH_DEMONIC, -4,
+ M_EVIL,
+ MR_RES_POISON,
+ 0, 10, MONS_HAIRY_DEVIL, MONS_HAIRY_DEVIL, MH_DEMONIC, -4,
{ 9, 9, 0, 0 },
{ 6, 3, 5, 0 },
7, 10, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SHOUT, I_HIGH,
@@ -1080,8 +1173,9 @@
{
MONS_ICE_DEVIL, '2', WHITE, "ice devil",
- M_RES_POISON | M_ED_FIRE | M_RES_COLD | M_SEE_INVIS,
- 0, 11, MONS_ICE_DEVIL, MH_DEMONIC, -6,
+ M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_VUL_FIRE | MR_RES_COLD,
+ 0, 11, MONS_ICE_DEVIL, MONS_ICE_DEVIL, MH_DEMONIC, -6,
{ 16, 0, 0, 0 },
{ 11, 3, 5, 0 },
12, 10, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_HIGH,
@@ -1091,8 +1185,9 @@
{
MONS_BLUE_DEVIL, '3', BLUE, "blue devil",
- M_RES_POISON | M_ED_FIRE | M_RES_COLD | M_FLIES,
- 0, 10, MONS_BLUE_DEVIL, MH_DEMONIC, -5,
+ M_FLIES | M_EVIL,
+ MR_RES_POISON | MR_VUL_FIRE | MR_RES_COLD,
+ 0, 10, MONS_BLUE_DEVIL, MONS_BLUE_DEVIL, MH_DEMONIC, -5,
{ 21, 0, 0, 0 },
{ 7, 3, 5, 0 },
14, 10, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_HIGH,
@@ -1103,8 +1198,9 @@
// random
{
MONS_BEAST, '4', BROWN, "beast",
- M_NO_FLAGS,
- 0, 10, MONS_BEAST, MH_DEMONIC, -3,
+ M_EVIL,
+ MR_NO_FLAGS,
+ 0, 10, MONS_BEAST, MONS_BEAST, MH_DEMONIC, -3,
{ 12, 0, 0, 0 },
{ 5, 3, 5, 0 },
0, 0, 0, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_RANDOM, I_NORMAL,
@@ -1114,8 +1210,9 @@
{
MONS_IRON_DEVIL, '3', CYAN, "iron devil",
- M_RES_ELEC | M_RES_POISON | M_RES_HELLFIRE | M_RES_COLD,
- 0, 10, MONS_IRON_DEVIL, MH_DEMONIC, -6,
+ M_EVIL,
+ MR_RES_ELEC | MR_RES_POISON | MR_RES_HELLFIRE | MR_RES_COLD,
+ 0, 10, MONS_IRON_DEVIL, MONS_IRON_DEVIL, MH_DEMONIC, -6,
{ 14, 14, 0, 0 },
{ 8, 3, 5, 0 },
16, 8, 8, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SCREECH, I_HIGH,
@@ -1126,7 +1223,8 @@
{
MONS_GLOWING_SHAPESHIFTER, '@', RED, "glowing shapeshifter",
M_NO_FLAGS,
- 600, 10, MONS_SHAPESHIFTER, MH_NATURAL, -6,
+ MR_NO_FLAGS,
+ 600, 10, MONS_SHAPESHIFTER, MONS_GLOWING_SHAPESHIFTER, MH_NATURAL, -6,
{ 15, 0, 0, 0 },
{ 10, 3, 5, 0 },
0, 10, 10, 7, MST_NO_SPELLS, CE_MUTAGEN_RANDOM, Z_NOZOMBIE, S_SILENT, I_HIGH,
@@ -1137,7 +1235,8 @@
{
MONS_SHAPESHIFTER, '@', LIGHTRED, "shapeshifter",
M_NO_FLAGS,
- 600, 10, MONS_SHAPESHIFTER, MH_NATURAL, -6,
+ MR_NO_FLAGS,
+ 600, 10, MONS_SHAPESHIFTER, MONS_SHAPESHIFTER, MH_NATURAL, -6,
{ 5, 0, 0, 0 },
{ 7, 3, 5, 0 },
0, 10, 10, 7, MST_NO_SPELLS, CE_MUTAGEN_RANDOM, Z_NOZOMBIE, S_SILENT, I_HIGH,
@@ -1147,8 +1246,9 @@
{
MONS_GIANT_MITE, 's', LIGHTRED, "giant mite",
- M_ED_POISON,
- 350, 10, MONS_GIANT_MITE, MH_NATURAL, -1,
+ M_NO_FLAGS,
+ MR_VUL_POISON,
+ 350, 10, MONS_GIANT_MITE, MONS_GIANT_MITE, MH_NATURAL, -1,
{ 5, 0, 0, 0 },
{ 2, 3, 5, 0 },
1, 7, 10, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_SILENT, I_INSECT,
@@ -1157,9 +1257,10 @@
,
{
- MONS_STEAM_DRAGON, 'd', LIGHTGREY, "steam dragon",
+ MONS_STEAM_DRAGON, 'D', LIGHTGREY, "steam dragon",
M_SPELLCASTER | M_FLIES,
- 1000, 10, MONS_STEAM_DRAGON, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 1000, 10, MONS_DRAGON, MONS_STEAM_DRAGON, MH_NATURAL, -3,
{ 12, 0, 0, 0 },
{ 4, 5, 5, 0 },
5, 10, 10, 7, MST_STEAM_DRAGON, CE_CLEAN, Z_BIG, S_SILENT, I_ANIMAL_LIKE,
@@ -1170,7 +1271,8 @@
{
MONS_VERY_UGLY_THING, 'u', RED, "very ugly thing",
M_WARM_BLOOD | M_AMPHIBIOUS,
- 750, 10, MONS_VERY_UGLY_THING, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 750, 10, MONS_UGLY_THING, MONS_VERY_UGLY_THING, MH_NATURAL, -3,
{ 17, 0, 0, 0 },
{ 12, 3, 5, 0 },
4, 8, 8, 7, MST_NO_SPELLS, CE_MUTAGEN_RANDOM, Z_BIG, S_SHOUT, I_NORMAL,
@@ -1180,8 +1282,9 @@
{
MONS_ORC_SORCERER, 'o', DARKGREY, "orc sorcerer",
- M_RES_FIRE | M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS | M_ACTUAL_SPELLS | M_WARM_BLOOD,
- 600, 12, MONS_ORC, MH_NATURAL, -3,
+ M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_EVIL,
+ MR_RES_FIRE,
+ 600, 12, MONS_ORC, MONS_ORC, MH_NATURAL, -3,
{ 7, 0, 0, 0 },
{ 8, 2, 3, 0 },
5, 12, 10, 7, MST_ORC_SORCERER, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -1192,7 +1295,8 @@
{
MONS_HIPPOGRIFF, 'H', BROWN, "hippogriff",
M_FLIES | M_WARM_BLOOD,
- 1000, 10, MONS_HIPPOGRIFF, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 1000, 10, MONS_HIPPOGRIFF, MONS_HIPPOGRIFF, MH_NATURAL, -3,
{ 10, 8, 8, 0 },
{ 7, 3, 5, 0 },
2, 7, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_BIG, S_SCREECH, I_ANIMAL,
@@ -1203,7 +1307,8 @@
{
MONS_GRIFFON, 'H', YELLOW, "griffon",
M_FLIES | M_WARM_BLOOD,
- 1800, 10, MONS_GRIFFON, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 1800, 10, MONS_GRIFFON, MONS_GRIFFON, MH_NATURAL, -3,
{ 18, 10, 10, 0 },
{ 12, 3, 5, 0 },
4, 6, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_BIG, S_SCREECH, I_ANIMAL,
@@ -1213,8 +1318,9 @@
{
MONS_HYDRA, 'D', LIGHTGREEN, "hydra",
- M_RES_POISON | M_AMPHIBIOUS, // because it likes the swamp -- bwr
- 1800, 11, MONS_HYDRA, MH_NATURAL, -3,
+ M_AMPHIBIOUS, // because it likes the swamp -- bwr
+ MR_RES_POISON,
+ 1800, 11, MONS_HYDRA, MONS_HYDRA, MH_NATURAL, -3,
{ 18, 0, 0, 0 },
{ 13, 3, 5, 0 },
0, 5, 10, 7, MST_NO_SPELLS, CE_POISONOUS, Z_NOZOMBIE, S_ROAR, I_REPTILE,
@@ -1225,8 +1331,9 @@
// small skeleton
{
MONS_SKELETON_SMALL, 'z', LIGHTGREY, "",
- M_RES_POISON | M_RES_COLD,
- 0, 10, MONS_SKELETON_SMALL, MH_UNDEAD, -1,
+ M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 10, MONS_SKELETON_SMALL, MONS_SKELETON_SMALL, MH_UNDEAD, -1,
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
0, 0, 0, 0, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -1237,8 +1344,9 @@
// large skeleton
{
MONS_SKELETON_LARGE, 'Z', LIGHTGREY, "",
- M_RES_POISON | M_RES_COLD,
- 0, 10, MONS_SKELETON_LARGE, MH_UNDEAD, -1,
+ M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 10, MONS_SKELETON_SMALL, MONS_SKELETON_LARGE, MH_UNDEAD, -1,
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
0, 0, 0, 0, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -1249,8 +1357,9 @@
{
MONS_HELL_KNIGHT, '@', RED, "hell knight",
- M_RES_FIRE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD,
- 550, 10, MONS_HUMAN, MH_NATURAL, -3,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_EVIL,
+ MR_RES_FIRE,
+ 550, 10, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -3,
{ 13, 0, 0, 0 },
{ 10, 3, 6, 0 },
0, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -1260,8 +1369,9 @@
{
MONS_NECROMANCER, '@', DARKGREY, "necromancer",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD,
- 550, 10, MONS_HUMAN, MH_NATURAL, -4,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 550, 10, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -4,
{ 6, 0, 0, 0 },
{ 10, 2, 4, 0 },
0, 13, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -1271,8 +1381,9 @@
{
MONS_WIZARD, '@', MAGENTA, "wizard",
- M_RES_ELEC | M_SPELLCASTER | M_SPEAKS | M_ACTUAL_SPELLS | M_WARM_BLOOD,
- 550, 10, MONS_HUMAN, MH_NATURAL, -4,
+ M_SPELLCASTER | M_SPEAKS | M_ACTUAL_SPELLS | M_WARM_BLOOD,
+ MR_RES_ELEC,
+ 550, 10, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -4,
{ 6, 0, 0, 0 },
{ 10, 2, 4, 0 },
0, 13, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -1282,8 +1393,9 @@
{
MONS_ORC_PRIEST, 'o', LIGHTGREEN, "orc priest",
- M_SPELLCASTER | M_PRIEST | M_WARM_BLOOD,
- 600, 10, MONS_ORC, MH_NATURAL, -4,
+ M_SPELLCASTER | M_PRIEST | M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 600, 10, MONS_ORC, MONS_ORC, MH_NATURAL, -4,
{ 6, 0, 0, 0 },
{ 3, 3, 4, 0 },
1, 10, 10, 7, MST_ORC_PRIEST, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -1293,8 +1405,9 @@
{
MONS_ORC_HIGH_PRIEST, 'o', GREEN, "orc high priest",
- M_RES_HELLFIRE | M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS | M_PRIEST | M_WARM_BLOOD,
- 600, 10, MONS_ORC, MH_NATURAL, -4,
+ M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS | M_PRIEST | M_WARM_BLOOD | M_EVIL,
+ MR_RES_HELLFIRE,
+ 600, 10, MONS_ORC, MONS_ORC, MH_NATURAL, -4,
{ 7, 0, 0, 0 },
{ 11, 3, 4, 0 },
1, 12, 10, 7, MST_ORC_HIGH_PRIEST, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -1310,7 +1423,8 @@
{
MONS_HUMAN, '@', LIGHTGRAY, "human",
M_WARM_BLOOD,
- 550, 10, MONS_HUMAN, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 550, 10, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -3,
{ 10, 0, 0, 0 },
{ 1, 3, 5, 0 },
0, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -1321,7 +1435,8 @@
{
MONS_GNOLL, 'g', YELLOW, "gnoll",
M_WARM_BLOOD,
- 750, 10, MONS_GNOLL, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 750, 10, MONS_GNOLL, MONS_GNOLL, MH_NATURAL, -3,
{ 9, 0, 0, 0 },
{ 2, 4, 5, 0 },
2, 9, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -1331,8 +1446,9 @@
{
MONS_CLAY_GOLEM, '8', BROWN, "clay golem",
- M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_RES_ELEC | M_SEE_INVIS,
- 0, 10, MONS_CLAY_GOLEM, MH_NONLIVING, 5000,
+ M_SEE_INVIS,
+ MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 10, MONS_CLAY_GOLEM, MONS_CLAY_GOLEM, MH_NONLIVING, MAG_IMMUNE,
{ 11, 11, 0, 0 },
{ 8, 7, 3, 0 },
7, 5, 8, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -1342,8 +1458,9 @@
{
MONS_WOOD_GOLEM, '8', YELLOW, "wood golem",
- M_RES_POISON | M_ED_FIRE | M_RES_COLD | M_RES_ELEC,
- 0, 10, MONS_WOOD_GOLEM, MH_NONLIVING, 5000,
+ M_NO_FLAGS,
+ MR_RES_POISON | MR_VUL_FIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 10, MONS_CLAY_GOLEM, MONS_WOOD_GOLEM, MH_NONLIVING, MAG_IMMUNE,
{ 10, 0, 0, 0 },
{ 6, 6, 3, 0 },
5, 6, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -1353,8 +1470,9 @@
{
MONS_STONE_GOLEM, '8', LIGHTGREY, "stone golem",
- M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_RES_ELEC,
- 0, 10, MONS_STONE_GOLEM, MH_NONLIVING, 5000,
+ M_NO_FLAGS,
+ MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 10, MONS_CLAY_GOLEM, MONS_STONE_GOLEM, MH_NONLIVING, MAG_IMMUNE,
{ 28, 0, 0, 0 },
{ 12, 7, 4, 0 },
12, 4, 7, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -1364,8 +1482,9 @@
{
MONS_IRON_GOLEM, '8', CYAN, "iron golem",
- M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_RES_ELEC | M_SEE_INVIS,
- 0, 10, MONS_IRON_GOLEM, MH_NONLIVING, 5000,
+ M_SEE_INVIS,
+ MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 10, MONS_CLAY_GOLEM, MONS_IRON_GOLEM, MH_NONLIVING, MAG_IMMUNE,
{ 35, 0, 0, 0 },
{ 15, 7, 4, 0 },
15, 3, 7, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -1375,8 +1494,9 @@
{
MONS_CRYSTAL_GOLEM, '8', WHITE, "crystal golem",
- M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_RES_ELEC | M_SEE_INVIS,
- 0, 10, MONS_CRYSTAL_GOLEM, MH_NONLIVING, 5000,
+ M_SEE_INVIS,
+ MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 10, MONS_CLAY_GOLEM, MONS_CRYSTAL_GOLEM, MH_NONLIVING, MAG_IMMUNE,
{ 40, 0, 0, 0 },
{ 13, 7, 4, 0 },
22, 3, 7, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -1386,8 +1506,9 @@
{
MONS_TOENAIL_GOLEM, '8', LIGHTGREY, "toenail golem",
- M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_RES_ELEC,
- 0, 10, MONS_TOENAIL_GOLEM, MH_NONLIVING, 5000,
+ M_NO_FLAGS,
+ MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 10, MONS_CLAY_GOLEM, MONS_TOENAIL_GOLEM, MH_NONLIVING, MAG_IMMUNE,
{ 13, 0, 0, 0 },
{ 9, 5, 3, 0 },
8, 5, 8, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -1396,9 +1517,10 @@
,
{
- MONS_MOTTLED_DRAGON, 'd', LIGHTMAGENTA, "mottled dragon",
- M_RES_POISON | M_RES_FIRE | M_SPELLCASTER | M_FLIES,
- 1100, 10, MONS_MOTTLED_DRAGON, MH_NATURAL, -3,
+ MONS_MOTTLED_DRAGON, 'D', RED, "mottled dragon",
+ M_SPELLCASTER | M_FLIES,
+ MR_RES_POISON | MR_RES_FIRE,
+ 1100, 10, MONS_DRAGON, MONS_MOTTLED_DRAGON, MH_NATURAL, -3,
{ 15, 0, 0, 0 },
{ 5, 3, 5, 0 },
5, 10, 10, 7, MST_MOTTLED_DRAGON, CE_POISONOUS, Z_BIG, S_SILENT, I_ANIMAL_LIKE,
@@ -1408,8 +1530,9 @@
{
MONS_EARTH_ELEMENTAL, '#', BROWN, "earth elemental",
- M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_RES_ELEC,
- 0, 10, MONS_EARTH_ELEMENTAL, MH_NONLIVING, 5000,
+ M_NO_FLAGS,
+ MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 10, MONS_EARTH_ELEMENTAL, MONS_EARTH_ELEMENTAL, MH_NONLIVING, MAG_IMMUNE,
{ 40, 0, 0, 0 },
{ 6, 5, 5, 0 },
14, 4, 6, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -1419,8 +1542,9 @@
{
MONS_FIRE_ELEMENTAL, '#', YELLOW, "fire elemental",
- M_RES_POISON | M_RES_HELLFIRE | M_ED_COLD | M_RES_ELEC | M_FLIES,
- 0, 10, MONS_FIRE_ELEMENTAL, MH_NONLIVING, 5000,
+ M_FLIES,
+ MR_RES_POISON | MR_RES_HELLFIRE | MR_VUL_COLD | MR_RES_ELEC,
+ 0, 10, MONS_EARTH_ELEMENTAL, MONS_FIRE_ELEMENTAL, MH_NONLIVING, MAG_IMMUNE,
{ 5, 0, 0, 0 },
{ 6, 3, 5, 0 },
4, 12, 13, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -1430,8 +1554,9 @@
{
MONS_AIR_ELEMENTAL, 'v', LIGHTGREY, "air elemental",
- M_RES_ELEC | M_RES_POISON | M_LEVITATE | M_SEE_INVIS | M_FLIES,
- 0, 5, MONS_AIR_ELEMENTAL, MH_NONLIVING, 5000,
+ M_LEVITATE | M_SEE_INVIS | M_FLIES,
+ MR_RES_ELEC | MR_RES_POISON,
+ 0, 5, MONS_EARTH_ELEMENTAL, MONS_AIR_ELEMENTAL, MH_NONLIVING, MAG_IMMUNE,
{ 15, 0, 0, 0 },
{ 6, 3, 5, 0 },
2, 18, 25, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -1443,8 +1568,9 @@
{
MONS_ICE_FIEND, '1', WHITE, "Ice Fiend",
- M_RES_POISON | M_ED_FIRE | M_RES_COLD | M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_FROZEN,
- 0, 10, MONS_ICE_FIEND, MH_DEMONIC, -12,
+ M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_FROZEN | M_EVIL,
+ MR_RES_POISON | MR_VUL_FIRE | MR_RES_COLD,
+ 0, 10, MONS_FIEND, MONS_ICE_FIEND, MH_DEMONIC, -12,
{ 25, 25, 0, 0 },
{ 18, 3, 5, 0 },
15, 6, 10, 7, MST_ICE_FIEND, CE_CONTAMINATED, Z_NOZOMBIE, S_ROAR, I_HIGH,
@@ -1454,8 +1580,9 @@
{
MONS_SHADOW_FIEND, '1', DARKGREY, "Shadow Fiend",
- M_RES_POISON | M_RES_COLD | M_RES_ELEC | M_SPELLCASTER | M_LEVITATE | M_SEE_INVIS,
- 0, 10, MONS_SHADOW_FIEND, MH_DEMONIC, -13,
+ M_SPELLCASTER | M_LEVITATE | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD | MR_RES_ELEC,
+ 0, 10, MONS_FIEND, MONS_SHADOW_FIEND, MH_DEMONIC, -13,
{ 25, 15, 15, 0 },
{ 18, 3, 5, 0 },
15, 6, 10, 7, MST_SHADOW_FIEND, CE_CONTAMINATED, Z_NOZOMBIE, S_ROAR, I_HIGH,
@@ -1465,8 +1592,9 @@
{
MONS_BROWN_SNAKE, 'S', BROWN, "brown snake",
- M_RES_POISON | M_COLD_BLOOD | M_AMPHIBIOUS,
- 300, 10, MONS_BROWN_SNAKE, MH_NATURAL, -3,
+ M_COLD_BLOOD | M_AMPHIBIOUS,
+ MR_RES_POISON,
+ 300, 10, MONS_SNAKE, MONS_BROWN_SNAKE, MH_NATURAL, -3,
{ 10, 0, 0, 0 },
{ 4, 3, 5, 0 },
2, 15, 14, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_HISS, I_REPTILE,
@@ -1477,7 +1605,8 @@
{
MONS_GIANT_LIZARD, 'l', GREEN, "giant lizard",
M_COLD_BLOOD,
- 600, 10, MONS_GIANT_LIZARD, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 600, 10, MONS_GIANT_LIZARD, MONS_GIANT_LIZARD, MH_NATURAL, -3,
{ 20, 0, 0, 0 },
{ 5, 3, 5, 0 },
4, 10, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_SILENT, I_REPTILE,
@@ -1487,8 +1616,9 @@
{
MONS_SPECTRAL_WARRIOR, 'W', LIGHTGREEN, "spectral warrior",
- M_RES_POISON | M_RES_COLD | M_LEVITATE | M_SEE_INVIS,
- 0, 13, MONS_SPECTRAL_WARRIOR, MH_UNDEAD, -6,
+ M_LEVITATE | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 13, MONS_WRAITH, MONS_SPECTRAL_WARRIOR, MH_UNDEAD, -6,
{ 18, 0, 0, 0 },
{ 9, 3, 5, 0 },
12, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SILENT, I_HIGH,
@@ -1498,8 +1628,9 @@
{
MONS_PULSATING_LUMP, 'J', RED, "pulsating lump",
- M_RES_POISON | M_SEE_INVIS,
- 0, 3, MONS_PULSATING_LUMP, MH_NATURAL, -3,
+ M_SEE_INVIS,
+ MR_RES_POISON | MR_RES_ASPHYX,
+ 0, 3, MONS_JELLY, MONS_PULSATING_LUMP, MH_NATURAL, -3,
{ 13, 0, 0, 0 },
{ 10, 3, 5, 0 },
2, 6, 5, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -1509,8 +1640,9 @@
{
MONS_STORM_DRAGON, 'D', LIGHTBLUE, "storm dragon",
- M_RES_ELEC | M_RES_COLD | M_SPELLCASTER | M_FLIES,
- 2800, 12, MONS_STORM_DRAGON, MH_NATURAL, -5,
+ M_SPELLCASTER | M_FLIES,
+ MR_RES_ELEC | MR_RES_COLD,
+ 2800, 12, MONS_DRAGON, MONS_STORM_DRAGON, MH_NATURAL, -5,
{ 25, 15, 15, 0 },
{ 14, 5, 5, 0 },
13, 10, 12, 7, MST_STORM_DRAGON, CE_CLEAN, Z_BIG, S_ROAR, I_NORMAL,
@@ -1521,7 +1653,8 @@
{
MONS_YAKTAUR, 'c', LIGHTRED, "yaktaur",
M_WARM_BLOOD,
- 2000, 10, MONS_YAKTAUR, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 2000, 10, MONS_YAKTAUR, MONS_YAKTAUR, MH_NATURAL, -3,
{ 15, 0, 0, 0 },
{ 8, 3, 5, 0 },
4, 4, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_BIG, S_SHOUT, I_NORMAL,
@@ -1531,8 +1664,9 @@
{
MONS_DEATH_YAK, 'Y', DARKGREY, "death yak",
- M_WARM_BLOOD,
- 1500, 10, MONS_DEATH_YAK, MH_NATURAL, -5,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 1500, 10, MONS_YAK, MONS_DEATH_YAK, MH_NATURAL, -5,
{ 30, 0, 0, 0 },
{ 14, 3, 5, 0 },
9, 5, 10, 7, MST_NO_SPELLS, CE_POISONOUS, Z_BIG, S_BELLOW, I_ANIMAL,
@@ -1542,8 +1676,9 @@
{
MONS_ROCK_TROLL, 'T', LIGHTGREY, "rock troll",
- M_WARM_BLOOD,
- 2200, 11, MONS_ROCK_TROLL, MH_NATURAL, -4,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 2200, 11, MONS_TROLL, MONS_ROCK_TROLL, MH_NATURAL, -4,
{ 30, 20, 20, 0 },
{ 11, 3, 5, 0 },
13, 6, 8, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_BIG, S_SHOUT, I_NORMAL,
@@ -1553,8 +1688,9 @@
{
MONS_STONE_GIANT, 'C', LIGHTGREY, "stone giant",
- M_WARM_BLOOD,
- 3000, 10, MONS_STONE_GIANT, MH_NATURAL, -4,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 3000, 10, MONS_HILL_GIANT, MONS_STONE_GIANT, MH_NATURAL, -4,
{ 45, 0, 0, 0 },
{ 16, 3, 5, 0 },
12, 2, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_BIG, S_SHOUT, I_NORMAL,
@@ -1564,8 +1700,9 @@
{
MONS_FLAYED_GHOST, 'p', RED, "flayed ghost",
- M_RES_POISON | M_FLIES,
- 0, 10, MONS_FLAYED_GHOST, MH_UNDEAD, -4,
+ M_FLIES | M_EVIL,
+ MR_RES_POISON,
+ 0, 10, MONS_PHANTOM, MONS_FLAYED_GHOST, MH_UNDEAD, -4,
{ 30, 0, 0, 0 },
{ 11, 3, 5, 0 },
0, 14, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -1575,8 +1712,9 @@
{
MONS_BUMBLEBEE, 'k', RED, "bumblebee",
- M_ED_POISON | M_FLIES,
- 300, 10, MONS_BUMBLEBEE, MH_NATURAL, -3,
+ M_FLIES,
+ MR_VUL_POISON,
+ 300, 10, MONS_KILLER_BEE, MONS_BUMBLEBEE, MH_NATURAL, -3,
{ 20, 0, 0, 0 },
{ 7, 3, 5, 0 },
4, 15, 10, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_BUZZ, I_INSECT,
@@ -1586,8 +1724,9 @@
{
MONS_REDBACK, 's', RED, "redback",
- M_ED_POISON,
- 1000, 14, MONS_REDBACK, MH_NATURAL, -3,
+ M_NO_FLAGS,
+ MR_VUL_POISON,
+ 1000, 14, MONS_WOLF_SPIDER, MONS_REDBACK, MH_NATURAL, -3,
{ 18, 0, 0, 0 },
{ 6, 3, 5, 0 },
2, 12, 15, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_SILENT, I_INSECT,
@@ -1597,8 +1736,9 @@
{
MONS_INSUBSTANTIAL_WISP, 'p', LIGHTGREY, "insubstantial wisp",
- M_RES_ELEC | M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_LEVITATE,
- 0, 17, MONS_INSUBSTANTIAL_WISP, MH_NONLIVING, 5000,
+ M_LEVITATE | M_SPECIAL_ABILITY,
+ MR_RES_ELEC | MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD,
+ 0, 17, MONS_INSUBSTANTIAL_WISP, MONS_INSUBSTANTIAL_WISP, MH_NONLIVING, MAG_IMMUNE,
{ 12, 0, 0, 0 },
{ 6, 1, 2, 0 },
20, 20, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_MOAN, I_PLANT,
@@ -1608,8 +1748,9 @@
{
MONS_VAPOUR, '#', LIGHTGREY, "vapour",
- M_RES_ELEC | M_RES_POISON | M_SPELLCASTER | M_LEVITATE | M_SEE_INVIS | M_INVIS | M_CONFUSED,
- 0, 21, MONS_VAPOUR, MH_NONLIVING, 5000,
+ M_SPELLCASTER | M_LEVITATE | M_SEE_INVIS | M_INVIS | M_CONFUSED,
+ MR_RES_ELEC | MR_RES_POISON,
+ 0, 21, MONS_VAPOUR, MONS_VAPOUR, MH_NONLIVING, MAG_IMMUNE,
{ 0, 0, 0, 0 },
{ 12, 2, 3, 0 },
0, 12, 10, 7, MST_STORM_DRAGON, CE_CONTAMINATED, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -1619,8 +1760,9 @@
{
MONS_OGRE_MAGE, 'O', MAGENTA, "ogre-mage",
- M_RES_ELEC | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_WARM_BLOOD,
- 0, 16, MONS_OGRE, MH_NATURAL, -6,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_WARM_BLOOD | M_EVIL,
+ MR_RES_ELEC,
+ 0, 16, MONS_OGRE, MONS_OGRE, MH_NATURAL, -6,
{ 12, 0, 0, 0 },
{ 10, 3, 5, 0 },
1, 7, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_BIG, S_SHOUT, I_HIGH,
@@ -1630,8 +1772,9 @@
{
MONS_SPINY_WORM, 'w', DARKGREY, "spiny worm",
- M_ED_POISON,
- 1300, 13, MONS_SPINY_WORM, MH_NATURAL, -3,
+ M_NO_FLAGS,
+ MR_VUL_POISON,
+ 1300, 13, MONS_WORM, MONS_SPINY_WORM, MH_NATURAL, -3,
{ 32, 0, 0, 0 },
{ 12, 3, 5, 0 },
10, 6, 9, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_SILENT, I_PLANT,
@@ -1643,8 +1786,9 @@
// to examine them.
{
MONS_DANCING_WEAPON, '(', BLACK, "dancing weapon",
- M_RES_POISON | M_RES_HELLFIRE | M_RES_COLD | M_RES_ELEC | M_LEVITATE,
- 0, 10, MONS_DANCING_WEAPON, MH_NONLIVING, 5000,
+ M_LEVITATE,
+ MR_RES_POISON | MR_RES_HELLFIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 10, MONS_DANCING_WEAPON, MONS_DANCING_WEAPON, MH_NONLIVING, MAG_IMMUNE,
{ 30, 0, 0, 0 },
{ 15, 0, 0, 15 },
10, 20, 15, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -1654,8 +1798,9 @@
{
MONS_TITAN, 'C', MAGENTA, "titan",
- M_RES_ELEC | M_SPELLCASTER | M_WARM_BLOOD | M_SEE_INVIS,
- 3500, 12, MONS_TITAN, MH_NATURAL, -7,
+ M_SPELLCASTER | M_WARM_BLOOD | M_SEE_INVIS | M_EVIL,
+ MR_RES_ELEC,
+ 3500, 12, MONS_HILL_GIANT, MONS_TITAN, MH_NATURAL, -7,
{ 55, 0, 0, 0 },
{ 20, 3, 5, 0 },
10, 3, 10, 7, MST_TITAN, CE_CLEAN, Z_BIG, S_SHOUT, I_HIGH,
@@ -1665,8 +1810,9 @@
{
MONS_GOLDEN_DRAGON, 'D', YELLOW, "golden dragon",
- M_RES_ELEC | M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_SPELLCASTER | M_FLIES | M_SEE_INVIS,
- 3000, 17, MONS_GOLDEN_DRAGON, MH_NATURAL, -8,
+ M_SPELLCASTER | M_FLIES | M_SEE_INVIS,
+ MR_RES_ELEC | MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD,
+ 3000, 17, MONS_DRAGON, MONS_GOLDEN_DRAGON, MH_NATURAL, -8,
{ 40, 20, 20, 0 },
{ 18, 4, 4, 0 },
15, 7, 10, 7, MST_GOLDEN_DRAGON, CE_POISONOUS, Z_BIG, S_ROAR, I_HIGH,
@@ -1679,10 +1825,11 @@
{
MONS_ELF, 'e', DARKGREY, "elf",
M_WARM_BLOOD,
- 450, 10, MONS_ELF, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -3,
{ 10, 0, 0, 0 },
{ 3, 3, 3, 0 },
- 0, 12, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SILENT, I_PLANT,
+ 0, 12, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SILENT, I_NORMAL,
MONUSE_WEAPONS_ARMOUR
}
,
@@ -1693,8 +1840,9 @@
// more intuitively know that this isn't a regular lizard. -- bwr
{
MONS_LINDWURM, 'd', LIGHTGREEN, "lindwurm",
- M_NO_FLAGS,
- 1000, 11, MONS_LINDWURM, MH_NATURAL, -3,
+ M_SPECIAL_ABILITY,
+ MR_NO_FLAGS,
+ 1000, 11, MONS_DRAGON, MONS_LINDWURM, MH_NATURAL, -3,
{ 20, 10, 10, 0 },
{ 9, 3, 5, 0 },
8, 6, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_BIG, S_ROAR, I_REPTILE,
@@ -1704,8 +1852,9 @@
{
MONS_ELEPHANT_SLUG, 'm', LIGHTGREY, "elephant slug",
- M_ED_POISON | M_NO_SKELETON,
- 1500, 10, MONS_ELEPHANT_SLUG, MH_NATURAL, -3,
+ M_NO_SKELETON,
+ MR_VUL_POISON,
+ 1500, 10, MONS_GIANT_SLUG, MONS_ELEPHANT_SLUG, MH_NATURAL, -3,
{ 40, 0, 0, 0 },
{ 20, 5, 3, 0 },
2, 1, 4, 10, MST_NO_SPELLS, CE_POISONOUS, Z_BIG, S_SILENT, I_INSECT,
@@ -1716,7 +1865,8 @@
{
MONS_WAR_DOG, 'h', CYAN, "war dog",
M_SEE_INVIS | M_WARM_BLOOD,
- 350, 10, MONS_WAR_DOG, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 350, 10, MONS_HOUND, MONS_WAR_DOG, MH_NATURAL, -3,
{ 12, 0, 0, 0 },
{ 4, 3, 5, 0 },
4, 15, 17, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_BARK, I_ANIMAL,
@@ -1727,7 +1877,8 @@
{
MONS_GREY_RAT, 'r', LIGHTGREY, "grey rat",
M_WARM_BLOOD,
- 250, 10, MONS_GREY_RAT, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 250, 10, MONS_RAT, MONS_GREY_RAT, MH_NATURAL, -3,
{ 5, 0, 0, 0 },
{ 1, 3, 6, 0 },
2, 12, 12, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SILENT, I_ANIMAL,
@@ -1738,7 +1889,8 @@
{
MONS_GREEN_RAT, 'r', LIGHTGREEN, "green rat",
M_WARM_BLOOD,
- 250, 10, MONS_GREEN_RAT, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 250, 10, MONS_RAT, MONS_GREEN_RAT, MH_NATURAL, -3,
{ 10, 0, 0, 0 },
{ 2, 3, 5, 0 },
5, 11, 10, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_SILENT, I_ANIMAL,
@@ -1749,7 +1901,8 @@
{
MONS_ORANGE_RAT, 'r', LIGHTRED, "orange rat",
M_WARM_BLOOD,
- 250, 10, MONS_ORANGE_RAT, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 250, 10, MONS_RAT, MONS_ORANGE_RAT, MH_NATURAL, -3,
{ 20, 0, 0, 0 },
{ 3, 3, 5, 0 },
7, 10, 12, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_ROAR, I_ANIMAL,
@@ -1759,8 +1912,9 @@
{
MONS_BLACK_SNAKE, 'S', DARKGREY, "black snake",
- M_RES_POISON | M_COLD_BLOOD,
- 500, 12, MONS_BLACK_SNAKE, MH_NATURAL, -3,
+ M_COLD_BLOOD,
+ MR_RES_POISON,
+ 500, 12, MONS_SNAKE, MONS_BLACK_SNAKE, MH_NATURAL, -3,
{ 20, 0, 0, 0 },
{ 7, 3, 5, 0 },
4, 15, 18, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_HISS, I_REPTILE,
@@ -1771,7 +1925,8 @@
{
MONS_SHEEP, 'Y', LIGHTGREY, "sheep",
M_WARM_BLOOD,
- 1200, 10, MONS_SHEEP, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 1200, 10, MONS_SHEEP, MONS_SHEEP, MH_NATURAL, -3,
{ 13, 0, 0, 0 },
{ 3, 3, 5, 0 },
2, 7, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_BELLOW, I_ANIMAL,
@@ -1781,8 +1936,9 @@
{
MONS_GHOUL, 'n', RED, "ghoul",
- M_RES_POISON | M_RES_COLD,
- 500, 12, MONS_GHOUL, MH_UNDEAD, -5,
+ M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 500, 12, MONS_GHOUL, MONS_GHOUL, MH_UNDEAD, -5,
{ 9, 0, 0, 0 },
{ 4, 3, 5, 0 },
4, 10, 10, 7, MST_NO_SPELLS, CE_HCL, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -1793,7 +1949,8 @@
{
MONS_HOG, 'h', LIGHTRED, "hog",
M_WARM_BLOOD,
- 700, 10, MONS_HOG, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 700, 10, MONS_HOG, MONS_HOG, MH_NATURAL, -3,
{ 14, 0, 0, 0 },
{ 6, 3, 5, 0 },
2, 9, 13, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_SILENT, I_ANIMAL,
@@ -1803,8 +1960,9 @@
{
MONS_GIANT_MOSQUITO, 'y', DARKGREY, "giant mosquito",
- M_ED_POISON | M_FLIES,
- 100, 10, MONS_GIANT_MOSQUITO, MH_NATURAL, -3,
+ M_FLIES,
+ MR_VUL_POISON,
+ 100, 10, MONS_GIANT_MOSQUITO, MONS_GIANT_MOSQUITO, MH_NATURAL, -3,
{ 10, 0, 0, 0 },
{ 1, 3, 5, 0 },
0, 13, 12, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_WHINE, I_PLANT,
@@ -1814,8 +1972,9 @@
{
MONS_GIANT_CENTIPEDE, 's', GREEN, "giant centipede",
- M_ED_POISON,
- 350, 10, MONS_GIANT_CENTIPEDE, MH_NATURAL, -3,
+ M_NO_FLAGS,
+ MR_VUL_POISON,
+ 350, 10, MONS_GIANT_CENTIPEDE, MONS_GIANT_CENTIPEDE, MH_NATURAL, -3,
{ 2, 0, 0, 0 },
{ 2, 3, 3, 0 },
2, 14, 13, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_SILENT, I_INSECT,
@@ -1827,8 +1986,9 @@
{
MONS_IRON_TROLL, 'T', CYAN, "iron troll",
- M_RES_FIRE | M_RES_COLD | M_WARM_BLOOD,
- 2400, 10, MONS_IRON_TROLL, MH_NATURAL, -5,
+ M_WARM_BLOOD | M_EVIL,
+ MR_RES_FIRE | MR_RES_COLD,
+ 2400, 10, MONS_TROLL, MONS_IRON_TROLL, MH_NATURAL, -5,
{ 35, 25, 25, 0 },
{ 16, 3, 5, 0 },
20, 4, 7, 7, MST_NO_SPELLS, CE_POISONOUS, Z_BIG, S_ROAR, I_NORMAL,
@@ -1838,9 +1998,10 @@
{
MONS_NAGA, 'N', GREEN, "naga",
- M_RES_POISON | M_SPELLCASTER | M_SEE_INVIS | M_WARM_BLOOD,
- 750, 10, MONS_NAGA, MH_NATURAL, -6,
- { 6, 0, 0, 0 },
+ M_SPELLCASTER | M_SEE_INVIS | M_WARM_BLOOD,
+ MR_RES_POISON,
+ 750, 10, MONS_NAGA, MONS_NAGA, MH_NATURAL, -6,
+ { 13, 0, 0, 0 },
{ 5, 3, 5, 0 },
6, 10, 8, 7, MST_NAGA, CE_POISONOUS, Z_SMALL, S_SHOUT, I_NORMAL,
MONUSE_WEAPONS_ARMOUR
@@ -1849,8 +2010,9 @@
{
MONS_FIRE_GIANT, 'C', RED, "fire giant",
- M_RES_FIRE | M_SPELLCASTER | M_WARM_BLOOD | M_SEE_INVIS,
- 2400, 11, MONS_FIRE_GIANT, MH_NATURAL, -4,
+ M_SPELLCASTER | M_WARM_BLOOD | M_SEE_INVIS | M_EVIL,
+ MR_RES_FIRE,
+ 2400, 11, MONS_HILL_GIANT, MONS_FIRE_GIANT, MH_NATURAL, -4,
{ 30, 0, 0, 0 },
{ 16, 3, 6, 0 },
8, 4, 10, 7, MST_EFREET, CE_CONTAMINATED, Z_BIG, S_SHOUT, I_NORMAL,
@@ -1860,8 +2022,9 @@
{
MONS_FROST_GIANT, 'C', LIGHTBLUE, "frost giant",
- M_RES_COLD | M_SPELLCASTER | M_WARM_BLOOD | M_SEE_INVIS,
- 2600, 11, MONS_FROST_GIANT, MH_NATURAL, -4,
+ M_SPELLCASTER | M_WARM_BLOOD | M_SEE_INVIS | M_EVIL,
+ MR_RES_COLD,
+ 2600, 11, MONS_HILL_GIANT, MONS_FROST_GIANT, MH_NATURAL, -4,
{ 35, 0, 0, 0 },
{ 16, 4, 5, 0 },
9, 3, 10, 7, MST_FROST_GIANT, CE_CONTAMINATED, Z_BIG, S_SHOUT, I_NORMAL,
@@ -1870,9 +2033,10 @@
,
{
- MONS_FIREDRAKE, 'd', RED, "firedrake",
- M_RES_FIRE | M_FLIES,
- 900, 10, MONS_FIREDRAKE, MH_NATURAL, -3,
+ MONS_FIREDRAKE, 'l', RED, "firedrake",
+ M_FLIES | M_SPECIAL_ABILITY,
+ MR_RES_FIRE,
+ 900, 10, MONS_FIREDRAKE, MONS_FIREDRAKE, MH_NATURAL, -3,
{ 8, 0, 0, 0 },
{ 6, 3, 5, 0 },
3, 12, 12, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SILENT, I_ANIMAL,
@@ -1882,8 +2046,9 @@
{
MONS_SHADOW_DRAGON, 'D', DARKGREY, "shadow dragon",
- M_RES_POISON | M_RES_COLD | M_SPELLCASTER | M_FLIES | M_SEE_INVIS,
- 2000, 12, MONS_SHADOW_DRAGON, MH_NATURAL, -5,
+ M_SPELLCASTER | M_FLIES | M_SEE_INVIS,
+ MR_RES_POISON | MR_RES_COLD,
+ 2000, 12, MONS_DRAGON, MONS_SHADOW_DRAGON, MH_NATURAL, -5,
{ 20, 15, 15, 0 },
{ 17, 5, 5, 0 },
15, 10, 10, 7, MST_SHADOW_DRAGON, CE_CLEAN, Z_BIG, S_ROAR, I_HIGH,
@@ -1892,8 +2057,9 @@
,
{
MONS_YELLOW_SNAKE, 'S', YELLOW, "yellow snake",
- M_RES_POISON | M_COLD_BLOOD,
- 400, 10, MONS_YELLOW_SNAKE, MH_NATURAL, -3,
+ M_COLD_BLOOD,
+ MR_RES_POISON,
+ 400, 10, MONS_SNAKE, MONS_YELLOW_SNAKE, MH_NATURAL, -3,
{ 15, 0, 0, 0 },
{ 6, 3, 5, 0 },
4, 14, 13, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_HISS, I_REPTILE,
@@ -1904,7 +2070,8 @@
{
MONS_GREY_SNAKE, 'S', LIGHTGREY, "grey snake",
M_COLD_BLOOD,
- 600, 10, MONS_GREY_SNAKE, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 600, 10, MONS_SNAKE, MONS_GREY_SNAKE, MH_NATURAL, -3,
{ 30, 0, 0, 0 },
{ 11, 3, 5, 0 },
4, 16, 18, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_HISS, I_REPTILE,
@@ -1914,8 +2081,9 @@
{
MONS_DEEP_TROLL, 'T', DARKGREY, "deep troll",
- M_WARM_BLOOD | M_SEE_INVIS,
- 1500, 12, MONS_DEEP_TROLL, MH_NATURAL, -3,
+ M_WARM_BLOOD | M_SEE_INVIS | M_EVIL,
+ MR_NO_FLAGS,
+ 1500, 12, MONS_TROLL, MONS_DEEP_TROLL, MH_NATURAL, -3,
{ 27, 20, 20, 0 },
{ 10, 3, 5, 0 },
6, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_BIG, S_SHOUT, I_NORMAL,
@@ -1925,8 +2093,9 @@
{
MONS_GIANT_BLOWFLY, 'y', LIGHTGREY, "giant blowfly",
- M_ED_POISON | M_FLIES,
- 200, 10, MONS_GIANT_BLOWFLY, MH_NATURAL, -3,
+ M_FLIES,
+ MR_VUL_POISON,
+ 200, 10, MONS_GIANT_BLOWFLY, MONS_GIANT_BLOWFLY, MH_NATURAL, -3,
{ 13, 0, 0, 0 },
{ 5, 3, 5, 0 },
2, 15, 19, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_BUZZ, I_PLANT,
@@ -1936,8 +2105,9 @@
{
MONS_RED_WASP, 'y', RED, "red wasp",
- M_ED_POISON | M_FLIES,
- 400, 14, MONS_RED_WASP, MH_NATURAL, -3,
+ M_FLIES,
+ MR_VUL_POISON,
+ 400, 14, MONS_YELLOW_WASP, MONS_RED_WASP, MH_NATURAL, -3,
{ 23, 0, 0, 0 },
{ 8, 3, 5, 0 },
7, 14, 15, 7, MST_NO_SPELLS, CE_POISONOUS, Z_NOZOMBIE, S_BUZZ, I_PLANT,
@@ -1947,9 +2117,10 @@
{
MONS_SWAMP_DRAGON, 'D', BROWN, "swamp dragon",
- M_SPELLCASTER | M_FLIES | M_RES_POISON,
- 1900, 11, MONS_SWAMP_DRAGON, MH_NATURAL, -3,
- { 13, 9, 9, 0 },
+ M_SPELLCASTER | M_FLIES,
+ MR_RES_POISON,
+ 1900, 11, MONS_DRAGON, MONS_SWAMP_DRAGON, MH_NATURAL, -3,
+ { 18, 9, 9, 0 },
{ 9, 5, 5, 0 },
7, 7, 10, 7, MST_SWAMP_DRAGON, CE_CONTAMINATED, Z_BIG, S_ROAR, I_ANIMAL_LIKE,
MONUSE_OPEN_DOORS
@@ -1957,10 +2128,11 @@
,
{
- MONS_SWAMP_DRAKE, 'd', BROWN, "swamp drake",
- M_SPELLCASTER | M_FLIES | M_RES_POISON,
- 900, 11, MONS_SWAMP_DRAKE, MH_NATURAL, -3,
- { 11, 0, 0, 0 },
+ MONS_SWAMP_DRAKE, 'l', BROWN, "swamp drake",
+ M_SPELLCASTER | M_FLIES | M_EVIL,
+ MR_RES_POISON,
+ 900, 11, MONS_DRAGON, MONS_SWAMP_DRAKE, MH_NATURAL, -3,
+ { 14, 0, 0, 0 },
{ 4, 5, 5, 0 },
3, 11, 11, 7, MST_SWAMP_DRAKE, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_ANIMAL_LIKE,
MONUSE_OPEN_DOORS
@@ -1968,9 +2140,22 @@
,
{
+ MONS_DEATH_DRAKE, 'l', DARKGREY, "death drake",
+ M_SPELLCASTER | M_FLIES | M_EVIL,
+ MR_RES_POISON,
+ 900, 11, MONS_DRAGON, MONS_DEATH_DRAKE, MH_NATURAL, -3,
+ { 12, 0, 0, 0 },
+ { 9, 5, 7, 0 },
+ 6, 14, 13, 10, MST_DEATH_DRAKE, CE_HCL, Z_BIG, S_ROAR, I_ANIMAL_LIKE,
+ MONUSE_OPEN_DOORS
+}
+,
+
+{
MONS_SOLDIER_ANT, 'a', LIGHTGREY, "soldier ant",
- M_ED_POISON,
- 900, 10, MONS_SOLDIER_ANT, MH_NATURAL, -3,
+ M_NO_FLAGS,
+ MR_VUL_POISON,
+ 900, 10, MONS_GIANT_ANT, MONS_SOLDIER_ANT, MH_NATURAL, -3,
{ 14, 0, 0, 0 },
{ 6, 3, 5, 0 },
8, 10, 10, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_SILENT, I_INSECT,
@@ -1980,8 +2165,9 @@
{
MONS_HILL_GIANT, 'C', LIGHTRED, "hill giant",
- M_WARM_BLOOD,
- 1600, 10, MONS_HILL_GIANT, MH_NATURAL, -3,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 1600, 10, MONS_HILL_GIANT, MONS_HILL_GIANT, MH_NATURAL, -3,
{ 30, 0, 0, 0 },
{ 11, 3, 5, 0 },
3, 4, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_BIG, S_SHOUT, I_NORMAL,
@@ -1991,8 +2177,9 @@
{
MONS_QUEEN_ANT, 'Q', DARKGREY, "queen ant",
- M_ED_POISON,
- 1200, 10, MONS_QUEEN_ANT, MH_NATURAL, -3,
+ M_NO_FLAGS,
+ MR_VUL_POISON,
+ 1200, 10, MONS_GIANT_ANT, MONS_QUEEN_ANT, MH_NATURAL, -3,
{ 20, 0, 0, 0 },
{ 13, 3, 5, 0 },
14, 3, 7, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_SILENT, I_INSECT,
@@ -2002,8 +2189,9 @@
{
MONS_ANT_LARVA, 'w', LIGHTGREY, "ant larva",
- M_ED_POISON | M_NO_SKELETON,
- 350, 5, MONS_ANT_LARVA, MH_NATURAL, -3,
+ M_NO_SKELETON,
+ MR_VUL_POISON,
+ 350, 5, MONS_GIANT_ANT, MONS_ANT_LARVA, MH_NATURAL, -3,
{ 5, 0, 0, 0 },
{ 2, 3, 5, 0 },
2, 6, 6, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_SILENT, I_INSECT,
@@ -2015,7 +2203,8 @@
{
MONS_GIANT_FROG, 'F', GREEN, "giant frog",
M_COLD_BLOOD | M_AMPHIBIOUS,
- 500, 10, MONS_GIANT_FROG, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 500, 10, MONS_GIANT_FROG, MONS_GIANT_FROG, MH_NATURAL, -3,
{ 9, 0, 0, 0 },
{ 4, 3, 5, 0 },
0, 12, 15, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_CROAK, I_ANIMAL,
@@ -2026,7 +2215,8 @@
{
MONS_GIANT_BROWN_FROG, 'F', BROWN, "giant brown frog",
M_COLD_BLOOD | M_AMPHIBIOUS,
- 890, 10, MONS_GIANT_BROWN_FROG, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 890, 10, MONS_GIANT_FROG, MONS_GIANT_BROWN_FROG, MH_NATURAL, -3,
{ 14, 0, 0, 0 },
{ 8, 3, 5, 0 },
2, 11, 13, 7, MST_NO_SPELLS, CE_CLEAN, Z_BIG, S_CROAK, I_ANIMAL,
@@ -2036,8 +2226,9 @@
{
MONS_SPINY_FROG, 'F', YELLOW, "spiny frog",
- M_COLD_BLOOD | M_RES_POISON | M_AMPHIBIOUS,
- 1000, 10, MONS_SPINY_FROG, MH_NATURAL, -3,
+ M_COLD_BLOOD | M_AMPHIBIOUS,
+ MR_RES_POISON,
+ 1000, 10, MONS_GIANT_FROG, MONS_SPINY_FROG, MH_NATURAL, -3,
{ 26, 0, 0, 0 },
{ 7, 3, 5, 0 },
6, 9, 12, 7, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_CROAK, I_ANIMAL,
@@ -2047,8 +2238,9 @@
{
MONS_BLINK_FROG, 'F', LIGHTGREEN, "blink frog",
- M_COLD_BLOOD | M_AMPHIBIOUS,
- 800, 12, MONS_BLINK_FROG, MH_NATURAL, -5,
+ M_COLD_BLOOD | M_AMPHIBIOUS | M_SPECIAL_ABILITY,
+ MR_NO_FLAGS,
+ 800, 12, MONS_GIANT_FROG, MONS_BLINK_FROG, MH_NATURAL, -5,
{ 20, 0, 0, 0 },
{ 6, 3, 5, 0 },
3, 12, 14, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_CROAK, I_ANIMAL,
@@ -2058,7 +2250,8 @@
{
MONS_GIANT_COCKROACH, 'a', BROWN, "giant cockroach",
M_NO_FLAGS,
- 250, 10, MONS_GIANT_COCKROACH, MH_NATURAL, -1,
+ MR_NO_FLAGS,
+ 250, 10, MONS_GIANT_COCKROACH, MONS_GIANT_COCKROACH, MH_NATURAL, -1,
{ 2, 0, 0, 0 },
{ 1, 3, 4, 0 },
3, 10, 12, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SILENT, I_INSECT,
@@ -2068,7 +2261,8 @@
{
MONS_SMALL_SNAKE, 'S', LIGHTGREEN, "small snake",
M_COLD_BLOOD,
- 100, 13, MONS_SMALL_SNAKE, MH_NATURAL, -1,
+ MR_NO_FLAGS,
+ 100, 13, MONS_SNAKE, MONS_SMALL_SNAKE, MH_NATURAL, -1,
{ 2, 0, 0, 0 },
{ 1, 2, 3, 0 },
0, 11, 12, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_SILENT, I_REPTILE,
@@ -2078,8 +2272,9 @@
{
MONS_WHITE_IMP, '5', WHITE, "white imp",
- M_RES_COLD | M_SPELLCASTER | M_FLIES | M_SPEAKS,
- 0, 10, MONS_WHITE_IMP, MH_DEMONIC, -3,
+ M_SPELLCASTER | M_FLIES | M_SPEAKS | M_EVIL,
+ MR_RES_COLD,
+ 0, 10, MONS_IMP, MONS_WHITE_IMP, MH_DEMONIC, -3,
{ 4, 0, 0, 0 },
{ 2, 3, 5, 0 },
4, 10, 10, 7, MST_WHITE_IMP, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL,
@@ -2089,8 +2284,9 @@
{
MONS_LEMURE, '5', YELLOW, "lemure",
- M_RES_POISON,
- 0, 10, MONS_LEMURE, MH_DEMONIC, -3,
+ M_EVIL,
+ MR_RES_POISON,
+ 0, 10, MONS_LEMURE, MONS_LEMURE, MH_DEMONIC, -3,
{ 12, 0, 0, 0 },
{ 2, 3, 5, 0 },
1, 12, 12, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_MOAN, I_NORMAL,
@@ -2100,8 +2296,9 @@
{
MONS_UFETUBUS, '5', LIGHTCYAN, "ufetubus",
- M_ED_FIRE | M_RES_COLD,
- 0, 10, MONS_UFETUBUS, MH_DEMONIC, -3,
+ M_EVIL,
+ MR_VUL_FIRE | MR_RES_COLD,
+ 0, 10, MONS_UFETUBUS, MONS_UFETUBUS, MH_DEMONIC, -3,
{ 5, 5, 0, 0 },
{ 1, 4, 6, 0 },
2, 15, 15, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL,
@@ -2111,8 +2308,9 @@
{
MONS_MANES, '5', LIGHTRED, "manes",
- M_RES_ELEC | M_RES_FIRE | M_RES_COLD | M_RES_POISON,
- 0, 10, MONS_MANES, MH_DEMONIC, -3,
+ M_EVIL,
+ MR_RES_ELEC | MR_RES_FIRE | MR_RES_COLD | MR_RES_POISON,
+ 0, 10, MONS_MANES, MONS_MANES, MH_DEMONIC, -3,
{ 5, 3, 3, 0 },
{ 3, 3, 5, 0 },
2, 8, 8, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL,
@@ -2122,8 +2320,9 @@
{
MONS_MIDGE, '5', LIGHTGREEN, "midge",
- M_RES_POISON | M_FLIES,
- 0, 10, MONS_MIDGE, MH_DEMONIC, -3,
+ M_FLIES | M_EVIL,
+ MR_RES_POISON,
+ 0, 10, MONS_MIDGE, MONS_MIDGE, MH_DEMONIC, -3,
{ 8, 0, 0, 0 },
{ 2, 3, 5, 0 },
4, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL,
@@ -2133,8 +2332,9 @@
{
MONS_NEQOXEC, '3', MAGENTA, "neqoxec",
- M_RES_POISON | M_SPELLCASTER | M_LEVITATE,
- 0, 12, MONS_NEQOXEC, MH_DEMONIC, -6,
+ M_SPELLCASTER | M_LEVITATE | M_EVIL,
+ MR_RES_POISON,
+ 0, 12, MONS_NEQOXEC, MONS_NEQOXEC, MH_DEMONIC, -6,
{ 15, 0, 0, 0 },
{ 6, 3, 5, 0 },
4, 12, 10, 7, MST_NEQOXEC, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL,
@@ -2144,8 +2344,9 @@
{
MONS_ORANGE_DEMON, '3', LIGHTRED, "orange demon",
- M_NO_FLAGS,
- 0, 12, MONS_ORANGE_DEMON, MH_DEMONIC, -6,
+ M_EVIL,
+ MR_NO_FLAGS,
+ 0, 12, MONS_ORANGE_DEMON, MONS_ORANGE_DEMON, MH_DEMONIC, -6,
{ 10, 5, 0, 0 },
{ 8, 4, 5, 0 },
3, 7, 7, 7, MST_NO_SPELLS, CE_POISONOUS, Z_NOZOMBIE, S_SCREECH, I_NORMAL,
@@ -2155,8 +2356,9 @@
{
MONS_HELLWING, '3', LIGHTGREY, "hellwing",
- M_RES_POISON | M_SPELLCASTER | M_FLIES,
- 0, 12, MONS_HELLWING, MH_DEMONIC, -6,
+ M_SPELLCASTER | M_FLIES | M_EVIL,
+ MR_RES_POISON,
+ 0, 12, MONS_HELLWING, MONS_HELLWING, MH_DEMONIC, -6,
{ 17, 10, 0, 0 },
{ 7, 4, 5, 0 },
8, 10, 10, 7, MST_HELLWING, CE_CONTAMINATED, Z_NOZOMBIE, S_MOAN, I_NORMAL,
@@ -2166,8 +2368,9 @@
{
MONS_SMOKE_DEMON, '4', LIGHTGREY, "smoke demon",
- M_RES_POISON | M_RES_FIRE | M_SPELLCASTER | M_FLIES,
- 0, 12, MONS_SMOKE_DEMON, MH_DEMONIC, -6,
+ M_SPELLCASTER | M_FLIES | M_EVIL,
+ MR_RES_POISON | MR_RES_FIRE,
+ 0, 12, MONS_SMOKE_DEMON, MONS_SMOKE_DEMON, MH_DEMONIC, -6,
{ 8, 5, 5, 0 },
{ 7, 3, 5, 0 },
5, 9, 9, 7, MST_SMOKE_DEMON, CE_CONTAMINATED, Z_NOZOMBIE, S_ROAR, I_NORMAL,
@@ -2177,8 +2380,9 @@
{
MONS_YNOXINUL, '3', CYAN, "ynoxinul",
- M_RES_ELEC | M_RES_POISON | M_RES_COLD | M_SPELLCASTER | M_FLIES | M_SEE_INVIS,
- 0, 12, MONS_YNOXINUL, MH_DEMONIC, -6,
+ M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_EVIL,
+ MR_RES_ELEC | MR_RES_POISON | MR_RES_COLD,
+ 0, 12, MONS_YNOXINUL, MONS_YNOXINUL, MH_DEMONIC, -6,
{ 12, 0, 0, 0 },
{ 6, 3, 5, 0 },
3, 10, 10, 7, MST_YNOXINUL, CE_CONTAMINATED, Z_NOZOMBIE, S_BELLOW, I_NORMAL,
@@ -2188,8 +2392,9 @@
{
MONS_EXECUTIONER, '1', LIGHTGREY, "Executioner",
- M_SPELLCASTER | M_RES_ELEC | M_RES_FIRE | M_RES_COLD | M_RES_POISON | M_SEE_INVIS,
- 0, 14, MONS_EXECUTIONER, MH_DEMONIC, -9,
+ M_SPELLCASTER | M_SEE_INVIS | M_EVIL,
+ MR_RES_ELEC | MR_RES_FIRE | MR_RES_COLD | MR_RES_POISON,
+ 0, 14, MONS_EXECUTIONER, MONS_EXECUTIONER, MH_DEMONIC, -9,
{ 30, 10, 10, 0 },
{ 12, 3, 5, 0 },
10, 15, 20, 7, MST_HELL_KNIGHT_I, CE_CONTAMINATED, Z_NOZOMBIE, S_SCREAM, I_HIGH,
@@ -2199,8 +2404,9 @@
{
MONS_GREEN_DEATH, '1', GREEN, "Green Death",
- M_RES_POISON | M_SPELLCASTER | M_SEE_INVIS,
- 0, 14, MONS_GREEN_DEATH, MH_DEMONIC, -9,
+ M_SPELLCASTER | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON,
+ 0, 14, MONS_GREEN_DEATH, MONS_GREEN_DEATH, MH_DEMONIC, -9,
{ 32, 0, 0, 0 },
{ 13, 3, 5, 0 },
5, 7, 12, 7, MST_GREEN_DEATH, CE_POISONOUS, Z_NOZOMBIE, S_ROAR, I_HIGH,
@@ -2210,8 +2416,9 @@
{
MONS_BLUE_DEATH, '1', BLUE, "Blue Death",
- M_RES_POISON | M_SPELLCASTER | M_ED_FIRE | M_RES_COLD | M_RES_ELEC | M_FLIES | M_SEE_INVIS,
- 0, 14, MONS_BLUE_DEATH, MH_DEMONIC, -9,
+ M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_VUL_FIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 14, MONS_BLUE_DEATH, MONS_BLUE_DEATH, MH_DEMONIC, -9,
{ 20, 20, 0, 0 },
{ 12, 3, 5, 0 },
10, 10, 12, 7, MST_BLUE_DEATH, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_HIGH,
@@ -2221,8 +2428,9 @@
{
MONS_BALRUG, '1', RED, "Balrug",
- M_RES_POISON | M_RES_HELLFIRE | M_ED_COLD | M_SPELLCASTER | M_FLIES | M_SEE_INVIS,
- 0, 14, MONS_BALRUG, MH_DEMONIC, -9,
+ M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_HELLFIRE | MR_VUL_COLD,
+ 0, 14, MONS_BALRUG, MONS_BALRUG, MH_DEMONIC, -9,
{ 25, 0, 0, 0 },
{ 14, 3, 5, 0 },
5, 12, 12, 7, MST_BALRUG, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_HIGH,
@@ -2232,8 +2440,9 @@
{
MONS_CACODEMON, '1', YELLOW, "Cacodemon",
- M_RES_POISON | M_RES_ELEC | M_SPELLCASTER | M_LEVITATE | M_SEE_INVIS,
- 0, 14, MONS_CACODEMON, MH_DEMONIC, -9,
+ M_SPELLCASTER | M_LEVITATE | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_ELEC,
+ 0, 14, MONS_CACODEMON, MONS_CACODEMON, MH_DEMONIC, -9,
{ 22, 0, 0, 0 },
{ 13, 3, 5, 0 },
11, 10, 10, 7, MST_CACODEMON, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_HIGH,
@@ -2244,8 +2453,9 @@
{
MONS_DEMONIC_CRAWLER, '3', DARKGREY, "demonic crawler",
- M_RES_ELEC | M_RES_POISON | M_RES_COLD | M_RES_FIRE | M_SEE_INVIS,
- 0, 12, MONS_DEMONIC_CRAWLER, MH_DEMONIC, -6,
+ M_SEE_INVIS | M_EVIL,
+ MR_RES_ELEC | MR_RES_POISON | MR_RES_COLD | MR_RES_FIRE,
+ 0, 12, MONS_DEMONIC_CRAWLER, MONS_DEMONIC_CRAWLER, MH_DEMONIC, -6,
{ 13, 13, 13, 13 },
{ 9, 3, 5, 0 },
10, 6, 9, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SCREAM, I_NORMAL,
@@ -2255,8 +2465,9 @@
{
MONS_SUN_DEMON, '2', YELLOW, "sun demon",
- M_RES_ELEC | M_RES_POISON | M_ED_COLD | M_RES_HELLFIRE | M_SEE_INVIS | M_LEVITATE,
- 0, 14, MONS_SUN_DEMON, MH_DEMONIC, -6,
+ M_SEE_INVIS | M_LEVITATE | M_EVIL,
+ MR_RES_ELEC | MR_RES_POISON | MR_VUL_COLD | MR_RES_HELLFIRE,
+ 0, 14, MONS_SUN_DEMON, MONS_SUN_DEMON, MH_DEMONIC, -6,
{ 30, 0, 0, 0 },
{ 10, 3, 5, 0 },
10, 12, 12, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL,
@@ -2266,8 +2477,9 @@
{
MONS_SHADOW_IMP, '5', DARKGREY, "shadow imp",
- M_RES_COLD | M_SPELLCASTER | M_FLIES | M_RES_POISON | M_SPEAKS,
- 0, 11, MONS_SHADOW_IMP, MH_DEMONIC, -3,
+ M_SPELLCASTER | M_FLIES | M_SPEAKS | M_EVIL,
+ MR_RES_COLD | MR_RES_POISON,
+ 0, 11, MONS_IMP, MONS_SHADOW_IMP, MH_DEMONIC, -3,
{ 6, 0, 0, 0 },
{ 2, 3, 5, 0 },
3, 11, 10, 7, MST_SHADOW_IMP, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL,
@@ -2277,8 +2489,9 @@
{
MONS_SHADOW_DEMON, '3', DARKGREY, "shadow demon",
- M_RES_POISON | M_RES_COLD | M_SEE_INVIS | M_INVIS,
- 0, 12, MONS_SHADOW_DEMON, MH_DEMONIC, -7,
+ M_SEE_INVIS | M_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 12, MONS_SHADOW_DEMON, MONS_SHADOW_DEMON, MH_DEMONIC, -7,
{ 21, 0, 0, 0 },
{ 6, 3, 5, 0 },
7, 12, 11, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_CROAK, I_HIGH,
@@ -2288,8 +2501,9 @@
{
MONS_LOROCYPROCA, '2', BLUE, "Lorocyproca",
- M_RES_POISON | M_RES_COLD | M_RES_FIRE | M_RES_ELEC | M_SEE_INVIS | M_INVIS,
- 0, 12, MONS_LOROCYPROCA, MH_DEMONIC, -7,
+ M_SEE_INVIS | M_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD | MR_RES_FIRE | MR_RES_ELEC,
+ 0, 12, MONS_LOROCYPROCA, MONS_LOROCYPROCA, MH_DEMONIC, -7,
{ 25, 25, 0, 0 },
{ 12, 3, 5, 0 },
10, 12, 9, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_MOAN, I_HIGH,
@@ -2299,8 +2513,9 @@
{
MONS_SHADOW_WRAITH, 'W', BLUE, "shadow wraith",
- M_RES_POISON | M_LEVITATE | M_SEE_INVIS | M_INVIS,
- 0, 15, MONS_SHADOW_WRAITH, MH_UNDEAD, -8,
+ M_LEVITATE | M_SEE_INVIS | M_INVIS | M_EVIL,
+ MR_RES_POISON,
+ 0, 15, MONS_WRAITH, MONS_SHADOW_WRAITH, MH_UNDEAD, -8,
{ 20, 0, 0, 0 },
{ 10, 3, 5, 0 },
7, 7, 10, 10, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_MOAN, I_HIGH,
@@ -2310,8 +2525,9 @@
{
MONS_GIANT_AMOEBA, 'J', BLUE, "giant amoeba",
- M_RES_POISON | M_NO_SKELETON | M_SEE_INVIS | M_AMPHIBIOUS,
- 1000, 10, MONS_GIANT_AMOEBA, MH_NATURAL, -3,
+ M_NO_SKELETON | M_SEE_INVIS | M_AMPHIBIOUS,
+ MR_RES_POISON,
+ 1000, 10, MONS_GIANT_AMOEBA, MONS_GIANT_AMOEBA, MH_NATURAL, -3,
{ 25, 0, 0, 0 },
{ 12, 3, 5, 0 },
0, 4, 10, 10, MST_NO_SPELLS, CE_POISONOUS, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -2322,7 +2538,8 @@
{
MONS_GIANT_SLUG, 'm', GREEN, "giant slug",
M_NO_SKELETON | M_AMPHIBIOUS,
- 700, 10, MONS_GIANT_SLUG, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 700, 10, MONS_GIANT_SLUG, MONS_GIANT_SLUG, MH_NATURAL, -3,
{ 23, 0, 0, 0 },
{ 10, 5, 3, 0 },
0, 2, 6, 10, MST_NO_SPELLS, CE_POISONOUS, Z_BIG, S_SILENT, I_INSECT,
@@ -2333,7 +2550,8 @@
{
MONS_GIANT_SNAIL, 'm', LIGHTGREEN, "giant snail",
M_NO_SKELETON | M_AMPHIBIOUS,
- 900, 10, MONS_GIANT_SNAIL, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 900, 10, MONS_GIANT_SLUG, MONS_GIANT_SNAIL, MH_NATURAL, -3,
{ 18, 0, 0, 0 },
{ 14, 5, 3, 0 },
7, 2, 4, 10, MST_NO_SPELLS, CE_POISONOUS, Z_BIG, S_SILENT, I_INSECT,
@@ -2343,8 +2561,9 @@
{
MONS_SPATIAL_VORTEX, 'v', BLACK, "spatial vortex",
- M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_RES_ELEC | M_LEVITATE | M_CONFUSED,
- 0, 5, MONS_SPATIAL_VORTEX, MH_NONLIVING, 5000,
+ M_LEVITATE | M_CONFUSED,
+ MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 5, MONS_FIRE_VORTEX, MONS_SPATIAL_VORTEX, MH_NONLIVING, MAG_IMMUNE,
{ 50, 0, 0, 0 },
{ 6, 6, 6, 0 },
0, 5, 15, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -2354,8 +2573,9 @@
{
MONS_PIT_FIEND, '1', BROWN, "Pit Fiend",
- M_RES_POISON | M_RES_HELLFIRE | M_RES_COLD | M_FLIES | M_SEE_INVIS | M_RES_ELEC,
- 0, 18, MONS_PIT_FIEND, MH_DEMONIC, -12,
+ M_FLIES | M_SEE_INVIS | M_EVIL | M_SPECIAL_ABILITY,
+ MR_RES_POISON | MR_RES_HELLFIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 18, MONS_FIEND, MONS_PIT_FIEND, MH_DEMONIC, -12,
{ 28, 21, 21, 0 },
{ 19, 4, 5, 0 },
17, 5, 8, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_ROAR, I_HIGH,
@@ -2365,8 +2585,9 @@
{
MONS_BORING_BEETLE, 'B', BROWN, "boring beetle",
- M_ED_POISON,
- 1300, 10, MONS_BORING_BEETLE, MH_NATURAL, -3,
+ M_NO_FLAGS,
+ MR_VUL_POISON,
+ 1300, 10, MONS_GIANT_BEETLE, MONS_BORING_BEETLE, MH_NATURAL, -3,
{ 26, 0, 0, 0 },
{ 8, 3, 5, 0 },
13, 4, 6, 7, MST_NO_SPELLS, CE_POISONOUS, Z_BIG, S_SILENT, I_INSECT,
@@ -2376,8 +2597,9 @@
{
MONS_GARGOYLE, 'g', DARKGREY, "gargoyle",
- M_RES_POISON | M_RES_ELEC | M_FLIES,
- 0, 12, MONS_GARGOYLE, MH_NONLIVING, -6,
+ M_FLIES,
+ MR_RES_POISON | MR_RES_ELEC,
+ 0, 12, MONS_GARGOYLE, MONS_GARGOYLE, MH_NONLIVING, -6,
{ 10, 6, 6, 0 },
{ 4, 3, 5, 0 },
18, 6, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -2388,8 +2610,9 @@
// only appear in Dis castle
{
MONS_METAL_GARGOYLE, 'g', CYAN, "metal gargoyle",
- M_RES_POISON | M_RES_ELEC | M_FLIES,
- 0, 12, MONS_METAL_GARGOYLE, MH_NONLIVING, -6,
+ M_FLIES,
+ MR_RES_POISON | MR_RES_ELEC,
+ 0, 12, MONS_GARGOYLE, MONS_METAL_GARGOYLE, MH_NONLIVING, -6,
{ 19, 10, 10, 0 },
{ 8, 3, 5, 0 },
20, 4, 7, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_HIGH,
@@ -2400,8 +2623,9 @@
// only appear in Gehenna castle & one minivault
{
MONS_MOLTEN_GARGOYLE, 'g', RED, "molten gargoyle",
- M_RES_POISON | M_RES_ELEC | M_FLIES | M_RES_FIRE,
- 0, 12, MONS_MOLTEN_GARGOYLE, MH_NONLIVING, -6,
+ M_FLIES,
+ MR_RES_POISON | MR_RES_ELEC | MR_RES_FIRE,
+ 0, 12, MONS_GARGOYLE, MONS_MOLTEN_GARGOYLE, MH_NONLIVING, -6,
{ 12, 8, 8, 0 },
{ 5, 3, 5, 0 },
14, 7, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -2415,8 +2639,9 @@
{
MONS_MNOLEG, '&', LIGHTGREEN, "Mnoleg",
- M_RES_ELEC | M_RES_POISON | M_RES_FIRE | M_SEE_INVIS | M_SPELLCASTER | M_SPEAKS,
- 0, 25, MONS_MNOLEG, MH_DEMONIC, 5000,
+ M_SEE_INVIS | M_SPELLCASTER | M_SPEAKS | M_EVIL | M_UNIQUE,
+ MR_RES_ELEC | MR_RES_POISON | MR_RES_FIRE,
+ 0, 25, MONS_MNOLEG, MONS_MNOLEG, MH_DEMONIC, MAG_IMMUNE,
{ 23, 23, 0, 0 },
{ 17, 0, 0, 199 },
10, 13, 13, 7, MST_MNOLEG, CE_CONTAMINATED, Z_NOZOMBIE, S_BUZZ, I_HIGH,
@@ -2426,8 +2651,9 @@
{
MONS_LOM_LOBON, '&', LIGHTBLUE, "Lom Lobon",
- M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_RES_ELEC | M_LEVITATE | M_SEE_INVIS | M_SPELLCASTER | M_SPEAKS,
- 0, 25, MONS_LOM_LOBON, MH_DEMONIC, 5000,
+ M_LEVITATE | M_SEE_INVIS | M_SPELLCASTER | M_SPEAKS | M_EVIL | M_UNIQUE,
+ MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 25, MONS_LOM_LOBON, MONS_LOM_LOBON, MH_DEMONIC, MAG_IMMUNE,
{ 40, 0, 0, 0 },
{ 19, 0, 0, 223 },
10, 7, 8, 7, MST_LOM_LOBON, CE_CONTAMINATED, Z_NOZOMBIE, S_SCREAM, I_HIGH,
@@ -2437,8 +2663,9 @@
{
MONS_CEREBOV, '&', RED, "Cerebov",
- M_RES_ELEC | M_RES_POISON | M_RES_HELLFIRE | M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS,
- 0, 25, MONS_CEREBOV, MH_DEMONIC, -6,
+ M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS | M_EVIL | M_UNIQUE,
+ MR_RES_ELEC | MR_RES_POISON | MR_RES_HELLFIRE,
+ 0, 25, MONS_CEREBOV, MONS_CEREBOV, MH_DEMONIC, -6,
{ 50, 0, 0, 0 },
{ 21, 0, 0, 253 },
15, 8, 10, 7, MST_CEREBOV, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL,
@@ -2448,8 +2675,9 @@
{
MONS_GLOORX_VLOQ, '&', DARKGREY, "Gloorx Vloq",
- M_RES_POISON | M_RES_COLD | M_RES_ELEC | M_LEVITATE | M_SEE_INVIS | M_SPELLCASTER | M_SPEAKS,
- 0, 25, MONS_GLOORX_VLOQ, MH_DEMONIC, -14,
+ M_LEVITATE | M_SEE_INVIS | M_SPELLCASTER | M_SPEAKS | M_EVIL | M_UNIQUE,
+ MR_RES_POISON | MR_RES_COLD | MR_RES_ELEC,
+ 0, 25, MONS_GLOORX_VLOQ, MONS_GLOORX_VLOQ, MH_DEMONIC, -14,
{ 20, 0, 0, 0 },
{ 16, 0, 0, 234 },
10, 10, 10, 7, MST_GLOORX_VLOQ, CE_CONTAMINATED, Z_NOZOMBIE, S_MOAN, I_HIGH,
@@ -2458,16 +2686,18 @@
,
/* ******************************************************************
-{MONS_MOLLUSC_LORD, 'U', GREEN, "The Mollusc Lord", M_RES_POISON,
+{MONS_MOLLUSC_LORD, 'U', GREEN, "The Mollusc Lord", M_NO_FLAGS,
+ MR_RES_POISON,
0, 25, 255, MH_DEMONIC, -3, {30,0,0,0},
{16,0,0,100}, 10, 10, 10, 7, 93, CE_POISONOUS, Z_NOZOMBIE, S_SILENT, I_HIGH, 1},
****************************************************************** */
{
MONS_NAGA_MAGE, 'N', LIGHTRED, "naga mage",
- M_RES_POISON | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_WARM_BLOOD,
- 750, 13, MONS_NAGA, MH_NATURAL, -6,
- { 5, 0, 0, 0 },
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_WARM_BLOOD,
+ MR_RES_POISON,
+ 750, 13, MONS_NAGA, MONS_NAGA, MH_NATURAL, -6,
+ { 10, 0, 0, 0 },
{ 7, 3, 5, 0 },
6, 10, 8, 7, MST_NAGA_MAGE, CE_POISONOUS, Z_SMALL, S_SHOUT, I_NORMAL,
MONUSE_WEAPONS_ARMOUR
@@ -2476,9 +2706,10 @@
{
MONS_NAGA_WARRIOR, 'N', BLUE, "naga warrior",
- M_RES_POISON | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_WARM_BLOOD,
- 750, 12, MONS_NAGA, MH_NATURAL, -6,
- { 11, 0, 0, 0 },
+ M_SPELLCASTER | M_SEE_INVIS | M_WARM_BLOOD,
+ MR_RES_POISON,
+ 750, 12, MONS_NAGA, MONS_NAGA, MH_NATURAL, -6,
+ { 20, 0, 0, 0 },
{ 10, 5, 5, 0 },
6, 10, 8, 7, MST_NAGA, CE_POISONOUS, Z_SMALL, S_SHOUT, I_NORMAL,
MONUSE_WEAPONS_ARMOUR
@@ -2487,8 +2718,9 @@
{
MONS_ORC_WARLORD, 'o', RED, "orc warlord",
- M_WARM_BLOOD,
- 600, 15, MONS_ORC, MH_NATURAL, -3,
+ M_WARM_BLOOD | M_EVIL,
+ MR_NO_FLAGS,
+ 600, 15, MONS_ORC, MONS_ORC, MH_NATURAL, -3,
{ 32, 0, 0, 0 },
{ 15, 4, 7, 0 },
3, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2499,7 +2731,8 @@
{
MONS_DEEP_ELF_SOLDIER, 'e', CYAN, "deep elf soldier",
M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD,
- 450, 10, MONS_ELF, MH_NATURAL, -6,
+ MR_NO_FLAGS,
+ 450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -6,
{ 6, 0, 0, 0 },
{ 3, 3, 3, 0 },
0, 12, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -2510,7 +2743,8 @@
{
MONS_DEEP_ELF_FIGHTER, 'e', LIGHTBLUE, "deep elf fighter",
M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD,
- 450, 10, MONS_ELF, MH_NATURAL, -6,
+ MR_NO_FLAGS,
+ 450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -6,
{ 9, 0, 0, 0 },
{ 6, 3, 3, 0 },
0, 13, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -2521,7 +2755,8 @@
{
MONS_DEEP_ELF_KNIGHT, 'e', BLUE, "deep elf knight",
M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD,
- 450, 10, MONS_ELF, MH_NATURAL, -6,
+ MR_NO_FLAGS,
+ 450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -6,
{ 14, 0, 0, 0 },
{ 11, 3, 3, 0 },
0, 15, 11, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -2531,8 +2766,9 @@
{
MONS_DEEP_ELF_MAGE, 'e', LIGHTRED, "deep elf mage",
- M_RES_ELEC | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD,
- 450, 10, MONS_ELF, MH_NATURAL, -6,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD,
+ MR_RES_ELEC,
+ 450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -6,
{ 5, 0, 0, 0 },
{ 4, 3, 3, 0 },
0, 13, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -2543,7 +2779,8 @@
{
MONS_DEEP_ELF_SUMMONER, 'e', YELLOW, "deep elf summoner",
M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD,
- 450, 10, MONS_ELF, MH_NATURAL, -6,
+ MR_NO_FLAGS,
+ 450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -6,
{ 5, 0, 0, 0 },
{ 6, 3, 3, 0 },
0, 13, 10, 7, MST_DEEP_ELF_SUMMONER, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -2553,8 +2790,9 @@
{
MONS_DEEP_ELF_CONJURER, 'e', LIGHTGREEN, "deep elf conjurer",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_RES_ELEC | M_WARM_BLOOD,
- 450, 10, MONS_ELF, MH_NATURAL, -6,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD,
+ MR_RES_ELEC,
+ 450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -6,
{ 5, 0, 0, 0 },
{ 6, 3, 3, 0 },
0, 13, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -2565,7 +2803,8 @@
{
MONS_DEEP_ELF_PRIEST, 'e', LIGHTGREY, "deep elf priest",
M_SPELLCASTER | M_PRIEST | M_WARM_BLOOD,
- 450, 10, MONS_ELF, MH_NATURAL, -6,
+ MR_NO_FLAGS,
+ 450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -6,
{ 9, 0, 0, 0 },
{ 5, 3, 3, 0 },
0, 13, 10, 7, MST_DEEP_ELF_PRIEST, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -2575,8 +2814,9 @@
{
MONS_DEEP_ELF_HIGH_PRIEST, 'e', DARKGREY, "deep elf high priest",
- M_SPELLCASTER | M_SPEAKS | M_PRIEST | M_WARM_BLOOD | M_SEE_INVIS,
- 450, 10, MONS_ELF, MH_NATURAL, -6,
+ M_SPELLCASTER | M_SPEAKS | M_PRIEST | M_WARM_BLOOD | M_SEE_INVIS | M_EVIL,
+ MR_NO_FLAGS,
+ 450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -6,
{ 14, 0, 0, 0 },
{ 11, 3, 3, 0 },
3, 13, 10, 7, MST_DEEP_ELF_HIGH_PRIEST, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -2586,8 +2826,9 @@
{
MONS_DEEP_ELF_DEMONOLOGIST, 'e', MAGENTA, "deep elf demonologist",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS,
- 450, 10, MONS_ELF, MH_NATURAL, -6,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS | M_EVIL,
+ MR_NO_FLAGS,
+ 450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -6,
{ 12, 0, 0, 0 },
{ 12, 3, 3, 0 },
0, 13, 10, 7, MST_DEEP_ELF_DEMONOLOGIST, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -2597,8 +2838,9 @@
{
MONS_DEEP_ELF_ANNIHILATOR, 'e', GREEN, "deep elf annihilator",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_RES_ELEC | M_SEE_INVIS,
- 450, 10, MONS_ELF, MH_NATURAL, -6,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS,
+ MR_RES_ELEC,
+ 450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -6,
{ 12, 0, 0, 0 },
{ 15, 3, 3, 0 },
0, 13, 10, 7, MST_DEEP_ELF_ANNIHILATOR, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -2609,7 +2851,8 @@
{
MONS_DEEP_ELF_SORCERER, 'e', RED, "deep elf sorcerer",
M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS | M_SPEAKS,
- 450, 10, MONS_ELF, MH_NATURAL, -6,
+ MR_NO_FLAGS,
+ 450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -6,
{ 12, 0, 0, 0 },
{ 14, 3, 3, 0 },
0, 13, 10, 7, MST_DEEP_ELF_SORCERER, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -2619,8 +2862,9 @@
{
MONS_DEEP_ELF_DEATH_MAGE, 'e', WHITE, "deep elf death mage",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS,
- 450, 10, MONS_ELF, MH_NATURAL, -6,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS | M_EVIL,
+ MR_NO_FLAGS,
+ 450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -6,
{ 12, 0, 0, 0 },
{ 15, 3, 3, 0 },
0, 13, 10, 7, MST_DEEP_ELF_DEATH_MAGE, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -2630,8 +2874,9 @@
{
MONS_BROWN_OOZE, 'J', BROWN, "brown ooze",
- M_RES_POISON | M_NO_SKELETON | M_SEE_INVIS,
- 0, 11, MONS_BROWN_OOZE, MH_NATURAL, -7,
+ M_NO_SKELETON | M_SEE_INVIS,
+ MR_RES_POISON | MR_RES_ASPHYX,
+ 0, 11, MONS_JELLY, MONS_BROWN_OOZE, MH_NATURAL, -7,
{ 25, 0, 0, 0 },
{ 7, 3, 5, 0 },
10, 1, 10, 7, MST_NO_SPELLS, CE_POISONOUS, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -2641,8 +2886,9 @@
{
MONS_AZURE_JELLY, 'J', LIGHTBLUE, "azure jelly",
- M_RES_POISON | M_RES_COLD | M_ED_FIRE | M_RES_ELEC | M_NO_SKELETON | M_SEE_INVIS,
- 0, 11, MONS_AZURE_JELLY, MH_NATURAL, -4,
+ M_NO_SKELETON | M_SEE_INVIS,
+ MR_RES_POISON | MR_RES_COLD | MR_VUL_FIRE | MR_RES_ELEC | MR_RES_ASPHYX,
+ 0, 11, MONS_JELLY, MONS_AZURE_JELLY, MH_NATURAL, -4,
{ 12, 12, 12, 12 },
{ 15, 3, 5, 0 },
5, 10, 12, 7, MST_NO_SPELLS, CE_POISONOUS, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -2652,8 +2898,9 @@
{
MONS_DEATH_OOZE, 'J', DARKGREY, "death ooze",
- M_RES_POISON | M_RES_COLD | M_NO_SKELETON | M_SEE_INVIS,
- 0, 13, MONS_DEATH_OOZE, MH_UNDEAD, -8,
+ M_NO_SKELETON | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD | MR_RES_ASPHYX,
+ 0, 13, MONS_JELLY, MONS_DEATH_OOZE, MH_UNDEAD, -8,
{ 32, 32, 0, 0 },
{ 11, 3, 3, 0 },
2, 4, 12, 7, MST_NO_SPELLS, CE_POISONOUS, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -2663,8 +2910,9 @@
{
MONS_ACID_BLOB, 'J', LIGHTGREEN, "acid blob",
- M_RES_POISON | M_NO_SKELETON | M_SEE_INVIS,
- 0, 12, MONS_ACID_BLOB, MH_NATURAL, -7,
+ M_NO_SKELETON | M_SEE_INVIS | M_SPECIAL_ABILITY,
+ MR_RES_POISON | MR_RES_ASPHYX,
+ 0, 12, MONS_JELLY, MONS_ACID_BLOB, MH_NATURAL, -7,
{ 42, 0, 0, 0 },
{ 18, 3, 5, 0 },
1, 3, 14, 7, MST_NO_SPELLS, CE_POISONOUS, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -2674,8 +2922,9 @@
{
MONS_ROYAL_JELLY, 'J', YELLOW, "royal jelly",
- M_RES_POISON | M_NO_SKELETON | M_SEE_INVIS,
- 0, 20, MONS_ROYAL_JELLY, MH_NATURAL, -7,
+ M_NO_SKELETON | M_SEE_INVIS,
+ MR_RES_POISON | MR_RES_ASPHYX,
+ 0, 20, MONS_JELLY, MONS_ROYAL_JELLY, MH_NATURAL, -7,
{ 50, 0, 0, 0 },
{ 21, 0, 0, 111 },
8, 4, 12, 7, MST_NO_SPELLS, CE_CLEAN, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -2685,8 +2934,9 @@
{
MONS_TERENCE, '@', LIGHTCYAN, "Terence",
- M_WARM_BLOOD| M_SPEAKS,
- 0, 20, MONS_HUMAN, MH_NATURAL, -3,
+ M_WARM_BLOOD | M_SPEAKS | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -3,
{ 3, 0, 0, 0 },
{ 1, 0, 0, 14 },
0, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2696,8 +2946,9 @@
{
MONS_JESSICA, '@', LIGHTGREY, "Jessica",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD,
- 0, 20, MONS_HUMAN, MH_NATURAL, -3,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -3,
{ 4, 0, 0, 0 },
{ 1, 0, 0, 10 },
0, 10, 10, 7, MST_ORC_WIZARD_I, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2707,8 +2958,9 @@
{
MONS_IJYB, 'g', BLUE, "Ijyb",
- M_WARM_BLOOD | M_SPEAKS,
- 0, 5, MONS_GOBLIN, MH_NATURAL, -3,
+ M_WARM_BLOOD | M_SPEAKS | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 5, MONS_GOBLIN, MONS_GOBLIN, MH_NATURAL, -3,
{ 4, 0, 0, 0 },
{ 3, 0, 0, 28 },
2, 12, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2718,8 +2970,9 @@
{
MONS_SIGMUND, '@', YELLOW, "Sigmund",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD,
- 0, 20, MONS_HUMAN, MH_NATURAL, -3,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -3,
{ 5, 0, 0, 0 },
{ 3, 0, 0, 25 },
0, 11, 10, 7, MST_ORC_WIZARD_II, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2729,8 +2982,9 @@
{
MONS_BLORK_THE_ORC, 'o', BROWN, "Blork the orc",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD,
- 0, 20, MONS_ORC, MH_NATURAL, -4,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_ORC, MONS_ORC, MH_NATURAL, -4,
{ 7, 0, 0, 0 },
{ 3, 0, 0, 32 },
0, 9, 8, 7, MST_ORC_WIZARD_III, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2740,8 +2994,9 @@
{
MONS_EDMUND, '@', RED, "Edmund",
- M_WARM_BLOOD | M_SPEAKS,
- 0, 20, MONS_HUMAN, MH_NATURAL, -4,
+ M_WARM_BLOOD | M_SPEAKS | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -4,
{ 6, 0, 0, 0 },
{ 4, 0, 0, 27 },
0, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2751,8 +3006,9 @@
{
MONS_PSYCHE, '@', LIGHTMAGENTA, "Psyche",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD,
- 0, 20, MONS_HUMAN, MH_NATURAL, -4,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -4,
{ 7, 0, 0, 0 },
{ 5, 0, 0, 24 },
0, 12, 13, 7, MST_ORC_WIZARD_III, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2762,8 +3018,10 @@
{
MONS_EROLCHA, 'O', LIGHTBLUE, "Erolcha",
- M_RES_ELEC | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_WARM_BLOOD | M_SPEAKS,
- 0, 20, MONS_OGRE, MH_NATURAL, -7,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_WARM_BLOOD
+ | M_SPEAKS | M_EVIL | M_UNIQUE,
+ MR_RES_ELEC,
+ 0, 20, MONS_OGRE, MONS_OGRE, MH_NATURAL, -7,
{ 20, 0, 0, 0 },
{ 6, 0, 0, 45 },
3, 7, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2773,8 +3031,9 @@
{
MONS_DONALD, '@', BLUE, "Donald",
- M_WARM_BLOOD | M_SPEAKS,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_WARM_BLOOD | M_SPEAKS | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 8, 0, 0, 0 },
{ 5, 0, 0, 33 },
0, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2784,8 +3043,9 @@
{
MONS_URUG, 'o', RED, "Urug",
- M_WARM_BLOOD | M_SPEAKS,
- 0, 20, MONS_ORC, MH_NATURAL, -5,
+ M_WARM_BLOOD | M_SPEAKS | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_ORC, MONS_ORC, MH_NATURAL, -5,
{ 12, 0, 0, 0 },
{ 6, 0, 0, 38 },
0, 11, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2795,8 +3055,9 @@
{
MONS_MICHAEL, '@', LIGHTGREY, "Michael",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 9, 0, 0, 0 },
{ 6, 0, 0, 36 },
0, 10, 10, 7, MST_ORC_WIZARD_III, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2806,8 +3067,9 @@
{
MONS_JOSEPH, '@', CYAN, "Joseph",
- M_WARM_BLOOD | M_SPEAKS,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_WARM_BLOOD | M_SPEAKS | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 9, 0, 0, 0 },
{ 7, 0, 0, 42 },
0, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2817,8 +3079,9 @@
{
MONS_SNORG, 'T', GREEN, "Snorg",
- M_WARM_BLOOD | M_SPEAKS,
- 0, 20, MONS_TROLL, MH_NATURAL, -6,
+ M_WARM_BLOOD | M_SPEAKS | M_EVIL | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_TROLL, MONS_TROLL, MH_NATURAL, -6,
{ 20, 15, 15, 0 },
{ 8, 0, 0, 45 },
0, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2828,8 +3091,9 @@
{
MONS_ERICA, '@', MAGENTA, "Erica",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 10, 0, 0, 0 },
{ 9, 0, 0, 43 },
0, 11, 11, 7, MST_WIZARD_II, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2839,8 +3103,9 @@
{
MONS_JOSEPHINE, '@', WHITE, "Josephine",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 11, 0, 0, 0 },
{ 9, 0, 0, 47 },
0, 10, 10, 7, MST_NECROMANCER_I, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2850,8 +3115,9 @@
{
MONS_HAROLD, '@', LIGHTGREEN, "Harold",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 12, 0, 0, 0 },
{ 9, 0, 0, 51 },
0, 8, 10, 7, MST_HELL_KNIGHT_II, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2861,8 +3127,9 @@
{
MONS_NORBERT, '@', BROWN, "Norbert",
- M_WARM_BLOOD | M_SPEAKS,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_WARM_BLOOD | M_SPEAKS | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 14, 0, 0, 0 },
{ 10, 0, 0, 53 },
0, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2872,8 +3139,9 @@
{
MONS_JOZEF, '@', LIGHTMAGENTA, "Jozef",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 14, 0, 0, 0 },
{ 11, 0, 0, 60 },
0, 9, 10, 7, MST_GUARDIAN_NAGA, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2883,8 +3151,9 @@
{
MONS_AGNES, '@', LIGHTBLUE, "Agnes",
- M_WARM_BLOOD | M_SPEAKS,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_WARM_BLOOD | M_SPEAKS | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 11, 0, 0, 0 },
{ 11, 0, 0, 64 },
0, 10, 15, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2894,8 +3163,9 @@
{
MONS_MAUD, '@', RED, "Maud",
- M_WARM_BLOOD | M_SPEAKS,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_WARM_BLOOD | M_SPEAKS | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 14, 0, 0, 0 },
{ 13, 0, 0, 55 },
0, 10, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2905,8 +3175,9 @@
{
MONS_LOUISE, '@', BLUE, "Louise",
- M_SPELLCASTER | M_RES_ELEC | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE,
+ MR_RES_ELEC,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 12, 0, 0, 0 },
{ 13, 0, 0, 52 },
0, 10, 10, 7, MST_WIZARD_IV, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2916,8 +3187,10 @@
{
MONS_FRANCIS, '@', YELLOW, "Francis",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_SEE_INVIS,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD
+ | M_SEE_INVIS | M_EVIL | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 12, 0, 0, 0 },
{ 14, 0, 0, 67 },
0, 10, 10, 7, MST_ORC_HIGH_PRIEST, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2927,8 +3200,10 @@
{
MONS_FRANCES, '@', YELLOW, "Frances",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_SEE_INVIS,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD
+ | M_SEE_INVIS | M_EVIL | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 11, 0, 0, 0 },
{ 14, 0, 0, 70 },
0, 10, 10, 7, MST_ORC_HIGH_PRIEST, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2938,8 +3213,10 @@
{
MONS_RUPERT, '@', RED, "Rupert",
- M_SPELLCASTER | M_RES_ELEC | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_SEE_INVIS,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD
+ | M_SEE_INVIS | M_UNIQUE,
+ MR_RES_ELEC,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 13, 0, 0, 0 },
{ 16, 0, 0, 80 },
0, 10, 10, 7, MST_WIZARD_IV, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2949,8 +3226,10 @@
{
MONS_WAYNE, '@', YELLOW, "Wayne",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_SEE_INVIS,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD
+ | M_SEE_INVIS | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 14, 0, 0, 0 },
{ 17, 0, 0, 78 },
1, 10, 7, 7, MST_ORC_PRIEST, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2960,8 +3239,10 @@
{
MONS_DUANE, '@', YELLOW, "Duane",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_SEE_INVIS,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD
+ | M_SEE_INVIS | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 14, 0, 0, 0 },
{ 18, 0, 0, 83 },
0, 10, 10, 7, MST_ORC_WIZARD_I, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -2971,8 +3252,9 @@
{
MONS_XTAHUA, 'D', RED, "Xtahua",
- M_SPEAKS | M_SEE_INVIS | M_RES_POISON | M_RES_FIRE | M_ED_COLD | M_FLIES,
- 0, 20, MONS_DRAGON, MH_NATURAL, -7,
+ M_SPEAKS | M_SEE_INVIS | M_FLIES | M_SPECIAL_ABILITY | M_UNIQUE,
+ MR_RES_POISON | MR_RES_FIRE | MR_VUL_COLD,
+ 0, 20, MONS_DRAGON, MONS_DRAGON, MH_NATURAL, -7,
{ 29, 17, 17, 0 },
{ 19, 0, 0, 133 },
15, 7, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_NORMAL,
@@ -2982,19 +3264,23 @@
{
MONS_NORRIS, '@', LIGHTRED, "Norris",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_SEE_INVIS,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD
+ | M_SEE_INVIS | M_EVIL | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 16, 0, 0, 0 },
{ 20, 0, 0, 95 },
- 1, 9, 9, 7, MST_HELL_KNIGHT_II, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
+ 1, 9, 9, 7, MST_MYSTIC, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
MONUSE_WEAPONS_ARMOUR
}
,
{
MONS_ADOLF, '@', DARKGREY, "Adolf",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_SEE_INVIS,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD
+ | M_SEE_INVIS | M_EVIL | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 17, 0, 0, 0 },
{ 21, 0, 0, 105 },
0, 10, 10, 7, MST_LICH_IV, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -3004,8 +3290,10 @@
{
MONS_MARGERY, '@', RED, "Margery",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_SEE_INVIS,
- 0, 20, MONS_HUMAN, MH_NATURAL, -5,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD
+ | M_SEE_INVIS | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5,
{ 18, 0, 0, 0 },
{ 22, 0, 0, 119 },
0, 10, 10, 7, MST_EFREET, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -3015,8 +3303,10 @@
{
MONS_BORIS, 'L', RED, "Boris",
- M_RES_POISON | M_RES_COLD | M_RES_ELEC | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_SPEAKS,
- 0, 23, MONS_LICH, MH_UNDEAD, -11,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_SPEAKS | M_EVIL
+ | M_UNIQUE,
+ MR_RES_POISON | MR_RES_COLD | MR_RES_ELEC,
+ 0, 23, MONS_LICH, MONS_LICH, MH_UNDEAD, -11,
{ 15, 0, 0, 0 },
{ 22, 0, 0, 99 },
12, 10, 10, 7, MST_LICH_IV, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -3027,8 +3317,9 @@
{
MONS_GERYON, '&', GREEN, "Geryon",
- M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS,
- 0, 25, MONS_GERYON, MH_DEMONIC, -6,
+ M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS | M_EVIL | M_UNIQUE,
+ MR_NO_FLAGS,
+ 0, 25, MONS_GERYON, MONS_GERYON, MH_DEMONIC, -6,
{ 30, 0, 0, 0 },
{ 15, 0, 0, 240 },
15, 6, 10, 7, MST_GERYON, CE_CONTAMINATED, Z_NOZOMBIE, S_ROAR, I_NORMAL,
@@ -3038,8 +3329,9 @@
{
MONS_DISPATER, '&', MAGENTA, "Dispater",
- M_RES_ELEC | M_RES_POISON | M_RES_HELLFIRE | M_RES_COLD | M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS,
- 0, 25, MONS_DISPATER, MH_DEMONIC, -10,
+ M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS | M_EVIL | M_UNIQUE,
+ MR_RES_ELEC | MR_RES_POISON | MR_RES_HELLFIRE | MR_RES_COLD,
+ 0, 25, MONS_DISPATER, MONS_DISPATER, MH_DEMONIC, -10,
{ 15, 0, 0, 0 },
{ 16, 0, 0, 222 },
15, 3, 6, 7, MST_DISPATER, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_HIGH,
@@ -3049,8 +3341,9 @@
{
MONS_ASMODEUS, '&', LIGHTMAGENTA, "Asmodeus",
- M_RES_ELEC | M_RES_POISON | M_RES_HELLFIRE | M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_SPEAKS,
- 0, 25, MONS_ASMODEUS, MH_DEMONIC, -12,
+ M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_SPEAKS | M_EVIL | M_UNIQUE,
+ MR_RES_ELEC | MR_RES_POISON | MR_RES_HELLFIRE,
+ 0, 25, MONS_ASMODEUS, MONS_ASMODEUS, MH_DEMONIC, -12,
{ 20, 0, 0, 0 },
{ 17, 0, 0, 245 },
12, 7, 9, 7, MST_ASMODEUS, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_HIGH,
@@ -3061,8 +3354,9 @@
// Antaeus is now demonic so that he'll resist torment. -- bwr
{
MONS_ANTAEUS, 'C', LIGHTCYAN, "Antaeus",
- M_RES_ELEC | M_ED_FIRE | M_RES_COLD | M_SPELLCASTER | M_SPEAKS,
- 0, 25, MONS_ANTAEUS, MH_DEMONIC, -9,
+ M_SPELLCASTER | M_SPEAKS | M_UNIQUE,
+ MR_RES_ELEC | MR_VUL_FIRE | MR_RES_COLD,
+ 0, 25, MONS_HILL_GIANT, MONS_ANTAEUS, MH_DEMONIC, -9,
{ 30, 0, 0, 0 },
{ 22, 0, 0, 250 },
10, 4, 7, 7, MST_ANTAEUS, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_HIGH,
@@ -3072,8 +3366,9 @@
{
MONS_ERESHKIGAL, '&', WHITE, "Ereshkigal",
- M_RES_ELEC | M_RES_POISON | M_RES_COLD | M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS,
- 0, 25, MONS_ERESHKIGAL, MH_DEMONIC, -10,
+ M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS | M_EVIL | M_UNIQUE,
+ MR_RES_ELEC | MR_RES_POISON | MR_RES_COLD,
+ 0, 25, MONS_ERESHKIGAL, MONS_ERESHKIGAL, MH_DEMONIC, -10,
{ 20, 0, 0, 0 },
{ 18, 0, 0, 238 },
15, 6, 9, 7, MST_ERESHKIGAL, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_HIGH,
@@ -3083,8 +3378,9 @@
{
MONS_ANCIENT_LICH, 'L', DARKGREY, "ancient lich",
- M_RES_POISON | M_RES_COLD | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_RES_FIRE | M_RES_ELEC,
- 0, 20, MONS_LICH, MH_UNDEAD, -14,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD | MR_RES_FIRE | MR_RES_ELEC,
+ 0, 20, MONS_LICH, MONS_LICH, MH_UNDEAD, -14,
{ 20, 0, 0, 0 },
{ 27, 2, 4, 0 },
20, 10, 12, 7, MST_LICH_I, CE_NOCORPSE, Z_NOZOMBIE, S_SHOUT, I_HIGH,
@@ -3095,8 +3391,9 @@
{
MONS_OOZE, 'J', LIGHTGREY, "ooze",
- M_RES_POISON | M_NO_SKELETON | M_SEE_INVIS,
- 0, 5, MONS_OOZE, MH_NATURAL, -6,
+ M_NO_SKELETON | M_SEE_INVIS,
+ MR_RES_POISON | MR_RES_ASPHYX,
+ 0, 5, MONS_JELLY, MONS_OOZE, MH_NATURAL, -6,
{ 5, 0, 0, 0 },
{ 3, 3, 5, 0 },
1, 3, 8, 7, MST_NO_SPELLS, CE_POISONOUS, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -3107,7 +3404,8 @@
{
MONS_VAULT_GUARD, '@', CYAN, "vault guard",
M_WARM_BLOOD | M_SEE_INVIS,
- 0, 12, MONS_HUMAN, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 0, 12, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -3,
{ 20, 0, 0, 0 },
{ 13, 3, 5, 0 },
1, 13, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -3119,8 +3417,9 @@
placed in the Crypt. */
{
MONS_CURSE_SKULL, 'z', DARKGREY, "curse skull",
- M_RES_ELEC | M_RES_POISON | M_RES_HELLFIRE | M_RES_COLD | M_LEVITATE | M_SPELLCASTER | M_SEE_INVIS,
- 0, 50, MONS_CURSE_SKULL, MH_UNDEAD, 5000,
+ M_LEVITATE | M_SPELLCASTER | M_SEE_INVIS | M_EVIL,
+ MR_RES_ELEC | MR_RES_POISON | MR_RES_HELLFIRE | MR_RES_COLD,
+ 0, 50, MONS_LICH, MONS_CURSE_SKULL, MH_UNDEAD, MAG_IMMUNE,
{ 0, 0, 0, 0 },
{ 13, 0, 0, 66 },
40, 3, 10, 7, MST_CURSE_SKULL, CE_NOCORPSE, Z_NOZOMBIE, S_MOAN, I_HIGH,
@@ -3130,8 +3429,9 @@
{
MONS_VAMPIRE_KNIGHT, 'V', CYAN, "vampire knight",
- M_RES_POISON | M_RES_COLD | M_SPELLCASTER | M_SEE_INVIS,
- 0, 13, MONS_VAMPIRE, MH_UNDEAD, -6,
+ M_SPELLCASTER | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 13, MONS_VAMPIRE, MONS_VAMPIRE, MH_UNDEAD, -6,
{ 33, 0, 0, 0 },
{ 11, 3, 7, 0 },
10, 10, 10, 7, MST_VAMPIRE_KNIGHT, CE_NOCORPSE, Z_NOZOMBIE, S_SHOUT, I_HIGH,
@@ -3141,8 +3441,9 @@
{
MONS_VAMPIRE_MAGE, 'V', MAGENTA, "vampire mage",
- M_RES_POISON | M_RES_COLD | M_SPELLCASTER | M_SEE_INVIS | M_FLIES,
- 0, 15, MONS_VAMPIRE, MH_UNDEAD, -6,
+ M_SPELLCASTER | M_SEE_INVIS | M_FLIES | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 15, MONS_VAMPIRE, MONS_VAMPIRE, MH_UNDEAD, -6,
{ 22, 0, 0, 0 },
{ 8, 3, 4, 0 },
10, 10, 10, 7, MST_VAMPIRE_MAGE, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_HIGH,
@@ -3153,7 +3454,8 @@
{
MONS_SHINING_EYE, 'G', LIGHTMAGENTA, "shining eye",
M_NO_SKELETON | M_LEVITATE | M_SPELLCASTER | M_SEE_INVIS,
- 0, 14, MONS_SHINING_EYE, MH_NATURAL, 5000,
+ MR_RES_ASPHYX,
+ 0, 14, MONS_SHINING_EYE, MONS_SHINING_EYE, MH_NATURAL, MAG_IMMUNE,
{ 0, 0, 0, 0 },
{ 10, 3, 5, 0 },
3, 1, 7, 7, MST_SHINING_EYE, CE_POISONOUS, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -3164,8 +3466,9 @@
{
MONS_ORB_GUARDIAN, 'X', MAGENTA, "Orb Guardian",
M_NO_SKELETON | M_SEE_INVIS,
- 0, 20, MONS_ORB_GUARDIAN, MH_NATURAL, -6,
- { 40, 0, 0, 0 },
+ MR_NO_FLAGS,
+ 0, 20, MONS_ORB_GUARDIAN, MONS_ORB_GUARDIAN, MH_NATURAL, -6,
+ { 45, 0, 0, 0 },
{ 15, 3, 5, 0 },
13, 13, 14, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
MONUSE_OPEN_DOORS
@@ -3174,8 +3477,9 @@
{
MONS_DAEVA, 'A', YELLOW, "Daeva",
- M_RES_POISON | M_LEVITATE | M_SPELLCASTER,
- 0, 12, MONS_DAEVA, MH_HOLY, -8,
+ M_LEVITATE | M_SPELLCASTER,
+ MR_RES_POISON,
+ 0, 12, MONS_ANGEL, MONS_DAEVA, MH_HOLY, -8,
{ 25, 0, 0, 0 },
{ 12, 3, 5, 0 },
10, 13, 13, 7, MST_DAEVA, CE_NOCORPSE, Z_NOZOMBIE, S_SHOUT, I_HIGH,
@@ -3186,8 +3490,9 @@
/* spectral thing - similar to zombies/skeletons */
{
MONS_SPECTRAL_THING, 'W', GREEN, "",
- M_RES_POISON | M_RES_COLD | M_LEVITATE | M_SEE_INVIS,
- 0, 11, MONS_SPECTRAL_THING, MH_UNDEAD, 5000,
+ M_LEVITATE | M_SEE_INVIS,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 11, MONS_WRAITH, MONS_SPECTRAL_THING, MH_UNDEAD, MAG_IMMUNE,
{ 20, 0, 0, 0 },
{ 8, 3, 5, 0 },
8, 5, 7, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -3197,9 +3502,10 @@
{
MONS_GREATER_NAGA, 'N', RED, "greater naga",
- M_RES_POISON | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_WARM_BLOOD,
- 750, 10, MONS_NAGA, MH_NATURAL, 5000,
- { 18, 0, 0, 0 },
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_WARM_BLOOD,
+ MR_RES_POISON,
+ 750, 10, MONS_NAGA, MONS_NAGA, MH_NATURAL, MAG_IMMUNE,
+ { 24, 0, 0, 0 },
{ 15, 3, 5, 0 },
6, 10, 8, 7, MST_NAGA_MAGE, CE_POISONOUS, Z_SMALL, S_SHOUT, I_HIGH,
MONUSE_WEAPONS_ARMOUR
@@ -3208,8 +3514,9 @@
{
MONS_SKELETAL_DRAGON, 'D', LIGHTGREY, "skeletal dragon",
- M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_RES_ELEC | M_SEE_INVIS,
- 0, 12, MONS_SKELETAL_DRAGON, MH_UNDEAD, -4,
+ M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 12, MONS_SKELETAL_WARRIOR, MONS_SKELETAL_DRAGON, MH_UNDEAD, -4,
{ 30, 20, 20, 0 },
{ 20, 8, 8, 0 },
20, 4, 8, 7, MST_NO_SPELLS, CE_CLEAN, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -3219,8 +3526,9 @@
{
MONS_TENTACLED_MONSTROSITY, 'X', GREEN, "tentacled monstrosity",
- M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_RES_ELEC | M_SEE_INVIS | M_AMPHIBIOUS,
- 0, 10, MONS_TENTACLED_MONSTROSITY, MH_NATURAL, -5,
+ M_SEE_INVIS | M_AMPHIBIOUS,
+ MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 10, MONS_TENTACLED_MONSTROSITY, MONS_TENTACLED_MONSTROSITY, MH_NATURAL, -5,
{ 22, 17, 13, 19 },
{ 25, 3, 5, 0 },
5, 5, 9, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -3231,7 +3539,8 @@
{
MONS_SPHINX, 'H', LIGHTGREY, "sphinx",
M_FLIES | M_SEE_INVIS | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD,
- 0, 10, MONS_SPHINX, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 0, 10, MONS_SPHINX, MONS_SPHINX, MH_NATURAL, -3,
{ 25, 12, 12, 0 },
{ 16, 3, 5, 0 },
5, 5, 13, 7, MST_SPHINX, CE_CLEAN, Z_NOZOMBIE, S_SHOUT, I_HIGH,
@@ -3241,8 +3550,9 @@
{
MONS_ROTTING_HULK, 'n', BROWN, "rotting hulk",
- M_RES_POISON | M_RES_COLD,
- 0, 12, MONS_ROTTING_HULK, MH_UNDEAD, -5,
+ M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 12, MONS_GHOUL, MONS_ROTTING_HULK, MH_UNDEAD, -5,
{ 25, 0, 0, 0 },
{ 10, 3, 5, 0 },
5, 7, 8, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -3252,8 +3562,9 @@
{
MONS_GUARDIAN_MUMMY, 'M', YELLOW, "guardian mummy",
- M_RES_POISON | M_RES_COLD | M_SEE_INVIS,
- 0, 13, MONS_GUARDIAN_MUMMY, MH_UNDEAD, -5,
+ M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 13, MONS_MUMMY, MONS_GUARDIAN_MUMMY, MH_UNDEAD, -5,
{ 30, 0, 0, 0 },
{ 7, 5, 3, 0 },
6, 9, 9, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -3263,8 +3574,9 @@
{
MONS_GREATER_MUMMY, 'M', DARKGREY, "greater mummy",
- M_RES_POISON | M_RES_COLD | M_RES_ELEC | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS,
- 0, 20, MONS_MUMMY, MH_UNDEAD, 5000,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD | MR_RES_ELEC,
+ 0, 20, MONS_MUMMY, MONS_MUMMY, MH_UNDEAD, MAG_IMMUNE,
{ 35, 0, 0, 0 },
{ 15, 5, 3, 100 },
10, 6, 10, 7, MST_MUMMY, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -3274,8 +3586,9 @@
{
MONS_MUMMY_PRIEST, 'M', RED, "mummy priest",
- M_RES_POISON | M_RES_COLD | M_RES_ELEC | M_SPELLCASTER | M_PRIEST | M_SEE_INVIS,
- 0, 16, MONS_MUMMY, MH_UNDEAD, 5000,
+ M_SPELLCASTER | M_PRIEST | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD | MR_RES_ELEC,
+ 0, 16, MONS_MUMMY, MONS_MUMMY, MH_UNDEAD, MAG_IMMUNE,
{ 30, 0, 0, 0 },
{ 10, 5, 3, 0 },
8, 7, 9, 7, MST_MUMMY, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -3286,7 +3599,8 @@
{
MONS_CENTAUR_WARRIOR, 'c', YELLOW, "centaur warrior",
M_WARM_BLOOD,
- 1500, 12, MONS_CENTAUR, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 1500, 12, MONS_CENTAUR, MONS_CENTAUR, MH_NATURAL, -3,
{ 16, 0, 0, 0 },
{ 9, 3, 5, 0 },
4, 8, 15, 7, MST_NO_SPELLS, CE_CLEAN, Z_BIG, S_SHOUT, I_HIGH,
@@ -3297,7 +3611,8 @@
{
MONS_YAKTAUR_CAPTAIN, 'c', RED, "yaktaur captain",
M_WARM_BLOOD,
- 2000, 10, MONS_YAKTAUR, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 2000, 10, MONS_YAKTAUR, MONS_YAKTAUR, MH_NATURAL, -3,
{ 23, 0, 0, 0 },
{ 14, 3, 5, 0 },
5, 5, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_BIG, S_SHOUT, I_HIGH,
@@ -3305,10 +3620,205 @@
}
,
+{ // Base draconian -- for use like MONS_HUMAN, MONS_ELF although we
+ // now store the draconian subspecies in the high byte of mon->number
+ // for those listed as species MONS_DRACONIAN.
+ MONS_DRACONIAN, 'd', BROWN, "draconian",
+ M_HUMANOID | M_FLIES | M_COLD_BLOOD,
+ MR_NO_FLAGS,
+ 900, 10, MONS_DRACONIAN, MONS_DRACONIAN, MH_NATURAL, -1,
+ { 15, 0, 0, 0 },
+ { 3, 6, 4, 0 },
+ 7, 8, 10, 10, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
+{
+ MONS_BLACK_DRACONIAN, 'd', DARKGREY, "black draconian",
+ M_HUMANOID | M_FLIES | M_COLD_BLOOD,
+ MR_RES_ELEC,
+ 900, 10, MONS_DRACONIAN, MONS_BLACK_DRACONIAN, MH_NATURAL, -2,
+ { 20, 0, 0, 0 },
+ { 14, 5, 4, 0 },
+ 9, 10, 10, 10, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
+{
+ MONS_YELLOW_DRACONIAN, 'd', YELLOW, "yellow draconian",
+ M_FLIES | M_HUMANOID | M_COLD_BLOOD | M_SPECIAL_ABILITY,
+ MR_NO_FLAGS,
+ 900, 10, MONS_DRACONIAN, MONS_YELLOW_DRACONIAN, MH_NATURAL, -2,
+ { 20, 0, 0, 0 },
+ { 14, 5, 4, 0 },
+ 9, 10, 10, 10, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
+{
+ MONS_PALE_DRACONIAN, 'd', LIGHTGREY, "pale draconian",
+ M_HUMANOID | M_FLIES | M_COLD_BLOOD,
+ MR_RES_FIRE,
+ 900, 10, MONS_DRACONIAN, MONS_PALE_DRACONIAN, MH_NATURAL, -2,
+ { 20, 0, 0, 0 },
+ { 14, 5, 4, 0 },
+ 9, 14, 12, 10, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
+{
+ MONS_GREEN_DRACONIAN, 'd', LIGHTGREEN, "green draconian",
+ M_HUMANOID | M_FLIES | M_COLD_BLOOD,
+ MR_RES_POISON,
+ 900, 10, MONS_DRACONIAN, MONS_GREEN_DRACONIAN, MH_NATURAL, -2,
+ { 20, 0, 0, 0 },
+ { 14, 5, 4, 0 },
+ 9, 10, 10, 10, MST_NO_SPELLS, CE_POISONOUS, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
+{
+ MONS_PURPLE_DRACONIAN, 'd', MAGENTA, "purple draconian",
+ M_HUMANOID | M_FLIES | M_COLD_BLOOD,
+ MR_NO_FLAGS,
+ 900, 10, MONS_DRACONIAN, MONS_PURPLE_DRACONIAN, MH_NATURAL, -2,
+ { 20, 0, 0, 0 },
+ { 14, 5, 4, 0 },
+ 8, 10, 10, 10, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
+{
+ MONS_RED_DRACONIAN, 'd', RED, "red draconian",
+ M_HUMANOID | M_FLIES | M_COLD_BLOOD | M_SPECIAL_ABILITY,
+ MR_RES_FIRE,
+ 900, 10, MONS_DRACONIAN, MONS_RED_DRACONIAN, MH_NATURAL, -2,
+ { 20, 0, 0, 0 },
+ { 14, 5, 4, 0 },
+ 9, 10, 10, 10, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
+{
+ MONS_WHITE_DRACONIAN, 'd', WHITE, "white draconian",
+ M_HUMANOID | M_FLIES | M_COLD_BLOOD | M_SPECIAL_ABILITY,
+ MR_RES_COLD,
+ 900, 10, MONS_DRACONIAN, MONS_WHITE_DRACONIAN, MH_NATURAL, -2,
+ { 20, 0, 0, 0 },
+ { 14, 5, 4, 0 },
+ 9, 10, 10, 10, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
+{
+ MONS_MOTTLED_DRACONIAN, 'd', LIGHTMAGENTA, "mottled draconian",
+ M_HUMANOID | M_FLIES | M_COLD_BLOOD,
+ MR_RES_FIRE,
+ 900, 10, MONS_DRACONIAN, MONS_MOTTLED_DRACONIAN, MH_NATURAL, -2,
+ { 20, 0, 0, 0 },
+ { 14, 5, 4, 0 },
+ 9, 10, 10, 10, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
+{
+ MONS_DRACONIAN_CALLER, 'd', BROWN, "draconian caller",
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_HUMANOID | M_FLIES | M_COLD_BLOOD,
+ MR_NO_FLAGS,
+ 900, 10, MONS_DRACONIAN, MONS_DRACONIAN, MH_NATURAL, -3,
+ { 20, 0, 0, 0 },
+ { 16, 4, 3, 0 },
+ 9, 10, 10, 10, MST_DRAC_CALLER, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
+{
+ MONS_DRACONIAN_MONK, 'd', BLUE, "draconian monk",
+ M_FIGHTER | M_HUMANOID | M_FLIES | M_COLD_BLOOD,
+ MR_NO_FLAGS,
+ 900, 10, MONS_DRACONIAN, MONS_DRACONIAN, MH_NATURAL, -3,
+ { 35, 20, 15, 0 },
+ { 16, 6, 3, 0 },
+ 6, 20, 10, 10, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
+{
+ MONS_DRACONIAN_ZEALOT, 'd', LIGHTBLUE, "draconian zealot",
+ M_SPELLCASTER | M_HUMANOID | M_PRIEST | M_FLIES | M_COLD_BLOOD,
+ MR_NO_FLAGS,
+ 900, 10, MONS_DRACONIAN, MONS_DRACONIAN, MH_NATURAL, -3,
+ { 15, 0, 0, 0 },
+ { 16, 4, 2, 0 },
+ 12, 10, 10, 10, MST_DEEP_ELF_HIGH_PRIEST, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
+{
+ MONS_DRACONIAN_SHIFTER, 'd', LIGHTCYAN, "draconian shifter",
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_HUMANOID | M_FLIES | M_COLD_BLOOD,
+ MR_NO_FLAGS,
+ 900, 10, MONS_DRACONIAN, MONS_DRACONIAN, MH_NATURAL, -4,
+ { 15, 0, 0, 0 },
+ { 16, 4, 4, 0 },
+ 8, 16, 10, 10, MST_DRAC_SHIFTER, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
+{
+ MONS_DRACONIAN_ANNIHILATOR, 'd', GREEN, "draconian annihilator",
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_HUMANOID | M_FLIES | M_COLD_BLOOD,
+ MR_NO_FLAGS,
+ 900, 10, MONS_DRACONIAN, MONS_DRACONIAN, MH_NATURAL, -4,
+ { 15, 0, 0, 0 },
+ { 16, 4, 2, 0 },
+ 8, 10, 10, 10, MST_DEEP_ELF_ANNIHILATOR, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
+{
+ MONS_DRACONIAN_KNIGHT, 'd', CYAN, "draconian knight",
+ M_SPELLCASTER | M_HUMANOID | M_FIGHTER | M_FLIES | M_COLD_BLOOD,
+ MR_NO_FLAGS,
+ 900, 10, MONS_DRACONIAN, MONS_DRACONIAN, MH_NATURAL, -4,
+ { 15, 0, 0, 0 },
+ { 16, 6, 4, 0 },
+ 12, 12, 10, 6, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
+{
+ MONS_DRACONIAN_SCORCHER, 'd', LIGHTRED, "draconian scorcher",
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_HUMANOID | M_FLIES | M_COLD_BLOOD,
+ MR_RES_FIRE | MR_RES_HELLFIRE,
+ 900, 10, MONS_DRACONIAN, MONS_DRACONIAN, MH_NATURAL, -4,
+ { 15, 0, 0, 0 },
+ { 16, 4, 2, 0 },
+ 8, 12, 10, 10, MST_DRAC_SCORCHER, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
+ MONUSE_STARTING_EQUIPMENT
+}
+,
+
{
MONS_KILLER_KLOWN, '@', BLACK, "Killer Klown",
- M_RES_FIRE | M_RES_COLD | M_RES_POISON | M_SEE_INVIS | M_SPEAKS | M_WARM_BLOOD,
- 0, 15, MONS_KILLER_KLOWN, MH_NATURAL, 5000,
+ M_SEE_INVIS | M_SPEAKS | M_WARM_BLOOD | M_SPECIAL_ABILITY,
+ MR_RES_FIRE | MR_RES_COLD | MR_RES_POISON,
+ 0, 15, MONS_HUMAN, MONS_KILLER_KLOWN, MH_NATURAL, MAG_IMMUNE,
{ 30, 0, 0, 0 },
{ 20, 5, 5, 0 },
10, 15, 15, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_HIGH,
@@ -3318,8 +3828,9 @@
{
MONS_ELECTRIC_GOLEM, '8', LIGHTCYAN, "electric golem",
- M_SPELLCASTER | M_RES_ELEC | M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_SEE_INVIS,
- 0, 10, MONS_ELECTRIC_GOLEM, MH_NONLIVING, 5000,
+ M_SPELLCASTER | M_SEE_INVIS,
+ MR_RES_ELEC | MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD,
+ 0, 10, MONS_CLAY_GOLEM, MONS_ELECTRIC_GOLEM, MH_NONLIVING, MAG_IMMUNE,
{ 12, 12, 12, 12 },
{ 15, 7, 4, 0 },
5, 20, 20, 7, MST_ELECTRIC_GOLEM, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -3329,8 +3840,9 @@
{
MONS_BALL_LIGHTNING, '*', LIGHTCYAN, "ball lightning",
- M_FLIES | M_RES_ELEC | M_CONFUSED | M_SPELLCASTER,
- 0, 20, MONS_BALL_LIGHTNING, MH_NONLIVING, 5000,
+ M_FLIES | M_CONFUSED | M_SPELLCASTER | M_SPECIAL_ABILITY,
+ MR_RES_ELEC,
+ 0, 20, MONS_BALL_LIGHTNING, MONS_BALL_LIGHTNING, MH_NONLIVING, MAG_IMMUNE,
{ 5, 0, 0, 0 },
{ 12, 0, 0, 1 },
0, 10, 20, 7, MST_STORM_DRAGON, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_PLANT,
@@ -3340,8 +3852,9 @@
{
MONS_ORB_OF_FIRE, '*', RED, "orb of fire",
- M_SPELLCASTER | M_FLIES | M_RES_ELEC | M_RES_FIRE | M_RES_COLD | M_RES_POISON | M_SEE_INVIS,
- 0, 10, MONS_ORB_OF_FIRE, MH_NONLIVING, 5000,
+ M_SPELLCASTER | M_FLIES | M_SEE_INVIS,
+ MR_RES_ELEC | MR_RES_FIRE | MR_RES_COLD | MR_RES_POISON,
+ 0, 10, MONS_ORB_OF_FIRE, MONS_ORB_OF_FIRE, MH_NONLIVING, MAG_IMMUNE,
{ 0, 0, 0, 0 },
{ 30, 0, 0, 150 },
20, 20, 20, 7, MST_ORB_OF_FIRE, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL,
@@ -3352,7 +3865,8 @@
{
MONS_QUOKKA, 'r', LIGHTGREY, "quokka",
M_WARM_BLOOD,
- 300, 10, MONS_QUOKKA, MH_NATURAL, -1,
+ MR_NO_FLAGS,
+ 300, 10, MONS_QUOKKA, MONS_QUOKKA, MH_NATURAL, -1,
{ 5, 0, 0, 0 },
{ 1, 3, 5, 0 },
2, 13, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_SILENT, I_NORMAL,
@@ -3363,7 +3877,8 @@
{
MONS_EYE_OF_DEVASTATION, 'G', YELLOW, "eye of devastation",
M_NO_SKELETON | M_LEVITATE | M_SPELLCASTER | M_SEE_INVIS,
- 0, 11, MONS_EYE_OF_DEVASTATION, MH_NATURAL, 5000,
+ MR_RES_ASPHYX,
+ 0, 11, MONS_GIANT_EYEBALL, MONS_EYE_OF_DEVASTATION, MH_NATURAL, MAG_IMMUNE,
{ 0, 0, 0, 0 },
{ 10, 3, 5, 0 },
12, 1, 7, 7, MST_EYE_OF_DEVASTATION, CE_POISONOUS, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -3374,7 +3889,8 @@
{
MONS_MOTH_OF_WRATH, 'y', BROWN, "moth of wrath",
M_FLIES,
- 0, 10, MONS_MOTH_OF_WRATH, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 0, 10, MONS_MOTH_OF_WRATH, MONS_MOTH_OF_WRATH, MH_NATURAL, -3,
{ 25, 0, 0, 0 },
{ 9, 3, 5, 0 },
0, 10, 12, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -3384,8 +3900,9 @@
{
MONS_DEATH_COB, '%', YELLOW, "death cob",
- M_RES_POISON | M_RES_COLD | M_SPEAKS,
- 0, 10, MONS_DEATH_COB, MH_UNDEAD, -3,
+ M_SPEAKS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 10, MONS_DEATH_COB, MONS_DEATH_COB, MH_UNDEAD, -3,
{ 20, 0, 0, 0 },
{ 10, 4, 5, 0 },
10, 15, 25, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_MOAN, I_NORMAL,
@@ -3394,12 +3911,13 @@
,
{
- MONS_CURSE_TOE, 'z', DARKGREY, "curse toe",
- M_RES_ELEC | M_RES_POISON | M_RES_HELLFIRE | M_RES_COLD | M_LEVITATE | M_SPELLCASTER | M_SEE_INVIS,
- 0, 60, MONS_CURSE_TOE, MH_UNDEAD, 5000,
+ MONS_CURSE_TOE, 'z', YELLOW, "curse toe",
+ M_LEVITATE | M_SPELLCASTER | M_SEE_INVIS | M_EVIL,
+ MR_RES_ELEC | MR_RES_POISON | MR_RES_HELLFIRE | MR_RES_COLD,
+ 0, 60, MONS_LICH, MONS_CURSE_TOE, MH_UNDEAD, MAG_IMMUNE,
{ 0, 0, 0, 0 },
{ 14, 0, 0, 77 },
- 50, 1, 12, 7, MST_CURSE_SKULL, CE_NOCORPSE, Z_NOZOMBIE, S_MOAN, I_HIGH,
+ 50, 1, 12, 7, MST_CURSE_TOE, CE_NOCORPSE, Z_NOZOMBIE, S_MOAN, I_HIGH,
MONUSE_NOTHING
}
,
@@ -3407,8 +3925,9 @@
{
// gold mimics are the only mimics that actually use their name -- bwr
MONS_GOLD_MIMIC, '$', YELLOW, "pile of gold coins",
- M_NO_SKELETON | M_RES_POISON | M_RES_ELEC | M_RES_FIRE | M_RES_COLD,
- 0, 13, MONS_GOLD_MIMIC, MH_NONLIVING, -3,
+ M_NO_SKELETON,
+ MR_RES_POISON | MR_RES_ELEC | MR_RES_FIRE | MR_RES_COLD,
+ 0, 13, MONS_GOLD_MIMIC, MONS_GOLD_MIMIC, MH_NONLIVING, -3,
{ 12, 12, 12, 0 },
{ 8, 3, 5, 0 },
5, 1, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -3418,8 +3937,9 @@
{
MONS_WEAPON_MIMIC, ')', BLACK, "mimic",
- M_NO_SKELETON | M_RES_POISON | M_RES_ELEC | M_RES_FIRE | M_RES_COLD,
- 0, 13, MONS_GOLD_MIMIC, MH_NONLIVING, -3,
+ M_NO_SKELETON,
+ MR_RES_POISON | MR_RES_ELEC | MR_RES_FIRE | MR_RES_COLD,
+ 0, 13, MONS_GOLD_MIMIC, MONS_GOLD_MIMIC, MH_NONLIVING, -3,
{ 17, 17, 17, 0 },
{ 8, 3, 5, 0 },
5, 1, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -3429,8 +3949,9 @@
{
MONS_ARMOUR_MIMIC, '[', BLACK, "mimic",
- M_NO_SKELETON | M_RES_POISON | M_RES_ELEC | M_RES_FIRE | M_RES_COLD,
- 0, 13, MONS_GOLD_MIMIC, MH_NONLIVING, -3,
+ M_NO_SKELETON,
+ MR_RES_POISON | MR_RES_ELEC | MR_RES_FIRE | MR_RES_COLD,
+ 0, 13, MONS_GOLD_MIMIC, MONS_GOLD_MIMIC, MH_NONLIVING, -3,
{ 12, 12, 12, 0 },
{ 8, 3, 5, 0 },
15, 1, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -3440,8 +3961,9 @@
{
MONS_SCROLL_MIMIC, '?', LIGHTGREY, "mimic",
- M_NO_SKELETON | M_RES_POISON | M_RES_ELEC | M_RES_FIRE | M_RES_COLD,
- 0, 13, MONS_GOLD_MIMIC, MH_NONLIVING, -3,
+ M_NO_SKELETON,
+ MR_RES_POISON | MR_RES_ELEC | MR_RES_FIRE | MR_RES_COLD,
+ 0, 13, MONS_GOLD_MIMIC, MONS_GOLD_MIMIC, MH_NONLIVING, -3,
{ 12, 12, 12, 0 },
{ 8, 3, 5, 0 },
5, 1, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -3451,8 +3973,9 @@
{
MONS_POTION_MIMIC, '!', BLACK, "mimic",
- M_NO_SKELETON | M_RES_POISON | M_RES_ELEC | M_RES_FIRE | M_RES_COLD,
- 0, 13, MONS_GOLD_MIMIC, MH_NONLIVING, -3,
+ M_NO_SKELETON,
+ MR_RES_POISON | MR_RES_ELEC | MR_RES_FIRE | MR_RES_COLD,
+ 0, 13, MONS_GOLD_MIMIC, MONS_GOLD_MIMIC, MH_NONLIVING, -3,
{ 12, 12, 12, 0 },
{ 8, 3, 5, 0 },
5, 1, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_NORMAL,
@@ -3462,8 +3985,9 @@
{
MONS_HELL_HOG, 'h', RED, "hell-hog",
- M_SPELLCASTER,
- 0, 10, MONS_HELL_HOG, MH_DEMONIC, -3,
+ M_SPELLCASTER | M_THICK_SKIN | M_EVIL,
+ MR_NO_FLAGS,
+ 0, 10, MONS_HELL_HOG, MONS_HELL_HOG, MH_DEMONIC, -3,
{ 20, 0, 0, 0 },
{ 11, 3, 5, 0 },
2, 9, 14, 7, MST_HELL_HOG, CE_CLEAN, Z_NOZOMBIE, S_SILENT, I_ANIMAL,
@@ -3473,8 +3997,9 @@
{
MONS_SERPENT_OF_HELL, 'D', RED, "Serpent of Hell",
- M_SPELLCASTER | M_RES_POISON | M_RES_HELLFIRE | M_FLIES | M_SEE_INVIS,
- 0, 18, MONS_SERPENT_OF_HELL, MH_DEMONIC, -13,
+ M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_EVIL,
+ MR_RES_POISON | MR_RES_HELLFIRE,
+ 0, 18, MONS_SERPENT_OF_HELL, MONS_SERPENT_OF_HELL, MH_DEMONIC, -13,
{ 35, 15, 15, 0 },
{ 20, 4, 4, 0 },
12, 9, 14, 7, MST_SERPENT_OF_HELL, CE_CLEAN, Z_NOZOMBIE, S_ROAR, I_HIGH,
@@ -3485,7 +4010,8 @@
{
MONS_BOGGART, 'g', DARKGREY, "boggart",
M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS,
- 0, 14, MONS_BOGGART, MH_NATURAL, -7,
+ MR_NO_FLAGS,
+ 0, 14, MONS_BOGGART, MONS_BOGGART, MH_NATURAL, -7,
{ 5, 0, 0, 0 },
{ 2, 3, 5, 0 },
0, 12, 12, 7, MST_BOGGART, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL,
@@ -3496,7 +4022,8 @@
{
MONS_QUICKSILVER_DRAGON, 'D', LIGHTCYAN, "quicksilver dragon",
M_SPELLCASTER | M_FLIES | M_SEE_INVIS,
- 0, 14, MONS_QUICKSILVER_DRAGON, MH_NATURAL, -7,
+ MR_NO_FLAGS,
+ 0, 14, MONS_DRAGON, MONS_QUICKSILVER_DRAGON, MH_NATURAL, -7,
{ 45, 0, 0, 0 },
{ 16, 3, 5, 0 },
10, 15, 15, 7, MST_QUICKSILVER_DRAGON, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
@@ -3506,8 +4033,9 @@
{
MONS_IRON_DRAGON, 'D', CYAN, "iron dragon",
- M_SPELLCASTER | M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_SEE_INVIS,
- 0, 14, MONS_IRON_DRAGON, MH_NATURAL, -7,
+ M_SPELLCASTER | M_SEE_INVIS,
+ MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD,
+ 0, 14, MONS_DRAGON, MONS_IRON_DRAGON, MH_NATURAL, -7,
{ 25, 25, 25, 0 },
{ 18, 5, 3, 0 },
20, 6, 8, 7, MST_IRON_DRAGON, CE_CONTAMINATED, Z_SMALL, S_ROAR, I_HIGH,
@@ -3517,8 +4045,9 @@
{
MONS_SKELETAL_WARRIOR, 'z', CYAN, "skeletal warrior",
- M_SPELLCASTER | M_RES_POISON | M_RES_COLD | M_ACTUAL_SPELLS,
- 0, 10, MONS_SKELETAL_WARRIOR, MH_UNDEAD, -7,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_EVIL,
+ MR_RES_POISON | MR_RES_COLD,
+ 0, 10, MONS_SKELETAL_WARRIOR, MONS_SKELETAL_WARRIOR, MH_UNDEAD, -7,
{ 25, 0, 0, 0 },
{ 10, 5, 3, 0 },
15, 10, 10, 7, MST_SKELETAL_WARRIOR, CE_CONTAMINATED, Z_SMALL, S_SILENT, I_NORMAL,
@@ -3530,8 +4059,9 @@
/* player ghost - only one per level. stats are stored in ghost struct */
{
MONS_PLAYER_GHOST, 'p', DARKGREY, "",
- M_RES_POISON | M_SPEAKS | M_SPELLCASTER | M_ACTUAL_SPELLS | M_FLIES,
- 0, 15, MONS_PLAYER_GHOST, MH_UNDEAD, -5,
+ M_SPEAKS | M_SPELLCASTER | M_ACTUAL_SPELLS | M_FLIES | M_UNIQUE,
+ MR_RES_POISON,
+ 0, 15, MONS_PHANTOM, MONS_PLAYER_GHOST, MH_UNDEAD, -5,
{ 5, 0, 0, 0 },
{ 4, 2, 3, 0 },
1, 2, 10, 7, MST_GHOST, CE_CONTAMINATED, Z_NOZOMBIE, S_SILENT, I_HIGH,
@@ -3542,8 +4072,9 @@
/* random demon in pan - only one per level. stats are stored in ghost struct */
{
MONS_PANDEMONIUM_DEMON, '&', BLACK, "&",
- M_SPELLCASTER | M_RES_POISON | M_SPEAKS,
- 0, 14, MONS_PANDEMONIUM_DEMON, MH_DEMONIC, -5,
+ M_SPELLCASTER | M_SPEAKS | M_EVIL | M_UNIQUE,
+ MR_RES_POISON,
+ 0, 14, MONS_PANDEMONIUM_DEMON, MONS_PANDEMONIUM_DEMON, MH_DEMONIC, -5,
{ 5, 0, 0, 0 },
{ 4, 2, 3, 0 },
1, 2, 10, 7, MST_GHOST, CE_CONTAMINATED, Z_NOZOMBIE, S_RANDOM, I_HIGH,
@@ -3554,8 +4085,9 @@
// begin lava monsters {dlb}
{
MONS_LAVA_WORM, 'w', RED, "lava worm",
- M_RES_FIRE | M_ED_COLD,
- 0, 10, MONS_LAVA_WORM, MH_NATURAL, -3,
+ M_NO_FLAGS,
+ MR_RES_FIRE | MR_VUL_COLD,
+ 0, 10, MONS_LAVA_WORM, MONS_LAVA_WORM, MH_NATURAL, -3,
{ 15, 0, 0, 0 },
{ 6, 3, 5, 0 },
1, 10, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_SMALL, S_SILENT, I_ANIMAL_LIKE,
@@ -3565,8 +4097,9 @@
{
MONS_LAVA_FISH, ';', RED, "lava fish",
- M_RES_FIRE | M_ED_COLD,
- 0, 10, MONS_LAVA_FISH, MH_NATURAL, -3,
+ M_NO_FLAGS,
+ MR_RES_FIRE | MR_VUL_COLD,
+ 0, 10, MONS_BIG_FISH, MONS_LAVA_FISH, MH_NATURAL, -3,
{ 10, 0, 0, 0 },
{ 4, 3, 5, 0 },
4, 15, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_SMALL, S_SILENT, I_ANIMAL_LIKE,
@@ -3576,8 +4109,9 @@
{
MONS_LAVA_SNAKE, 'S', RED, "lava snake",
- M_RES_FIRE | M_ED_COLD,
- 0, 10, MONS_LAVA_SNAKE, MH_NATURAL, -3,
+ M_SPECIAL_ABILITY,
+ MR_RES_FIRE | MR_VUL_COLD,
+ 0, 10, MONS_SNAKE, MONS_LAVA_SNAKE, MH_NATURAL, -3,
{ 7, 0, 0, 0 },
{ 3, 3, 5, 0 },
2, 17, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_SMALL, S_HISS, I_ANIMAL_LIKE,
@@ -3587,8 +4121,9 @@
{ // mv: was another lava thing
MONS_SALAMANDER, 'S', LIGHTRED, "salamander",
- M_RES_FIRE | M_ED_COLD | M_WARM_BLOOD,
- 0, 10, MONS_SALAMANDER, MH_NATURAL, -3,
+ M_WARM_BLOOD,
+ MR_RES_FIRE | MR_VUL_COLD,
+ 0, 10, MONS_SALAMANDER, MONS_SALAMANDER, MH_NATURAL, -3,
{ 23, 0, 0, 0 },
{ 14, 3, 5, 0 },
5, 5, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_SMALL, S_SILENT, I_HIGH,
@@ -3602,7 +4137,8 @@
{
MONS_BIG_FISH, ';', LIGHTGREEN, "big fish",
M_COLD_BLOOD,
- 0, 10, MONS_BIG_FISH, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 0, 10, MONS_BIG_FISH, MONS_BIG_FISH, MH_NATURAL, -3,
{ 8, 0, 0, 0 },
{ 4, 3, 5, 0 },
1, 12, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_SMALL, S_SILENT, I_ANIMAL_LIKE,
@@ -3613,7 +4149,8 @@
{
MONS_GIANT_GOLDFISH, ';', LIGHTRED, "giant goldfish",
M_COLD_BLOOD,
- 0, 10, MONS_GIANT_GOLDFISH, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 0, 10, MONS_BIG_FISH, MONS_GIANT_GOLDFISH, MH_NATURAL, -3,
{ 15, 0, 0, 0 },
{ 7, 3, 5, 0 },
5, 7, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_SMALL, S_SILENT, I_ANIMAL_LIKE,
@@ -3623,8 +4160,9 @@
{
MONS_ELECTRICAL_EEL, ';', LIGHTBLUE, "electrical eel",
- M_RES_ELEC | M_COLD_BLOOD,
- 0, 10, MONS_ELECTRICAL_EEL, MH_NATURAL, -3,
+ M_COLD_BLOOD | M_SPECIAL_ABILITY,
+ MR_RES_ELEC,
+ 0, 10, MONS_ELECTRICAL_EEL, MONS_ELECTRICAL_EEL, MH_NATURAL, -3,
{ 0, 0, 0, 0 },
{ 3, 3, 5, 0 },
1, 15, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_SMALL, S_SILENT, I_ANIMAL_LIKE,
@@ -3634,8 +4172,9 @@
{
MONS_JELLYFISH, 'J', CYAN, "jellyfish",
- M_RES_POISON,
- 0, 10, MONS_JELLYFISH, MH_NATURAL, -3,
+ M_NO_FLAGS,
+ MR_RES_POISON,
+ 0, 10, MONS_JELLYFISH, MONS_JELLYFISH, MH_NATURAL, -3,
{ 1, 1, 0, 0 },
{ 4, 3, 5, 0 },
0, 5, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_SMALL, S_SILENT, I_PLANT,
@@ -3645,8 +4184,9 @@
{
MONS_WATER_ELEMENTAL, '{', LIGHTBLUE, "water elemental",
- M_RES_POISON | M_ED_FIRE | M_FLIES | M_RES_ELEC,
- 0, 10, MONS_WATER_ELEMENTAL, MH_NONLIVING, 5000,
+ M_FLIES,
+ MR_RES_POISON | MR_VUL_FIRE | MR_RES_ELEC,
+ 0, 10, MONS_EARTH_ELEMENTAL, MONS_WATER_ELEMENTAL, MH_NONLIVING, MAG_IMMUNE,
{ 25, 0, 0, 0 },
{ 6, 5, 3, 0 },
0, 7, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -3657,7 +4197,8 @@
{
MONS_SWAMP_WORM, 'w', BROWN, "swamp worm",
M_AMPHIBIOUS,
- 0, 10, MONS_SWAMP_WORM, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 0, 10, MONS_WORM, MONS_SWAMP_WORM, MH_NATURAL, -3,
{ 20, 0, 0, 0 },
{ 5, 5, 5, 0 },
3, 12, 12, 0, MST_NO_SPELLS, CE_NOCORPSE, Z_SMALL, S_SILENT, I_PLANT,
@@ -3679,8 +4220,9 @@ not think it fits into Crawl ... {dlb}
#if 0
{
MONS_SHUGGOTH, 'A', LIGHTGREEN, "shuggoth",
- M_NO_SKELETON | M_RES_ELEC | M_RES_POISON | M_RES_FIRE | M_RES_COLD | M_SEE_INVIS,
- 1000, 10, MONS_SHUGGOTH, MH_DEMONIC, 300,
+ M_NO_SKELETON | M_SEE_INVIS,
+ MR_RES_ELEC | MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD,
+ 1000, 10, MONS_SHUGGOTH, MONS_SHUGGOTH, MH_DEMONIC, 300,
{ 5, 5, 5, 0 },
{ 10, 4, 4, 0 },
10, 10, 20, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, -1, I_NORMAL,
@@ -3692,7 +4234,8 @@ not think it fits into Crawl ... {dlb}
{
MONS_WOLF, 'h', LIGHTGREY, "wolf",
M_WARM_BLOOD | M_SEE_INVIS, //jmf: until smell exists
- 450, 10, MONS_WOLF, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 450, 10, MONS_HOUND, MONS_WOLF, MH_NATURAL, -3,
{ 8, 2, 2, 0 },
{ 4, 3, 5, 0 },
3, 15, 17, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_BARK, I_ANIMAL,
@@ -3702,8 +4245,9 @@ not think it fits into Crawl ... {dlb}
{
MONS_WARG, 'h', DARKGREY, "warg",
- M_SEE_INVIS | M_RES_POISON | M_WARM_BLOOD,
- 600, 12, MONS_WARG, MH_NATURAL, -6,
+ M_SEE_INVIS | M_WARM_BLOOD,
+ MR_RES_POISON,
+ 600, 12, MONS_HOUND, MONS_WARG, MH_NATURAL, -6,
{ 12, 3, 3, 0 },
{ 4, 4, 5, 0 },
4, 12, 13, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_SMALL, S_BARK, I_ANIMAL,
@@ -3714,7 +4258,8 @@ not think it fits into Crawl ... {dlb}
{
MONS_BEAR, 'U', BROWN, "bear",
M_WARM_BLOOD,
- 2000, 10, MONS_BEAR, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 2000, 10, MONS_BEAR, MONS_BEAR, MH_NATURAL, -3,
{ 10, 6, 6, 0 },
{ 7, 3, 3, 0 },
4, 4, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_BIG, S_GROWL, I_ANIMAL,
@@ -3725,7 +4270,8 @@ not think it fits into Crawl ... {dlb}
{
MONS_GRIZZLY_BEAR, 'U', LIGHTGREY, "grizzly bear",
M_WARM_BLOOD,
- 2500, 10, MONS_GRIZZLY_BEAR, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 2500, 10, MONS_BEAR, MONS_GRIZZLY_BEAR, MH_NATURAL, -3,
{ 12, 8, 8, 0 },
{ 7, 4, 4, 0 },
5, 8, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_BIG, S_GROWL, I_ANIMAL,
@@ -3735,8 +4281,9 @@ not think it fits into Crawl ... {dlb}
{
MONS_POLAR_BEAR, 'U', WHITE, "polar bear",
- M_RES_COLD | M_WARM_BLOOD | M_AMPHIBIOUS,
- 2500, 10, MONS_POLAR_BEAR, MH_NATURAL, -3,
+ M_WARM_BLOOD | M_AMPHIBIOUS,
+ MR_RES_COLD,
+ 2500, 10, MONS_BEAR, MONS_POLAR_BEAR, MH_NATURAL, -3,
{ 20, 5, 5, 0 }, //jmf: polar bears have very strong jaws & necks
{ 7, 5, 3, 0 },
7, 8, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_BIG, S_GROWL, I_ANIMAL,
@@ -3747,7 +4294,8 @@ not think it fits into Crawl ... {dlb}
{
MONS_BLACK_BEAR, 'U', DARKGREY, "black bear",
M_WARM_BLOOD,
- 1800, 10, MONS_BLACK_BEAR, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 1800, 10, MONS_BEAR, MONS_BLACK_BEAR, MH_NATURAL, -3,
{ 4, 4, 4, 0 },
{ 6, 3, 3, 0 },
2, 8, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_GROWL, I_ANIMAL,
@@ -3758,8 +4306,9 @@ not think it fits into Crawl ... {dlb}
// small simulacrum
{
MONS_SIMULACRUM_SMALL, 'z', WHITE, "",
- M_RES_POISON | M_ED_FIRE | M_RES_COLD,
- 0, 6, MONS_SIMULACRUM_SMALL, MH_UNDEAD, -1,
+ M_EVIL,
+ MR_RES_POISON | MR_VUL_FIRE | MR_RES_COLD,
+ 0, 6, MONS_SIMULACRUM_SMALL, MONS_SIMULACRUM_SMALL, MH_UNDEAD, -1,
{ 6, 0, 0, 0 },
{ 2, 3, 5, 0 },
10, 4, 7, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -3770,8 +4319,9 @@ not think it fits into Crawl ... {dlb}
// large simulacrum
{
MONS_SIMULACRUM_LARGE, 'Z', WHITE, "",
- M_RES_POISON | M_ED_FIRE | M_RES_COLD,
- 0, 6, MONS_SIMULACRUM_LARGE, MH_UNDEAD, -1,
+ M_EVIL,
+ MR_RES_POISON | MR_VUL_FIRE | MR_RES_COLD,
+ 0, 6, MONS_SIMULACRUM_SMALL, MONS_SIMULACRUM_LARGE, MH_UNDEAD, -1,
{ 14, 0, 0, 0 },
{ 5, 3, 5, 0 },
10, 5, 7, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SILENT, I_PLANT,
@@ -3782,7 +4332,8 @@ not think it fits into Crawl ... {dlb}
{
MONS_GIANT_NEWT, 'l', LIGHTGREEN, "giant newt",
M_COLD_BLOOD | M_AMPHIBIOUS,
- 150, 10, MONS_GIANT_NEWT, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 150, 10, MONS_GIANT_LIZARD, MONS_GIANT_NEWT, MH_NATURAL, -3,
{ 3, 0, 0, 0 },
{ 1, 1, 2, 0 },
0, 15, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_SILENT, I_REPTILE,
@@ -3793,7 +4344,8 @@ not think it fits into Crawl ... {dlb}
{
MONS_GIANT_GECKO, 'l', YELLOW, "giant gecko",
M_COLD_BLOOD,
- 250, 10, MONS_GIANT_GECKO, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 250, 10, MONS_GIANT_LIZARD, MONS_GIANT_GECKO, MH_NATURAL, -3,
{ 5, 0, 0, 0 },
{ 1, 3, 5, 0 },
1, 14, 12, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_SILENT, I_REPTILE,
@@ -3804,7 +4356,8 @@ not think it fits into Crawl ... {dlb}
{
MONS_GIANT_IGUANA, 'l', BLUE, "giant iguana",
M_COLD_BLOOD,
- 400, 10, MONS_GIANT_IGUANA, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 400, 10, MONS_GIANT_LIZARD, MONS_GIANT_IGUANA, MH_NATURAL, -3,
{ 15, 0, 0, 0 },
{ 3, 3, 5, 0 },
5, 9, 10, 7, MST_NO_SPELLS, CE_CLEAN, Z_SMALL, S_HISS, I_REPTILE,
@@ -3816,7 +4369,8 @@ not think it fits into Crawl ... {dlb}
// gila monsters colours: lightmagenta, magenta, lightred, red, yellow
MONS_GILA_MONSTER, 'l', BLACK, "gila monster",
M_COLD_BLOOD,
- 500, 10, MONS_GILA_MONSTER, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 500, 10, MONS_GIANT_LIZARD, MONS_GILA_MONSTER, MH_NATURAL, -3,
{ 20, 0, 0, 0 },
{ 5, 4, 4, 0 },
3, 12, 10, 7, MST_NO_SPELLS, CE_POISONOUS, Z_BIG, S_HISS, I_REPTILE,
@@ -3825,9 +4379,10 @@ not think it fits into Crawl ... {dlb}
,
{
- MONS_KOMODO_DRAGON, 'l', BROWN, "komodo dragon",
+ MONS_KOMODO_DRAGON, 'l', LIGHTRED, "komodo dragon",
M_COLD_BLOOD | M_AMPHIBIOUS,
- 800, 10, MONS_KOMODO_DRAGON, MH_NATURAL, -3,
+ MR_NO_FLAGS,
+ 800, 10, MONS_GIANT_LIZARD, MONS_KOMODO_DRAGON, MH_NATURAL, -3,
{ 30, 0, 0, 0 },
{ 8, 3, 5, 0 },
7, 8, 10, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_BIG, S_HISS, I_REPTILE,
@@ -3835,4 +4390,28 @@ not think it fits into Crawl ... {dlb}
}
,
+{
+ MONS_ORANGE_STATUE, '8', LIGHTRED, "orange crystal statue",
+ M_SPECIAL_ABILITY,
+ MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 10, MONS_CLAY_GOLEM, MONS_ORANGE_STATUE, MH_NONLIVING, MAG_IMMUNE,
+ { 0, 0, 0, 0 },
+ { 3, 50, 30, 120 },
+ 30, 3, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_HIGH,
+ MONUSE_NOTHING
+}
+,
+
+{
+ MONS_SILVER_STATUE, '8', WHITE, "silver statue",
+ M_SPECIAL_ABILITY,
+ MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC,
+ 0, 10, MONS_CLAY_GOLEM, MONS_SILVER_STATUE, MH_NONLIVING, MAG_IMMUNE,
+ { 0, 0, 0, 0 },
+ { 3, 50, 0, 120 },
+ 30, 3, 10, 7, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_HIGH,
+ MONUSE_NOTHING
+}
+,
+
#endif
diff --git a/crawl-ref/source/mon-pick.cc b/crawl-ref/source/mon-pick.cc
index f4a3446230..ee5dba276a 100644
--- a/crawl-ref/source/mon-pick.cc
+++ b/crawl-ref/source/mon-pick.cc
@@ -3,6 +3,8 @@
* Summary: Functions used to help determine which monsters should appear.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <2> 08-Mar-2000 DLB enumeration & clean-up
@@ -46,6 +48,8 @@ static int mons_tartarus_level(int mcls);
static int mons_tartarus_rare(int mcls);
static int mons_tomb_level(int mcls);
static int mons_tomb_rare(int mcls);
+static int mons_caverns_level(int mcls);
+static int mons_caverns_rare(int mcls);
/* ******************* BEGIN EXTERNAL FUNCTIONS ******************* */
int branch_depth(int branch)
@@ -86,6 +90,28 @@ int branch_depth(int branch)
}
} // end branch_depth()
+int branch_stair(int branch)
+{
+ switch (branch)
+ {
+ case BRANCH_ORCISH_MINES: return STAIRS_ORCISH_MINES;
+ case BRANCH_HIVE: return STAIRS_HIVE;
+ case BRANCH_LAIR: return STAIRS_LAIR;
+ case BRANCH_SLIME_PITS: return STAIRS_SLIME_PITS;
+ case BRANCH_VAULTS: return STAIRS_VAULTS;
+ case BRANCH_CRYPT: return STAIRS_CRYPT;
+ case BRANCH_HALL_OF_BLADES: return STAIRS_HALL_OF_BLADES;
+ case BRANCH_HALL_OF_ZOT: return STAIRS_HALL_OF_ZOT;
+ case BRANCH_ECUMENICAL_TEMPLE: return STAIRS_ECUMENICAL_TEMPLE;
+ case BRANCH_SNAKE_PIT: return STAIRS_SNAKE_PIT;
+ case BRANCH_ELVEN_HALLS: return STAIRS_ELVEN_HALLS;
+ case BRANCH_TOMB: return STAIRS_TOMB;
+ case BRANCH_SWAMP: return STAIRS_SWAMP;
+ default:
+ return -1;
+ }
+}
+
// NB - When adding new branches or levels above 50, you must
// change pre-game deletion routine in new_game in newgame.cc
@@ -116,7 +142,8 @@ int mons_level(int mcls)
(you.where_are_you == BRANCH_ELVEN_HALLS) ? mons_hallelf_level :
(you.where_are_you == BRANCH_TOMB) ? mons_tomb_level :
(you.where_are_you == BRANCH_SWAMP) ? mons_swamp_level :
- (you.where_are_you == BRANCH_VAULTS) ? mons_standard_level
+ (you.where_are_you == BRANCH_VAULTS) ? mons_standard_level :
+ (you.where_are_you == BRANCH_CAVERNS) ? mons_caverns_level
: mons_standard_level);
monster_level = fnc_level(mcls);
@@ -153,7 +180,8 @@ int mons_rarity(int mcls)
(you.where_are_you == BRANCH_ELVEN_HALLS) ? mons_hallelf_rare :
(you.where_are_you == BRANCH_TOMB) ? mons_tomb_rare :
(you.where_are_you == BRANCH_SWAMP) ? mons_swamp_rare :
- (you.where_are_you == BRANCH_VAULTS) ? mons_standard_rare
+ (you.where_are_you == BRANCH_VAULTS) ? mons_standard_rare :
+ (you.where_are_you == BRANCH_CAVERNS) ? mons_caverns_rare
: mons_standard_rare);
monster_rarity = fnc_rarity(mcls);
@@ -188,6 +216,7 @@ bool mons_abyss(int mcls)
case MONS_FLAYED_GHOST:
case MONS_FLYING_SKULL:
case MONS_FREEZING_WRAITH:
+ case MONS_DEATH_DRAKE:
case MONS_FUNGUS:
case MONS_GIANT_EYEBALL:
case MONS_GIANT_ORANGE_BRAIN:
@@ -539,11 +568,12 @@ static int mons_dis_level(int mcls)
case MONS_FLAYED_GHOST:
case MONS_FREEZING_WRAITH:
+ case MONS_DEATH_DRAKE:
case MONS_HAIRY_DEVIL:
case MONS_IRON_DEVIL:
case MONS_VAMPIRE:
case MONS_WRAITH:
- mlev += 4;
+ mlev += 3;
break;
case MONS_BLUE_DEVIL:
@@ -1092,6 +1122,7 @@ static int mons_tartarus_rare(int mcls)
case MONS_IMP:
case MONS_SHADOW_DRAGON:
+ case MONS_DEATH_DRAKE:
return 20;
case MONS_RED_DEVIL:
@@ -2139,6 +2170,7 @@ static int mons_hallzot_level(int mcls)
case MONS_SHADOW_DRAGON:
case MONS_SKELETAL_DRAGON:
case MONS_STORM_DRAGON:
+ case MONS_CURSE_TOE:
mlev += 5;
break;
case MONS_DEATH_COB:
@@ -2146,11 +2178,21 @@ static int mons_hallzot_level(int mcls)
case MONS_ICE_DRAGON:
mlev += 4;
break;
- case MONS_DEEP_ELF_ANNIHILATOR:
- case MONS_DEEP_ELF_DEATH_MAGE:
- case MONS_DEEP_ELF_DEMONOLOGIST:
- case MONS_DEEP_ELF_HIGH_PRIEST:
- case MONS_DEEP_ELF_SORCERER:
+ case MONS_MOTTLED_DRACONIAN:
+ case MONS_YELLOW_DRACONIAN:
+ case MONS_BLACK_DRACONIAN:
+ case MONS_WHITE_DRACONIAN:
+ case MONS_RED_DRACONIAN:
+ case MONS_PURPLE_DRACONIAN:
+ case MONS_PALE_DRACONIAN:
+ case MONS_GREEN_DRACONIAN:
+ case MONS_DRACONIAN_CALLER:
+ case MONS_DRACONIAN_MONK:
+ case MONS_DRACONIAN_SCORCHER:
+ case MONS_DRACONIAN_KNIGHT:
+ case MONS_DRACONIAN_ANNIHILATOR:
+ case MONS_DRACONIAN_ZEALOT:
+ case MONS_DRACONIAN_SHIFTER:
case MONS_TENTACLED_MONSTROSITY:
mlev += 3;
break;
@@ -2186,16 +2228,32 @@ static int mons_hallzot_rare(int mcls)
case MONS_SKELETAL_DRAGON:
return 40;
case MONS_SHADOW_DRAGON:
+ case MONS_DEATH_DRAKE:
return 30;
- case MONS_DEEP_ELF_ANNIHILATOR:
- case MONS_DEEP_ELF_DEATH_MAGE:
- case MONS_DEEP_ELF_DEMONOLOGIST:
- case MONS_DEEP_ELF_HIGH_PRIEST:
- case MONS_DEEP_ELF_SORCERER:
- return 29;
case MONS_GUARDIAN_MUMMY:
case MONS_ELECTRIC_GOLEM:
+ case MONS_CURSE_TOE:
return 20;
+
+ case MONS_MOTTLED_DRACONIAN:
+ case MONS_YELLOW_DRACONIAN:
+ case MONS_BLACK_DRACONIAN:
+ case MONS_WHITE_DRACONIAN:
+ case MONS_RED_DRACONIAN:
+ case MONS_PURPLE_DRACONIAN:
+ case MONS_PALE_DRACONIAN:
+ case MONS_GREEN_DRACONIAN:
+ return 18;
+
+ case MONS_DRACONIAN_CALLER:
+ case MONS_DRACONIAN_MONK:
+ case MONS_DRACONIAN_SCORCHER:
+ case MONS_DRACONIAN_KNIGHT:
+ case MONS_DRACONIAN_ANNIHILATOR:
+ case MONS_DRACONIAN_ZEALOT:
+ case MONS_DRACONIAN_SHIFTER:
+ return 16;
+
case MONS_KILLER_KLOWN:
case MONS_ORB_OF_FIRE:
return 15;
@@ -2204,6 +2262,68 @@ static int mons_hallzot_rare(int mcls)
}
} // end mons_hallzot_rare()
+static int mons_caverns_level( int mcls )
+{
+
+ int mlev = you.branch_stairs[STAIRS_CAVERNS] + 1;
+
+ switch (mcls)
+ {
+ case MONS_YELLOW_DRACONIAN:
+ case MONS_BLACK_DRACONIAN:
+ case MONS_WHITE_DRACONIAN:
+ case MONS_RED_DRACONIAN:
+ case MONS_PURPLE_DRACONIAN:
+ case MONS_PALE_DRACONIAN:
+ case MONS_GREEN_DRACONIAN:
+ case MONS_MOTTLED_DRACONIAN:
+ mlev++;
+ break;
+
+ case MONS_DRACONIAN_CALLER:
+ case MONS_DRACONIAN_MONK:
+ case MONS_DRACONIAN_SCORCHER:
+ case MONS_DRACONIAN_KNIGHT:
+ case MONS_DRACONIAN_ANNIHILATOR:
+ case MONS_DRACONIAN_ZEALOT:
+ case MONS_DRACONIAN_SHIFTER:
+ mlev += 3;
+ break;
+
+ default:
+ mlev += 99;
+ break;
+ }
+
+ return (mlev);
+}
+
+static int mons_caverns_rare( int mcls )
+{
+ switch (mcls)
+ {
+ case MONS_YELLOW_DRACONIAN:
+ case MONS_BLACK_DRACONIAN:
+ case MONS_WHITE_DRACONIAN:
+ case MONS_RED_DRACONIAN:
+ case MONS_PURPLE_DRACONIAN:
+ case MONS_PALE_DRACONIAN:
+ case MONS_GREEN_DRACONIAN:
+ case MONS_MOTTLED_DRACONIAN:
+ case MONS_DRACONIAN_CALLER:
+ case MONS_DRACONIAN_MONK:
+ case MONS_DRACONIAN_SCORCHER:
+ case MONS_DRACONIAN_KNIGHT:
+ case MONS_DRACONIAN_ANNIHILATOR:
+ case MONS_DRACONIAN_ZEALOT:
+ case MONS_DRACONIAN_SHIFTER:
+ return (500);
+
+ default:
+ return (0);
+ }
+}
+
static int mons_standard_level(int mcls)
{
switch (mcls)
@@ -2602,6 +2722,7 @@ static int mons_standard_rare(int mcls)
case MONS_NECROPHAGE:
case MONS_POTION_MIMIC:
case MONS_SCROLL_MIMIC:
+ case MONS_QUASIT:
case MONS_SKELETAL_WARRIOR:
case MONS_SMALL_SNAKE:
case MONS_SOUL_EATER:
diff --git a/crawl-ref/source/mon-pick.h b/crawl-ref/source/mon-pick.h
index 79312e6043..880efa2550 100644
--- a/crawl-ref/source/mon-pick.h
+++ b/crawl-ref/source/mon-pick.h
@@ -41,18 +41,14 @@ bool mons_abyss(int mcls);
int mons_rare_abyss(int mcls);
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: dungeon - spells3
- * *********************************************************************** */
-int branch_depth(int branch);
-
-
// last updated 10jun2000 {dlb}
/* ***********************************************************************
* called from: levels - mon-pick
* *********************************************************************** */
bool mons_pan(int mcls);
+// [ds] Why in the name of all that's holy are these in mon-pick.cc?
+int branch_depth(int branch);
+int branch_stair(int branch);
#endif
diff --git a/crawl-ref/source/mon-spll.h b/crawl-ref/source/mon-spll.h
index 4799b4e2db..650a5103ee 100644
--- a/crawl-ref/source/mon-spll.h
+++ b/crawl-ref/source/mon-spll.h
@@ -1,3 +1,7 @@
+/*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ */
+
#ifndef MON_SPLL_H
#define MON_SPLL_H
@@ -355,7 +359,7 @@
MS_SUMMON_DEMON },
{ MST_GREEN_DEATH,
- MS_POISON_BLAST,
+ MS_POISON_ARROW,
MS_POISON_BLAST,
MS_NO_SPELL,
MS_VENOM_BOLT,
@@ -443,7 +447,7 @@
MS_NO_SPELL },
{ MST_GLOORX_VLOQ,
- MS_POISON_BLAST,
+ MS_POISON_ARROW,
MS_SLOW,
MS_SUMMON_DEMON,
MS_NEGATIVE_BOLT,
@@ -519,7 +523,7 @@
MS_CRYSTAL_SPEAR,
MS_BLINK,
MS_IRON_BOLT,
- MS_POISON_BLAST,
+ MS_POISON_ARROW,
MS_TELEPORT },
{ MST_DEEP_ELF_SORCERER,
@@ -558,7 +562,7 @@
MS_VENOM_BOLT,
MS_ORB_ENERGY,
MS_HASTE,
- MS_VENOM_BOLT,
+ MS_POISON_ARROW,
MS_TELEPORT_OTHER,
MS_TELEPORT },
@@ -730,5 +734,54 @@
MS_NO_SPELL,
MS_NO_SPELL },
+ { MST_MYSTIC,
+ MS_BRAIN_FEED,
+ MS_SMITE,
+ MS_INVIS,
+ MS_CONFUSE,
+ MS_PARALYSIS,
+ MS_HEAL },
+
+ { MST_DEATH_DRAKE,
+ MS_MIASMA,
+ MS_MIASMA,
+ MS_NO_SPELL,
+ MS_MIASMA,
+ MS_MIASMA,
+ MS_NO_SPELL },
+
+ { MST_DRAC_SCORCHER,
+ MS_FIRE_BOLT,
+ MS_STICKY_FLAME,
+ MS_NO_SPELL,
+ MS_FIREBALL,
+ MS_HELLFIRE,
+ MS_HELLFIRE_BURST },
+
+ { MST_DRAC_CALLER,
+ MS_NO_SPELL,
+ MS_SUMMON_LIZARDS,
+ MS_SUMMON_LIZARDS,
+ MS_NO_SPELL,
+ MS_NO_SPELL,
+ MS_SUMMON_LIZARDS },
+
+ { MST_DRAC_SHIFTER,
+ MS_NO_SPELL,
+ MS_BLINK_OTHER,
+ MS_BLINK,
+ MS_NO_SPELL,
+ MS_BLINK_OTHER,
+ MS_CONTROLLED_BLINK },
+
+ // Curse toe menu should be kept full, because otherwise the toe spends
+ // too much time crawling around.
+ { MST_CURSE_TOE,
+ MS_SUMMON_UNDEAD,
+ MS_SUMMON_MUSHROOMS, // fungal theme
+ MS_SUMMON_MUSHROOMS,
+ MS_TORMENT,
+ MS_SUMMON_UNDEAD,
+ MS_TORMENT },
#endif
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 4df429aab7..f4ef56fb8d 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -30,6 +30,8 @@
#include "debug.h"
#include "itemname.h"
+#include "itemprop.h"
+#include "monplace.h"
#include "mstuff2.h"
#include "player.h"
#include "randart.h"
@@ -42,6 +44,20 @@ static FixedVector < int, NUM_MONSTERS > mon_entry;
// really important extern -- screen redraws suck w/o it {dlb}
FixedVector < unsigned short, 1000 > mcolour;
+enum habitat_type
+{
+ // Flying monsters will appear in all categories
+ HT_NORMAL, // Normal critters
+ HT_SHALLOW_WATER, // Union of normal + water
+ HT_DEEP_WATER, // Water critters
+ HT_LAVA, // Lava critters
+
+ NUM_HABITATS
+};
+
+static bool initialized_randmons = false;
+static std::vector<int> monsters_by_habitat[NUM_HABITATS];
+
static struct monsterentry mondata[] = {
#include "mon-data.h"
};
@@ -59,8 +75,8 @@ static const char *monster_spell_name[] = {
"Throw Frost",
"Paralysis",
"Slow",
- "Haste",
- "Confuse",
+ "Haste",
+ "Confuse",
"Venom Bolt",
"Fire Bolt",
"Cold Bolt",
@@ -79,45 +95,153 @@ static const char *monster_spell_name[] = {
"Orb Energy",
"Brain Feed",
"Level Summon",
- "Fake Rakshasa Summon",
+ "Fake Rakshasa Summon",
"Steam Ball",
"Summon Demon",
"Animate Dead",
"Pain",
- "Smite",
+ "Smite",
"Sticky Flame",
"Poison Blast",
"Summon Demon Lesser",
"Summon Ufetubus",
- "Purple Blast",
+ "Purple Blast",
"Summon Beast",
"Energy Bolt",
"Sting",
"Iron Bolt",
- "Stone Arrow",
+ "Stone Arrow",
"Poison Splash",
"Summon Undead",
- "Mutation",
+ "Mutation",
"Cantrip",
"Disintegrate",
"Marsh Gas",
"Quicksilver Bolt",
"Torment",
"Hellfire",
- "Metal Splinters",
+ "Metal Splinters",
"Summon Demon Greater",
"Banishment",
+ "Controlled Blink",
+ "Control Undead",
+ "Miasma",
+ "Summon Lizards",
+ "Blink Other",
+ "Dispel Undead",
+ "Hellfrost",
+ "Poison Arrow",
+ "Summon Small Mammals",
+ "Summon Mushrooms",
};
#endif
static int mons_exp_mod(int mclass);
-static monsterentry *seekmonster(int *p_monsterid);
+static monsterentry *seekmonster(int p_monsterid);
// macro that saves some typing, nothing more
-#define smc seekmonster(&mc)
+#define smc seekmonster(mc)
/* ******************** BEGIN PUBLIC FUNCTIONS ******************** */
-void mons_init(FixedVector < unsigned short, 1000 > &colour)
+
+habitat_type grid2habitat(int grid)
+{
+ switch (grid)
+ {
+ case DNGN_DEEP_WATER:
+ return (HT_DEEP_WATER);
+ case DNGN_SHALLOW_WATER:
+ return (HT_SHALLOW_WATER);
+ case DNGN_LAVA:
+ return (HT_LAVA);
+ default:
+ return (HT_NORMAL);
+ }
+}
+
+int habitat2grid(habitat_type ht)
+{
+ switch (ht)
+ {
+ case HT_DEEP_WATER:
+ return (DNGN_DEEP_WATER);
+ case HT_SHALLOW_WATER:
+ return (DNGN_SHALLOW_WATER);
+ case HT_LAVA:
+ return (DNGN_LAVA);
+ case HT_NORMAL:
+ default:
+ return (DNGN_FLOOR);
+ }
+}
+
+static void initialize_randmons()
+{
+ for (int i = 0; i < NUM_HABITATS; ++i)
+ {
+ int grid = habitat2grid( habitat_type(i) );
+
+ for (int m = 0; m < NUM_MONSTERS; ++m)
+ {
+ if (invalid_monster_class(m))
+ continue;
+ if (monster_habitable_grid(m, grid))
+ monsters_by_habitat[i].push_back(m);
+ }
+ }
+ initialized_randmons = true;
+}
+
+monster_type random_monster_at_grid(int x, int y)
+{
+ return (random_monster_at_grid(grd[x][y]));
+}
+
+monster_type random_monster_at_grid(int grid)
+{
+ if (!initialized_randmons)
+ initialize_randmons();
+
+ const habitat_type ht = grid2habitat(grid);
+ const std::vector<int> &valid_mons = monsters_by_habitat[ht];
+ ASSERT(!valid_mons.empty());
+ return valid_mons.empty()? MONS_PROGRAM_BUG
+ : monster_type(valid_mons[ random2(valid_mons.size()) ]);
+}
+
+monster_type get_monster_by_name(std::string name, bool exact)
+{
+ lowercase(name);
+
+ monster_type mon = MONS_PROGRAM_BUG;
+ for (unsigned i = 0; i < sizeof(mondata) / sizeof(*mondata); ++i)
+ {
+ std::string candidate = mondata[i].name;
+ lowercase(candidate);
+
+ const int mtype = mondata[i].mc;
+
+ if (exact)
+ {
+ if (name == candidate)
+ return monster_type(mtype);
+
+ continue;
+ }
+
+ const std::string::size_type match = candidate.find(name);
+ if (match == std::string::npos)
+ continue;
+
+ mon = monster_type(mtype);
+ // we prefer prefixes over partial matches
+ if (match == 0)
+ break;
+ }
+ return (mon);
+}
+
+void init_monsters(FixedVector < unsigned short, 1000 > &colour)
{
unsigned int x; // must be unsigned to match size_t {dlb}
@@ -143,13 +267,40 @@ void mons_init(FixedVector < unsigned short, 1000 > &colour)
//return (monsterentry *) 0; // return value should not matter here {dlb}
} // end mons_init()
+unsigned long get_mons_class_resists(int mc)
+{
+ return (smc->resists);
+}
-int mons_flag(int mc, int bf)
+unsigned long get_mons_resists(const monsters *mon)
{
- return ((smc->bitfields & bf) != 0);
-} // end mons_flag()
+ unsigned long resists = get_mons_class_resists(mon->type);
+ if (mons_genus(mon->type) == MONS_DRACONIAN
+ && mon->type != MONS_DRACONIAN)
+ {
+ monster_type draco_species = draco_subspecies(mon);
+ if (draco_species != mon->type)
+ resists |= get_mons_class_resists(draco_species);
+ }
+ return (resists);
+}
+
+unsigned long mons_resist(const monsters *mon, unsigned long flags)
+{
+ return (get_mons_resists(mon) & flags);
+}
+
+bool mons_class_flag(int mc, int bf)
+{
+ const monsterentry *me = smc;
+
+ if (!me)
+ return (false);
-static int scan_mon_inv_randarts( struct monsters *mon, int ra_prop )
+ return ((me->bitfields & bf) != 0);
+} // end mons_class_flag()
+
+static int scan_mon_inv_randarts( const monsters *mon, int ra_prop )
{
int ret = 0;
@@ -181,15 +332,52 @@ static int scan_mon_inv_randarts( struct monsters *mon, int ra_prop )
return (ret);
}
+mon_holy_type mons_holiness(const monsters *mon)
+{
+ return (mons_class_holiness(mon->type));
+}
-int mons_holiness(int mc)
+mon_holy_type mons_class_holiness(int mc)
{
return (smc->holiness);
} // end mons_holiness()
+bool mons_class_is_stationary(int type)
+{
+ return (type == MONS_OKLOB_PLANT
+ || type == MONS_PLANT
+ || type == MONS_FUNGUS
+ || type == MONS_CURSE_SKULL
+ || mons_is_statue(type)
+ || mons_is_mimic(type));
+}
+
+bool mons_is_stationary(const monsters *mons)
+{
+ return (mons_class_is_stationary(mons->type));
+}
+
+bool invalid_monster(const monsters *mons)
+{
+ return (!mons || mons->type == -1);
+}
+
+bool invalid_monster_class(int mclass)
+{
+ return (mclass < 0
+ || mclass >= NUM_MONSTERS
+ || mon_entry[mclass] == -1
+ || mon_entry[mclass] == MONS_PROGRAM_BUG);
+}
+
+bool mons_is_statue(int mc)
+{
+ return (mc == MONS_ORANGE_STATUE || mc == MONS_SILVER_STATUE);
+}
+
bool mons_is_mimic( int mc )
{
- return (mons_charclass( mc ) == MONS_GOLD_MIMIC);
+ return (mons_species( mc ) == MONS_GOLD_MIMIC);
}
bool mons_is_demon( int mc )
@@ -197,7 +385,7 @@ bool mons_is_demon( int mc )
const int show_char = mons_char( mc );
// Not every demonic monster is a demon (ie hell hog, hell hound)
- if (mons_holiness( mc ) == MH_DEMONIC
+ if (mons_class_holiness( mc ) == MH_DEMONIC
&& (isdigit( show_char ) || show_char == '&'))
{
return (true);
@@ -248,18 +436,34 @@ int mons_weight(int mc)
return (smc->weight);
} // end mons_weight()
-
-int mons_corpse_thingy(int mc)
+corpse_effect_type mons_corpse_effect(int mc)
{
return (smc->corpse_thingy);
-} // end mons_corpse_thingy()
+} // end mons_corpse_effect()
+
+
+monster_type mons_species( int mc )
+{
+ const monsterentry *me = seekmonster(mc);
+ return (me? me->species : MONS_PROGRAM_BUG);
+} // end mons_species()
+monster_type mons_genus( int mc )
+{
+ return (smc->genus);
+}
-int mons_charclass(int mc)
+monster_type draco_subspecies( const monsters *mon )
{
- return (smc->charclass);
-} // end mons_charclass()
+ ASSERT( mons_genus( mon->type ) == MONS_DRACONIAN );
+
+ monster_type ret = mons_species( mon->type );
+ if (ret == MONS_DRACONIAN && mon->type != MONS_DRACONIAN)
+ ret = static_cast<monster_type>( mon->number );
+
+ return (ret);
+}
int mons_shouts(int mc)
{
@@ -273,22 +477,14 @@ int mons_shouts(int mc)
bool mons_is_unique( int mc )
{
- if (mc <= MONS_PROGRAM_BUG
- || (mc >= MONS_NAGA_MAGE && mc <= MONS_ROYAL_JELLY)
- || (mc >= MONS_ANCIENT_LICH
- && (mc != MONS_PLAYER_GHOST && mc != MONS_PANDEMONIUM_DEMON)))
- {
- return (false);
- }
-
- return (true);
+ return (mons_class_flag(mc, M_UNIQUE));
}
char mons_see_invis( struct monsters *mon )
{
if (mon->type == MONS_PLAYER_GHOST || mon->type == MONS_PANDEMONIUM_DEMON)
return (ghost.values[ GVAL_SEE_INVIS ]);
- else if (((seekmonster(&mon->type))->bitfields & M_SEE_INVIS) != 0)
+ else if (((seekmonster(mon->type))->bitfields & M_SEE_INVIS) != 0)
return (1);
else if (scan_mon_inv_randarts( mon, RAP_EYESIGHT ) > 0)
return (1);
@@ -339,11 +535,20 @@ char mons_itemuse(int mc)
return (smc->gmon_use);
} // end mons_itemuse()
-unsigned char mons_colour(int mc)
+int mons_class_colour(int mc)
{
- return (smc->colour);
+ const monsterentry *m = smc;
+ if (!m)
+ return (BLACK);
+
+ const int class_colour = m->colour;
+ return (class_colour);
} // end mons_colour()
+int mons_colour(const monsters *monster)
+{
+ return (monster->colour);
+}
int mons_damage(int mc, int rt)
{
@@ -359,9 +564,9 @@ int mons_damage(int mc, int rt)
return (smc->damage[rt]);
} // end mons_damage()
-int mons_resist_magic( struct monsters *mon )
+int mons_resist_magic( const monsters *mon )
{
- int u = (seekmonster(&mon->type))->resist_magic;
+ int u = (seekmonster(mon->type))->resist_magic;
// negative values get multiplied with mhd
if (u < 0)
@@ -384,7 +589,7 @@ int mons_resist_magic( struct monsters *mon )
// Returns true if the monster made its save against hostile
// enchantments/some other magics.
-bool check_mons_resist_magic( struct monsters *monster, int pow )
+bool check_mons_resist_magic( const monsters *monster, int pow )
{
int mrs = mons_resist_magic(monster);
@@ -422,7 +627,7 @@ bool check_mons_resist_magic( struct monsters *monster, int pow )
} // end check_mons_resist_magic()
-int mons_res_elec( struct monsters *mon )
+int mons_res_elec( const monsters *mon )
{
int mc = mon->type;
@@ -430,11 +635,10 @@ int mons_res_elec( struct monsters *mon )
return (ghost.values[ GVAL_RES_ELEC ]);
/* this is a variable, not a player_xx() function, so can be above 1 */
- int u = 0, f = (seekmonster(&mc))->bitfields;
+ int u = 0;
- // of course it makes no sense setting them both :)
- if (f & M_RES_ELEC)
- u++; //if(f&M_ED_ELEC) u--;
+ if (mons_resist(mon, MR_RES_ELEC))
+ u++;
// don't bother checking equipment if the monster can't use it
if (mons_itemuse(mc) >= MONUSE_STARTING_EQUIPMENT)
@@ -453,17 +657,26 @@ int mons_res_elec( struct monsters *mon )
return (u);
} // end mons_res_elec()
+bool mons_res_asphyx( const monsters *mon )
+{
+ const int holiness = mons_holiness( mon );
+ return (holiness == MH_UNDEAD
+ || holiness == MH_DEMONIC
+ || holiness == MH_NONLIVING
+ || holiness == MH_PLANT
+ || mons_resist(mon, MR_RES_ASPHYX));
+}
-int mons_res_poison( struct monsters *mon )
+int mons_res_poison( const monsters *mon )
{
int mc = mon->type;
- int u = 0, f = (seekmonster(&mc))->bitfields;
+ int u = 0, f = get_mons_resists(mon);
- if (f & M_RES_POISON)
+ if (f & MR_RES_POISON)
u++;
- if (f & M_ED_POISON)
+ if (f & MR_VUL_POISON)
u--;
if (mons_itemuse(mc) >= MONUSE_STARTING_EQUIPMENT)
@@ -491,25 +704,25 @@ int mons_res_poison( struct monsters *mon )
} // end mons_res_poison()
-int mons_res_fire( struct monsters *mon )
+int mons_res_fire( const monsters *mon )
{
int mc = mon->type;
if (mc == MONS_PLAYER_GHOST || mc == MONS_PANDEMONIUM_DEMON)
return (ghost.values[ GVAL_RES_FIRE ]);
- int u = 0, f = (seekmonster(&mc))->bitfields;
+ int u = 0, f = get_mons_resists(mon);
// no Big Prize (tm) here either if you set all three flags. It's a pity uh?
//
// Note that natural monster resistance is two levels, this is duplicate
// the fact that having this flag used to be a lot better than armour
// for monsters (it used to make them immune in a lot of cases) -- bwr
- if (f & M_RES_HELLFIRE)
+ if (f & MR_RES_HELLFIRE)
u += 3;
- else if (f & M_RES_FIRE)
+ else if (f & MR_RES_FIRE)
u += 2;
- else if (f & M_ED_FIRE)
+ else if (f & MR_VUL_FIRE)
u--;
if (mons_itemuse(mc) >= MONUSE_STARTING_EQUIPMENT)
@@ -539,21 +752,21 @@ int mons_res_fire( struct monsters *mon )
} // end mons_res_fire()
-int mons_res_cold( struct monsters *mon )
+int mons_res_cold( const monsters *mon )
{
int mc = mon->type;
if (mc == MONS_PLAYER_GHOST || mc == MONS_PANDEMONIUM_DEMON)
return (ghost.values[ GVAL_RES_COLD ]);
- int u = 0, f = (seekmonster(&mc))->bitfields;
+ int u = 0, f = get_mons_resists(mon);
// Note that natural monster resistance is two levels, this is duplicate
// the fact that having this flag used to be a lot better than armour
// for monsters (it used to make them immune in a lot of cases) -- bwr
- if (f & M_RES_COLD)
+ if (f & MR_RES_COLD)
u += 2;
- else if (f & M_ED_COLD)
+ else if (f & MR_VUL_COLD)
u--;
if (mons_itemuse(mc) >= MONUSE_STARTING_EQUIPMENT)
@@ -582,15 +795,16 @@ int mons_res_cold( struct monsters *mon )
return (u);
} // end mons_res_cold()
-int mons_res_negative_energy( struct monsters *mon )
+int mons_res_negative_energy( const monsters *mon )
{
int mc = mon->type;
- if (mons_holiness( mon->type ) == MH_UNDEAD
- || mons_holiness( mon->type ) == MH_DEMONIC
- || mons_holiness( mon->type ) == MH_NONLIVING
- || mons_holiness( mon->type ) == MH_PLANT
- || mon->type == MONS_SHADOW_DRAGON)
+ if (mons_holiness(mon) == MH_UNDEAD
+ || mons_holiness(mon) == MH_DEMONIC
+ || mons_holiness(mon) == MH_NONLIVING
+ || mons_holiness(mon) == MH_PLANT
+ || mon->type == MONS_SHADOW_DRAGON
+ || mon->type == MONS_DEATH_DRAKE)
{
return (3); // to match the value for players
}
@@ -613,6 +827,26 @@ int mons_res_negative_energy( struct monsters *mon )
return (u);
} // end mons_res_negative_energy()
+bool mons_is_evil( const monsters *mon )
+{
+ return (mons_class_flag( mon->type, M_EVIL ));
+}
+
+bool mons_is_unholy( const monsters *mon )
+{
+ const mon_holy_type holy = mons_holiness( mon );
+
+ return (holy == MH_UNDEAD || holy == MH_DEMONIC);
+}
+
+bool mons_has_lifeforce( const monsters *mon )
+{
+ const int holy = mons_holiness( mon );
+
+ return (holy == MH_NATURAL || holy == MH_PLANT);
+ // && !mons_has_ench( mon, ENCH_PETRIFY ));
+}
+
int mons_skeleton(int mc)
{
if (mons_zombie_size(mc) == 0
@@ -624,7 +858,7 @@ int mons_skeleton(int mc)
return (1);
} // end mons_skeleton()
-char mons_class_flies(int mc)
+int mons_class_flies(int mc)
{
if (mc == MONS_PANDEMONIUM_DEMON)
return (ghost.values[ GVAL_DEMONLORD_FLY ]);
@@ -640,10 +874,9 @@ char mons_class_flies(int mc)
return (0);
}
-char mons_flies( struct monsters *mon )
+int mons_flies( const monsters *mon )
{
- char ret = mons_class_flies( mon->type );
-
+ int ret = mons_class_flies( mon->type );
return (ret ? ret : (scan_mon_inv_randarts(mon, RAP_LEVITATE) > 0) ? 2 : 0);
} // end mons_flies()
@@ -666,7 +899,7 @@ int hit_points(int hit_dice, int min_hp, int rand_hp)
// of monster, not a pacticular monsters current hit dice. -- bwr
int mons_type_hit_dice( int type )
{
- struct monsterentry *mon_class = seekmonster( &type );
+ struct monsterentry *mon_class = seekmonster( type );
if (mon_class)
return (mon_class->hpdice[0]);
@@ -675,7 +908,7 @@ int mons_type_hit_dice( int type )
}
-int exper_value( struct monsters *monster )
+int exper_value( const struct monsters *monster )
{
long x_val = 0;
@@ -690,10 +923,15 @@ int exper_value( struct monsters *monster )
const int item_usage = mons_itemuse(mclass);
// XXX: shapeshifters can qualify here, even though they can't cast:
- const bool spellcaster = mons_flag( mclass, M_SPELLCASTER );
+ const bool spellcaster = mons_class_flag( mclass, M_SPELLCASTER );
// early out for no XP monsters
- if (mons_flag(mclass, M_NO_EXP_GAIN))
+ if (mons_class_flag(mclass, M_NO_EXP_GAIN))
+ return (0);
+
+ // no experience for destroying furniture, even if the furniture started
+ // the fight.
+ if (mons_is_statue(mclass))
return (0);
// These undead take damage to maxhp, so we use only HD. -- bwr
@@ -718,14 +956,7 @@ int exper_value( struct monsters *monster )
// Let's look for big spells:
if (spellcaster)
{
- const int msecc = ((mclass == MONS_HELLION) ? MST_BURNING_DEVIL :
- (mclass == MONS_PANDEMONIUM_DEMON) ? MST_GHOST
- : monster->number);
-
- int hspell_pass[6] = { MS_NO_SPELL, MS_NO_SPELL, MS_NO_SPELL,
- MS_NO_SPELL, MS_NO_SPELL, MS_NO_SPELL };
-
- mons_spell_list( msecc, hspell_pass );
+ const monster_spells &hspell_pass = monster->spells;
for (int i = 0; i < 6; i++)
{
@@ -831,35 +1062,58 @@ int exper_value( struct monsters *monster )
return (x_val);
} // end exper_value()
+int obsolete_mons_spell_template_index(const monsters *mon)
+{
+ return (mons_class_flag(mon->type, M_SPELLCASTER)?
+ mon->number
+ : MST_NO_SPELLS);
+}
-// this needs to be rewritten a la the monsterseek rewrite {dlb}:
-void mons_spell_list( unsigned char sec, int splist[6] )
+void mons_load_spells( monsters *mon, int book )
{
- unsigned int x;
+ int x, y;
- for (x = 0; x < NUM_MSTYPES; x++)
+ if (book == MST_NO_SPELLS)
{
- if (mspell_list[x][0] == sec)
- break;
+ for (y = 0; y < NUM_MONSTER_SPELL_SLOTS; y++)
+ mon->spells[y] = MS_NO_SPELL;
+ return;
}
- if (x >= NUM_MSTYPES)
- return;
+#if DEBUG_DIAGNOSTICS
+ mprf( MSGCH_DIAGNOSTICS, "%s: loading spellbook #%d",
+ ptr_monam( mon, DESC_PLAIN ), book );
+#endif
- // I *KNOW* this can easily be done in a loop
- splist[0] = mspell_list[x][1]; // bolt spell
- splist[1] = mspell_list[x][2]; // enchantment
- splist[2] = mspell_list[x][3]; // self_ench
- splist[3] = mspell_list[x][4]; // misc
- splist[4] = mspell_list[x][5]; // misc2
- splist[5] = mspell_list[x][6]; // emergency
+ for (x = 0; x < 6; x++)
+ mon->spells[x] = MS_NO_SPELL;
- if (sec == MST_GHOST) /* ghost */
+ if (book == MST_GHOST)
+ {
+ for (y = 0; y < NUM_MONSTER_SPELL_SLOTS; y++)
+ {
+ mon->spells[y] = ghost.values[ GVAL_SPELL_1 + y ];
+#if DEBUG_DIAGNOSTICS
+ mprf( MSGCH_DIAGNOSTICS, "spell #%d: %d", y, mon->spells[y] );
+#endif
+ }
+ }
+ else
{
- for (x = 0; x < 6; x++)
- splist[x] = ghost.values[ GVAL_SPELL_1 + x ];
+ // this needs to be rewritten a la the monsterseek rewrite {dlb}:
+ for (x = 0; x < NUM_MSTYPES; x++)
+ {
+ if (mspell_list[x][0] == book)
+ break;
+ }
+
+ if (x < NUM_MSTYPES)
+ {
+ for (y = 0; y < 6; y++)
+ mon->spells[y] = mspell_list[x][y + 1];
+ }
}
-} // end mons_spell_list()
+}
#if DEBUG_DIAGNOSTICS
const char *mons_spell_name( int spell )
@@ -872,152 +1126,200 @@ const char *mons_spell_name( int spell )
#endif
// generate a shiny new and unscarred monster
-void define_monster(int k)
+void define_monster(int index)
{
+ monsters &mons = menv[index];
+
int temp_rand = 0; // probability determination {dlb}
- int m2_class = menv[k].type;
- int m2_HD, m2_hp, m2_hp_max, m2_AC, m2_ev, m2_speed;
- int m2_sec = menv[k].number;
- struct monsterentry *m = seekmonster(&m2_class);
+ int mcls = mons.type;
+ int hd, hp, hp_max, ac, ev, speed;
+ int monnumber = mons.number;
+ const monsterentry *m = seekmonster(mcls);
+ int col = mons_class_colour(mons.type);
+ int spells = MST_NO_SPELLS;
- m2_HD = m->hpdice[0];
+ hd = m->hpdice[0];
// misc
- m2_AC = m->AC;
- m2_ev = m->ev;
+ ac = m->AC;
+ ev = m->ev;
- // speed
- m2_speed = m->speed;
+ speed = m->speed;
- // some monsters are randomized:
- // did I get them all? // I don't think so {dlb}
- if (mons_is_mimic( m2_class ))
- m2_sec = get_mimic_colour( &menv[k] );
- else
+ switch (mcls)
{
- switch (m2_class)
- {
- case MONS_ABOMINATION_SMALL:
- m2_HD = 4 + random2(4);
- m2_AC = 3 + random2(7);
- m2_ev = 7 + random2(6);
- m2_speed = 7 + random2avg(9, 2);
-
- if (m2_sec == 250)
- m2_sec = random_colour();
- break;
+ case MONS_ABOMINATION_SMALL:
+ hd = 4 + random2(4);
+ ac = 3 + random2(7);
+ ev = 7 + random2(6);
+ speed = 7 + random2avg(9, 2);
+
+ if (monnumber == 250)
+ col = random_colour();
+ break;
- case MONS_ZOMBIE_SMALL:
- m2_HD = (coinflip() ? 1 : 2);
- break;
+ case MONS_ZOMBIE_SMALL:
+ hd = (coinflip() ? 1 : 2);
+ break;
- case MONS_ZOMBIE_LARGE:
- m2_HD = 3 + random2(5);
- break;
+ case MONS_ZOMBIE_LARGE:
+ hd = 3 + random2(5);
+ break;
- case MONS_ABOMINATION_LARGE:
- m2_HD = 8 + random2(4);
- m2_AC = 5 + random2avg(9, 2);
- m2_ev = 3 + random2(5);
- m2_speed = 6 + random2avg(7, 2);
+ case MONS_ABOMINATION_LARGE:
+ hd = 8 + random2(4);
+ ac = 5 + random2avg(9, 2);
+ ev = 3 + random2(5);
+ speed = 6 + random2avg(7, 2);
- if (m2_sec == 250)
- m2_sec = random_colour();
- break;
+ if (monnumber == 250)
+ col = random_colour();
+ break;
- case MONS_BEAST:
- m2_HD = 4 + random2(4);
- m2_AC = 2 + random2(5);
- m2_ev = 7 + random2(5);
- m2_speed = 8 + random2(5);
- break;
+ case MONS_BEAST:
+ hd = 4 + random2(4);
+ ac = 2 + random2(5);
+ ev = 7 + random2(5);
+ speed = 8 + random2(5);
+ break;
- case MONS_HYDRA:
- m2_sec = 4 + random2(5);
- break;
+ case MONS_HYDRA:
+ monnumber = random_range(4, 8);
+ break;
- case MONS_DEEP_ELF_FIGHTER:
- case MONS_DEEP_ELF_KNIGHT:
- case MONS_DEEP_ELF_SOLDIER:
- case MONS_ORC_WIZARD:
- m2_sec = MST_ORC_WIZARD_I + random2(3);
- break;
+ case MONS_DEEP_ELF_FIGHTER:
+ case MONS_DEEP_ELF_KNIGHT:
+ case MONS_DEEP_ELF_SOLDIER:
+ case MONS_ORC_WIZARD:
+ spells = MST_ORC_WIZARD_I + random2(3);
+ break;
- case MONS_LICH:
- case MONS_ANCIENT_LICH:
- m2_sec = MST_LICH_I + random2(4);
- break;
+ case MONS_LICH:
+ case MONS_ANCIENT_LICH:
+ spells = MST_LICH_I + random2(4);
+ break;
- case MONS_HELL_KNIGHT:
- m2_sec = (coinflip() ? MST_HELL_KNIGHT_I : MST_HELL_KNIGHT_II);
- break;
+ case MONS_HELL_KNIGHT:
+ spells = (coinflip() ? MST_HELL_KNIGHT_I : MST_HELL_KNIGHT_II);
+ break;
- case MONS_NECROMANCER:
- m2_sec = (coinflip() ? MST_NECROMANCER_I : MST_NECROMANCER_II);
- break;
+ case MONS_NECROMANCER:
+ spells = (coinflip() ? MST_NECROMANCER_I : MST_NECROMANCER_II);
+ break;
- case MONS_WIZARD:
- case MONS_OGRE_MAGE:
- case MONS_EROLCHA:
- case MONS_DEEP_ELF_MAGE:
- m2_sec = MST_WIZARD_I + random2(5);
- break;
+ case MONS_WIZARD:
+ case MONS_OGRE_MAGE:
+ case MONS_EROLCHA:
+ case MONS_DEEP_ELF_MAGE:
+ spells = MST_WIZARD_I + random2(5);
+ break;
- case MONS_DEEP_ELF_CONJURER:
- m2_sec = (coinflip()? MST_DEEP_ELF_CONJURER_I : MST_DEEP_ELF_CONJURER_II);
- break;
+ case MONS_DEEP_ELF_CONJURER:
+ spells =
+ (coinflip()? MST_DEEP_ELF_CONJURER_I : MST_DEEP_ELF_CONJURER_II);
+ break;
- case MONS_BUTTERFLY:
- case MONS_SPATIAL_VORTEX:
- case MONS_KILLER_KLOWN:
- m2_sec = random_colour();
- break;
+ case MONS_BUTTERFLY:
+ case MONS_SPATIAL_VORTEX:
+ case MONS_KILLER_KLOWN:
+ col = random_colour();
+ break;
- case MONS_GILA_MONSTER:
- temp_rand = random2(7);
+ case MONS_GILA_MONSTER:
+ temp_rand = random2(7);
- m2_sec = (temp_rand >= 5 ? LIGHTRED : // 2/7
- temp_rand >= 3 ? LIGHTMAGENTA : // 2/7
- temp_rand == 2 ? RED : // 1/7
- temp_rand == 1 ? MAGENTA // 1/7
- : YELLOW); // 1/7
- break;
+ col = (temp_rand >= 5 ? LIGHTRED : // 2/7
+ temp_rand >= 3 ? LIGHTMAGENTA : // 2/7
+ temp_rand == 2 ? RED : // 1/7
+ temp_rand == 1 ? MAGENTA // 1/7
+ : YELLOW); // 1/7
+ break;
- case MONS_HUMAN:
- case MONS_ELF:
- // these are supposed to only be created by polymorph
- m2_HD += random2(10);
- m2_AC += random2(5);
- m2_ev += random2(5);
- break;
+ case MONS_DRACONIAN:
+ // these are supposed to only be created by polymorph
+ hd += random2(10);
+ ac += random2(5);
+ ev += random2(5);
- default:
- break;
+ if (hd >= 7)
+ {
+ mons.type = MONS_BLACK_DRACONIAN + random2(8);
+ col = mons_class_colour( mons.type );
}
+ break;
+
+ case MONS_DRACONIAN_CALLER:
+ case MONS_DRACONIAN_MONK:
+ case MONS_DRACONIAN_ZEALOT:
+ case MONS_DRACONIAN_SHIFTER:
+ case MONS_DRACONIAN_ANNIHILATOR:
+ case MONS_DRACONIAN_SCORCHER:
+ {
+ // Professional draconians still have a base draconian type.
+ // White draconians will never be draconian scorchers, but
+ // apart from that, anything goes.
+ do
+ monnumber = MONS_BLACK_DRACONIAN + random2(8);
+ while (monnumber == MONS_WHITE_DRACONIAN
+ && mcls == MONS_DRACONIAN_SCORCHER);
+ break;
+ }
+ case MONS_DRACONIAN_KNIGHT:
+ {
+ temp_rand = random2(10);
+ // hell knight, death knight, chaos knight...
+ if (temp_rand < 6)
+ spells = (coinflip() ? MST_HELL_KNIGHT_I : MST_HELL_KNIGHT_II);
+ else if (temp_rand < 9)
+ spells = (coinflip() ? MST_NECROMANCER_I : MST_NECROMANCER_II);
+ else
+ spells = (coinflip() ? MST_DEEP_ELF_CONJURER_I
+ : MST_DEEP_ELF_CONJURER_II);
+
+ monnumber = MONS_BLACK_DRACONIAN + random2(8);
+ break;
}
+ case MONS_HUMAN:
+ case MONS_ELF:
+ // these are supposed to only be created by polymorph
+ hd += random2(10);
+ ac += random2(5);
+ ev += random2(5);
+ break;
+
+ default:
+ if (mons_is_mimic( mcls ))
+ col = get_mimic_colour( &mons );
+ break;
+ }
+
+ if (spells == MST_NO_SPELLS && mons_class_flag(mons.type, M_SPELLCASTER))
+ spells = m->sec;
// some calculations
- m2_hp = hit_points(m2_HD, m->hpdice[1], m->hpdice[2]);
- m2_hp += m->hpdice[3];
- m2_hp_max = m2_hp;
+ hp = hit_points(hd, m->hpdice[1], m->hpdice[2]);
+ hp += m->hpdice[3];
+ hp_max = hp;
- if (m2_sec == 250)
- m2_sec = m->sec;
+ if (monnumber == 250)
+ monnumber = m->sec;
// so let it be written, so let it be done
- menv[k].hit_dice = m2_HD;
- menv[k].hit_points = m2_hp;
- menv[k].max_hit_points = m2_hp_max;
- menv[k].armour_class = m2_AC;
- menv[k].evasion = m2_ev;
- menv[k].speed = m2_speed;
- menv[k].speed_increment = 70;
- menv[k].number = m2_sec;
- menv[k].flags = 0;
+ mons.hit_dice = hd;
+ mons.hit_points = hp;
+ mons.max_hit_points = hp_max;
+ mons.armour_class = ac;
+ mons.evasion = ev;
+ mons.speed = speed;
+ mons.speed_increment = 70;
+ mons.number = monnumber;
+ mons.flags = 0;
+ mons.colour = col;
+ mons_load_spells( &mons, spells );
// reset monster enchantments
for (int i = 0; i < NUM_MON_ENCHANTS; i++)
- menv[k].enchantment[i] = ENCH_NONE;
+ mons.enchantment[i] = ENCH_NONE;
} // end define_monster()
@@ -1048,7 +1350,7 @@ const char *monam( int mons_num, int mons, bool vis, char desc, int mons_wpn )
static char gmo_n[ ITEMNAME_SIZE ];
char gmo_n2[ ITEMNAME_SIZE ] = "";
- gmo_n[0] = '\0';
+ gmo_n[0] = 0;
// If you can't see the critter, let moname() print [Ii]t.
if (!vis)
@@ -1059,7 +1361,7 @@ const char *monam( int mons_num, int mons, bool vis, char desc, int mons_wpn )
// These need their description level handled here instead of
// in monam().
- if (mons == MONS_SPECTRAL_THING)
+ if (mons == MONS_SPECTRAL_THING || mons_genus(mons) == MONS_DRACONIAN)
{
switch (desc)
{
@@ -1107,6 +1409,33 @@ const char *monam( int mons_num, int mons, bool vis, char desc, int mons_wpn )
strcat(gmo_n, gmo_n2);
break;
+ case MONS_DRACONIAN_CALLER:
+ case MONS_DRACONIAN_MONK:
+ case MONS_DRACONIAN_ZEALOT:
+ case MONS_DRACONIAN_SHIFTER:
+ case MONS_DRACONIAN_ANNIHILATOR:
+ case MONS_DRACONIAN_KNIGHT:
+ case MONS_DRACONIAN_SCORCHER:
+ if (desc != DESC_PLAIN)
+ strcat( gmo_n, " " );
+
+ switch (mons_num)
+ {
+ default: break;
+ case MONS_BLACK_DRACONIAN: strcat(gmo_n, "black "); break;
+ case MONS_MOTTLED_DRACONIAN: strcat(gmo_n, "mottled "); break;
+ case MONS_YELLOW_DRACONIAN: strcat(gmo_n, "yellow "); break;
+ case MONS_GREEN_DRACONIAN: strcat(gmo_n, "green "); break;
+ case MONS_PURPLE_DRACONIAN: strcat(gmo_n, "purple "); break;
+ case MONS_RED_DRACONIAN: strcat(gmo_n, "red "); break;
+ case MONS_WHITE_DRACONIAN: strcat(gmo_n, "white "); break;
+ case MONS_PALE_DRACONIAN: strcat(gmo_n, "pale "); break;
+ }
+
+ moname( mons, vis, DESC_PLAIN, gmo_n2 );
+ strcat( gmo_n, gmo_n2 );
+ break;
+
case MONS_DANCING_WEAPON:
// safety check -- if we don't have/know the weapon use default name
if (mons_wpn == NON_ITEM)
@@ -1136,12 +1465,12 @@ const char *monam( int mons_num, int mons, bool vis, char desc, int mons_wpn )
return (gmo_n);
} // end monam()
-void moname(int mons_num, bool vis, char descrip, char glog[ ITEMNAME_SIZE ])
+const char *moname(int mons_num, bool vis, char descrip, char glog[ ITEMNAME_SIZE ])
{
- glog[0] = '\0';
+ glog[0] = 0;
char gmon_name[ ITEMNAME_SIZE ] = "";
- strcpy( gmon_name, seekmonster( &mons_num )->name );
+ strcpy( gmon_name, seekmonster( mons_num )->name );
if (!vis)
{
@@ -1159,7 +1488,7 @@ void moname(int mons_num, bool vis, char descrip, char glog[ ITEMNAME_SIZE ])
}
strcpy(gmon_name, glog);
- return;
+ return (glog);
}
if (!mons_is_unique( mons_num ))
@@ -1203,19 +1532,19 @@ void moname(int mons_num, bool vis, char descrip, char glog[ ITEMNAME_SIZE ])
}
strcat(glog, gmon_name);
+
+ return (glog);
} // end moname()
/* ********************* END PUBLIC FUNCTIONS ********************* */
// see mons_init for initialization of mon_entry array.
-static struct monsterentry *seekmonster(int *p_monsterid)
+static monsterentry *seekmonster(int p_monsterid)
{
- ASSERT(p_monsterid != 0);
-
- int me = mon_entry[(*p_monsterid)];
+ int me = p_monsterid != -1? mon_entry[p_monsterid] : -1;
if (me >= 0) // PARANOIA
- return (&mondata[mon_entry[(*p_monsterid)]]);
+ return (&mondata[me]);
else
return (NULL);
} // end seekmonster()
@@ -1261,7 +1590,7 @@ int mons_intel_type(int mc) //jmf: new, used by my spells
int mons_power(int mc)
{
- // for now, just return monster hit dice.
+ // for now, just return monster hit dice.
return (smc->hpdice[0]);
}
@@ -1292,79 +1621,67 @@ bool mons_aligned(int m1, int m2)
return (fr1 == fr2);
}
-bool mons_friendly(struct monsters *m)
+bool mons_friendly(const monsters *m)
{
return (m->attitude == ATT_FRIENDLY || mons_has_ench(m, ENCH_CHARM));
}
-bool mons_is_stabbable(struct monsters *m)
+bool mons_is_submerged( struct monsters *mon )
{
- // Make sure oklob plants are never highlighted. That'll defeat the
- // point of making them look like normal plants.
- return (!mons_flag(m->type, M_NO_EXP_GAIN)
- && m->type != MONS_OKLOB_PLANT
- && !mons_friendly(m)
- && m->behaviour == BEH_SLEEP);
+ // FIXME, switch to 4.1's MF_SUBMERGED system which is much cleaner.
+ return (mons_has_ench( mon, ENCH_SUBMERGED ));
}
-bool mons_maybe_stabbable(struct monsters *m)
+bool mons_is_paralysed(const monsters *m)
{
- return (!mons_flag(m->type, M_NO_EXP_GAIN)
- && m->type != MONS_OKLOB_PLANT
- && !mons_friendly(m)
- && ((m->foe != MHITYOU && !testbits(m->flags, MF_BATTY))
- || (mons_has_ench(m, ENCH_CONFUSION) &&
- !mons_flag(m->type, M_CONFUSED))
- || m->behaviour == BEH_FLEE));
+ // maybe this should be 70
+ return (m->speed_increment <= 60);
}
-/* ******************************************************************
-
-// In the name of England, I declare this function wasteful! {dlb}
-
-static monsterentry *seekmonster( int mc )
+bool mons_is_confused(const monsters *m)
{
+ return (mons_has_ench(m, ENCH_CONFUSION) &&
+ !mons_class_flag(m->type, M_CONFUSED));
+}
- ASSERT(mc >= 0);
-
- int x = 0;
-
- while (x < mondatasize)
- {
- if (mondata[x].mc == mc)
- return &mondata[x];
-
- x++;
- }
-
- ASSERT(false);
-
- return seekmonster(MONS_PROGRAM_BUG); // see the disasters coming if there is no 250?
-
-} // end seekmonster()
-****************************************************************** */
-
-
-/* ******************************************************************
-
-// only used once, and internal to this file, to boot {dlb}:
-
-// These are easy to implement here. The difficult (dull!) work of converting
-// the data structures is finally finished now!
-inline char *mons_name( int mc )
+bool mons_is_fleeing(const monsters *m)
{
+ return (m->behaviour == BEH_FLEE);
+}
- return smc->name;
-
-} // end mons_name()
-****************************************************************** */
+bool mons_is_sleeping(const monsters *m)
+{
+ return (m->behaviour == BEH_SLEEP);
+}
-/*****************************************************************
+bool mons_is_batty(const monsters *m)
+{
+ return testbits(m->flags, MF_BATTY);
+}
- Used to determine whether or not a monster should fire a beam (MUST be
- called _after_ fire_tracer() for meaningful result.
+bool mons_looks_stabbable(const monsters *m)
+{
+ // Make sure oklob plants are never highlighted. That'll defeat the
+ // point of making them look like normal plants.
+ return (!mons_class_flag(m->type, M_NO_EXP_GAIN)
+ && m->type != MONS_OKLOB_PLANT
+ && !mons_is_mimic(m->type)
+ && !mons_is_statue(m->type)
+ && !mons_friendly(m)
+ && mons_is_sleeping(m));
+}
-*/
+bool mons_looks_distracted(const monsters *m)
+{
+ return (!mons_class_flag(m->type, M_NO_EXP_GAIN)
+ && m->type != MONS_OKLOB_PLANT
+ && !mons_is_mimic(m->type)
+ && !mons_is_statue(m->type)
+ && !mons_friendly(m)
+ && ((m->foe != MHITYOU && !mons_is_batty(m))
+ || mons_is_confused(m)
+ || mons_is_fleeing(m)));
+}
bool mons_should_fire(struct bolt &beam)
{
@@ -1380,19 +1697,19 @@ bool mons_should_fire(struct bolt &beam)
return (false);
// if we either hit no friends, or monster too dumb to care
- if (beam.fr_count == 0 || !beam.smartMonster)
+ if (beam.fr_count == 0 || !beam.smart_monster)
return (true);
// only fire if they do acceptably low collateral damage
// the default for this is 50%; in other words, don't
// hit a foe unless you hit 2 or fewer friends.
- if (beam.foe_power >= (beam.foeRatio * beam.fr_power) / 100)
+ if (beam.foe_power >= (beam.foe_ratio * beam.fr_power) / 100)
return (true);
return (false);
}
-int mons_has_ench(struct monsters *mon, unsigned int ench, unsigned int ench2)
+int mons_has_ench(const monsters *mon, unsigned int ench, unsigned int ench2)
{
// silliness
if (ench == ENCH_NONE)
@@ -1474,7 +1791,7 @@ int mons_del_ench( struct monsters *mon, unsigned int ench, unsigned int ench2,
if (ench == ENCH_INVIS)
{
// invisible monsters stay invisible
- if (mons_flag(mon->type, M_INVIS))
+ if (mons_class_flag(mon->type, M_INVIS))
{
mon->enchantment[p] = ENCH_INVIS;
}
@@ -1487,6 +1804,7 @@ int mons_del_ench( struct monsters *mon, unsigned int ench, unsigned int ench2,
strcat( info, " appears!" );
mpr( info );
}
+ seen_monster(mon);
}
}
@@ -1598,6 +1916,7 @@ bool ms_requires_tracer(int monspell)
case MS_IRON_BOLT:
case MS_LIGHTNING_BOLT:
case MS_MARSH_GAS:
+ case MS_MIASMA:
case MS_METAL_SPLINTERS:
case MS_MMISSILE:
case MS_NEGATIVE_BOLT:
@@ -1605,6 +1924,7 @@ bool ms_requires_tracer(int monspell)
case MS_PAIN:
case MS_PARALYSIS:
case MS_POISON_BLAST:
+ case MS_POISON_ARROW:
case MS_POISON_SPLASH:
case MS_QUICKSILVER_BOLT:
case MS_SLOW:
@@ -1637,6 +1957,7 @@ bool ms_requires_tracer(int monspell)
case MS_SUMMON_UFETUBUS:
case MS_TELEPORT:
case MS_TORMENT:
+ case MS_SUMMON_SMALL_MAMMALS:
case MS_VAMPIRE_SUMMON:
case MS_CANTRIP:
@@ -1677,6 +1998,7 @@ bool ms_direct_nasty(int monspell)
case MS_SUMMON_DEMON_GREATER:
case MS_SUMMON_UFETUBUS:
case MS_TELEPORT:
+ case MS_SUMMON_SMALL_MAMMALS:
case MS_VAMPIRE_SUMMON:
nasty = false;
break;
@@ -1714,6 +2036,7 @@ bool ms_useful_fleeing_out_of_sight( struct monsters *mon, int monspell )
case MS_ANIMATE_DEAD:
return (true);
+ case MS_SUMMON_SMALL_MAMMALS:
case MS_VAMPIRE_SUMMON:
case MS_SUMMON_UFETUBUS:
case MS_FAKE_RAKSHASA_SUMMON:
@@ -1722,6 +2045,7 @@ bool ms_useful_fleeing_out_of_sight( struct monsters *mon, int monspell )
case MS_SUMMON_DEMON_LESSER:
case MS_SUMMON_BEAST:
case MS_SUMMON_UNDEAD:
+ case MS_SUMMON_MUSHROOMS:
case MS_SUMMON_DEMON_GREATER:
if (one_chance_in(10)) // only summon friends some of the time
return (true);
@@ -1763,6 +2087,7 @@ bool ms_low_hitpoint_cast( struct monsters *mon, int monspell )
ret = true;
break;
+ case MS_SUMMON_SMALL_MAMMALS:
case MS_VAMPIRE_SUMMON:
case MS_SUMMON_UFETUBUS:
case MS_FAKE_RAKSHASA_SUMMON:
@@ -1793,7 +2118,8 @@ bool ms_waste_of_time( struct monsters *mon, int monspell )
break;
case MS_INVIS:
- if (mons_has_ench( mon, ENCH_INVIS ))
+ if (mons_has_ench( mon, ENCH_INVIS ) ||
+ (mons_friendly(mon) && !player_see_invis(false)))
ret = true;
break;
@@ -1902,20 +2228,11 @@ bool mons_has_ranged_spell( struct monsters *mon )
{
const int mclass = mon->type;
- if (mons_flag( mclass, M_SPELLCASTER ))
+ if (mons_class_flag( mclass, M_SPELLCASTER ))
{
- const int msecc = ((mclass == MONS_HELLION) ? MST_BURNING_DEVIL :
- (mclass == MONS_PANDEMONIUM_DEMON) ? MST_GHOST
- : mon->number);
-
- int hspell_pass[6] = { MS_NO_SPELL, MS_NO_SPELL, MS_NO_SPELL,
- MS_NO_SPELL, MS_NO_SPELL, MS_NO_SPELL };
-
- mons_spell_list( msecc, hspell_pass );
-
- for (int i = 0; i < 6; i++)
+ for (int i = 0; i < NUM_MONSTER_SPELL_SLOTS; i++)
{
- if (ms_ranged_spell( hspell_pass[i] ))
+ if (ms_ranged_spell( mon->spells[i] ))
return (true);
}
}
@@ -2004,3 +2321,98 @@ const char *mons_pronoun(int mon_type, int variant)
return ("");
}
+
+/*
+ * Checks if the monster can use smiting/torment to attack without unimpeded
+ * LOS to the player.
+ */
+static bool mons_can_smite(const monsters *monster)
+{
+ if (monster->type == MONS_FIEND)
+ return (true);
+
+ const monster_spells &hspell_pass = monster->spells;
+ for (unsigned i = 0; i < hspell_pass.size(); ++i)
+ if (hspell_pass[i] == MS_TORMENT || hspell_pass[i] == MS_SMITE)
+ return (true);
+
+ return (false);
+}
+
+/*
+ * Determines if a monster is smart and pushy enough to displace other monsters.
+ * A shover should not cause damage to the shovee by displacing it, so monsters
+ * that trail clouds of badness are ineligible. The shover should also benefit
+ * from shoving, so monsters that can smite/torment are ineligible.
+ *
+ * (Smiters would be eligible for shoving when fleeing if the AI allowed for
+ * smart monsters to flee.)
+ */
+bool monster_shover(const monsters *m)
+{
+ const monsterentry *me = seekmonster(m->type);
+ if (!me)
+ return (false);
+
+ // Efreet and fire elementals are disqualified because they leave behind
+ // clouds of flame. Rotting devils trail clouds of miasma.
+ if (m->type == MONS_EFREET || m->type == MONS_FIRE_ELEMENTAL
+ || m->type == MONS_ROTTING_DEVIL
+ || m->type == MONS_CURSE_TOE)
+ return (false);
+
+ // Smiters profit from staying back and smiting.
+ if (mons_can_smite(m))
+ return (false);
+
+ int mchar = me->showchar;
+ // Somewhat arbitrary: giants and dragons are too big to get past anything,
+ // beetles are too dumb (arguable), dancing weapons can't communicate, eyes
+ // aren't pushers and shovers, zombies are zombies. Worms and elementals
+ // are on the list because all 'w' are currently unrelated.
+ return (mchar != 'C' && mchar != 'B' && mchar != '(' && mchar != 'D'
+ && mchar != 'G' && mchar != 'Z' && mchar != 'z'
+ && mchar != 'w' && mchar != '#');
+}
+
+// Returns true if m1 and m2 are related, and m1 is higher up the totem pole
+// than m2. The criteria for being related are somewhat loose, as you can see
+// below.
+bool monster_senior(const monsters *m1, const monsters *m2)
+{
+ const monsterentry *me1 = seekmonster(m1->type),
+ *me2 = seekmonster(m2->type);
+
+ if (!me1 || !me2)
+ return (false);
+
+ int mchar1 = me1->showchar,
+ mchar2 = me2->showchar;
+
+ // If both are demons, the smaller number is the nastier demon.
+ if (isdigit(mchar1) && isdigit(mchar2))
+ return (mchar1 < mchar2);
+
+ // &s are the evillest demons of all, well apart from Geryon, who really
+ // profits from *not* pushing past beasts.
+ if (mchar1 == '&' && isdigit(mchar2) && m1->type != MONS_GERYON)
+ return (m1->hit_dice > m2->hit_dice);
+
+ // Skeletal warriors can push past zombies large and small.
+ if (m1->type == MONS_SKELETAL_WARRIOR && (mchar2 == 'z' || mchar2 == 'Z'))
+ return (m1->hit_dice > m2->hit_dice);
+
+ if (m1->type == MONS_QUEEN_BEE
+ && (m2->type == MONS_KILLER_BEE
+ || m2->type == MONS_KILLER_BEE_LARVA))
+ return (true);
+
+ if (m1->type == MONS_KILLER_BEE && m2->type == MONS_KILLER_BEE_LARVA)
+ return (true);
+
+ // Special-case gnolls so they can't get past (hob)goblins
+ if (m1->type == MONS_GNOLL && m2->type != MONS_GNOLL)
+ return (false);
+
+ return (mchar1 == mchar2 && m1->hit_dice > m2->hit_dice);
+}
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index 9a1fc22688..3ad17c8f11 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -15,57 +15,10 @@
#define MONUTIL_H
#include "externs.h"
+#include "enum.h"
// ($pellbinder) (c) D.G.S.E. 1998
-// ****remember***** must make an hardcopy of this sometime
-
-#if defined(macintosh) || defined(__IBMCPP__) || defined(SOLARIS) || defined(__BCPLUSPLUS__)
-#define PACKED
-#else
-#ifndef PACKED
-#define PACKED __attribute__ ((packed))
-#endif
-#endif
-
-// leaves no skeleton? ("blob" monsters?)
-// if weight=0 or zombie_size=0, this is always true
-#define M_NO_FLAGS 0 // clear
-#define M_NO_SKELETON (1<<0)
-// resistances
-#define M_RES_ELEC (1<<1)
-#define M_RES_POISON (1<<2)
-#define M_RES_FIRE (1<<3)
-#define M_RES_HELLFIRE (1<<4)
-#define M_RES_COLD (1<<5)
-// invisible
-#define M_INVIS (1<<6) // is created with invis enchantment set, and never runs out
-// vulnerabilities
-//#define M_ED_ELEC (1<<6) // never used
-#define M_ED_POISON (1<<7) // ??? - - This flag is now (2.50) set for insects (LRH)
-#define M_ED_FIRE (1<<8)
-#define M_ED_COLD (1<<9)
-#define M_SPELLCASTER (1<<10) // any non-physical-attack powers
-#define M_FLIES (1<<11) // will crash to ground if paralysed (wings)
-#define M_LEVITATE (1<<12) // not if this is set
-#define M_SEE_INVIS (1<<13)
-// killing this beast only gives 10 experience (makes sense for plants/fungi)
-#define M_NO_EXP_GAIN (1<<14) // must do this manually
-#define M_SPEAKS (1<<15)
-//jmf: M_SPELLCASTER was taken ... :-b
-#define M_ACTUAL_SPELLS (1<<16) // monster is a wizard
-#define M_PRIEST (1<<17) // monster is a priest of Brian's Orc God (BOG)
-#define M_COLD_BLOOD (1<<18)
-#define M_WARM_BLOOD (1<<19)
-#define M_CONFUSED (1<<20) // monster is perma-confused
-#define M_SPLITS (1<<21) // monster is perma-confused
-#define M_AMPHIBIOUS (1<<22) // monster can swim in water
-
-//jmf: it'd be nice if these next two were implimented ...
-#define M_ON_FIRE (1<<29) // flag for Hellion-like colour shift
-#define M_FROZEN (1<<30) // flag for ice-like colour shift
-
-
// zombie size
#define Z_NOZOMBIE 0 // no zombie (and no skeleton)
#define Z_SMALL 1
@@ -111,7 +64,9 @@ struct monsterentry
unsigned char showchar, colour;
const char *name /*[32]*/; //longest is 23 till now (31 is max alowed here)
- int bitfields;
+ unsigned long bitfields;
+ unsigned long resists;
+
short weight;
// experience is calculated like this:
// ((((max_hp / 7) + 1) * (mHD * mHD) + 1) * exp_mod) / 10
@@ -119,9 +74,10 @@ struct monsterentry
// Note that this may make draining attacks less attractive (LRH)
char exp_mod;
- unsigned short charclass; //
+ monster_type genus, // "team" the monster plays for
+ species; // corpse type of the monster
- char holiness; // -1=holy,0=normal,1=undead,2=very very evil
+ mon_holy_type holiness; // -1=holy,0=normal,1=undead,2=very very evil
short resist_magic; // (positive is ??)
// max damage in a turn is total of these four?
@@ -146,7 +102,7 @@ struct monsterentry
short sec; // not used (250) most o/t time
// eating the corpse: 1=clean,2=might be contaminated,3=poison,4=very bad
- char corpse_thingy;
+ corpse_effect_type corpse_thingy;
// 0=no zombie, 1=small zombie (z) 107, 2=_BIG_ zombie (Z) 108
char zombie_size;
// 0-12: see above, -1=random one of (0-7)
@@ -165,7 +121,7 @@ struct monsterentry
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
-void mons_init( FixedVector<unsigned short, 1000>& colour );
+void init_monsters( FixedVector<unsigned short, 1000>& colour );
// last updated 12may2000 {dlb}
/* ***********************************************************************
@@ -184,8 +140,8 @@ const char *ptr_monam( struct monsters *mon, char desc );
/* ***********************************************************************
* called from: beam - direct - fight - monstuff - mstuff2 - spells4 - view
* *********************************************************************** */
-char mons_class_flies( int mc );
-char mons_flies( struct monsters *mon );
+int mons_class_flies( int mc );
+int mons_flies( const monsters *mon );
// last updated XXmay2000 {dlb}
@@ -218,7 +174,7 @@ bool mons_is_unique(int mclass);
* called from: describe - fight
* *********************************************************************** */
// int exper_value(int mclass, int mHD, int maxhp);
-int exper_value( struct monsters *monster );
+int exper_value( const struct monsters *monster );
// last updated 12may2000 {dlb}
@@ -234,8 +190,8 @@ int mons_type_hit_dice( int type );
/* ***********************************************************************
* called from: beam - effects
* *********************************************************************** */
-int mons_resist_magic( struct monsters *mon );
-int mons_resist_turn_undead( struct monsters *mon );
+int mons_resist_magic( const monsters *mon );
+int mons_resist_turn_undead( const monsters *mon );
// last updated 12may2000 {dlb}
@@ -247,23 +203,15 @@ int mons_damage(int mc, int rt);
// last updated 12may2000 {dlb}
/* ***********************************************************************
- * called from: dungeon - fight - monstuff - spells4
- * *********************************************************************** */
-int mons_charclass(int mcls);
-
-
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
* called from: food - spells4
* *********************************************************************** */
-int mons_corpse_thingy(int mclass);
-
+corpse_effect_type mons_corpse_effect(int mc);
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: dungeon - fight - monstuff - mon-util
* *********************************************************************** */
-int mons_flag(int mc, int bf);
+bool mons_class_flag(int mc, int bf);
// last updated 12may2000 {dlb}
@@ -271,10 +219,12 @@ int mons_flag(int mc, int bf);
* called from: beam - effects - fight - monstuff - mstuff2 - spells2 -
* spells3 - spells4
* *********************************************************************** */
-int mons_holiness(int mclass);
+mon_holy_type mons_class_holiness(int mclass);
+mon_holy_type mons_holiness(const monsters *);
bool mons_is_mimic( int mc );
-bool mons_is_demon( int mc );
+bool mons_is_statue(int mc);
+bool mons_is_demon( int mc );
bool mons_is_humanoid( int mc );
@@ -296,30 +246,32 @@ int mons_intel_type(int mclass); //jmf: added 20mar2000
/* ***********************************************************************
* called from: beam - fight - monstuff
* *********************************************************************** */
-int mons_res_cold( struct monsters *mon );
+int mons_res_cold( const monsters *mon );
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: beam - fight - spells4
* *********************************************************************** */
-int mons_res_elec( struct monsters *mon );
+int mons_res_elec( const monsters *mon );
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: beam - fight - monstuff
* *********************************************************************** */
-int mons_res_fire( struct monsters *mon );
+int mons_res_fire( const monsters *mon );
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: beam - monstuff - spells4
* *********************************************************************** */
-int mons_res_poison( struct monsters *mon );
+int mons_res_poison( const monsters *mon );
-int mons_res_negative_energy( struct monsters *mon );
+int mons_res_negative_energy( const monsters *mon );
+
+bool mons_res_asphyx( const monsters *mon );
// last updated 12may2000 {dlb}
@@ -376,8 +328,13 @@ unsigned char mons_char(int mc);
/* ***********************************************************************
* called from: dungeon - fight - misc
* *********************************************************************** */
-unsigned char mons_colour(int mc);
+int mons_class_colour(int mc);
+int mons_colour(const monsters *m);
+
+// Only for save-compatibility.
+int obsolete_mons_spell_template_index(const monsters *mon);
+void mons_load_spells( monsters *mon, int book );
// last updated 12may2000 {dlb}
/* ***********************************************************************
@@ -390,15 +347,9 @@ void define_monster(int mid);
/* ***********************************************************************
* called from: debug - itemname - mon-util
* *********************************************************************** */
-void moname(int mcl, bool vis, char descrip, char glog[ ITEMNAME_SIZE ]);
+const char *moname(int mcl, bool vis, char descrip, char glog[ ITEMNAME_SIZE ]);
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: monstuff
- * *********************************************************************** */
-void mons_spell_list(unsigned char sec, int splist[6]);
-
#if DEBUG_DIAGNOSTICS
// last updated 25sep2001 {dlb}
/* ***********************************************************************
@@ -449,10 +400,19 @@ bool mons_aligned(int m1, int m2);
/* ***********************************************************************
* called from: monstuff acr
* *********************************************************************** */
-bool mons_friendly(struct monsters *m);
+bool mons_friendly(const monsters *m);
+bool mons_is_confused(const monsters *m);
+bool mons_is_fleeing(const monsters *m);
+bool mons_is_sleeping(const monsters *m);
+bool mons_is_batty(const monsters *m);
+bool mons_is_evil( const monsters *mon );
+bool mons_is_unholy( const monsters *mon );
+bool mons_has_lifeforce( const monsters *mon );
+monster_type mons_genus( int mc );
+monster_type mons_species( int mc );
-int mons_has_ench( struct monsters *mon, unsigned int ench,
+int mons_has_ench( const monsters *mon, unsigned int ench,
unsigned int ench2 = ENCH_NONE );
int mons_del_ench( struct monsters *mon, unsigned int ench,
@@ -460,10 +420,28 @@ int mons_del_ench( struct monsters *mon, unsigned int ench,
bool mons_add_ench( struct monsters *mon, unsigned int ench );
-bool mons_is_stabbable(struct monsters *m);
+bool mons_looks_stabbable(const monsters *m);
+
+bool mons_looks_distracted(const monsters *m);
+
+bool check_mons_resist_magic( const monsters *monster, int pow );
+
+bool mons_class_is_stationary(int monsclass);
+bool mons_is_stationary(const monsters *mons);
+bool mons_is_submerged( struct monsters *mon );
+
+bool invalid_monster(const monsters *mons);
+bool invalid_monster_class(int mclass);
+
+bool monster_shover(const monsters *m);
+bool mons_is_paralysed(const monsters *m);
+
+bool monster_senior(const monsters *first, const monsters *second);
+monster_type draco_subspecies( const monsters *mon );
-bool mons_maybe_stabbable(struct monsters *m);
+monster_type random_monster_at_grid(int x, int y);
+monster_type random_monster_at_grid(int grid);
-bool check_mons_resist_magic( struct monsters *monster, int pow );
+monster_type get_monster_by_name(std::string name, bool exact = false);
#endif
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index eeab5c61d7..98bb07551d 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -3,6 +3,8 @@
* Summary: Functions used when placing monsters in the dungeon.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -20,6 +22,7 @@
#include "player.h"
#include "stuff.h"
#include "spells4.h"
+#include "view.h"
// NEW place_monster -- note that power should be set to:
// 51 for abyss
@@ -39,6 +42,97 @@ static int place_monster_aux(int mon_type, char behaviour, int target,
int px, int py, int power, int extra, bool first_band_member,
int dur = 0);
+// Returns whether actual_grid is compatible with grid_wanted for monster
+// movement (or for monster generation, if generation is true).
+bool grid_compatible(int grid_wanted, int actual_grid, bool generation)
+{
+ // XXX What in Xom's name is DNGN_WATER_STUCK? It looks like an artificial
+ // device to slow down fiery monsters flying over water.
+ if (grid_wanted == DNGN_FLOOR)
+ return actual_grid >= DNGN_FLOOR
+ || (!generation
+ && actual_grid == DNGN_SHALLOW_WATER);
+
+ return (grid_wanted == actual_grid
+ || (grid_wanted == DNGN_DEEP_WATER
+ && (actual_grid == DNGN_SHALLOW_WATER
+ || actual_grid == DNGN_BLUE_FOUNTAIN)));
+}
+
+// Can this monster happily on actual_grid?
+//
+// If you have an actual monster, use this instead of the overloaded function
+// that uses only the monster class to make decisions.
+bool monster_habitable_grid(const monsters *m, int actual_grid)
+{
+ return (monster_habitable_grid(m->type, actual_grid, mons_flies(m)));
+}
+
+// Can monsters of class monster_class live happily on actual_grid? Use flies
+// == true to pretend the monster can fly.
+//
+// [dshaligram] We're trying to harmonise the checks from various places into
+// one check, so we no longer care if a water elemental springs into existence
+// on dry land, because they're supposed to be able to move onto dry land
+// anyway.
+bool monster_habitable_grid(int monster_class, int actual_grid, bool flies)
+{
+ const int preferred_habitat = monster_habitat(monster_class);
+ return (grid_compatible(preferred_habitat, actual_grid)
+ // [dshaligram] Flying creatures are all DNGN_FLOOR, so we
+ // only have to check for the additional valid grids of deep
+ // water and lava.
+ || ((flies || mons_class_flies(monster_class))
+ && (actual_grid == DNGN_LAVA
+ || actual_grid == DNGN_DEEP_WATER))
+
+ // Amphibious critters are happy in the water.
+ || (mons_class_flag(monster_class, M_AMPHIBIOUS)
+ && grid_compatible(DNGN_DEEP_WATER, actual_grid))
+
+ // And water elementals are native to the water but happy on land
+ // as well.
+ || (monster_class == MONS_WATER_ELEMENTAL
+ && grid_compatible(DNGN_FLOOR, actual_grid)));
+}
+
+// Returns true if the monster is floundering in water and susceptible to
+// extra damage from water-natives.
+bool monster_floundering(const monsters *m)
+{
+ const int grid = grd[m->x][m->y];
+ return ((grid == DNGN_DEEP_WATER || grid == DNGN_SHALLOW_WATER)
+ // Can't use monster_habitable_grid because that'll return true
+ // for non-water monsters in shallow water.
+ && monster_habitat(m->type) != DNGN_DEEP_WATER
+ && !mons_class_flag(m->type, M_AMPHIBIOUS)
+ && !mons_flies(m));
+}
+
+// Returns true if the monster can submerge in the given grid
+bool monster_can_submerge(int monster_class, int grid)
+{
+ switch (monster_class)
+ {
+ case MONS_BIG_FISH:
+ case MONS_GIANT_GOLDFISH:
+ case MONS_ELECTRICAL_EEL:
+ case MONS_JELLYFISH:
+ case MONS_WATER_ELEMENTAL:
+ case MONS_SWAMP_WORM:
+ return (grid == DNGN_DEEP_WATER || grid == DNGN_BLUE_FOUNTAIN);
+
+ case MONS_LAVA_WORM:
+ case MONS_LAVA_FISH:
+ case MONS_LAVA_SNAKE:
+ case MONS_SALAMANDER:
+ return (grid == DNGN_LAVA);
+
+ default:
+ return (false);
+ }
+}
+
bool place_monster(int &id, int mon_type, int power, char behaviour,
int target, bool summoned, int px, int py, bool allow_bands,
int proximity, int extra, int dur)
@@ -160,7 +254,7 @@ bool place_monster(int &id, int mon_type, int power, char behaviour,
}
// Monsters that can't move shouldn't be taking the stairs -- bwr
- if (proximity == PROX_NEAR_STAIRS && mons_speed( mon_type ) == 0)
+ if (proximity == PROX_NEAR_STAIRS && mons_class_is_stationary( mon_type ))
proximity = PROX_AWAY_FROM_PLAYER;
// (4) for first monster, choose location. This is pretty intensive.
@@ -205,18 +299,10 @@ bool place_monster(int &id, int mon_type, int power, char behaviour,
continue;
}
- // compatible - floor?
- if (grid_wanted == DNGN_FLOOR && grd[px][py] < DNGN_FLOOR)
+ // Is the monster happy where we want to put it?
+ if (!grid_compatible(grid_wanted, grd[px][py], true))
continue;
- // compatible - others (must match, except for deep water monsters
- // generated in shallow water)
- if ((grid_wanted != DNGN_FLOOR && grd[px][py] != grid_wanted)
- && (grid_wanted != DNGN_DEEP_WATER || grd[px][py] != DNGN_SHALLOW_WATER))
- {
- continue;
- }
-
// don't generate monsters on top of teleport traps
// (how did they get there?)
int trap = trap_at_xy(px, py);
@@ -259,7 +345,7 @@ bool place_monster(int &id, int mon_type, int power, char behaviour,
proxOK = false;
break;
}
- // swap the monster and the player spots, unless the
+ // swap the monster and the player spots, unless the
// monster was generated in lava or deep water.
if (grd[px][py] == DNGN_LAVA || grd[px][py] == DNGN_DEEP_WATER)
{
@@ -290,17 +376,17 @@ bool place_monster(int &id, int mon_type, int power, char behaviour,
}
id = place_monster_aux( mon_type, behaviour, target, px, py, lev_mons,
- extra, true );
+ extra, true);
- // now, forget about banding if the first placement failed, or there's too
- // many monsters already, or we successfully placed by stairs
+ // now, forget about banding if the first placement failed, or there's too
+ // many monsters already, or we successfully placed by stairs
if (id < 0 || id+30 > MAX_MONSTERS)
return false;
// message to player from stairwell/gate appearance?
if (see_grid(px, py) && proximity == PROX_NEAR_STAIRS)
{
- info[0] = '\0';
+ info[0] = 0;
if (player_monster_visible( &menv[id] ))
strcpy(info, ptr_monam( &menv[id], DESC_CAP_A ));
@@ -335,7 +421,7 @@ bool place_monster(int &id, int mon_type, int power, char behaviour,
for(i = 1; i < band_size; i++)
{
place_monster_aux( band_monsters[i], behaviour, target, px, py,
- lev_mons, extra, false, dur );
+ lev_mons, extra, false, dur);
}
// placement of first monster, at least, was a success.
@@ -347,7 +433,7 @@ static int place_monster_aux( int mon_type, char behaviour, int target,
bool first_band_member, int dur )
{
int id, i;
- char grid_wanted;
+ unsigned char grid_wanted;
int fx=0, fy=0; // final x,y
// gotta be able to pick an ID
@@ -388,14 +474,7 @@ static int place_monster_aux( int mon_type, char behaviour, int target,
if (mgrd[fx][fy] != NON_MONSTER)
continue;
- // compatible - floor?
- if (grid_wanted == DNGN_FLOOR && grd[fx][fy] < DNGN_FLOOR)
- continue;
-
- // compatible - others (must match, except for deep water monsters
- // generated in shallow water)
- if ((grid_wanted != DNGN_FLOOR && grd[fx][fy] != grid_wanted)
- && (grid_wanted != DNGN_DEEP_WATER || grd[fx][fy] != DNGN_SHALLOW_WATER))
+ if (!grid_compatible(grid_wanted, grd[fx][fy], true))
continue;
// don't generate monsters on top of teleport traps
@@ -449,10 +528,10 @@ static int place_monster_aux( int mon_type, char behaviour, int target,
if (extra != 250)
menv[id].number = extra;
- if (mons_flag(mon_type, M_INVIS))
+ if (mons_class_flag(mon_type, M_INVIS))
mons_add_ench(&menv[id], ENCH_INVIS);
- if (mons_flag(mon_type, M_CONFUSED))
+ if (mons_class_flag(mon_type, M_CONFUSED))
mons_add_ench(&menv[id], ENCH_CONFUSION);
if (mon_type == MONS_SHAPESHIFTER)
@@ -467,28 +546,10 @@ static int place_monster_aux( int mon_type, char behaviour, int target,
menv[id].flags |= MF_BATTY;
}
- if ((mon_type == MONS_BIG_FISH
- || mon_type == MONS_GIANT_GOLDFISH
- || mon_type == MONS_ELECTRICAL_EEL
- || mon_type == MONS_JELLYFISH
- || mon_type == MONS_WATER_ELEMENTAL
- || mon_type == MONS_SWAMP_WORM)
- && grd[fx][fy] == DNGN_DEEP_WATER
- && !one_chance_in(5))
- {
+ if (monster_can_submerge(mon_type, grd[fx][fy])
+ && !one_chance_in(5))
mons_add_ench( &menv[id], ENCH_SUBMERGED );
- }
-
- if ((mon_type == MONS_LAVA_WORM
- || mon_type == MONS_LAVA_FISH
- || mon_type == MONS_LAVA_SNAKE
- || mon_type == MONS_SALAMANDER)
- && grd[fx][fy] == DNGN_LAVA
- && !one_chance_in(5))
- {
- mons_add_ench( &menv[id], ENCH_SUBMERGED );
- }
-
+
menv[id].flags |= MF_JUST_SUMMONED;
if (mon_type == MONS_DANCING_WEAPON && extra != 1) // ie not from spell
@@ -496,7 +557,7 @@ static int place_monster_aux( int mon_type, char behaviour, int target,
give_item( id, power );
if (menv[id].inv[MSLOT_WEAPON] != NON_ITEM)
- menv[id].number = mitm[ menv[id].inv[MSLOT_WEAPON] ].colour;
+ menv[id].colour = mitm[ menv[id].inv[MSLOT_WEAPON] ].colour;
}
else if (mons_itemuse(mon_type) >= MONUSE_STARTING_EQUIPMENT)
{
@@ -518,11 +579,15 @@ static int place_monster_aux( int mon_type, char behaviour, int target,
// set attitude, behaviour and target
menv[id].attitude = ATT_HOSTILE;
menv[id].behaviour = behaviour;
+
+ if (mon_type == MONS_ORANGE_STATUE || mon_type == MONS_SILVER_STATUE)
+ menv[id].behaviour = BEH_WANDER;
+
menv[id].foe_memory = 0;
// setting attitude will always make the
// monster wander.. if you want sleeping
- // hostiles, use BEH_SLEEP since the default
+ // hostiles, use BEH_SLEEP since the default
// attitude is hostile.
if (behaviour > NUM_BEHAVIOURS)
{
@@ -538,6 +603,11 @@ static int place_monster_aux( int mon_type, char behaviour, int target,
menv[id].foe = target;
+ mark_interesting_monst(&menv[id], behaviour);
+
+ if (player_monster_visible(&menv[id]) && mons_near(&menv[id]))
+ seen_monster(&menv[id]);
+
return (id);
} // end place_monster_aux()
@@ -771,6 +841,34 @@ static int choose_band( int mon_type, int power, int &band_size )
band = BAND_SKELETAL_WARRIORS; // skeletal warrior
band_size = 2 + random2(3);
break;
+ // Journey -- Added Draconian Packs
+ case MONS_WHITE_DRACONIAN:
+ case MONS_RED_DRACONIAN:
+ case MONS_PURPLE_DRACONIAN:
+ case MONS_MOTTLED_DRACONIAN:
+ case MONS_YELLOW_DRACONIAN:
+ case MONS_BLACK_DRACONIAN:
+ case MONS_GREEN_DRACONIAN:
+ case MONS_PALE_DRACONIAN:
+ if (power > 18 && one_chance_in(3))
+ {
+ band = BAND_DRACONIAN;
+ band_size = random_range(2, 4);
+ }
+ break;
+ case MONS_DRACONIAN_CALLER:
+ case MONS_DRACONIAN_MONK:
+ case MONS_DRACONIAN_SCORCHER:
+ case MONS_DRACONIAN_KNIGHT:
+ case MONS_DRACONIAN_ANNIHILATOR:
+ case MONS_DRACONIAN_ZEALOT:
+ case MONS_DRACONIAN_SHIFTER:
+ if (power > 20)
+ {
+ band = BAND_DRACONIAN;
+ band_size = random_range(3, 6);
+ }
+ break;
} // end switch
if (band != BAND_NO_BAND && band_size == 0)
@@ -1002,20 +1100,81 @@ static int band_member(int band, int power)
case BAND_SKELETAL_WARRIORS:
mon_type = MONS_SKELETAL_WARRIOR;
break;
+ case BAND_DRACONIAN:
+ {
+ temp_rand = random2( (power < 24) ? 24 : 37 );
+ mon_type =
+ ((temp_rand > 35) ? MONS_DRACONIAN_CALLER : // 1 in 34
+ (temp_rand > 33) ? MONS_DRACONIAN_KNIGHT : // 2 in 34
+ (temp_rand > 31) ? MONS_DRACONIAN_MONK : // 2 in 34
+ (temp_rand > 29) ? MONS_DRACONIAN_SHIFTER : // 2 in 34
+ (temp_rand > 27) ? MONS_DRACONIAN_ANNIHILATOR :// 2 in 34
+ (temp_rand > 25) ? MONS_DRACONIAN_SCORCHER : // 2 in 34
+ (temp_rand > 23) ? MONS_DRACONIAN_ZEALOT : // 2 in 34
+ (temp_rand > 20) ? MONS_YELLOW_DRACONIAN : // 3 in 34
+ (temp_rand > 17) ? MONS_GREEN_DRACONIAN : // 3 in 34
+ (temp_rand > 14) ? MONS_BLACK_DRACONIAN : // 3 in 34
+ (temp_rand > 11) ? MONS_WHITE_DRACONIAN : // 3 in 34
+ (temp_rand > 8) ? MONS_PALE_DRACONIAN : // 3 in 34
+ (temp_rand > 5) ? MONS_PURPLE_DRACONIAN : // 3 in 34
+ (temp_rand > 2) ? MONS_MOTTLED_DRACONIAN : // 3 in 34
+ MONS_RED_DRACONIAN ); // 3 in 34
+ break;
+ }
}
return (mon_type);
}
+static int ood_limit() {
+ return Options.ood_interesting;
+}
+
+void mark_interesting_monst(struct monsters* monster, char behaviour)
+{
+ bool interesting = false;
+
+ // Unique monsters are always intersting
+ if ( mons_is_unique(monster->type) )
+ interesting = true;
+ // If it's never going to attack us, then not interesting
+ else if (behaviour == BEH_FRIENDLY || behaviour == BEH_GOD_GIFT)
+ interesting = false;
+ // Don't waste time on moname() if user isn't using this option
+ else if ( Options.note_monsters.size() > 0 )
+ {
+ char namebuf[ITEMNAME_SIZE];
+ moname(monster->type, true, DESC_NOCAP_A, namebuf);
+
+ std::string iname = namebuf;
+
+ for (unsigned i = 0; i < Options.note_monsters.size(); ++i) {
+ if (Options.note_monsters[i].matches(iname)) {
+ interesting = true;
+ break;
+ }
+ }
+ }
+ else if ( you.where_are_you == BRANCH_MAIN_DUNGEON &&
+ you.level_type == LEVEL_DUNGEON &&
+ mons_level(monster->type) >= you.your_level + ood_limit() &&
+ mons_level(monster->type) < 99 &&
+ !(monster->type >= MONS_EARTH_ELEMENTAL &&
+ monster->type <= MONS_AIR_ELEMENTAL) )
+ interesting = true;
+
+ if ( interesting )
+ monster->flags |= MF_INTERESTING;
+}
+
// PUBLIC FUNCTION -- mons_place().
int mons_place( int mon_type, char behaviour, int target, bool summoned,
int px, int py, int level_type, int proximity, int extra,
- int dur )
+ int dur, bool permit_bands )
{
int mon_count = 0;
- int temp_rand; // probabilty determination {dlb}
- bool permit_bands = false;
+ int temp_rand; // probability determination {dlb}
for (int il = 0; il < MAX_MONSTERS; il++)
{
@@ -1051,7 +1210,9 @@ int mons_place( int mon_type, char behaviour, int target, bool summoned,
: MONS_PIT_FIEND); // 5.07%
}
- if (mon_type == RANDOM_MONSTER || level_type == LEVEL_PANDEMONIUM)
+ if (permit_bands
+ || mon_type == RANDOM_MONSTER
+ || level_type == LEVEL_PANDEMONIUM)
permit_bands = true;
int mid = -1;
@@ -1107,26 +1268,42 @@ int mons_place( int mon_type, char behaviour, int target, bool summoned,
return (mid);
} // end mons_place()
-
-int create_monster( int cls, int dur, int beha, int cr_x, int cr_y,
- int hitting, int zsec )
+coord_def find_newmons_square(int mons_class, int x, int y)
{
- int summd = -1;
FixedVector < char, 2 > empty;
-
- unsigned char spcw = ((cls == RANDOM_MONSTER) ? DNGN_FLOOR
- : monster_habitat( cls ));
+ coord_def pos = { -1, -1 };
empty[0] = 0;
empty[1] = 0;
+ if (mons_class == WANDERING_MONSTER)
+ mons_class = RANDOM_MONSTER;
+
+ int spcw = ((mons_class == RANDOM_MONSTER)? DNGN_FLOOR
+ : monster_habitat( mons_class ));
+
// Might be better if we chose a space and tried to match the monster
// to it in the case of RANDOM_MONSTER, that way if the target square
// is surrounded by water of lava this function would work. -- bwr
- if (empty_surrounds( cr_x, cr_y, spcw, true, empty ))
+ if (empty_surrounds( x, y, spcw, 2, true, empty ))
{
- summd = mons_place( cls, beha, hitting, true, empty[0], empty[1],
- you.level_type, 0, zsec, dur );
+ pos.x = empty[0];
+ pos.y = empty[1];
+ }
+
+ return (pos);
+}
+
+int create_monster( int cls, int dur, int beha, int cr_x, int cr_y,
+ int hitting, int zsec, bool permit_bands )
+{
+ int summd = -1;
+ coord_def pos = find_newmons_square(cls, cr_x, cr_y);
+
+ if (pos.x != -1 && pos.y != -1)
+ {
+ summd = mons_place( cls, beha, hitting, true, pos.x, pos.y,
+ you.level_type, 0, zsec, dur, permit_bands );
}
// determine whether creating a monster is successful (summd != -1) {dlb}:
@@ -1153,6 +1330,20 @@ int create_monster( int cls, int dur, int beha, int cr_x, int cr_y,
if (beha == BEH_GOD_GIFT)
creation->flags |= MF_GOD_GIFT;
+
+ // get the drawbacks, not the benefits...
+ // (to prevent demon-scumming)
+ if ( (you.religion == GOD_ZIN ||
+ you.religion == GOD_SHINING_ONE ||
+ you.religion == GOD_ELYVILON) &&
+ mons_is_unholy(creation) )
+ {
+ creation->attitude = ATT_HOSTILE;
+ creation->behaviour = BEH_HOSTILE;
+ beha = BEH_HOSTILE;
+ if ( see_grid(cr_x, cr_y) )
+ mpr("The monster is enraged by your holy aura!");
+ }
if (beha == BEH_CHARMED)
{
@@ -1175,25 +1366,19 @@ int create_monster( int cls, int dur, int beha, int cr_x, int cr_y,
bool empty_surrounds(int emx, int emy, unsigned char spc_wanted,
- bool allow_centre, FixedVector < char, 2 > &empty)
+ int radius, bool allow_centre,
+ FixedVector < char, 2 > &empty)
{
bool success;
// assume all player summoning originates from player x,y
bool playerSummon = (emx == you.x_pos && emy == you.y_pos);
- int xpos[25]; // good x pos
- int ypos[25]; // good y pos
int good_count = 0;
int count_x, count_y;
- char minx = -2;
- char maxx = 2;
- char miny = -2;
- char maxy = 2;
-
- for (count_x = minx; count_x <= maxx; count_x++)
+ for (count_x = -radius; count_x <= radius; count_x++)
{
- for (count_y = miny; count_y <= maxy; count_y++)
+ for (count_y = -radius; count_y <= radius; count_y++)
{
success = false;
@@ -1216,31 +1401,18 @@ bool empty_surrounds(int emx, int emy, unsigned char spc_wanted,
if (grd[tx][ty] == spc_wanted)
success = true;
- // those seeking ground can stand in shallow water or better
- if (spc_wanted == DNGN_FLOOR && grd[tx][ty] >= DNGN_SHALLOW_WATER)
+ if (grid_compatible(spc_wanted, grd[tx][ty]))
success = true;
- // water monsters can be created in shallow as well as deep water
- if (spc_wanted == DNGN_DEEP_WATER && grd[tx][ty] == DNGN_SHALLOW_WATER)
- success = true;
-
- if (success)
+ if (success && one_chance_in(++good_count))
{
// add point to list of good points
- xpos[good_count] = tx;
- ypos[good_count] = ty;
- good_count ++;
+ empty[0] = tx;
+ empty[1] = ty;
}
} // end "for count_y"
} // end "for count_x"
- if (good_count > 0)
- {
- int pick = random2(good_count);
- empty[0] = xpos[pick];
- empty[1] = ypos[pick];
- }
-
return (good_count > 0);
} // end empty_surrounds()
@@ -1304,3 +1476,53 @@ int summon_any_demon(char demon_class)
return summoned;
} // end summon_any_demon()
+
+monster_type rand_dragon( dragon_class_type type )
+{
+ monster_type summoned = MONS_PROGRAM_BUG;
+ int temp_rand;
+
+ switch (type)
+ {
+ case DRAGON_LIZARD:
+ temp_rand = random2(100);
+ summoned = ((temp_rand > 85) ? MONS_GIANT_GECKO :
+ (temp_rand > 59) ? MONS_GIANT_LIZARD :
+ (temp_rand > 34) ? MONS_GIANT_IGUANA :
+ (temp_rand > 22) ? MONS_GILA_MONSTER :
+ (temp_rand > 11) ? MONS_KOMODO_DRAGON :
+ (temp_rand > 8) ? MONS_FIREDRAKE :
+ (temp_rand > 2) ? MONS_SWAMP_DRAKE
+ : MONS_DEATH_DRAKE );
+ break;
+
+ case DRAGON_DRACONIAN:
+ temp_rand = random2(70);
+ summoned = ((temp_rand > 60) ? MONS_YELLOW_DRACONIAN :
+ (temp_rand > 50) ? MONS_BLACK_DRACONIAN :
+ (temp_rand > 40) ? MONS_PALE_DRACONIAN :
+ (temp_rand > 30) ? MONS_GREEN_DRACONIAN :
+ (temp_rand > 20) ? MONS_PURPLE_DRACONIAN :
+ (temp_rand > 10) ? MONS_RED_DRACONIAN
+ : MONS_WHITE_DRACONIAN);
+ break;
+
+ case DRAGON_DRAGON:
+ temp_rand = random2(90);
+ summoned = ((temp_rand > 80) ? MONS_MOTTLED_DRAGON :
+ (temp_rand > 70) ? MONS_LINDWURM :
+ (temp_rand > 60) ? MONS_STORM_DRAGON :
+ (temp_rand > 50) ? MONS_MOTTLED_DRAGON :
+ (temp_rand > 40) ? MONS_STEAM_DRAGON :
+ (temp_rand > 30) ? MONS_DRAGON :
+ (temp_rand > 20) ? MONS_ICE_DRAGON :
+ (temp_rand > 10) ? MONS_SWAMP_DRAGON
+ : MONS_SHADOW_DRAGON);
+ break;
+
+ default:
+ break;
+ }
+
+ return (summoned);
+}
diff --git a/crawl-ref/source/monplace.h b/crawl-ref/source/monplace.h
index f2fde75111..5dfb00e4b7 100644
--- a/crawl-ref/source/monplace.h
+++ b/crawl-ref/source/monplace.h
@@ -3,6 +3,8 @@
* Summary: Functions used when placing monsters in the dungeon.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -37,7 +39,8 @@
int mons_place( int mon_type, char behaviour, int target, bool summoned,
int px, int py, int level_type = LEVEL_DUNGEON,
int proximity = PROX_ANYWHERE, int extra = 250,
- int dur = 0 );
+ int dur = 0,
+ bool permit_bands = false );
// last updated 12may2000 {dlb}
/* ***********************************************************************
@@ -46,14 +49,14 @@ int mons_place( int mon_type, char behaviour, int target, bool summoned,
* spells2 - spells3 - spells4
* *********************************************************************** */
int create_monster( int cls, int dur, int beha, int cr_x, int cr_y,
- int hitting, int zsec );
+ int hitting, int zsec, bool permit_bands = false );
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: misc - monplace - spells3
* *********************************************************************** */
-bool empty_surrounds( int emx, int emy, unsigned char spc_wanted,
+bool empty_surrounds( int emx, int emy, unsigned char spc_wanted, int radius,
bool allow_centre, FixedVector<char, 2>& empty );
@@ -78,4 +81,19 @@ bool place_monster( int &id, int mon_type, int power, char behaviour,
int proximity = PROX_ANYWHERE, int extra = 250,
int dur = 0 );
+monster_type rand_dragon( dragon_class_type type );
+
+/* ***********************************************************************
+ * called from: monplace monstuff
+ * *********************************************************************** */
+void mark_interesting_monst(struct monsters* monster,
+ char behaviour = BEH_SLEEP);
+
+bool grid_compatible(int grid_wanted, int actual_grid, bool generation = false);
+bool monster_habitable_grid(int monster_class, int actual_grid,
+ bool flies = false);
+bool monster_habitable_grid(const monsters *m, int actual_grid);
+bool monster_floundering(const monsters *m);
+bool monster_can_submerge(int monster_class, int grid);
+
#endif // MONPLACE_H
diff --git a/crawl-ref/source/monspeak.cc b/crawl-ref/source/monspeak.cc
index 09b348867d..c8899f0528 100644
--- a/crawl-ref/source/monspeak.cc
+++ b/crawl-ref/source/monspeak.cc
@@ -2,6 +2,8 @@
* File: monspeak.cc
* Summary: Functions to handle speaking monsters
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> 01/09/00 BWR Created
@@ -114,7 +116,7 @@ bool mons_speaks(struct monsters *monster)
if (mons_has_ench(monster, ENCH_CONFUSION))
{
- if (mons_holiness( monster->type ) == MH_DEMONIC
+ if (mons_holiness( monster ) == MH_DEMONIC
&& monster->type != MONS_IMP)
{
return (false);
@@ -259,7 +261,7 @@ bool mons_speaks(struct monsters *monster)
}
else if (monster->behaviour == BEH_FLEE)
{
- if (mons_holiness( monster->type ) == MH_DEMONIC
+ if (mons_holiness( monster ) == MH_DEMONIC
&& monster->type != MONS_IMP)
{
return (false);
@@ -378,7 +380,7 @@ bool mons_speaks(struct monsters *monster)
}
else if (mons_friendly(monster))
{
- if (mons_holiness( monster->type ) == MH_DEMONIC
+ if (mons_holiness( monster ) == MH_DEMONIC
&& monster->type != MONS_IMP)
{
return (false);
@@ -1289,7 +1291,7 @@ bool mons_speaks(struct monsters *monster)
break;
case 11:
strcat(info,
- " says, \"I love to fight, but killing is better.\"");
+ " says, \"I love to fight, but killing is better.\"");
break;
}
break; // end Erica
@@ -2115,7 +2117,7 @@ bool mons_speaks(struct monsters *monster)
switch (random2(13))
{
case 0:
- strcat(info, " roars, \"DIE, PUNY ONE!\"");
+ strcat(info, " roars, \"DIE, PUNY ONE!\"");
break;
case 1:
strcat(info, " growls, \"YOU BORE ME SO.\"");
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 644462b798..df7f5184b5 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -3,6 +3,8 @@
* Summary: Misc monster related functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <8> 7 Aug 2001 MV Inteligent monsters now pick up gold
@@ -36,11 +38,14 @@
#include "fight.h"
#include "itemname.h"
#include "items.h"
+#include "itemprop.h"
#include "misc.h"
#include "monplace.h"
#include "monspeak.h"
+#include "mon-pick.h"
#include "mon-util.h"
#include "mstuff2.h"
+#include "notes.h"
#include "player.h"
#include "randart.h"
#include "religion.h"
@@ -49,6 +54,7 @@
#include "spells4.h"
#include "stuff.h"
#include "view.h"
+#include "stash.h"
static bool handle_special_ability(struct monsters *monster, bolt & beem);
static bool handle_pickup(struct monsters *monster);
@@ -58,14 +64,17 @@ static void monster_move(struct monsters *monster);
static bool plant_spit(struct monsters *monster, struct bolt &pbolt);
static int map_wand_to_mspell(int wand_type);
-char mmov_x, mmov_y;
+// [dshaligram] Doesn't need to be extern.
+static int mmov_x, mmov_y;
static int compass_x[8] = { -1, 0, 1, 1, 1, 0, -1, -1 };
static int compass_y[8] = { -1, -1, -1, 0, 1, 1, 1, 0 };
+static bool immobile_monster[MAX_MONSTERS];
+
#define FAR_AWAY 1000000 // used in monster_move()
-// This function creates an arteficial item to represent a mimic's appearance.
+// This function creates an artificial item to represent a mimic's appearance.
// Eventually, mimics could be redone to be more like Dancing wepaons...
// there'd only be one type and it would look like the item it carries. -- bwr
void get_mimic_item( const struct monsters *mimic, item_def &item )
@@ -114,6 +123,11 @@ void get_mimic_item( const struct monsters *mimic, item_def &item )
case MONS_ARMOUR_MIMIC:
item.base_type = OBJ_ARMOUR;
item.sub_type = (59 * mimic->x + 79 * mimic->y) % NUM_ARMOURS;
+ // FIXME: Remove fudges once these armours are completely implemented.
+ if (item.sub_type == ARM_STUDDED_LEATHER_ARMOUR)
+ item.sub_type = ARM_CRYSTAL_PLATE_MAIL;
+ else if (item.sub_type == ARM_CAP)
+ item.sub_type = ARM_MOTTLED_DRAGON_ARMOUR;
prop %= 100;
@@ -238,9 +252,7 @@ static void monster_drop_ething(struct monsters *monster,
bool destroyed = false;
bool hostile_grid = false;
- if (grd[monster->x][monster->y] == DNGN_LAVA ||
- grd[monster->x][monster->y] == DNGN_DEEP_WATER)
- {
+ if ( grid_destroys_items(grd[monster->x][monster->y]) ) {
hostile_grid = true;
}
@@ -268,18 +280,18 @@ static void monster_drop_ething(struct monsters *monster,
}
}
- if (destroyed)
- {
- if (grd[monster->x][monster->y] == DNGN_LAVA)
- mpr("You hear a hissing sound.");
- else
- mpr("You hear a splashing sound.");
+ if (destroyed) {
+ mprf(MSGCH_SOUND,
+ grid_item_destruction_message(grd[monster->x][monster->y]));
}
} // end monster_drop_ething()
-static void place_monster_corpse(struct monsters *monster)
+static void place_monster_corpse(const monsters *monster)
{
- int corpse_class = mons_charclass(monster->type);
+ int corpse_class = mons_species(monster->type);
+
+ if (corpse_class == MONS_DRACONIAN)
+ corpse_class = draco_subspecies(monster);
if (mons_has_ench(monster, ENCH_SHAPESHIFTER))
corpse_class = MONS_SHAPESHIFTER;
@@ -287,8 +299,8 @@ static void place_monster_corpse(struct monsters *monster)
corpse_class = MONS_GLOWING_SHAPESHIFTER;
if (mons_weight(corpse_class) == 0
- || grd[monster->x][monster->y] == DNGN_LAVA
- || grd[monster->x][monster->y] == DNGN_DEEP_WATER || coinflip())
+ || grid_destroys_items(grd[monster->x][monster->y])
+ || coinflip())
{
return;
}
@@ -303,11 +315,11 @@ static void place_monster_corpse(struct monsters *monster)
mitm[o].plus2 = 0; // butcher work done
mitm[o].sub_type = CORPSE_BODY;
mitm[o].special = 210; // rot time
- mitm[o].colour = mons_colour(corpse_class);
+ mitm[o].colour = mons_class_colour(corpse_class);
mitm[o].quantity = 1;
if (mitm[o].colour == BLACK)
- mitm[o].colour = monster->number;
+ mitm[o].colour = monster->colour;
// Don't care if 'o' is changed, and it shouldn't be (corpses don't stack)
move_item_to_grid( &o, monster->x, monster->y );
@@ -316,6 +328,7 @@ static void place_monster_corpse(struct monsters *monster)
void monster_die(struct monsters *monster, char killer, int i)
{
int dmi; // dead monster's inventory
+ int xom_will_act = 0;
int monster_killed = monster_index(monster);
bool death_message = mons_near(monster) && player_monster_visible(monster);
@@ -435,42 +448,44 @@ void monster_die(struct monsters *monster, char killer, int i)
// Xom doesn't care who you killed:
if (you.religion == GOD_XOM
- && random2(70) <= 10 + monster->hit_dice)
+ && random2(70) <= 10 + monster->hit_dice)
{
- Xom_acts(true, 1 + random2(monster->hit_dice), false);
+ // postpone Xom action until after the monster dies
+ xom_will_act = 1 + random2(monster->hit_dice);
}
// Trying to prevent summoning abuse here, so we're trying to
- // prevent summoned creatures from being being done_good kills,
+ // prevent summoned creatures from being done_good kills,
// Only affects monsters friendly when created.
if (!created_friendly)
{
if (you.duration[DUR_PRAYER])
{
- if (mons_holiness(monster->type) == MH_NATURAL)
- done_good(GOOD_KILLED_LIVING, monster->hit_dice);
+ if (mons_holiness(monster) == MH_NATURAL)
+ did_god_conduct(DID_DEDICATED_KILL_LIVING,
+ monster->hit_dice);
- if (mons_holiness(monster->type) == MH_UNDEAD)
- done_good(GOOD_KILLED_UNDEAD, monster->hit_dice);
+ if (mons_holiness(monster) == MH_UNDEAD)
+ did_god_conduct(DID_DEDICATED_KILL_UNDEAD,
+ monster->hit_dice);
- if (mons_holiness(monster->type) == MH_DEMONIC)
- done_good(GOOD_KILLED_DEMON, monster->hit_dice);
-
- if (mons_holiness(monster->type) == MH_HOLY)
- done_good(GOOD_KILLED_ANGEL_II, monster->hit_dice);
+ if (mons_holiness(monster) == MH_DEMONIC)
+ did_god_conduct(DID_DEDICATED_KILL_DEMON,
+ monster->hit_dice);
//jmf: Trog hates wizards
- if (mons_flag(monster->type, M_ACTUAL_SPELLS))
- done_good(GOOD_KILLED_WIZARD, monster->hit_dice);
+ if (mons_class_flag(monster->type, M_ACTUAL_SPELLS))
+ did_god_conduct(DID_DEDICATED_KILL_WIZARD,
+ monster->hit_dice);
//jmf: maybe someone hates priests?
- if (mons_flag(monster->type, M_PRIEST))
- done_good(GOOD_KILLED_PRIEST, monster->hit_dice);
- }
- else if (mons_holiness(monster->type) == MH_HOLY)
- {
- done_good(GOOD_KILLED_ANGEL_I, monster->hit_dice);
+ if (mons_class_flag(monster->type, M_PRIEST))
+ did_god_conduct(DID_DEDICATED_KILL_PRIEST,
+ monster->hit_dice);
}
+
+ if (mons_holiness(monster) == MH_HOLY)
+ did_god_conduct(DID_KILL_ANGEL, monster->hit_dice);
}
// Divine health and mp restoration doesn't happen when killing
@@ -501,12 +516,12 @@ void monster_die(struct monsters *monster, char killer, int i)
}
if (you.duration[DUR_DEATH_CHANNEL]
- && mons_holiness(monster->type) == MH_NATURAL
- && mons_weight(mons_charclass(monster->type)))
+ && mons_holiness(monster) == MH_NATURAL
+ && mons_weight(mons_species(monster->type)))
{
if (create_monster( MONS_SPECTRAL_THING, 0, BEH_FRIENDLY,
monster->x, monster->y, you.pet_target,
- mons_charclass(monster->type)) != -1)
+ mons_species(monster->type)) != -1)
{
if (death_message)
mpr("A glowing mist starts to gather...");
@@ -522,40 +537,83 @@ void monster_die(struct monsters *monster, char killer, int i)
// no piety loss if god gifts killed by other monsters
if (mons_friendly(monster) && !testbits(monster->flags,MF_GOD_GIFT))
- naughty(NAUGHTY_FRIEND_DIES, 1 + (monster->hit_dice / 2));
+ did_god_conduct(DID_FRIEND_DIES, 1 + (monster->hit_dice / 2));
// Trying to prevent summoning abuse here, so we're trying to
// prevent summoned creatures from being being done_good kills.
// Only affects creatures which were friendly when summoned.
if (!testbits(monster->flags, MF_CREATED_FRIENDLY) && pet_kill)
{
+ bool notice = false;
+
gain_exp(exper_value( monster ) / 2 + 1);
- if (mons_holiness(menv[i].type) == MH_UNDEAD)
+ int targ_holy = mons_holiness(monster),
+ attacker_holy = mons_holiness(&menv[i]);
+
+ if (attacker_holy == MH_UNDEAD)
{
- if (mons_holiness(monster->type) == MH_NATURAL)
- done_good(GOOD_SLAVES_KILL_LIVING, monster->hit_dice);
- else
- done_good(GOOD_SERVANTS_KILL, monster->hit_dice);
+ if (targ_holy == MH_NATURAL)
+ notice |=
+ did_god_conduct(DID_LIVING_KILLED_BY_UNDEAD_SLAVE,
+ monster->hit_dice);
}
- else
+ else if (you.religion == GOD_VEHUMET
+ || testbits( menv[i].flags, MF_GOD_GIFT ))
{
- done_good(GOOD_SERVANTS_KILL, monster->hit_dice);
-
- if (you.religion == GOD_VEHUMET
- && (!player_under_penance()
- && random2(you.piety) >= 30))
+ // Yes, we are splitting undead pets from the others
+ // as a way to focus Necomancy vs Summoning (ignoring
+ // Summon Wraith here)... at least we're being nice and
+ // putting the natural creature Summons together with
+ // the Demon ones. Note that Vehumet gets a free
+ // pass here since those followers are assumed to
+ // come from Summoning spells... the others are
+ // from invocations (Zin, TSO, Makh, Kiku). -- bwr
+
+ if (targ_holy == MH_NATURAL)
{
- /* Vehumet - only for non-undead servants (coding
- convenience, no real reason except that Vehumet
- prefers demons) */
- if (you.magic_points < you.max_magic_points)
+ notice |= did_god_conduct( DID_LIVING_KILLED_BY_SERVANT,
+ monster->hit_dice );
+
+ if (mons_class_flag( monster->type, M_EVIL ))
{
- mpr("You feel your power returning.");
- inc_mp(1 + random2(random2(monster->hit_dice)),
- false);
+ notice |=
+ did_god_conduct(
+ DID_NATURAL_EVIL_KILLED_BY_SERVANT,
+ monster->hit_dice );
}
}
+ else if (targ_holy == MH_DEMONIC)
+ {
+ notice |= did_god_conduct( DID_DEMON_KILLED_BY_SERVANT,
+ monster->hit_dice );
+ }
+ else if (targ_holy == MH_UNDEAD)
+ {
+ notice |= did_god_conduct( DID_UNDEAD_KILLED_BY_SERVANT,
+ monster->hit_dice );
+ }
+ }
+
+ // Angel kills are always noticed.
+ if (targ_holy == MH_HOLY)
+ {
+ notice |= did_god_conduct( DID_ANGEL_KILLED_BY_SERVANT,
+ monster->hit_dice );
+ }
+
+ if (you.religion == GOD_VEHUMET
+ && notice
+ && (!player_under_penance() && random2(you.piety) >= 30))
+ {
+ /* Vehumet - only for non-undead servants (coding
+ convenience, no real reason except that Vehumet
+ prefers demons) */
+ if (you.magic_points < you.max_magic_points)
+ {
+ mpr("You feel your power returning.");
+ inc_mp( 1 + random2(monster->hit_dice / 2), false );
+ }
}
}
break;
@@ -576,6 +634,9 @@ void monster_die(struct monsters *monster, char killer, int i)
place_cloud( CLOUD_GREY_SMOKE_MON + random2(3), monster->x,
monster->y, 1 + random2(3) );
+ // fall-through
+
+ case KILL_DISMISSED:
for (dmi = MSLOT_GOLD; dmi >= MSLOT_WEAPON; dmi--)
{ /* takes whatever it's carrying back home */
if (monster->inv[dmi] != NON_ITEM)
@@ -625,7 +686,7 @@ void monster_die(struct monsters *monster, char killer, int i)
(tmp == 1) ? " says, \"I'll get you next time!\"" :
(tmp == 2) ? " says, \"This isn't over yet!\"" :
(tmp == 3) ? " says, \"I'll be back!\"" :
- (tmp == 4) ? " says, \"This isn't the end, its only just beginning!\"" :
+ (tmp == 4) ? " says, \"This isn't the end, it's only just beginning!\"" :
(tmp == 5) ? " says, \"Kill me? I think not!\""
: " says, \"You cannot defeat me so easily!\"",
MSGCH_TALK );
@@ -636,13 +697,31 @@ void monster_die(struct monsters *monster, char killer, int i)
you.unique_creatures[ monster->type - 280 ] = 0;
}
- if (killer != KILL_RESET)
+ if (killer != KILL_RESET && killer != KILL_DISMISSED)
{
+ if ( MONST_INTERESTING(monster) ||
+ // XXX yucky hack
+ monster->type == MONS_PLAYER_GHOST ||
+ monster->type == MONS_PANDEMONIUM_DEMON ) {
+ /* make a note of it */
+ char namebuf[ITEMNAME_SIZE];
+ if ( monster->type == MONS_PLAYER_GHOST ) {
+ snprintf( namebuf, sizeof(namebuf), "the ghost of %s",
+ ghost.name );
+ }
+ else if ( monster->type == MONS_PANDEMONIUM_DEMON ) {
+ strncpy( namebuf, ghost.name, sizeof(namebuf) );
+ }
+ else
+ moname(monster->type, true, DESC_NOCAP_A, namebuf);
+ take_note(Note(NOTE_KILL_MONSTER, monster->type, 0, namebuf));
+ }
+
you.kills.record_kill(monster, killer, pet_kill);
if (mons_has_ench(monster, ENCH_ABJ_I, ENCH_ABJ_VI))
{
- if (mons_weight(mons_charclass(monster->type)))
+ if (mons_weight(mons_species(monster->type)))
{
if (monster->type == MONS_SIMULACRUM_SMALL
|| monster->type == MONS_SIMULACRUM_LARGE)
@@ -674,9 +753,13 @@ void monster_die(struct monsters *monster, char killer, int i)
|| killer == KILL_YOU
|| pet_kill);
monster_cleanup(monster);
+
+ if ( xom_will_act )
+ Xom_acts(true, xom_will_act, false);
+
} // end monster_die
-void monster_cleanup(struct monsters *monster)
+void monster_cleanup(monsters *monster)
{
unsigned int monster_killed = monster_index(monster);
int dmi = 0;
@@ -696,7 +779,8 @@ void monster_cleanup(struct monsters *monster)
monster->behaviour = BEH_SLEEP;
monster->foe = MHITNOT;
- mgrd[monster->x][monster->y] = NON_MONSTER;
+ if (in_bounds(monster->x, monster->y))
+ mgrd[monster->x][monster->y] = NON_MONSTER;
for (dmi = MSLOT_GOLD; dmi >= MSLOT_WEAPON; dmi--)
{
@@ -720,7 +804,7 @@ static bool jelly_divide(struct monsters * parent)
bool foundSpot = false; // to rid code of hideous goto {dlb}
struct monsters *child = 0; // NULL - value determined with loop {dlb}
- if (!mons_flag( parent->type, M_SPLITS ) || parent->hit_points == 1)
+ if (!mons_class_flag( parent->type, M_SPLITS ) || parent->hit_points == 1)
return (false);
// first, find a suitable spot for the child {dlb}:
@@ -734,7 +818,7 @@ static bool jelly_divide(struct monsters * parent)
{
// 10-50 for now - must take clouds into account:
if (mgrd[parent->x + jex][parent->y + jey] == NON_MONSTER
- && grd[parent->x + jex][parent->y + jey] > DNGN_LAST_SOLID_TILE
+ && !grid_is_solid(grd[parent->x + jex][parent->y + jey])
&& (parent->x + jex != you.x_pos || parent->y + jey != you.y_pos))
{
foundSpot = true;
@@ -779,6 +863,11 @@ static bool jelly_divide(struct monsters * parent)
child->behaviour = parent->behaviour; /* Look at this! */
child->foe = parent->foe;
child->attitude = parent->attitude;
+ child->colour = parent->colour;
+
+ // duplicate enchantments
+ for ( int i = 0; i < NUM_MON_ENCHANTS; ++i )
+ child->enchantment[i] = parent->enchantment[i];
child->x = parent->x + jex;
child->y = parent->y + jey;
@@ -788,7 +877,7 @@ static bool jelly_divide(struct monsters * parent)
if (!simple_monster_message(parent, " splits in two!"))
{
if (!silenced(parent->x, parent->y) || !silenced(child->x, child->y))
- mpr("You hear a squelching noise.");
+ mpr("You hear a squelching noise.", MSGCH_SOUND);
}
return (true);
@@ -821,13 +910,13 @@ static bool valid_morph( struct monsters *monster, int new_mclass )
{
unsigned char current_tile = grd[monster->x][monster->y];
- // morph targets are _always_ "base" classes, not derived ones.
- new_mclass = mons_charclass(new_mclass);
+ // morph targets are _always_ "base" classes, not derived ones.
+ new_mclass = mons_species(new_mclass);
/* various inappropriate polymorph targets */
- if (mons_holiness( new_mclass ) != mons_holiness( monster->type )
- || mons_flag( new_mclass, M_NO_EXP_GAIN ) // not helpless
- || new_mclass == mons_charclass( monster->type ) // must be different
+ if (mons_class_holiness( new_mclass ) != mons_holiness( monster )
+ || mons_class_flag( new_mclass, M_NO_EXP_GAIN ) // not helpless
+ || new_mclass == mons_species( monster->type ) // must be different
|| new_mclass == MONS_PROGRAM_BUG
|| new_mclass == MONS_SHAPESHIFTER
|| new_mclass == MONS_GLOWING_SHAPESHIFTER
@@ -841,30 +930,8 @@ static bool valid_morph( struct monsters *monster, int new_mclass )
return (false);
}
- /* Not fair to instakill a monster like this --
- order of evaluation of inner conditional important */
- if (current_tile == DNGN_LAVA || current_tile == DNGN_DEEP_WATER)
- {
- if (!mons_class_flies(new_mclass)
- || monster_habitat(new_mclass) != current_tile)
- {
- return (false);
- }
- }
-
- // not fair to strand a water monster on dry land, either. :)
- if (monster_habitat(new_mclass) == DNGN_DEEP_WATER
- && current_tile != DNGN_DEEP_WATER
- && current_tile != DNGN_SHALLOW_WATER)
- {
- return (false);
- }
-
- // and putting lava monsters on non-lava sqaures is a no-no, too
- if (monster_habitat(new_mclass) == DNGN_LAVA && current_tile != DNGN_LAVA)
- return (false);
-
- return (true);
+ // Determine if the monster is happy on current tile
+ return (monster_habitable_grid(new_mclass, current_tile));
} // end valid_morph()
// note that power is (as of yet) unused within this function -
@@ -890,10 +957,12 @@ bool monster_polymorph( struct monsters *monster, int targetc, int power )
{
do
{
- targetc = random2( NUM_MONSTERS );
+ // Pick a monster that's guaranteed happy at this grid
+ targetc = random_monster_at_grid(monster->x, monster->y);
- // valid targets are always base classes
- targetc = mons_charclass( targetc );
+ // valid targets are always base classes ([ds] which is unfortunate
+ // in that well-populated monster classes will dominate polymorphs)
+ targetc = mons_species( targetc );
target_power = mons_power( targetc );
@@ -914,9 +983,21 @@ bool monster_polymorph( struct monsters *monster, int targetc, int power )
return (player_messaged);
}
+ // If old monster is visible to the player, and is interesting,
+ // then note why the interesting monster went away.
+ if (player_monster_visible(monster) && mons_near(monster)
+ && MONST_INTERESTING(monster)) {
+
+ char namebuf[ITEMNAME_SIZE];
+ moname(monster->type, true, DESC_NOCAP_A, namebuf);
+ take_note(Note(NOTE_POLY_MONSTER, monster->type, 0, namebuf));
+
+ }
+
// messaging: {dlb}
- bool invis = mons_flag( targetc, M_INVIS )
- || mons_has_ench( monster, ENCH_INVIS );
+ bool invis = (mons_class_flag( targetc, M_INVIS )
+ || mons_has_ench( monster, ENCH_INVIS )) &&
+ (!player_see_invis());
if (mons_has_ench( monster, ENCH_GLOWING_SHAPESHIFTER, ENCH_SHAPESHIFTER ))
strcat( str_polymon, " changes into " );
@@ -925,11 +1006,11 @@ bool monster_polymorph( struct monsters *monster, int targetc, int power )
else
strcat( str_polymon, " evaporates and reforms as " );
- if (invis && !player_see_invis())
+ if (invis)
strcat( str_polymon, "something you cannot see!" );
else
{
- strcat( str_polymon, monam( 250, targetc, !invis, DESC_NOCAP_A ) );
+ strcat( str_polymon, monam( 250, targetc, true, DESC_NOCAP_A ) );
if (targetc == MONS_PULSATING_LUMP)
strcat( str_polymon, " of flesh" );
@@ -961,7 +1042,7 @@ bool monster_polymorph( struct monsters *monster, int targetc, int power )
if (shifter != ENCH_NONE)
mons_add_ench( monster, shifter );
- if (mons_flag( monster->type, M_INVIS ))
+ if (mons_class_flag( monster->type, M_INVIS ))
mons_add_ench( monster, ENCH_INVIS );
monster->hit_points = monster->max_hit_points
@@ -975,16 +1056,23 @@ bool monster_polymorph( struct monsters *monster, int targetc, int power )
monster_drop_ething(monster);
+ // New monster type might be interesting
+ mark_interesting_monst(monster);
+
+ // If new monster is visible to player, then we've seen it
+ if (player_monster_visible(monster) && mons_near(monster))
+ seen_monster(monster);
+
return (player_messaged);
} // end monster_polymorph()
-void monster_blink(struct monsters *monster)
+bool monster_blink(monsters *monster)
{
int nx, ny;
if (!random_near_space(monster->x, monster->y, nx, ny,
- false, false))
- return;
+ false, false))
+ return (false);
mgrd[monster->x][monster->y] = NON_MONSTER;
@@ -992,6 +1080,11 @@ void monster_blink(struct monsters *monster)
monster->y = ny;
mgrd[nx][ny] = monster_index(monster);
+
+ if (player_monster_visible(monster) && mons_near(monster))
+ seen_monster(monster);
+
+ return (true);
} // end monster_blink()
// allow_adjacent: allow target to be adjacent to origin
@@ -1025,45 +1118,7 @@ bool random_near_space(int ox, int oy, int &tx, int &ty, bool allow_adjacent,
static bool habitat_okay( struct monsters *monster, int targ )
{
- bool ret = false;
- const int habitat = monster_habitat( monster->type );
-
- if (mons_flies( monster ))
- {
- // flying monsters don't care
- ret = true;
- }
- else if (mons_flag( monster->type, M_AMPHIBIOUS )
- && (targ == DNGN_DEEP_WATER || targ == DNGN_SHALLOW_WATER))
- {
- // Amphibious creatures are "land" by default in mon-data,
- // we allow them to swim here. -- bwr
- ret = true;
- }
- else if (monster->type == MONS_WATER_ELEMENTAL && targ >= DNGN_DEEP_WATER)
- {
- // water elementals can crawl out over the land
- ret = true;
- }
- else if (habitat == DNGN_FLOOR
- && (targ >= DNGN_FLOOR || targ == DNGN_SHALLOW_WATER))
- {
- // FLOOR habitat monster going to a non-bad place
- ret = true;
- }
- else if (habitat == DNGN_DEEP_WATER
- && (targ == DNGN_DEEP_WATER || targ == DNGN_SHALLOW_WATER))
- {
- // Water monster to water
- ret = true;
- }
- else if (habitat == DNGN_LAVA && targ == DNGN_LAVA)
- {
- // Lava monster to lava
- ret = true;
- }
-
- return (ret);
+ return (monster_habitable_grid(monster, targ));
}
// This doesn't really swap places, it just sets the monster's
@@ -1216,7 +1271,7 @@ void print_wounds(struct monsters *monster)
bool wounded_damaged(int wound_class)
{
// this schema needs to be abstracted into real categories {dlb}:
- const int holy = mons_holiness(wound_class);
+ const int holy = mons_class_holiness(wound_class);
if (holy == MH_UNDEAD || holy == MH_NONLIVING || holy == MH_PLANT)
return (true);
@@ -1266,10 +1321,12 @@ void behaviour_event( struct monsters *mon, int event, int src,
case ME_WHACK:
case ME_ANNOY:
- // will turn monster against <src>, unless they
+ // will turn monster against <src>, unless they
// are BOTH friendly and stupid. Hitting someone
// over the head, of course, always triggers this code.
- if (isFriendly != sourceFriendly || isSmart || event == ME_WHACK)
+ if ( event == ME_WHACK ||
+ ((isFriendly != sourceFriendly || isSmart) &&
+ (mon->behaviour != BEH_FLEE && mon->behaviour != BEH_PANIC)))
{
mon->foe = src;
@@ -1291,7 +1348,7 @@ void behaviour_event( struct monsters *mon, int event, int src,
case ME_ALERT:
// will alert monster to <src> and turn them
- // against them, unless they have a current foe.
+ // against them, unless they have a current foe.
// it won't turn friends hostile either.
if (mon->behaviour != BEH_CORNERED)
mon->behaviour = BEH_SEEK;
@@ -1362,12 +1419,7 @@ static void handle_behaviour(struct monsters *mon)
bool isHealthy = (mon->hit_points > mon->max_hit_points / 2);
bool isSmart = (mons_intel(mon->type) > I_ANIMAL);
bool isScared = mons_has_ench(mon, ENCH_FEAR);
-
- // immobility logic stolen from later on in handle_monster().. argh! --gdl
- bool isMobile = !(mon->type == MONS_OKLOB_PLANT
- || mon->type == MONS_CURSE_SKULL
- || (mon->type >= MONS_CURSE_TOE
- && mon->type <= MONS_POTION_MIMIC));
+ bool isMobile = !mons_is_stationary(mon);
// check for confusion -- early out.
if (mons_has_ench(mon, ENCH_CONFUSION))
@@ -1395,13 +1447,18 @@ static void handle_behaviour(struct monsters *mon)
if (!see_grid(mon->x, mon->y))
proxPlayer = false;
+ const int intel = mons_intel(mon->type);
// now, the corollary to that is that sometimes, if a
// player is right next to a monster, they will 'see'
if (grid_distance( you.x_pos, you.y_pos, mon->x, mon->y ) == 1
- && one_chance_in(3))
- {
+ && one_chance_in(3))
+ proxPlayer = true;
+
+ // [dshaligram] Very smart monsters have a chance of cluing in to
+ // invisible players in various ways.
+ else if ((intel == I_NORMAL && one_chance_in(10))
+ || (intel == I_HIGH && one_chance_in(6)))
proxPlayer = true;
- }
}
// set friendly target, if they don't already have one
@@ -1424,7 +1481,7 @@ static void handle_behaviour(struct monsters *mon)
}
// unfriendly monsters fighting other monsters will usually
- // target the player, if they're healthy
+ // target the player, if they're healthy
if (!isFriendly && mon->foe != MHITYOU && mon->foe != MHITNOT
&& proxPlayer && !one_chance_in(3) && isHealthy)
{
@@ -1515,7 +1572,7 @@ static void handle_behaviour(struct monsters *mon)
{
// if we've arrived at our target x,y
// do a stealth check. If the foe
- // fails, monster will then start
+ // fails, monster will then start
// tracking foe's CURRENT position,
// but only for a few moves (smell and
// intuition only go so far)
@@ -1583,7 +1640,7 @@ static void handle_behaviour(struct monsters *mon)
// by updating target x,y
if (mon->foe == MHITYOU)
{
- // sometimes, your friends will wander a bit.
+ // sometimes, your friends will wander a bit.
if (isFriendly && one_chance_in(8))
{
mon->target_x = 10 + random2(GXM - 10);
@@ -1635,9 +1692,9 @@ static void handle_behaviour(struct monsters *mon)
mon->target_y = 10 + random2(GYM - 10);
}
- // during their wanderings, monsters will
+ // during their wanderings, monsters will
// eventually relax their guard (stupid
- // ones will do so faster, smart monsters
+ // ones will do so faster, smart monsters
// have longer memories
if (!proxFoe && mon->foe != MHITNOT)
{
@@ -1652,7 +1709,7 @@ static void handle_behaviour(struct monsters *mon)
new_beh = BEH_SEEK;
// smart monsters flee until they can
// flee no more... possible to get a
- // 'CORNERED' event, at which point
+ // 'CORNERED' event, at which point
// we can jump back to WANDER if the foe
// isn't present.
@@ -1727,7 +1784,6 @@ static inline int mod_speed( int val, int speed )
static bool handle_enchantment(struct monsters *monster)
{
- const int habitat = monster_habitat( monster->type );
bool died = false;
int grid;
int poisonval;
@@ -1735,7 +1791,7 @@ static bool handle_enchantment(struct monsters *monster)
int tmp;
// Yes, this is the speed we want. This function will be called in
- // two curcumstances: (1) the monster can move and have enough energy,
+ // two circumstances: (1) the monster can move and has enough energy,
// and (2) the monster cannot move (speed == 0) and the monster loop
// is running.
//
@@ -1787,7 +1843,7 @@ static bool handle_enchantment(struct monsters *monster)
if (random2(120) < mod_speed( monster->hit_dice + 5, speed ))
{
// don't delete perma-confusion
- if (!mons_flag(monster->type, M_CONFUSED))
+ if (!mons_class_flag(monster->type, M_CONFUSED))
mons_del_ench(monster, ENCH_CONFUSION);
}
break;
@@ -1796,7 +1852,7 @@ static bool handle_enchantment(struct monsters *monster)
if (random2(1000) < mod_speed( 25, speed ))
{
// don't delete perma-invis
- if (!mons_flag( monster->type, M_INVIS ))
+ if (!mons_class_flag( monster->type, M_INVIS ))
mons_del_ench(monster, ENCH_INVIS);
}
break;
@@ -1824,7 +1880,7 @@ static bool handle_enchantment(struct monsters *monster)
// Badly injured monsters prefer to stay submerged...
// electrical eels and lava snakes have ranged attacks
// and are more likely to surface. -- bwr
- if (habitat == DNGN_FLOOR || habitat != grid)
+ if (!monster_can_submerge(monster->type, grid))
mons_del_ench( monster, ENCH_SUBMERGED ); // forced to surface
else if (monster->hit_points <= monster->max_hit_points / 2)
break;
@@ -1834,7 +1890,10 @@ static bool handle_enchantment(struct monsters *monster)
|| (mons_near(monster)
&& monster->hit_points == monster->max_hit_points
&& !one_chance_in(10))))
- || random2(5000) < mod_speed( 10, speed ))
+ || random2(2000) < mod_speed(10, speed)
+ || (mons_near(monster)
+ && monster->hit_points == monster->max_hit_points
+ && !one_chance_in(5)))
{
mons_del_ench( monster, ENCH_SUBMERGED );
}
@@ -2133,7 +2192,7 @@ static void handle_movement(struct monsters *monster)
// reproduced here is some semi-legacy code that makes monsters
// move somewhat randomly along oblique paths. It is an exceedingly
- // good idea, given crawl's unique line of sight properties.
+ // good idea, given crawl's unique line of sight properties.
//
// Added a check so that oblique movement paths aren't used when
// close to the target square. -- bwr
@@ -2172,7 +2231,7 @@ static void handle_nearby_ability(struct monsters *monster)
return;
}
- if (mons_flag(monster->type, M_SPEAKS) && one_chance_in(21)
+ if (mons_class_flag(monster->type, M_SPEAKS) && one_chance_in(21)
&& monster->behaviour != BEH_WANDER)
{
mons_speaks(monster);
@@ -2183,7 +2242,7 @@ static void handle_nearby_ability(struct monsters *monster)
case MONS_SPATIAL_VORTEX:
case MONS_KILLER_KLOWN:
// used for colour (butterflies too, but they don't change)
- monster->number = random_colour();
+ monster->colour = random_colour();
break;
case MONS_GIANT_EYEBALL:
@@ -2236,10 +2295,13 @@ static void handle_nearby_ability(struct monsters *monster)
mons_del_ench( monster, ENCH_SUBMERGED );
}
}
- else if (monster_habitat(monster->type) == grd[monster->x][monster->y]
+ else if (monster_can_submerge(monster->type,
+ grd[monster->x][monster->y])
&& (one_chance_in(5)
|| (grid_distance( monster->x, monster->y,
you.x_pos, you.y_pos ) > 1
+ // FIXME This is better expressed as a function
+ // such as monster_has_ranged_attack:
&& monster->type != MONS_ELECTRICAL_EEL
&& monster->type != MONS_LAVA_SNAKE
&& !one_chance_in(20))
@@ -2257,7 +2319,7 @@ static void handle_nearby_ability(struct monsters *monster)
case MONS_PANDEMONIUM_DEMON:
if (ghost.values[ GVAL_DEMONLORD_CYCLE_COLOUR ])
- monster->number = random_colour();
+ monster->colour = random_colour();
break;
}
} // end handle_nearby_ability()
@@ -2275,6 +2337,10 @@ static bool handle_special_ability(struct monsters *monster, bolt & beem)
FixedArray < unsigned int, 19, 19 > show;
+ const monster_type mclass = (mons_genus( monster->type ) == MONS_DRACONIAN)
+ ? draco_subspecies( monster )
+ : static_cast<monster_type>( monster->type );
+
if (!mons_near( monster )
|| monster->behaviour == BEH_SLEEP
|| mons_has_ench( monster, ENCH_SUBMERGED ))
@@ -2284,8 +2350,16 @@ static bool handle_special_ability(struct monsters *monster, bolt & beem)
// losight(show, grd, you.x_pos, you.y_pos);
- switch (monster->type)
+ switch (mclass)
{
+ case MONS_ORANGE_STATUE:
+ used = orange_statue_effects(monster);
+ break;
+
+ case MONS_SILVER_STATUE:
+ used = silver_statue_effects(monster);
+ break;
+
case MONS_BALL_LIGHTNING:
if (monster->attitude == ATT_HOSTILE
&& distance( you.x_pos, you.y_pos, monster->x, monster->y ) <= 5)
@@ -2323,7 +2397,7 @@ static bool handle_special_ability(struct monsters *monster, bolt & beem)
if (tx < 0 || tx > GXM || ty < 0 || ty > GYM)
continue;
- if (grd[tx][ty] > DNGN_LAST_SOLID_TILE)
+ if (!grid_is_solid(grd[tx][ty]))
{
monster->hit_points = -1;
used = true;
@@ -2343,7 +2417,7 @@ static bool handle_special_ability(struct monsters *monster, bolt & beem)
break;
// setup tracer
- strcpy(beem.beam_name, "glob of lava");
+ beem.name = "glob of lava";
beem.range = 4;
beem.rangeMax = 13;
beem.damage = dice_def( 3, 10 );
@@ -2378,7 +2452,7 @@ static bool handle_special_ability(struct monsters *monster, bolt & beem)
break;
// setup tracer
- strcpy(beem.beam_name, "bolt of electricity");
+ beem.name = "bolt of electricity";
beem.damage = dice_def( 3, 6 );
beem.colour = LIGHTCYAN;
beem.type = SYM_ZAP;
@@ -2389,7 +2463,7 @@ static bool handle_special_ability(struct monsters *monster, bolt & beem)
beem.aux_source = "bolt of electricity";
beem.range = 4;
beem.rangeMax = 13;
- beem.isBeam = true;
+ beem.is_beam = true;
// fire tracer
fire_tracer(monster, beem);
@@ -2405,6 +2479,7 @@ static bool handle_special_ability(struct monsters *monster, bolt & beem)
case MONS_ACID_BLOB:
case MONS_OKLOB_PLANT:
+ case MONS_YELLOW_DRACONIAN:
if (mons_has_ench(monster, ENCH_CONFUSION))
break;
@@ -2424,7 +2499,7 @@ static bool handle_special_ability(struct monsters *monster, bolt & beem)
if (mons_has_ench(monster, ENCH_CONFUSION))
break;
- // friendly fiends won't use torment, preferring hellfire
+ // friendly fiends won't use torment, preferring hellfire
// (right now there is no way a monster can predict how
// badly they'll damage the player with torment) -- GDL
if (one_chance_in(4))
@@ -2490,16 +2565,16 @@ static bool handle_special_ability(struct monsters *monster, bolt & beem)
if (!mons_near(monster))
break;
- // the fewer spikes the manticore has left, the less
+ // the fewer spikes the manticore has left, the less
// likely it will use them.
if (random2(16) >= static_cast<int>(monster->number))
break;
- // do the throwing right here, since the beam is so
+ // do the throwing right here, since the beam is so
// easy to set up and doesn't involve inventory.
// set up the beam
- strcpy(beem.beam_name, "volley of spikes");
+ beem.name = "volley of spikes";
beem.range = 9;
beem.rangeMax = 9;
beem.hit = 14;
@@ -2510,7 +2585,7 @@ static bool handle_special_ability(struct monsters *monster, bolt & beem)
beem.flavour = BEAM_MISSILE;
beem.thrower = KILL_MON;
beem.aux_source = "volley of spikes";
- beem.isBeam = false;
+ beem.is_beam = false;
// fire tracer
fire_tracer(monster, beem);
@@ -2533,6 +2608,8 @@ static bool handle_special_ability(struct monsters *monster, bolt & beem)
case MONS_LINDWURM:
case MONS_FIREDRAKE:
case MONS_XTAHUA:
+ case MONS_WHITE_DRACONIAN:
+ case MONS_RED_DRACONIAN:
if (!mons_player_visible( monster ))
break;
@@ -2550,7 +2627,8 @@ static bool handle_special_ability(struct monsters *monster, bolt & beem)
// good idea?
if (mons_should_fire(beem))
{
- simple_monster_message(monster, " breathes.");
+ simple_monster_message(monster, " breathes.",
+ MSGCH_MONSTER_SPELL);
fire_beam(beem);
mmov_x = 0;
mmov_y = 0;
@@ -2558,6 +2636,9 @@ static bool handle_special_ability(struct monsters *monster, bolt & beem)
}
}
break;
+
+ default:
+ break;
}
return (used);
@@ -2590,9 +2671,9 @@ static bool handle_potion(struct monsters *monster, bolt & beem)
case POT_HEALING:
case POT_HEAL_WOUNDS:
if (monster->hit_points <= monster->max_hit_points / 2
- && mons_holiness(monster->type) != MH_UNDEAD
- && mons_holiness(monster->type) != MH_NONLIVING
- && mons_holiness(monster->type) != MH_PLANT)
+ && mons_holiness(monster) != MH_UNDEAD
+ && mons_holiness(monster) != MH_NONLIVING
+ && mons_holiness(monster) != MH_PLANT)
{
simple_monster_message(monster, " drinks a potion.");
@@ -2616,7 +2697,13 @@ static bool handle_potion(struct monsters *monster, bolt & beem)
// intentional fall through
case POT_INVISIBILITY:
if (mitm[monster->inv[MSLOT_POTION]].sub_type == POT_INVISIBILITY)
+ {
beem.colour = MAGENTA;
+ // Friendly monsters won't go invisible if the player
+ // can't see invisible. We're being nice.
+ if ( mons_friendly(monster) && !player_see_invis(false) )
+ break;
+ }
// why only drink these if not near player? {dlb}
if (!mons_near(monster))
@@ -2797,12 +2884,12 @@ static bool handle_wand(struct monsters *monster, bolt &beem)
// set up the beam
int power = 30 + monster->hit_dice;
- struct SBeam theBeam = mons_spells(mzap, power);
+ bolt theBeam = mons_spells(mzap, power);
// XXX: ugly hack this:
static char wand_buff[ ITEMNAME_SIZE ];
- strcpy( beem.beam_name, theBeam.name.c_str() );
+ beem.name = theBeam.name;
beem.beam_source = monster_index(monster);
beem.source_x = monster->x;
beem.source_y = monster->y;
@@ -2814,8 +2901,9 @@ static bool handle_wand(struct monsters *monster, bolt &beem)
beem.hit = theBeam.hit;
beem.type = theBeam.type;
beem.flavour = theBeam.flavour;
- beem.thrower = theBeam.thrown;
- beem.isBeam = theBeam.isBeam;
+ beem.thrower = theBeam.thrower;
+ beem.is_beam = theBeam.is_beam;
+ beem.is_explosion = theBeam.is_explosion;
item_def item = mitm[ monster->inv[MSLOT_WAND] ];
@@ -2864,7 +2952,8 @@ static bool handle_wand(struct monsters *monster, bolt &beem)
case WAND_INVISIBILITY:
if (!mons_has_ench( monster, ENCH_INVIS )
- && !mons_has_ench( monster, ENCH_SUBMERGED ))
+ && !mons_has_ench( monster, ENCH_SUBMERGED )
+ && (!mons_friendly(monster) || player_see_invis(false)))
{
beem.target_x = monster->x;
beem.target_y = monster->y;
@@ -2905,12 +2994,12 @@ static bool handle_wand(struct monsters *monster, bolt &beem)
if (!simple_monster_message(monster, " zaps a wand."))
{
if (!silenced(you.x_pos, you.y_pos))
- mpr("You hear a zap.");
+ mpr("You hear a zap.", MSGCH_SOUND);
}
// charge expenditure {dlb}
mitm[monster->inv[MSLOT_WAND]].plus--;
- beem.isTracer = false;
+ beem.is_tracer = false;
fire_beam( beem );
return (true);
@@ -2920,6 +3009,69 @@ static bool handle_wand(struct monsters *monster, bolt &beem)
return (false);
} // end handle_wand()
+// Returns a suitable breath weapon for the draconian; does not handle all
+// draconians, does fire a tracer.
+static int get_draconian_breath_spell( struct monsters *monster )
+{
+ int draco_breath = MS_NO_SPELL;
+
+ if (mons_genus( monster->type ) == MONS_DRACONIAN)
+ {
+ switch (draco_subspecies( monster ))
+ {
+ case MONS_BLACK_DRACONIAN:
+ draco_breath = MS_LIGHTNING_BOLT;
+ break;
+
+ case MONS_PALE_DRACONIAN:
+ draco_breath = MS_STEAM_BALL;
+ break;
+
+ case MONS_GREEN_DRACONIAN:
+ draco_breath = MS_POISON_BLAST;
+ break;
+
+ case MONS_PURPLE_DRACONIAN:
+ draco_breath = MS_ORB_ENERGY;
+ break;
+
+ case MONS_MOTTLED_DRACONIAN:
+ draco_breath = MS_STICKY_FLAME;
+ break;
+
+ case MONS_DRACONIAN:
+ case MONS_YELLOW_DRACONIAN: // already handled as ability
+ case MONS_RED_DRACONIAN: // already handled as ability
+ case MONS_WHITE_DRACONIAN: // already handled as ability
+ default:
+ break;
+ }
+
+ if (draco_breath != MS_NO_SPELL)
+ {
+ // [ds] Check line-of-fire here. It won't happen elsewhere.
+ bolt beem;
+ setup_mons_cast(monster, beem, draco_breath);
+ fire_tracer(monster, beem);
+ if (!mons_should_fire(beem))
+ draco_breath = MS_NO_SPELL;
+ }
+
+ }
+
+ return (draco_breath);
+}
+
+static bool is_emergency_spell(const monster_spells &msp, int spell)
+{
+ // If the emergency spell appears early, it's probably not a dedicated
+ // escape spell.
+ for (int i = 0; i < 5; ++i)
+ if (msp[i] == spell)
+ return (false);
+ return (msp[5] == spell);
+}
+
//---------------------------------------------------------------
//
// handle_spell
@@ -2928,28 +3080,30 @@ static bool handle_wand(struct monsters *monster, bolt &beem)
// a spell was cast.
//
//---------------------------------------------------------------
-static bool handle_spell( struct monsters *monster, bolt & beem )
+static bool handle_spell( monsters *monster, bolt & beem )
{
bool monsterNearby = mons_near(monster);
bool finalAnswer = false; // as in: "Is that your...?" {dlb}
+ const int draco_breath = get_draconian_breath_spell(monster);
// yes, there is a logic to this ordering {dlb}:
if (monster->behaviour == BEH_SLEEP
- || !mons_flag( monster->type, M_SPELLCASTER )
+ || (!mons_class_flag(monster->type, M_SPELLCASTER)
+ && draco_breath == MS_NO_SPELL)
|| mons_has_ench( monster, ENCH_SUBMERGED ))
{
return (false);
}
- if ((mons_flag(monster->type, M_ACTUAL_SPELLS)
- || mons_flag(monster->type, M_PRIEST))
+ if ((mons_class_flag(monster->type, M_ACTUAL_SPELLS)
+ || mons_class_flag(monster->type, M_PRIEST))
&& (mons_has_ench(monster, ENCH_GLOWING_SHAPESHIFTER, ENCH_SHAPESHIFTER)))
{
return (false); //jmf: shapeshiftes don't get spells, just
// physical powers.
}
else if (mons_has_ench(monster, ENCH_CONFUSION)
- && !mons_flag(monster->type, M_CONFUSED))
+ && !mons_class_flag(monster->type, M_CONFUSED))
{
return (false);
}
@@ -2966,14 +3120,7 @@ static bool handle_spell( struct monsters *monster, bolt & beem )
else
{
int spell_cast = MS_NO_SPELL;
- int hspell_pass[6] = { MS_NO_SPELL, MS_NO_SPELL, MS_NO_SPELL,
- MS_NO_SPELL, MS_NO_SPELL, MS_NO_SPELL };
-
- int msecc = ((monster->type == MONS_HELLION) ? MST_BURNING_DEVIL :
- (monster->type == MONS_PANDEMONIUM_DEMON) ? MST_GHOST
- : monster->number);
-
- mons_spell_list( msecc, hspell_pass );
+ monster_spells hspell_pass = monster->spells;
// forces the casting of dig when player not visible - this is EVIL!
if (!monsterNearby)
@@ -3055,7 +3202,7 @@ static bool handle_spell( struct monsters *monster, bolt & beem )
}
// If no useful spells... cast no spell.
- if (num_no_spell == 6)
+ if (num_no_spell == 6 && draco_breath == MS_NO_SPELL)
return (false);
// up to four tries to pick a spell.
@@ -3129,6 +3276,17 @@ static bool handle_spell( struct monsters *monster, bolt & beem )
}
}
+ // If there's otherwise no ranged attack use the breath weapon.
+ // The breath weapon is also occasionally used.
+ if (draco_breath != MS_NO_SPELL
+ && (spell_cast == MS_NO_SPELL
+ || (!is_emergency_spell(hspell_pass, spell_cast)
+ && one_chance_in(4))))
+ {
+ spell_cast = draco_breath;
+ finalAnswer = true;
+ }
+
// should the monster *still* not have a spell, well, too bad {dlb}:
if (spell_cast == MS_NO_SPELL)
return (false);
@@ -3160,10 +3318,24 @@ static bool handle_spell( struct monsters *monster, bolt & beem )
switch (monster->type)
{
default:
+ if (spell_cast == draco_breath)
+ {
+ if (!simple_monster_message(monster, " breathes.",
+ MSGCH_MONSTER_SPELL))
+ {
+ if (!silenced(monster->x, monster->y)
+ && !silenced(you.x_pos, you.y_pos))
+ {
+ mpr("You hear a roar.", MSGCH_SOUND);
+ }
+ }
+ break;
+ }
+
if (silenced(monster->x, monster->y))
return (false);
- if (mons_flag(monster->type, M_PRIEST))
+ if (mons_class_flag(monster->type, M_PRIEST))
{
switch (random2(3))
{
@@ -3193,9 +3365,10 @@ static bool handle_spell( struct monsters *monster, bolt & beem )
// XXX: could be better, chosen to match the
// ones in monspeak.cc... has the problem
// that it doesn't suggest a vocal component. -- bwr
- simple_monster_message( monster,
- " gestures wildly.",
- MSGCH_MONSTER_SPELL );
+ if (player_monster_visible(monster))
+ simple_monster_message( monster,
+ " gestures wildly.",
+ MSGCH_MONSTER_SPELL );
break;
case 1:
simple_monster_message( monster,
@@ -3223,6 +3396,7 @@ static bool handle_spell( struct monsters *monster, bolt & beem )
case MONS_SHADOW_DRAGON:
case MONS_SWAMP_DRAGON:
case MONS_SWAMP_DRAKE:
+ case MONS_DEATH_DRAKE:
case MONS_HELL_HOG:
case MONS_SERPENT_OF_HELL:
case MONS_QUICKSILVER_DRAGON:
@@ -3233,7 +3407,7 @@ static bool handle_spell( struct monsters *monster, bolt & beem )
if (!silenced(monster->x, monster->y)
&& !silenced(you.x_pos, you.y_pos))
{
- mpr("You hear a roar.", MSGCH_MONSTER_SPELL);
+ mpr("You hear a roar.", MSGCH_SOUND);
}
}
break;
@@ -3271,16 +3445,21 @@ static bool handle_spell( struct monsters *monster, bolt & beem )
if (monster->type == MONS_GERYON
&& !silenced(you.x_pos, you.y_pos))
{
- mpr("You hear a weird and mournful sound.");
+ mpr("You hear a weird and mournful sound.", MSGCH_SOUND);
}
}
// FINALLY! determine primary spell effects {dlb}:
- if (spell_cast == MS_BLINK && monsterNearby)
- // why only cast blink if nearby? {dlb}
+ if (spell_cast == MS_BLINK)
{
- simple_monster_message(monster, " blinks!");
- monster_blink(monster);
+ // why only cast blink if nearby? {dlb}
+ if (monsterNearby)
+ {
+ simple_monster_message(monster, " blinks!");
+ monster_blink(monster);
+ }
+ else
+ return (false);
}
else
{
@@ -3288,7 +3467,7 @@ static bool handle_spell( struct monsters *monster, bolt & beem )
mmov_x = 0;
mmov_y = 0;
}
- } // end "if mons_flag(monster->type, M_SPELLCASTER) ...
+ } // end "if mons_class_flag(monster->type, M_SPELLCASTER) ...
return (true);
} // end handle_spell()
@@ -3327,7 +3506,7 @@ static bool handle_throw(struct monsters *monster, bolt & beem)
return (false);
// recent addition {GDL} - monsters won't throw if they can do melee.
- // wastes valuable ammo, and most monsters are better at melee anyway.
+ // wastes valuable ammo, and most monsters are better at melee anyway.
if (adjacent( beem.target_x, beem.target_y, monster->x, monster->y ))
return (false);
@@ -3360,364 +3539,367 @@ static bool handle_throw(struct monsters *monster, bolt & beem)
// good idea?
if (mons_should_fire( beem ))
{
- beem.beam_name[0] = '\0';
+ beem.name.clear();
return (mons_throw( monster, beem, mon_item ));
}
return (false);
} // end handle_throw()
-
-//---------------------------------------------------------------
-//
-// handle_monsters
-//
-// This is the routine that controls monster AI.
-//
-//---------------------------------------------------------------
-void handle_monsters(void)
+static void handle_monster_move(int i, monsters *monster)
{
- bool brkk = false;
+ bool brkk = false;
struct bolt beem;
- int i;
+ FixedArray <unsigned int, 19, 19> show;
- FixedArray < unsigned int, 19, 19 > show;
+ if (monster->hit_points > monster->max_hit_points)
+ monster->hit_points = monster->max_hit_points;
-// losight(show, grd, you.x_pos, you.y_pos);
+ // monster just summoned (or just took stairs), skip this action
+ if (testbits( monster->flags, MF_JUST_SUMMONED ))
+ {
+ monster->flags &= ~MF_JUST_SUMMONED;
+ return;
+ }
+
+ monster->speed_increment += (monster->speed * you.time_taken) / 10;
- for (i = 0; i < MAX_MONSTERS; i++)
+ if (you.slow > 0)
{
- struct monsters *monster = &menv[i];
+ monster->speed_increment += (monster->speed * you.time_taken) / 10;
+ }
- if (monster->type != -1)
+ // Handle enchantments and clouds on nonmoving monsters:
+ if (monster->speed == 0)
+ {
+ if (env.cgrid[monster->x][monster->y] != EMPTY_CLOUD
+ && !mons_has_ench( monster, ENCH_SUBMERGED ))
{
- if (monster->hit_points > monster->max_hit_points)
- monster->hit_points = monster->max_hit_points;
+ mons_in_cloud( monster );
+ }
- // monster just summoned (or just took stairs), skip this action
- if (testbits( monster->flags, MF_JUST_SUMMONED ))
- {
- monster->flags &= ~MF_JUST_SUMMONED;
- continue;
- }
+ handle_enchantment( monster );
+ }
- monster->speed_increment += (monster->speed * you.time_taken) / 10;
+ // memory is decremented here for a reason -- we only want it
+ // decrementing once per monster "move"
+ if (monster->foe_memory > 0)
+ monster->foe_memory--;
+
+ if (monster->type == MONS_GLOWING_SHAPESHIFTER)
+ mons_add_ench( monster, ENCH_GLOWING_SHAPESHIFTER );
+
+ // otherwise there are potential problems with summonings
+ if (monster->type == MONS_SHAPESHIFTER)
+ mons_add_ench( monster, ENCH_SHAPESHIFTER );
+
+ // We reset batty monsters from wander to seek here, instead
+ // of in handle_behaviour() since that will be called with
+ // every single movement, and we want these monsters to
+ // hit and run. -- bwr
+ if (monster->foe != MHITNOT
+ && monster->behaviour == BEH_WANDER
+ && testbits( monster->flags, MF_BATTY ))
+ {
+ monster->behaviour = BEH_SEEK;
+ }
- if (you.slow > 0)
- {
- monster->speed_increment += (monster->speed * you.time_taken) / 10;
- }
+ while (monster->speed_increment >= 80)
+ { // The continues & breaks are WRT this.
+ if (monster->type != -1 && monster->hit_points < 1)
+ break;
- // Handle enchantments and clouds on nonmoving monsters:
- if (monster->speed == 0)
- {
- if (env.cgrid[monster->x][monster->y] != EMPTY_CLOUD
- && !mons_has_ench( monster, ENCH_SUBMERGED ))
- {
- mons_in_cloud( monster );
- }
+ monster->speed_increment -= 10;
- handle_enchantment( monster );
- }
+ if (env.cgrid[monster->x][monster->y] != EMPTY_CLOUD)
+ {
+ if (mons_has_ench( monster, ENCH_SUBMERGED ))
+ break;
+
+ if (monster->type == -1)
+ break; // problem with vortices
- // memory is decremented here for a reason -- we only want it
- // decrementing once per monster "move"
- if (monster->foe_memory > 0)
- monster->foe_memory--;
-
- if (monster->type == MONS_GLOWING_SHAPESHIFTER)
- mons_add_ench( monster, ENCH_GLOWING_SHAPESHIFTER );
-
- // otherwise there are potential problems with summonings
- if (monster->type == MONS_SHAPESHIFTER)
- mons_add_ench( monster, ENCH_SHAPESHIFTER );
-
- // We reset batty monsters from wander to seek here, instead
- // of in handle_behaviour() since that will be called with
- // every single movement, and we want these monsters to
- // hit and run. -- bwr
- if (monster->foe != MHITNOT
- && monster->behaviour == BEH_WANDER
- && testbits( monster->flags, MF_BATTY ))
+ mons_in_cloud(monster);
+
+ if (monster->type == -1)
{
- monster->behaviour = BEH_SEEK;
+ monster->speed_increment = 1;
+ break;
}
+ }
- while (monster->speed_increment >= 80)
- { // The continues & breaks are WRT this.
- if (monster->type != -1 && monster->hit_points < 1)
- break;
+ handle_behaviour(monster);
- monster->speed_increment -= 10;
+ if (handle_enchantment(monster))
+ continue;
- if (env.cgrid[monster->x][monster->y] != EMPTY_CLOUD)
- {
- if (mons_has_ench( monster, ENCH_SUBMERGED ))
- break;
+ // submerging monsters will hide from clouds
+ if (monster_can_submerge(monster->type, grd[monster->x][monster->y])
+ && env.cgrid[monster->x][monster->y] != EMPTY_CLOUD)
+ {
+ mons_add_ench( monster, ENCH_SUBMERGED );
+ }
- if (monster->type == -1)
- break; // problem with vortices
+ // regenerate:
+ if (monster_descriptor(monster->type, MDSC_REGENERATES)
- mons_in_cloud(monster);
+ || (monster->type == MONS_FIRE_ELEMENTAL
+ && (grd[monster->x][monster->y] == DNGN_LAVA
+ || env.cgrid[monster->x][monster->y] == CLOUD_FIRE
+ || env.cgrid[monster->x][monster->y] == CLOUD_FIRE_MON))
- if (monster->type == -1)
- {
- monster->speed_increment = 1;
- break;
- }
- }
+ || (monster->type == MONS_WATER_ELEMENTAL
+ && (grd[monster->x][monster->y] == DNGN_SHALLOW_WATER
+ || grd[monster->x][monster->y] == DNGN_DEEP_WATER))
- handle_behaviour(monster);
+ || (monster->type == MONS_AIR_ELEMENTAL
+ && env.cgrid[monster->x][monster->y] == EMPTY_CLOUD
+ && one_chance_in(3))
- if (handle_enchantment(monster))
- continue;
+ || one_chance_in(25))
+ {
+ heal_monster(monster, 1, false);
+ }
- // submerging monsters will hide from clouds
- const int habitat = monster_habitat( monster->type );
- if (habitat != DNGN_FLOOR
- && habitat == grd[monster->x][monster->y]
- && env.cgrid[monster->x][monster->y] != EMPTY_CLOUD)
- {
- mons_add_ench( monster, ENCH_SUBMERGED );
- }
+ if (monster->speed >= 100)
+ continue;
+
+ if (monster->type == MONS_ZOMBIE_SMALL
+ || monster->type == MONS_ZOMBIE_LARGE
+ || monster->type == MONS_SIMULACRUM_SMALL
+ || monster->type == MONS_SIMULACRUM_LARGE
+ || monster->type == MONS_SKELETON_SMALL
+ || monster->type == MONS_SKELETON_LARGE)
+ {
+ monster->max_hit_points = monster->hit_points;
+ }
- // regenerate:
- if (monster_descriptor(monster->type, MDSC_REGENERATES)
+ if (igrd[monster->x][monster->y] != NON_ITEM
+ && (mons_itemuse(monster->type) == MONUSE_WEAPONS_ARMOUR
+ || mons_itemuse(monster->type) == MONUSE_EATS_ITEMS
+ || monster->type == MONS_NECROPHAGE
+ || monster->type == MONS_GHOUL))
+ {
+ if (handle_pickup(monster))
+ continue;
+ }
- || (monster->type == MONS_FIRE_ELEMENTAL
- && (grd[monster->x][monster->y] == DNGN_LAVA
- || env.cgrid[monster->x][monster->y] == CLOUD_FIRE
- || env.cgrid[monster->x][monster->y] == CLOUD_FIRE_MON))
+ // calculates mmov_x, mmov_y based on monster target.
+ handle_movement(monster);
- || (monster->type == MONS_WATER_ELEMENTAL
- && (grd[monster->x][monster->y] == DNGN_SHALLOW_WATER
- || grd[monster->x][monster->y] == DNGN_DEEP_WATER))
+ brkk = false;
- || (monster->type == MONS_AIR_ELEMENTAL
- && env.cgrid[monster->x][monster->y] == EMPTY_CLOUD
- && one_chance_in(3))
+ if (mons_has_ench( monster, ENCH_CONFUSION )
+ || (monster->type == MONS_AIR_ELEMENTAL
+ && mons_has_ench( monster, ENCH_SUBMERGED )))
+ {
+ mmov_x = random2(3) - 1;
+ mmov_y = random2(3) - 1;
- || one_chance_in(25))
- {
- heal_monster(monster, 1, false);
- }
+ // bounds check: don't let confused monsters try to run
+ // off the map
+ if (monster->target_x + mmov_x < 0
+ || monster->target_x + mmov_x >= GXM)
+ {
+ mmov_x = 0;
+ }
- if (monster->speed >= 100)
- continue;
+ if (monster->target_y + mmov_y < 0
+ || monster->target_y + mmov_y >= GYM)
+ {
+ mmov_y = 0;
+ }
- if (monster->type == MONS_ZOMBIE_SMALL
- || monster->type == MONS_ZOMBIE_LARGE
- || monster->type == MONS_SIMULACRUM_SMALL
- || monster->type == MONS_SIMULACRUM_LARGE
- || monster->type == MONS_SKELETON_SMALL
- || monster->type == MONS_SKELETON_LARGE)
- {
- monster->max_hit_points = monster->hit_points;
- }
+ if (mgrd[monster->x + mmov_x][monster->y + mmov_y] != NON_MONSTER
+ && (mmov_x != 0 || mmov_y != 0))
+ {
+ mmov_x = 0;
+ mmov_y = 0;
- if (igrd[monster->x][monster->y] != NON_ITEM
- && (mons_itemuse(monster->type) == MONUSE_WEAPONS_ARMOUR
- || mons_itemuse(monster->type) == MONUSE_EATS_ITEMS
- || monster->type == MONS_NECROPHAGE
- || monster->type == MONS_GHOUL))
+ if (monsters_fight(i, mgrd[monster->x + mmov_x][monster->y + mmov_y]))
{
- if (handle_pickup(monster))
- continue;
+ brkk = true;
}
+ }
+ }
- // calculates mmov_x, mmov_y based on monster target.
- handle_movement(monster);
+ if (brkk)
+ continue;
- brkk = false;
+ handle_nearby_ability( monster );
- if (mons_has_ench( monster, ENCH_CONFUSION )
- || (monster->type == MONS_AIR_ELEMENTAL
- && mons_has_ench( monster, ENCH_SUBMERGED )))
- {
- mmov_x = random2(3) - 1;
- mmov_y = random2(3) - 1;
+ beem.target_x = monster->target_x;
+ beem.target_y = monster->target_y;
- // bounds check: don't let confused monsters try to run
- // off the map
- if (monster->target_x + mmov_x < 0
- || monster->target_x + mmov_x >= GXM)
- {
- mmov_x = 0;
- }
+ if (monster->behaviour != BEH_SLEEP
+ && monster->behaviour != BEH_WANDER)
+ {
+ // prevents unfriendlies from nuking you from offscreen.
+ // How nice!
+ if (mons_friendly(monster) || mons_near(monster))
+ {
+ if (handle_special_ability(monster, beem))
+ continue;
- if (monster->target_y + mmov_y < 0
- || monster->target_y + mmov_y >= GYM)
- {
- mmov_y = 0;
- }
+ if (handle_potion(monster, beem))
+ continue;
- if (mgrd[monster->x + mmov_x][monster->y + mmov_y] != NON_MONSTER
- && (mmov_x != 0 || mmov_y != 0))
- {
- mmov_x = 0;
- mmov_y = 0;
+ if (handle_scroll(monster))
+ continue;
- if (monsters_fight(i, mgrd[monster->x + mmov_x][monster->y + mmov_y]))
- {
- brkk = true;
- }
- }
+ // shapeshifters don't get spells
+ if (!mons_has_ench( monster, ENCH_GLOWING_SHAPESHIFTER,
+ ENCH_SHAPESHIFTER )
+ || !mons_class_flag( monster->type, M_ACTUAL_SPELLS ))
+ {
+ if (handle_spell(monster, beem))
+ continue;
}
- if (brkk)
+ if (handle_wand(monster, beem))
continue;
- handle_nearby_ability( monster );
+ if (handle_reaching(monster))
+ continue;
+ }
- beem.target_x = monster->target_x;
- beem.target_y = monster->target_y;
+ if (handle_throw(monster, beem))
+ continue;
+ }
- if (monster->behaviour != BEH_SLEEP
- && monster->behaviour != BEH_WANDER)
+ // see if we move into (and fight) an unfriendly monster
+ int targmon = mgrd[monster->x + mmov_x][monster->y + mmov_y];
+ if (targmon != NON_MONSTER
+ && targmon != i
+ && !mons_aligned(i, targmon))
+ {
+ // figure out if they fight
+ if (monsters_fight(i, targmon))
+ {
+ if (testbits(monster->flags, MF_BATTY))
{
- // prevents unfriendlies from nuking you from offscreen.
- // How nice!
- if (mons_friendly(monster) || mons_near(monster))
- {
- if (handle_special_ability(monster, beem))
- continue;
-
- if (handle_potion(monster, beem))
- continue;
-
- if (handle_scroll(monster))
- continue;
+ monster->behaviour = BEH_WANDER;
+ monster->target_x = 10 + random2(GXM - 10);
+ monster->target_y = 10 + random2(GYM - 10);
+ // monster->speed_increment -= monster->speed;
+ }
- // shapeshifters don't get spells
- if (!mons_has_ench( monster, ENCH_GLOWING_SHAPESHIFTER,
- ENCH_SHAPESHIFTER )
- || !mons_flag( monster->type, M_ACTUAL_SPELLS ))
- {
- if (handle_spell(monster, beem))
- continue;
- }
+ mmov_x = 0;
+ mmov_y = 0;
+ brkk = true;
+ }
+ }
- if (handle_wand(monster, beem))
- continue;
+ if (brkk)
+ continue;
- if (handle_reaching(monster))
- continue;
- }
+ if (monster->x + mmov_x == you.x_pos
+ && monster->y + mmov_y == you.y_pos)
+ {
+ bool isFriendly = mons_friendly(monster);
+ bool attacked = false;
- if (handle_throw(monster, beem))
- continue;
- }
+ if (!isFriendly)
+ {
+ monster_attack(i);
+ attacked = true;
- // see if we move into (and fight) an unfriendly monster
- int targmon = mgrd[monster->x + mmov_x][monster->y + mmov_y];
- if (targmon != NON_MONSTER
- && targmon != i
- && !mons_aligned(i, targmon))
+ if (testbits(monster->flags, MF_BATTY))
{
- // figure out if they fight
- if (monsters_fight(i, targmon))
- {
- if (testbits(monster->flags, MF_BATTY))
- {
- monster->behaviour = BEH_WANDER;
- monster->target_x = 10 + random2(GXM - 10);
- monster->target_y = 10 + random2(GYM - 10);
- // monster->speed_increment -= monster->speed;
- }
-
- mmov_x = 0;
- mmov_y = 0;
- brkk = true;
- }
+ monster->behaviour = BEH_WANDER;
+ monster->target_x = 10 + random2(GXM - 10);
+ monster->target_y = 10 + random2(GYM - 10);
}
+ }
- if (brkk)
- continue;
+ if ((monster->type == MONS_GIANT_SPORE
+ || monster->type == MONS_BALL_LIGHTNING)
+ && monster->hit_points < 1)
+ {
- if (monster->x + mmov_x == you.x_pos
- && monster->y + mmov_y == you.y_pos)
- {
- bool isFriendly = mons_friendly(monster);
- bool attacked = false;
+ // detach monster from the grid first, so it
+ // doesn't get hit by its own explosion (GDL)
+ mgrd[monster->x][monster->y] = NON_MONSTER;
- if (!isFriendly)
- {
- monster_attack(i);
- attacked = true;
+ spore_goes_pop(monster);
+ monster_cleanup(monster);
+ continue;
+ }
- if (testbits(monster->flags, MF_BATTY))
- {
- monster->behaviour = BEH_WANDER;
- monster->target_x = 10 + random2(GXM - 10);
- monster->target_y = 10 + random2(GYM - 10);
- }
- }
+ if (attacked)
+ {
+ mmov_x = 0;
+ mmov_y = 0;
+ continue; //break;
+ }
+ }
- if ((monster->type == MONS_GIANT_SPORE
- || monster->type == MONS_BALL_LIGHTNING)
- && monster->hit_points < 1)
- {
+ if (invalid_monster(monster) || mons_is_stationary(monster))
+ continue;
- // detach monster from the grid first, so it
- // doesn't get hit by its own explosion (GDL)
- mgrd[monster->x][monster->y] = NON_MONSTER;
+ monster_move(monster);
- spore_goes_pop(monster);
- monster_cleanup(monster);
- continue;
- }
+ // reevaluate behaviour, since the monster's
+ // surroundings have changed (it may have moved,
+ // or died for that matter. Don't bother for
+ // dead monsters. :)
+ if (monster->type != -1)
+ handle_behaviour(monster);
- if (attacked)
- {
- mmov_x = 0;
- mmov_y = 0;
- continue; //break;
- }
- }
+ } // end while
- if (monster->type == -1 || monster->type == MONS_OKLOB_PLANT
- || monster->type == MONS_CURSE_SKULL
- || (monster->type >= MONS_CURSE_TOE
- && monster->type <= MONS_POTION_MIMIC))
- {
- continue;
- }
+ if (monster->type != -1 && monster->hit_points < 1)
+ {
+ if (monster->type == MONS_GIANT_SPORE
+ || monster->type == MONS_BALL_LIGHTNING)
+ {
+ // detach monster from the grid first, so it
+ // doesn't get hit by its own explosion (GDL)
+ mgrd[monster->x][monster->y] = NON_MONSTER;
+
+ spore_goes_pop( monster );
+ monster_cleanup( monster );
+ return;
+ }
+ else
+ {
+ monster_die( monster, KILL_MISC, 0 );
+ }
+ }
+}
- monster_move(monster);
+//---------------------------------------------------------------
+//
+// handle_monsters
+//
+// This is the routine that controls monster AI.
+//
+//---------------------------------------------------------------
+void handle_monsters(void)
+{
+ // Keep track of monsters that have already moved and don't allow
+ // them to move again.
+ memset(immobile_monster, 0, sizeof immobile_monster);
- // reevaluate behaviour, since the monster's
- // surroundings have changed (it may have moved,
- // or died for that matter. Don't bother for
- // dead monsters. :)
- if (monster->type != -1)
- handle_behaviour(monster);
+ for (int i = 0; i < MAX_MONSTERS; i++)
+ {
+ struct monsters *monster = &menv[i];
- } // end while
+ if (monster->type == -1 || immobile_monster[i])
+ continue;
- if (monster->type != -1 && monster->hit_points < 1)
- {
- if (monster->type == MONS_GIANT_SPORE
- || monster->type == MONS_BALL_LIGHTNING)
- {
- // detach monster from the grid first, so it
- // doesn't get hit by its own explosion (GDL)
- mgrd[monster->x][monster->y] = NON_MONSTER;
+ const int mx = monster->x,
+ my = monster->y;
+ handle_monster_move(i, monster);
- spore_goes_pop( monster );
- monster_cleanup( monster );
- continue;
- }
- else
- {
- monster_die( monster, KILL_MISC, 0 );
- }
- }
- } // end of if (mons_class != -1)
+ if (!invalid_monster(monster)
+ && (monster->x != mx || monster->y != my))
+ immobile_monster[i] = true;
} // end of for loop
// Clear any summoning flags so that lower indiced
// monsters get their actions in the next round.
- for (i = 0; i < MAX_MONSTERS; i++)
+ for (int i = 0; i < MAX_MONSTERS; i++)
{
menv[i].flags &= ~MF_JUST_SUMMONED;
}
@@ -3744,10 +3926,7 @@ static bool handle_pickup(struct monsters *monster)
if (monster->behaviour == BEH_SLEEP)
return (false);
- if (monster->type == MONS_JELLY
- || monster->type == MONS_BROWN_OOZE
- || monster->type == MONS_ACID_BLOB
- || monster->type == MONS_ROYAL_JELLY)
+ if (mons_itemuse(monster->type) == MONUSE_EATS_ITEMS)
{
int hps_gained = 0;
int max_eat = roll_dice( 1, 10 );
@@ -3785,7 +3964,7 @@ static bool handle_pickup(struct monsters *monster)
if (quant > max_eat - eaten)
quant = max_eat - eaten;
- hps_gained += (quant * mass_item( mitm[item] )) / 20 + quant;
+ hps_gained += (quant * item_mass( mitm[item] )) / 20 + quant;
eaten += quant;
}
else
@@ -3822,10 +4001,10 @@ static bool handle_pickup(struct monsters *monster)
if (!monsterNearby)
strcat(info, " distant");
strcat(info, " slurping noise.");
- mpr(info);
+ mpr(info, MSGCH_SOUND);
}
- if (mons_flag( monster->type, M_SPLITS ))
+ if (mons_class_flag( monster->type, M_SPLITS ))
{
const int reqd = (monster->hit_dice <= 6)
? 50 : monster->hit_dice * 8;
@@ -3855,8 +4034,8 @@ static bool handle_pickup(struct monsters *monster)
// wimpy monsters (Kob, gob) shouldn't pick up halberds etc
// of course, this also block knives {dlb}:
- if ((mons_charclass(monster->type) == MONS_KOBOLD
- || mons_charclass(monster->type) == MONS_GOBLIN)
+ if ((mons_species(monster->type) == MONS_KOBOLD
+ || mons_species(monster->type) == MONS_GOBLIN)
&& property( mitm[item], PWPN_HIT ) <= 0)
{
return (false);
@@ -4058,6 +4237,135 @@ static bool handle_pickup(struct monsters *monster)
return (true);
} // end handle_pickup()
+static void jelly_grows(monsters *monster)
+{
+ if (!silenced(you.x_pos, you.y_pos)
+ && !silenced(monster->x, monster->y))
+ {
+ strcpy(info, "You hear a");
+ if (!mons_near(monster))
+ strcat(info, " distant");
+ strcat(info, " slurping noise.");
+ mpr(info, MSGCH_SOUND);
+ }
+
+ monster->hit_points += 5;
+
+ // note here, that this makes jellies "grow" {dlb}:
+ if (monster->hit_points > monster->max_hit_points)
+ monster->max_hit_points = monster->hit_points;
+
+ if (mons_class_flag( monster->type, M_SPLITS ))
+ {
+ // and here is where the jelly might divide {dlb}
+ const int reqd = (monster->hit_dice < 6) ? 50
+ : monster->hit_dice * 8;
+
+ if (monster->hit_points >= reqd)
+ jelly_divide(monster);
+ }
+}
+
+static bool mons_can_displace(const monsters *mpusher, const monsters *mpushee)
+{
+ if (invalid_monster(mpusher) || invalid_monster(mpushee))
+ return (false);
+
+ const int ipushee = monster_index(mpushee);
+ if (ipushee < 0 || ipushee >= MAX_MONSTERS)
+ return (false);
+
+ if (immobile_monster[ipushee])
+ return (false);
+
+ // Confused monsters can't be pushed past, sleeping monsters
+ // can't push. Note that sleeping monsters can't be pushed
+ // past, either, but they may be woken up by a crowd trying to
+ // elbow past them, and the wake-up check happens downstream.
+ if (mons_is_confused(mpusher) || mons_is_confused(mpushee)
+ || mons_is_paralysed(mpusher) || mons_is_paralysed(mpushee)
+ || mons_is_sleeping(mpusher))
+ return (false);
+
+ // Batty monsters are unpushable
+ if (mons_is_batty(mpusher) || mons_is_batty(mpushee))
+ return (false);
+
+ if (!monster_shover(mpusher))
+ return (false);
+
+ if (!monster_senior(mpusher, mpushee))
+ return (false);
+
+ return (true);
+}
+
+static bool monster_swaps_places( monsters *mon, int mx, int my )
+{
+ if (!mx && !my)
+ return (false);
+
+ int targmon = mgrd[mon->x + mx][mon->y + my];
+ if (targmon == MHITNOT || targmon == MHITYOU)
+ return (false);
+
+ monsters *m2 = &menv[targmon];
+ if (!mons_can_displace(mon, m2))
+ return (false);
+
+ if (mons_is_sleeping(m2))
+ {
+ if (one_chance_in(2))
+ {
+#ifdef DEBUG_DIAGNOSTICS
+ char mname[ITEMNAME_SIZE];
+ moname(m2->type, true, DESC_PLAIN, mname);
+ mprf(MSGCH_DIAGNOSTICS,
+ "Alerting monster %s at (%d,%d)", mname, m2->x, m2->y);
+#endif
+ behaviour_event( m2, ME_ALERT, MHITNOT );
+ }
+ return (false);
+ }
+
+ // Check that both monsters will be happy at their proposed new locations.
+ const int cx = mon->x, cy = mon->y,
+ nx = mon->x + mx, ny = mon->y + my;
+ if (!habitat_okay(mon, grd[nx][ny])
+ || !habitat_okay(m2, grd[cx][cy]))
+ return (false);
+
+ // Okay, do the swap!
+#ifdef DEBUG_DIAGNOSTICS
+ char mname[ITEMNAME_SIZE];
+ moname(mon->type, true, DESC_PLAIN, mname);
+ mprf(MSGCH_DIAGNOSTICS,
+ "Swap: %s (%d,%d)->(%d,%d) (%d;%d)",
+ mname, mon->x, mon->y, nx, ny, mon->speed_increment, mon->speed);
+#endif
+ mon->x = nx;
+ mon->y = ny;
+ mgrd[nx][ny] = monster_index(mon);
+
+#ifdef DEBUG_DIAGNOSTICS
+ moname(m2->type, true, DESC_PLAIN, mname);
+ mprf(MSGCH_DIAGNOSTICS,
+ "Swap: %s (%d,%d)->(%d,%d) (%d;%d)",
+ mname, m2->x, m2->y, cx, cy, mon->speed_increment, mon->speed);
+#endif
+ m2->x = cx;
+ m2->y = cy;
+ const int m2i = monster_index(m2);
+ ASSERT(m2i >= 0 && m2i < MAX_MONSTERS);
+ mgrd[cx][cy] = m2i;
+ immobile_monster[m2i] = true;
+
+ mons_trap(mon);
+ mons_trap(m2);
+
+ return (false);
+}
+
static void monster_move(struct monsters *monster)
{
FixedArray < bool, 3, 3 > good_move;
@@ -4078,7 +4386,7 @@ static void monster_move(struct monsters *monster)
if (mons_flies(monster) > 0
|| habitat != DNGN_FLOOR
- || mons_flag( monster->type, M_AMPHIBIOUS ))
+ || mons_class_flag( monster->type, M_AMPHIBIOUS ))
{
okmove = MINMOVE;
}
@@ -4088,12 +4396,11 @@ static void monster_move(struct monsters *monster)
for (count_y = 0; count_y < 3; count_y++)
{
good_move[count_x][count_y] = true;
+
const int targ_x = monster->x + count_x - 1;
const int targ_y = monster->y + count_y - 1;
- int target_grid = grd[targ_x][targ_y];
-
- const int targ_cloud = env.cgrid[ targ_x ][ targ_y ];
- const int curr_cloud = env.cgrid[ monster->x ][ monster->y ];
+ // [ds] Bounds check was after grd[targ_x][targ_y] which would
+ // trigger an ASSERT. Moved it up.
// bounds check - don't consider moving out of grid!
if (targ_x < 0 || targ_x >= GXM || targ_y < 0 || targ_y >= GYM)
@@ -4102,6 +4409,18 @@ static void monster_move(struct monsters *monster)
continue;
}
+ int target_grid = grd[targ_x][targ_y];
+
+ const int targ_cloud_num = env.cgrid[ targ_x ][ targ_y ];
+ const int targ_cloud_type =
+ targ_cloud_num == EMPTY_CLOUD? CLOUD_NONE
+ : env.cloud[targ_cloud_num].type;
+
+ const int curr_cloud_num = env.cgrid[ monster->x ][ monster->y ];
+ const int curr_cloud_type =
+ curr_cloud_num == EMPTY_CLOUD? CLOUD_NONE
+ : env.cloud[curr_cloud_num].type;
+
if (target_grid == DNGN_DEEP_WATER)
deep_water_available = true;
@@ -4144,10 +4463,10 @@ static void monster_move(struct monsters *monster)
// Water elementals avoid fire and heat
if (monster->type == MONS_WATER_ELEMENTAL
&& (target_grid == DNGN_LAVA
- || targ_cloud == CLOUD_FIRE
- || targ_cloud == CLOUD_FIRE_MON
- || targ_cloud == CLOUD_STEAM
- || targ_cloud == CLOUD_STEAM_MON))
+ || targ_cloud_type == CLOUD_FIRE
+ || targ_cloud_type == CLOUD_FIRE_MON
+ || targ_cloud_type == CLOUD_STEAM
+ || targ_cloud_type == CLOUD_STEAM_MON))
{
good_move[count_x][count_y] = false;
continue;
@@ -4158,8 +4477,8 @@ static void monster_move(struct monsters *monster)
&& (target_grid == DNGN_DEEP_WATER
|| target_grid == DNGN_SHALLOW_WATER
|| target_grid == DNGN_BLUE_FOUNTAIN
- || targ_cloud == CLOUD_COLD
- || targ_cloud == CLOUD_COLD_MON))
+ || targ_cloud_type == CLOUD_COLD
+ || targ_cloud_type == CLOUD_COLD_MON))
{
good_move[count_x][count_y] = false;
continue;
@@ -4167,12 +4486,14 @@ static void monster_move(struct monsters *monster)
// Submerged water creatures avoid the shallows where
// they would be forced to surface. -- bwr
+ // [dshaligram] Monsters now prefer to head for deep water only if
+ // they're low on hitpoints. No point in hiding if they want a
+ // fight.
if (habitat == DNGN_DEEP_WATER
&& (targ_x != you.x_pos || targ_y != you.y_pos)
&& target_grid != DNGN_DEEP_WATER
&& grd[monster->x][monster->y] == DNGN_DEEP_WATER
- && (mons_has_ench( monster, ENCH_SUBMERGED )
- || monster->hit_points < (monster->max_hit_points * 3) / 4))
+ && monster->hit_points < (monster->max_hit_points * 3) / 4)
{
good_move[count_x][count_y] = false;
continue;
@@ -4182,11 +4503,16 @@ static void monster_move(struct monsters *monster)
// we're hostile (even if we're heading somewhere
// else)
- // smacking another monster is good, if the monsters
+ // smacking another monster is good, if the monsters
// are aligned differently
if (mgrd[targ_x][targ_y] != NON_MONSTER)
{
- if (mons_aligned(monster_index(monster), mgrd[targ_x][targ_y]))
+ const int thismonster = monster_index(monster),
+ targmonster = mgrd[targ_x][targ_y];
+ if (mons_aligned(thismonster, targmonster)
+ && targmonster != MHITNOT
+ && targmonster != MHITYOU
+ && !mons_can_displace(monster, &menv[targmonster]))
{
good_move[count_x][count_y] = false;
continue;
@@ -4205,15 +4531,15 @@ static void monster_move(struct monsters *monster)
}
}
- if (targ_cloud != EMPTY_CLOUD)
+ if (targ_cloud_num != EMPTY_CLOUD)
{
- if (curr_cloud != EMPTY_CLOUD
- && env.cloud[targ_cloud].type == env.cloud[curr_cloud].type)
+ if (curr_cloud_num != EMPTY_CLOUD
+ && targ_cloud_type == curr_cloud_type)
{
continue;
}
- switch (env.cloud[ targ_cloud ].type)
+ switch (targ_cloud_type)
{
case CLOUD_FIRE:
case CLOUD_FIRE_MON:
@@ -4252,7 +4578,7 @@ static void monster_move(struct monsters *monster)
continue;
break;
- // this isn't harmful, but dumb critters might think so.
+ // this isn't harmful, but dumb critters might think so.
case CLOUD_GREY_SMOKE:
case CLOUD_GREY_SMOKE_MON:
if (mons_intel(monster->type) > I_ANIMAL || coinflip())
@@ -4313,42 +4639,20 @@ static void monster_move(struct monsters *monster)
{
grd[monster->x + mmov_x][monster->y + mmov_y] = DNGN_FLOOR;
- if (!silenced(you.x_pos, you.y_pos)
- && !silenced(monster->x, monster->y))
- {
- strcpy(info, "You hear a");
- if (!mons_near(monster))
- strcat(info, " distant");
- strcat(info, " slurping noise.");
- mpr(info);
- }
-
- monster->hit_points += 5;
-
- // note here, that this makes jellies "grow" {dlb}:
- if (monster->hit_points > monster->max_hit_points)
- monster->max_hit_points = monster->hit_points;
-
- if (mons_flag( monster->type, M_SPLITS ))
- {
- // and here is where the jelly might divide {dlb}
- const int reqd = (monster->hit_dice < 6) ? 50
- : monster->hit_dice * 8;
-
- if (monster->hit_points >= reqd)
- jelly_divide(monster);
- }
+ jelly_grows(monster);
} // done door-eating jellies
- // water creatures have a preferance for water they can hide in -- bwr
+ // water creatures have a preference for water they can hide in -- bwr
+ // [ds] Weakened the powerful attraction to deep water if the monster
+ // is in good health.
if (habitat == DNGN_DEEP_WATER
&& deep_water_available
&& grd[monster->x][monster->y] != DNGN_DEEP_WATER
&& grd[monster->x + mmov_x][monster->y + mmov_y] != DNGN_DEEP_WATER
&& (monster->x + mmov_x != you.x_pos
|| monster->y + mmov_y != you.y_pos)
- && (coinflip()
+ && (one_chance_in(3)
|| monster->hit_points <= (monster->max_hit_points * 3) / 4))
{
count = 0;
@@ -4374,10 +4678,10 @@ static void monster_move(struct monsters *monster)
}
- // now, if a monster can't move in its intended direction, try
- // either side. If they're both good, move in whichever dir
+ // now, if a monster can't move in its intended direction, try
+ // either side. If they're both good, move in whichever dir
// gets it closer(farther for fleeing monsters) to its target.
- // If neither does, do nothing.
+ // If neither does, do nothing.
if (good_move[mmov_x + 1][mmov_y + 1] == false)
{
int current_distance = grid_distance( monster->x, monster->y,
@@ -4401,7 +4705,7 @@ static void monster_move(struct monsters *monster)
int dist[2];
- // first 1 away, then 2 (3 is silly)
+ // first 1 away, then 2 (3 is silly)
for (int j = 1; j <= 2; j++)
{
int sdir, inc;
@@ -4488,7 +4792,7 @@ forget_it:
grd[monster->x + mmov_x][monster->y + mmov_y] = DNGN_FLOOR;
if (!silenced(you.x_pos, you.y_pos))
- mpr("You hear a grinding noise.");
+ mpr("You hear a grinding noise.", MSGCH_SOUND);
}
}
@@ -4523,7 +4827,12 @@ forget_it:
int targmon = mgrd[monster->x + mmov_x][monster->y + mmov_y];
if (targmon != NON_MONSTER)
{
- monsters_fight(monster_index(monster), targmon);
+ if (mons_aligned(monster_index(monster), targmon))
+ monster_swaps_places(monster, mmov_x, mmov_y);
+ else
+ monsters_fight(monster_index(monster), targmon);
+
+ // If the monster swapped places, the work's already done.
mmov_x = 0;
mmov_y = 0;
}
@@ -4535,9 +4844,24 @@ forget_it:
2 + random2(4) );
}
+ if (monster->type == MONS_ROTTING_DEVIL
+ || monster->type == MONS_CURSE_TOE)
+ {
+ place_cloud( CLOUD_MIASMA_MON, monster->x, monster->y,
+ 2 + random2(3) );
+ }
+
/* this appears to be the real one, ie where the movement occurs: */
monster->x += mmov_x;
monster->y += mmov_y;
+
+ if (monster->type == MONS_CURSE_TOE)
+ {
+ // Curse toes are a special case; they can only move at half their
+ // attack rate. To simulate that, the toe loses another action's
+ // worth of energy when moving.
+ monster->speed_increment -= 10;
+ }
}
else
{
@@ -4552,9 +4876,7 @@ forget_it:
mgrd[monster->x][monster->y] = monster_index(monster);
// monsters stepping on traps:
- if (grd[monster->x][monster->y] >= DNGN_TRAP_MECHANICAL
- && grd[monster->x][monster->y] <= DNGN_UNDISCOVERED_TRAP
- && (mmov_x != 0 || mmov_y != 0))
+ if (mmov_x != 0 || mmov_y != 0)
{
mons_trap(monster);
}
@@ -4568,7 +4890,7 @@ static bool plant_spit(struct monsters *monster, struct bolt &pbolt)
char spit_string[INFO_SIZE];
// setup plant spit
- strcpy( pbolt.beam_name, "acid" );
+ pbolt.name = "acid";
pbolt.type = SYM_ZAP;
pbolt.range = 9;
pbolt.rangeMax = 9;
@@ -4578,7 +4900,7 @@ static bool plant_spit(struct monsters *monster, struct bolt &pbolt)
pbolt.damage = dice_def( 3, 7 );
pbolt.hit = 20 + (3 * monster->hit_dice);
pbolt.thrower = KILL_MON_MISSILE;
- pbolt.aux_source = NULL;
+ pbolt.aux_source.clear();
// fire tracer
fire_tracer(monster, pbolt);
@@ -4718,7 +5040,8 @@ static void mons_in_cloud(struct monsters *monster)
case CLOUD_MIASMA_MON:
simple_monster_message(monster, " is engulfed in a dark miasma!");
- if (mons_holiness(monster->type) != MH_NATURAL)
+ if (mons_holiness(monster) != MH_NATURAL
+ || monster->type == MONS_DEATH_DRAKE)
return;
poison_monster(monster, (env.cloud[wc].type == CLOUD_MIASMA));
@@ -4891,7 +5214,7 @@ bool message_current_target(void)
} // end message_current_target()
// aaah, the simple joys of pointer arithmetic! {dlb}:
-unsigned int monster_index(struct monsters *monster)
+unsigned int monster_index(const monsters *monster)
{
return (monster - menv.buffer());
} // end monster_index()
@@ -4912,6 +5235,9 @@ bool hurt_monster(struct monsters * victim, int damage_dealt)
bool heal_monster(struct monsters * patient, int health_boost,
bool permit_growth)
{
+ if (mons_is_statue(patient->type))
+ return (false);
+
if (health_boost < 1)
return (false);
else if (!permit_growth && patient->hit_points == patient->max_hit_points)
@@ -4987,3 +5313,98 @@ static int map_wand_to_mspell(int wand_type)
return (mzap);
}
+
+void seen_monster(struct monsters *monster)
+{
+ if ( monster->flags & MF_SEEN )
+ return;
+
+ // First time we've seen this particular monster
+ monster->flags |= MF_SEEN;
+
+ if ( MONST_INTERESTING(monster) &&
+ monster->type != MONS_PANDEMONIUM_DEMON &&
+ monster->type != MONS_PLAYER_GHOST )
+ {
+ char namebuf[ITEMNAME_SIZE];
+ moname(monster->type, true, DESC_NOCAP_A, namebuf);
+ take_note(Note(NOTE_SEEN_MONSTER, monster->type, 0, namebuf));
+ }
+}
+
+//---------------------------------------------------------------
+//
+// shift_monster
+//
+// Moves a monster to approximately (x,y) and returns true
+// if monster was moved.
+//
+//---------------------------------------------------------------
+bool shift_monster( struct monsters *mon, int x, int y )
+{
+ bool found_move = false;
+
+ int i, j;
+ int tx, ty;
+ int nx = 0, ny = 0;
+
+ int count = 0;
+
+ if (x == 0 && y == 0)
+ {
+ // try and find a random floor space some distance away
+ for (i = 0; i < 50; i++)
+ {
+ tx = 5 + random2( GXM - 10 );
+ ty = 5 + random2( GYM - 10 );
+
+ int dist = grid_distance(x, y, tx, ty);
+ if (grd[tx][ty] == DNGN_FLOOR && dist > 10)
+ break;
+ }
+
+ if (i == 50)
+ return (false);
+ }
+
+ for (i = -1; i <= 1; i++)
+ {
+ for (j = -1; j <= 1; j++)
+ {
+ tx = x + i;
+ ty = y + j;
+
+ if (tx < 5 || tx > GXM - 5 || ty < 5 || ty > GXM - 5)
+ continue;
+
+ // won't drop on anything but vanilla floor right now
+ if (grd[tx][ty] != DNGN_FLOOR)
+ continue;
+
+ if (mgrd[tx][ty] != NON_MONSTER)
+ continue;
+
+ if (tx == you.x_pos && ty == you.y_pos)
+ continue;
+
+ count++;
+ if (one_chance_in(count))
+ {
+ nx = tx;
+ ny = ty;
+ found_move = true;
+ }
+ }
+ }
+
+ if (found_move)
+ {
+ const int mon_index = mgrd[mon->x][mon->y];
+ mgrd[mon->x][mon->y] = NON_MONSTER;
+ mgrd[nx][ny] = mon_index;
+ mon->x = nx;
+ mon->y = ny;
+ }
+
+ return (found_move);
+}
diff --git a/crawl-ref/source/monstuff.h b/crawl-ref/source/monstuff.h
index f6202f23ae..dbbb85aeae 100644
--- a/crawl-ref/source/monstuff.h
+++ b/crawl-ref/source/monstuff.h
@@ -3,6 +3,8 @@
* Summary: Misc monster related functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -16,6 +18,8 @@
// useful macro
#define SAME_ATTITUDE(x) (mons_friendly(x)?BEH_FRIENDLY:BEH_HOSTILE)
+#define MONST_INTERESTING(x) (x->flags & MF_INTERESTING)
+
// for definition of type monsters {dlb}
#include "externs.h"
// for definition of type monsters {dlb}
@@ -65,7 +69,7 @@ bool curse_an_item(char which, char power);
/* ***********************************************************************
* called from: fight
* *********************************************************************** */
-void monster_blink(struct monsters *monster);
+bool monster_blink(struct monsters *monster);
/* ***********************************************************************
@@ -131,7 +135,7 @@ bool message_current_target(void);
/* ***********************************************************************
* called from: xxx
* *********************************************************************** */
-unsigned int monster_index(struct monsters *monster);
+unsigned int monster_index(const monsters *monster);
// last updated 08jun2000 {dlb}
@@ -147,5 +151,11 @@ bool hurt_monster(struct monsters *victim, int damage_dealt);
* *********************************************************************** */
bool heal_monster(struct monsters *patient, int health_boost, bool permit_growth);
+/* ***********************************************************************
+ * called from: monplace - spells2 - view
+ * *********************************************************************** */
+void seen_monster(struct monsters *monster);
+
+bool shift_monster( struct monsters *mon, int x = 0, int y = 0 );
#endif
diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc
index 38d0d8c885..c47363ad7d 100644
--- a/crawl-ref/source/mstuff2.cc
+++ b/crawl-ref/source/mstuff2.cc
@@ -3,6 +3,8 @@
* Summary: Misc monster related functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <5> 31 July 2000 JDJ Fixed mon_throw to use lnchType.
@@ -26,7 +28,9 @@
#include "beam.h"
#include "debug.h"
#include "effects.h"
+#include "item_use.h"
#include "itemname.h"
+#include "itemprop.h"
#include "items.h"
#include "misc.h"
#include "monplace.h"
@@ -38,7 +42,6 @@
#include "spl-cast.h"
#include "stuff.h"
#include "view.h"
-#include "wpn-misc.h"
static unsigned char monster_abjuration(int pow, bool test);
@@ -49,6 +52,9 @@ static unsigned char monster_abjuration(int pow, bool test);
// to be some sort of trap prior to function call: {dlb}
void mons_trap(struct monsters *monster)
{
+ if (!is_trap_square(monster->x, monster->y))
+ return;
+
int temp_rand = 0; // probability determination {dlb}
// single calculation permissible {dlb}
@@ -90,42 +96,42 @@ void mons_trap(struct monsters *monster)
{
case TRAP_DART:
projectileFired = true;
- strcpy(beem.beam_name, " dart");
+ beem.name = " dart";
beem.damage = dice_def( 1, 4 );
beem.colour = OBJ_MISSILES;
beem.type = MI_DART;
break;
case TRAP_NEEDLE:
projectileFired = true;
- strcpy(beem.beam_name, " needle");
+ beem.name = " needle";
beem.damage = dice_def( 1, 0 );
beem.colour = OBJ_MISSILES;
beem.type = MI_NEEDLE;
break;
case TRAP_ARROW:
projectileFired = true;
- strcpy(beem.beam_name, "n arrow");
+ beem.name = "n arrow";
beem.damage = dice_def( 1, 7 );
beem.colour = OBJ_MISSILES;
beem.type = MI_ARROW;
break;
case TRAP_SPEAR:
projectileFired = true;
- strcpy(beem.beam_name, " spear");
+ beem.name = " spear";
beem.damage = dice_def( 1, 10 );
beem.colour = OBJ_WEAPONS;
beem.type = WPN_SPEAR;
break;
case TRAP_BOLT:
projectileFired = true;
- strcpy(beem.beam_name, " bolt");
+ beem.name = " bolt";
beem.damage = dice_def( 1, 13 );
beem.colour = OBJ_MISSILES;
beem.type = MI_BOLT;
break;
case TRAP_AXE:
projectileFired = true;
- strcpy(beem.beam_name, "n axe");
+ beem.name = "n axe";
beem.damage = dice_def( 1, 15 );
beem.colour = OBJ_WEAPONS;
beem.type = WPN_HAND_AXE;
@@ -229,7 +235,7 @@ void mons_trap(struct monsters *monster)
temp_rand = random2(16);
beem.thrower = KILL_MON; // probably unnecessary
- beem.aux_source = NULL;
+ beem.aux_source.clear();
if (mons_friendly(monster))
{
@@ -282,13 +288,11 @@ void mons_trap(struct monsters *monster)
if (monsterNearby)
{
- snprintf( info, INFO_SIZE, "A%s %s %s%s!",
- beem.beam_name,
+ mprf("A%s %s %s%s!",
+ beem.name.c_str(),
(damage_taken >= 0) ? "hits" : "misses",
ptr_monam( monster, DESC_NOCAP_THE ),
- (damage_taken == 0) ? ", but does no damage" : "" );
-
- mpr(info);
+ (damage_taken == 0) ? ", but does no damage" : "");
}
if (apply_poison)
@@ -362,8 +366,12 @@ void mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cast)
switch (spell_cast)
{
+ case MS_SUMMON_SMALL_MAMMALS:
case MS_VAMPIRE_SUMMON:
- sumcount2 = 3 + random2(3) + monster->hit_dice / 5;
+ if ( spell_cast == MS_SUMMON_SMALL_MAMMALS )
+ sumcount2 = 1 + random2(4);
+ else
+ sumcount2 = 3 + random2(3) + monster->hit_dice / 5;
for (sumcount = 0; sumcount < sumcount2; sumcount++)
{
@@ -486,6 +494,28 @@ void mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cast)
monster->x, monster->y, monster->foe, 250 );
return;
+ case MS_SUMMON_MUSHROOMS: // Summon swarms of icky crawling fungi.
+ if (!mons_friendly(monster) && monsterNearby
+ && monster_abjuration(1, true) > 0 && coinflip())
+ {
+ monster_abjuration( monster->hit_dice * 10, false );
+ return;
+ }
+
+ sumcount2 = 1 + random2(2) + random2( monster->hit_dice / 4 + 1 );
+
+ duration = ENCH_ABJ_II + monster->hit_dice / 5;
+ if (duration > ENCH_ABJ_VI)
+ duration = ENCH_ABJ_VI;
+
+ for (int i = 0; i < sumcount2; ++i)
+ create_monster(MONS_WANDERING_MUSHROOM, duration,
+ SAME_ATTITUDE(monster),
+ monster->x, monster->y,
+ monster->foe,
+ 250);
+ return;
+
case MS_SUMMON_UNDEAD: // summon undead around player
if (!mons_friendly(monster) && monsterNearby
&& monster_abjuration(1, true) > 0 && coinflip())
@@ -506,7 +536,7 @@ void mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cast)
{
summonik = random2(241); // hmmmm ... {dlb}
}
- while (mons_holiness(summonik) != MH_UNDEAD);
+ while (mons_class_holiness(summonik) != MH_UNDEAD);
create_monster(summonik, duration, SAME_ATTITUDE(monster),
you.x_pos, you.y_pos, monster->foe, 250);
@@ -519,7 +549,7 @@ void mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cast)
simple_monster_message(monster, " calls on the powers of Hell!");
- torment(monster->x, monster->y);
+ torment(monster_index(monster), monster->x, monster->y);
return;
case MS_SUMMON_DEMON_GREATER:
@@ -544,6 +574,29 @@ void mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cast)
}
return;
+ // Journey -- Added in Summon Lizards and Draconian
+ case MS_SUMMON_LIZARDS:
+ if (!mons_friendly( monster ) && !monsterNearby &&
+ monster_abjuration( 1, true ) > 0 && coinflip())
+ {
+ monster_abjuration( monster->hit_dice * 10, false );
+ return;
+ }
+
+ sumcount2 = 1 + random2(3) + random2( monster->hit_dice / 5 + 1 );
+
+ duration = ENCH_ABJ_II + monster->hit_dice / 10;
+ if (duration > ENCH_ABJ_VI)
+ duration = ENCH_ABJ_VI;
+
+ for (sumcount = 0; sumcount < sumcount2; sumcount++)
+ {
+ create_monster( rand_dragon( DRAGON_LIZARD ), duration,
+ SAME_ATTITUDE(monster),
+ monster->x, monster->y, monster->foe, 250 );
+ }
+ break;
+
case MS_CANTRIP:
// Monster spell of uselessness, just prints a message.
// This spell exists so that some monsters with really strong
@@ -633,6 +686,7 @@ void setup_mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cas
// fire_tracer, or beam.
switch (spell_cast)
{
+ case MS_SUMMON_SMALL_MAMMALS:
case MS_VAMPIRE_SUMMON:
case MS_LEVEL_SUMMON: // summon anything appropriate for level
case MS_FAKE_RAKSHASA_SUMMON:
@@ -642,6 +696,8 @@ void setup_mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cas
case MS_SUMMON_UFETUBUS:
case MS_SUMMON_BEAST: // Geryon
case MS_SUMMON_UNDEAD: // summon undead around player
+ case MS_SUMMON_MUSHROOMS:
+ case MS_SUMMON_LIZARDS:
case MS_TORMENT:
case MS_SUMMON_DEMON_GREATER:
case MS_CANTRIP:
@@ -653,7 +709,7 @@ void setup_mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cas
// Need to correct this for power of spellcaster
int power = 12 * monster->hit_dice;
- struct SBeam theBeam = mons_spells(spell_cast, power);
+ struct bolt theBeam = mons_spells(spell_cast, power);
pbolt.colour = theBeam.colour;
pbolt.range = theBeam.range;
@@ -663,18 +719,19 @@ void setup_mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cas
pbolt.ench_power = theBeam.ench_power;
pbolt.type = theBeam.type;
pbolt.flavour = theBeam.flavour;
- pbolt.thrower = theBeam.thrown;
- pbolt.aux_source = NULL;
- strcpy( pbolt.beam_name, theBeam.name.c_str() );
- pbolt.isBeam = theBeam.isBeam;
+ pbolt.thrower = theBeam.thrower;
+ pbolt.aux_source.clear();
+ pbolt.name = theBeam.name;
+ pbolt.is_beam = theBeam.is_beam;
pbolt.source_x = monster->x;
pbolt.source_y = monster->y;
- pbolt.isTracer = false;
+ pbolt.is_tracer = false;
+ pbolt.is_explosion = theBeam.is_explosion;
- if (pbolt.beam_name[0] && pbolt.beam_name[0] != '0')
- pbolt.aux_source = pbolt.beam_name;
+ if (pbolt.name.length() && pbolt.name[0] != '0')
+ pbolt.aux_source = pbolt.name;
else
- pbolt.aux_source = NULL;
+ pbolt.aux_source.clear();
if (spell_cast == MS_HASTE
|| spell_cast == MS_INVIS
@@ -683,16 +740,25 @@ void setup_mons_cast(struct monsters *monster, struct bolt &pbolt, int spell_cas
pbolt.target_x = monster->x;
pbolt.target_y = monster->y;
}
+
+ // Convenience for the hapless innocent who assumes that this
+ // damn function does all possible setup. [ds]
+ if (!pbolt.target_x && !pbolt.target_y)
+ {
+ pbolt.target_x = monster->target_x;
+ pbolt.target_y = monster->target_y;
+ }
} // end setup_mons_cast()
-void monster_teleport(struct monsters *monster, bool instan)
+void monster_teleport(struct monsters *monster, bool instan, bool silent)
{
if (!instan)
{
if (mons_del_ench(monster, ENCH_TP_I, ENCH_TP_IV))
{
- simple_monster_message(monster, " seems more stable.");
+ if (!silent)
+ simple_monster_message(monster, " seems more stable.");
}
else
mons_add_ench(monster, (coinflip() ? ENCH_TP_III : ENCH_TP_IV ));
@@ -700,13 +766,14 @@ void monster_teleport(struct monsters *monster, bool instan)
return;
}
- simple_monster_message(monster, " disappears!");
+ bool was_seen = player_monster_visible(monster) && mons_near(monster);
+
+ if (!silent)
+ simple_monster_message(monster, " disappears!");
// pick the monster up
mgrd[monster->x][monster->y] = NON_MONSTER;
- char ogrid = monster_habitat(monster->type);
-
int newx, newy;
while(true)
{
@@ -717,12 +784,7 @@ void monster_teleport(struct monsters *monster, bool instan)
if (mgrd[newx][newy] != NON_MONSTER)
continue;
- // monsters going to the same habitat
- if (ogrid == grd[newx][newy])
- break;
-
- // DEEP_WATER monsters can be teleported to SHALLOW_WATER
- if (ogrid == DNGN_DEEP_WATER && grd[newx][newy] == DNGN_SHALLOW_WATER)
+ if (monster_habitable_grid(monster, grd[newx][newy]))
break;
}
@@ -735,46 +797,85 @@ void monster_teleport(struct monsters *monster, bool instan)
if (mons_is_mimic( monster->type ))
{
monster->type = MONS_GOLD_MIMIC + random2(5);
- monster->number = get_mimic_colour( monster );
+ monster->colour = get_mimic_colour( monster );
+ }
+
+ if (!silent)
+ {
+ if (was_seen)
+ simple_monster_message(monster, " reappears nearby!");
+ else
+ simple_monster_message(monster, " appears out of thin air!");
}
+
+ if (player_monster_visible(monster) && mons_near(monster))
+ seen_monster(monster);
} // end monster_teleport()
void setup_dragon(struct monsters *monster, struct bolt &pbolt)
{
- strcpy(pbolt.beam_name, ptr_monam( monster, DESC_PLAIN ));
+ const int type = (mons_genus( monster->type ) == MONS_DRACONIAN)
+ ? draco_subspecies( monster ) : monster->type;
+ int scaling = 100;
+
+ pbolt.name = ptr_monam( monster, DESC_PLAIN );
- switch (monster->type)
+ switch (type)
{
case MONS_FIREDRAKE:
case MONS_HELL_HOUND:
case MONS_DRAGON:
case MONS_LINDWURM:
case MONS_XTAHUA:
- strcat(pbolt.beam_name, "'s blast of flame");
+ pbolt.name += "'s blast of flame";
pbolt.flavour = BEAM_FIRE;
pbolt.colour = RED;
- pbolt.aux_source = "blast of flame";
+ pbolt.aux_source = "blast of fiery breath";
break;
case MONS_ICE_DRAGON:
- strcat(pbolt.beam_name, "'s blast of cold");
+ pbolt.name += "'s blast of cold";
pbolt.flavour = BEAM_COLD;
pbolt.colour = WHITE;
- pbolt.aux_source = "blast of cold";
+ pbolt.aux_source = "blast of icy breath";
+ break;
+
+ case MONS_RED_DRACONIAN:
+ pbolt.name += "'s searing breath";
+#ifdef DEBUG_DIAGNOSTICS
+ mprf( MSGCH_DIAGNOSTICS, "bolt name: '%s'", pbolt.name.c_str() );
+#endif
+ pbolt.flavour = BEAM_FIRE;
+ pbolt.colour = RED;
+ pbolt.aux_source = "blast of searing breath";
+ scaling = 65;
break;
+ case MONS_WHITE_DRACONIAN:
+ pbolt.name += "'s chilling breath";
+#ifdef DEBUG_DIAGNOSTICS
+ mprf( MSGCH_DIAGNOSTICS, "bolt name: '%s'", pbolt.name.c_str() );
+#endif
+ pbolt.flavour = BEAM_COLD;
+ pbolt.colour = WHITE;
+ pbolt.aux_source = "blast of chilling breath";
+ scaling = 65;
+ break;
+
default:
DEBUGSTR("Bad monster class in setup_dragon()");
+ break;
}
pbolt.range = 4;
pbolt.rangeMax = 13;
pbolt.damage = dice_def( 3, (monster->hit_dice * 2) );
+ pbolt.damage.size = scaling * pbolt.damage.size / 100;
pbolt.type = SYM_ZAP;
pbolt.hit = 30;
pbolt.beam_source = monster_index(monster);
pbolt.thrower = KILL_MON;
- pbolt.isBeam = true;
+ pbolt.is_beam = true;
} // end setup_dragon();
void setup_generic_throw(struct monsters *monster, struct bolt &pbolt)
@@ -786,19 +887,20 @@ void setup_generic_throw(struct monsters *monster, struct bolt &pbolt)
pbolt.type = SYM_MISSILE;
pbolt.flavour = BEAM_MISSILE;
pbolt.thrower = KILL_MON_MISSILE;
- pbolt.aux_source = NULL;
- pbolt.isBeam = false;
+ pbolt.aux_source.clear();
+ pbolt.is_beam = false;
}
// decide if something is launched or thrown
-// pass -1 for launcher class & 0 for type if no weapon is weilded
+// pass -1 for launcher class & 0 for type if no weapon is wielded
void throw_type( int lnchClass, int lnchType, int wepClass, int wepType,
bool &launched, bool &thrown )
{
if (wepClass == OBJ_MISSILES
&& lnchClass == OBJ_WEAPONS
- && launches_things(lnchType) && wepType == launched_by(lnchType))
+ && is_range_weapon_type((weapon_type) lnchType)
+ && wepType == fires_ammo_type((weapon_type) lnchType))
{
launched = true;
}
@@ -836,9 +938,11 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
int ammoHitBonus = 0, ammoDamBonus = 0; // from thrown or ammo
int lnchHitBonus = 0, lnchDamBonus = 0; // special add from launcher
int exHitBonus = 0, exDamBonus = 0; // 'extra' bonus from skill/dex/str
+ int lnchBaseDam = 0;
int hitMult = 0;
int damMult = 0;
+ int diceMult = 100;
bool launched = false; // item is launched
bool thrown = false; // item is sensible thrown item
@@ -862,7 +966,7 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
pbolt.colour = item.colour;
pbolt.flavour = BEAM_MISSILE;
pbolt.thrower = KILL_MON_MISSILE;
- pbolt.aux_source = NULL;
+ pbolt.aux_source.clear();
// figure out if we're thrown or launched
throw_type( lnchClass, lnchType, wepClass, wepType, launched, thrown );
@@ -872,6 +976,7 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
{
lnchHitBonus = mitm[ weapon ].plus;
lnchDamBonus = mitm[ weapon ].plus2;
+ lnchBaseDam = property(mitm[weapon], PWPN_DAMAGE);
}
// extract weapon/ammo bonuses due to magic
@@ -897,9 +1002,14 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
baseDam = property( item, PWPN_DAMAGE );
if (wepClass == OBJ_MISSILES) // throw missile
+ {
// ammo damage needs adjusting here - OBJ_MISSILES
// don't get separate tohit/damage bonuses!
ammoDamBonus = ammoHitBonus;
+ // [dshaligram] Thrown stones/darts do only half the damage of
+ // launched stones/darts. This matches 4.0 behaviour.
+ baseDam = div_rand_round(baseDam, 2);
+ }
// give monster "skill" bonuses based on HD
exHitBonus = (hitMult * monster->hit_dice) / 10 + 1;
@@ -917,6 +1027,7 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
lnchDamBonus = 0;
break;
case WPN_BOW:
+ case WPN_LONGBOW:
baseHit = 0;
hitMult = 60;
damMult = 35;
@@ -944,7 +1055,10 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
break;
}
- baseDam = property( item, PWPN_HIT );
+ // Launcher is now more important than ammo for base damage.
+ baseDam = property(item, PWPN_DAMAGE);
+ if (lnchBaseDam)
+ baseDam = lnchBaseDam + random2(1 + baseDam);
// missiles don't have pluses2; use hit bonus
ammoDamBonus = ammoHitBonus;
@@ -952,6 +1066,21 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
exHitBonus = (hitMult * monster->hit_dice) / 10 + 1;
exDamBonus = (damMult * monster->hit_dice) / 10 + 1;
+ // monsters no longer gain unfair advantages with weapons of fire/ice
+ // and incorrect ammo. They now have same restriction as players.
+
+ const int bow_brand =
+ get_weapon_brand(mitm[monster->inv[MSLOT_WEAPON]]);
+ const int ammo_brand = get_ammo_brand( item );
+
+ if (!baseDam && elemental_missile_beam(bow_brand, ammo_brand))
+ baseDam = 4;
+
+ // [dshaligram] This is a horrible hack - we force beam.cc to consider
+ // this beam "needle-like".
+ if (wepClass == OBJ_MISSILES && wepType == MI_NEEDLE)
+ pbolt.ench_power = AUTOMATIC_HIT;
+
// elven bow w/ elven arrow, also orcish
if (get_equip_race( mitm[monster->inv[MSLOT_WEAPON]] )
== get_equip_race( mitm[monster->inv[MSLOT_MISSILE]] ))
@@ -959,17 +1088,10 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
baseHit++;
baseDam++;
- if (cmp_equip_race(mitm[monster->inv[MSLOT_WEAPON]], ISFLAG_ELVEN))
+ if (get_equip_race(mitm[monster->inv[MSLOT_WEAPON]]) == ISFLAG_ELVEN)
pbolt.hit++;
}
- // monsters no longer gain unfair advantages with weapons of fire/ice
- // and incorrect ammo. They now have same restriction as players.
-
- const int bow_brand = get_weapon_brand(mitm[monster->inv[MSLOT_WEAPON]]);
-
- const int ammo_brand = get_ammo_brand( item );
-
bool poison = (ammo_brand == SPMSL_POISONED
|| ammo_brand == SPMSL_POISONED_II);
@@ -977,6 +1099,9 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
if (bow_brand == SPWPN_VENOM && ammo_brand == SPMSL_NORMAL)
set_item_ego_type( item, OBJ_MISSILES, SPMSL_POISONED );
+ // Vorpal brand increases damage dice size.
+ if (bow_brand == SPWPN_VORPAL)
+ diceMult = diceMult * 130 / 100;
// WEAPON or AMMO of FIRE
if ((bow_brand == SPWPN_FLAME || ammo_brand == SPMSL_FLAME)
@@ -984,13 +1109,14 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
{
baseHit += 2;
exDamBonus += 6;
+
pbolt.flavour = BEAM_FIRE;
- strcpy(pbolt.beam_name, "bolt of ");
+ pbolt.name = "bolt of ";
if (poison)
- strcat(pbolt.beam_name, "poison ");
+ pbolt.name += "poison ";
- strcat(pbolt.beam_name, "flame");
+ pbolt.name += "flame";
pbolt.colour = RED;
pbolt.type = SYM_ZAP;
}
@@ -1001,13 +1127,14 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
{
baseHit += 2;
exDamBonus += 6;
+
pbolt.flavour = BEAM_COLD;
- strcpy(pbolt.beam_name, "bolt of ");
+ pbolt.name = "bolt of ";
if (poison)
- strcat(pbolt.beam_name, "poison ");
+ pbolt.name += "poison ";
- strcat(pbolt.beam_name, "frost");
+ pbolt.name += "frost";
pbolt.colour = WHITE;
pbolt.type = SYM_ZAP;
}
@@ -1023,16 +1150,16 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
if (mons_intel(monster->type) == I_HIGH)
exHitBonus += 10;
- // now, if a monster is, for some reason, throwing something really
- // stupid, it will have baseHit of 0 and damage of 0. Ah well.
+ // now, if a monster is, for some reason, throwing something really
+ // stupid, it will have baseHit of 0 and damage of 0. Ah well.
strcpy(info, ptr_monam( monster, DESC_CAP_THE) );
strcat(info, (launched) ? " shoots " : " throws ");
- if (strlen(pbolt.beam_name) > 0)
+ if (pbolt.name.length())
{
strcat(info, "a ");
- strcat(info, pbolt.beam_name);
+ strcat(info, pbolt.name.c_str());
}
else
{
@@ -1043,23 +1170,24 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
// build beam name
item_name( item, DESC_PLAIN, str_pass );
- strcpy(pbolt.beam_name, str_pass);
+ pbolt.name = str_pass;
}
strcat(info, ".");
mpr(info);
-
+ // [dshaligram] When changing bolt names here, you must edit
+ // hiscores.cc (scorefile_entry::terse_missile_cause()) to match.
if (launched)
{
snprintf( throw_buff, sizeof(throw_buff), "Shot with a%s %s by %s",
- (is_vowel(pbolt.beam_name[0]) ? "n" : ""), pbolt.beam_name,
+ (is_vowel(pbolt.name[0]) ? "n" : ""), pbolt.name.c_str(),
ptr_monam( monster, DESC_NOCAP_A ) );
}
else
{
snprintf( throw_buff, sizeof(throw_buff), "Hit by a%s %s thrown by %s",
- (is_vowel(pbolt.beam_name[0]) ? "n" : ""), pbolt.beam_name,
+ (is_vowel(pbolt.name[0]) ? "n" : ""), pbolt.name.c_str(),
ptr_monam( monster, DESC_NOCAP_A ) );
}
@@ -1075,6 +1203,9 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
pbolt.hit += lnchHitBonus;
}
+ pbolt.damage.size = diceMult * pbolt.damage.size / 100;
+ scale_dice(pbolt.damage);
+
// decrease inventory
fire_beam( pbolt, &item );
@@ -1094,18 +1225,19 @@ void spore_goes_pop(struct monsters *monster)
if (monster == NULL)
return;
- beam.isTracer = false;
+ beam.is_tracer = false;
+ beam.is_explosion = true;
beam.beam_source = monster_index(monster);
beam.type = SYM_BURST;
beam.target_x = monster->x;
beam.target_y = monster->y;
beam.thrower = KILL_MON; // someone else's explosion
- beam.aux_source = NULL;
+ beam.aux_source.clear();
if (type == MONS_GIANT_SPORE)
{
beam.flavour = BEAM_SPORE;
- strcpy(beam.beam_name, "explosion of spores");
+ beam.name = "explosion of spores";
beam.colour = LIGHTGREY;
beam.damage = dice_def( 3, 15 );
beam.ex_size = 2;
@@ -1114,7 +1246,7 @@ void spore_goes_pop(struct monsters *monster)
else
{
beam.flavour = BEAM_ELECTRICITY;
- strcpy(beam.beam_name, "blast of lightning");
+ beam.name = "blast of lightning";
beam.colour = LIGHTCYAN;
beam.damage = dice_def( 3, 20 );
beam.ex_size = coinflip() ? 3 : 2;
@@ -1130,21 +1262,23 @@ void spore_goes_pop(struct monsters *monster)
explosion(beam);
} // end spore_goes_pop()
-struct SBeam mons_spells( int spell_cast, int power )
+bolt mons_spells( int spell_cast, int power )
{
ASSERT(power > 0);
- struct SBeam beam;
+ bolt beam;
beam.name = "****"; // initialize to some bogus values so we can catch problems
beam.colour = 1000;
- beam.range = -1;
+ beam.range = beam.rangeMax = 8;
beam.hit = -1;
beam.damage = dice_def( 1, 0 );
beam.ench_power = -1;
beam.type = -1;
beam.flavour = -1;
- beam.thrown = -1;
+ beam.thrower = -1;
+ beam.is_beam = false;
+ beam.is_explosion = false;
switch (spell_cast)
{
@@ -1156,9 +1290,9 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 4 + (power / 100) );
beam.hit = 1500;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_MMISSILE;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_FLAME:
@@ -1174,9 +1308,9 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.hit = 60;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_FIRE;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_FROST:
@@ -1191,9 +1325,9 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.hit = 60;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_COLD;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_PARALYSIS:
@@ -1202,8 +1336,8 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_PARALYSIS;
- beam.thrown = KILL_MON_MISSILE;
- beam.isBeam = true;
+ beam.thrower = KILL_MON_MISSILE;
+ beam.is_beam = true;
break;
case MS_SLOW:
@@ -1212,8 +1346,8 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_SLOW;
- beam.thrown = KILL_MON_MISSILE;
- beam.isBeam = true;
+ beam.thrower = KILL_MON_MISSILE;
+ beam.is_beam = true;
break;
case MS_HASTE: // (self)
@@ -1222,8 +1356,8 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_HASTE;
- beam.thrown = KILL_MON_MISSILE;
- beam.isBeam = true;
+ beam.thrower = KILL_MON_MISSILE;
+ beam.is_beam = true;
break;
case MS_CONFUSE:
@@ -1232,8 +1366,8 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_CONFUSION;
- beam.thrown = KILL_MON_MISSILE;
- beam.isBeam = true;
+ beam.thrower = KILL_MON_MISSILE;
+ beam.is_beam = true;
break;
case MS_VENOM_BOLT:
@@ -1243,10 +1377,21 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 6 + power / 13 );
beam.colour = LIGHTGREEN;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_POISON;
- beam.hit = 7 + random2(power) / 80;
- beam.isBeam = true;
+ beam.hit = 8 + power / 20;
+ beam.is_beam = true;
+ break;
+
+ case MS_POISON_ARROW:
+ beam.name = "poison arrow";
+ beam.damage = dice_def( 4, 5 + power / 12 );
+ beam.colour = LIGHTGREEN;
+ beam.type = SYM_MISSILE;
+ beam.thrower = KILL_MON;
+ beam.flavour = BEAM_POISON_ARROW;
+ beam.hit = 14 + power / 25;
+ beam.range = beam.rangeMax = 8;
break;
case MS_FIRE_BOLT:
@@ -1256,10 +1401,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 8 + power / 11 );
beam.colour = RED;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_FIRE;
- beam.hit = 8 + random2(power) / 80; // hit
- beam.isBeam = true;
+ beam.hit = 12 + power / 25;
+ beam.is_beam = true;
break;
case MS_COLD_BOLT:
@@ -1269,10 +1414,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 8 + power / 11 );
beam.colour = WHITE;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_COLD;
- beam.hit = 8 + random2(power) / 80; // hit
- beam.isBeam = true;
+ beam.hit = 12 + power / 25;
+ beam.is_beam = true;
break;
case MS_LIGHTNING_BOLT:
@@ -1282,10 +1427,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 10 + power / 9 );
beam.colour = LIGHTCYAN;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_ELECTRICITY;
- beam.hit = 10 + random2(power) / 40;
- beam.isBeam = true;
+ beam.hit = 10 + power / 40;
+ beam.is_beam = true;
break;
case MS_INVIS:
@@ -1294,8 +1439,8 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_INVISIBILITY;
- beam.thrown = KILL_MON;
- beam.isBeam = true;
+ beam.thrower = KILL_MON;
+ beam.is_beam = true;
break;
case MS_FIREBALL:
@@ -1306,9 +1451,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 7 + power / 10 );
beam.hit = 40;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
- beam.flavour = BEAM_EXPLOSION; // why not BEAM_FIRE? {dlb}
- beam.isBeam = false;
+ beam.thrower = KILL_MON;
+ beam.flavour = BEAM_FIRE; // why not BEAM_FIRE? {dlb}
+ beam.is_beam = false;
+ beam.is_explosion = true;
break;
case MS_HEAL:
@@ -1317,9 +1463,9 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_HEALING;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.hit = 5 + (power / 5);
- beam.isBeam = true;
+ beam.is_beam = true;
break;
case MS_TELEPORT:
@@ -1328,8 +1474,8 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_TELEPORT; // 6 is used by digging
- beam.thrown = KILL_MON;
- beam.isBeam = true;
+ beam.thrower = KILL_MON;
+ beam.is_beam = true;
break;
case MS_TELEPORT_OTHER:
@@ -1338,12 +1484,12 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_TELEPORT; // 6 is used by digging
- beam.thrown = KILL_MON;
- beam.isBeam = true;
+ beam.thrower = KILL_MON;
+ beam.is_beam = true;
break;
case MS_BLINK:
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_CRYSTAL_SPEAR: // was splinters
@@ -1353,10 +1499,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 12 + power / 10 );
beam.colour = WHITE;
beam.type = SYM_MISSILE;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_MMISSILE;
- beam.hit = 6; // + random2(power) / 10;
- beam.isBeam = false;
+ beam.hit = 14 + power / 20;
+ beam.is_beam = false;
break;
case MS_DIG:
@@ -1365,8 +1511,8 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 7 + random2(power) / 10;
beam.type = 0;
beam.flavour = BEAM_DIGGING;
- beam.thrown = KILL_MON;
- beam.isBeam = true;
+ beam.thrower = KILL_MON;
+ beam.is_beam = true;
break;
case MS_NEGATIVE_BOLT: // negative energy
@@ -1376,10 +1522,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 6 + power / 13 );
beam.colour = DARKGREY;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_NEG;
- beam.hit = 7 + random2(power) / 80;
- beam.isBeam = true;
+ beam.hit = 11 + power / 35;
+ beam.is_beam = true;
break;
// 20, 21 are used
@@ -1390,11 +1536,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.range = 6;
beam.rangeMax = 10;
beam.damage = dice_def( 3, 7 + (power / 14) );
- beam.hit = 10 + (power / 20);
+ beam.hit = 12 + (power / 20);
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_MMISSILE;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
// 23 is brain feed
@@ -1404,12 +1550,12 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.name = "ball of steam";
beam.range = 6;
beam.rangeMax = 10;
- beam.damage = dice_def( 3, 6 );
- beam.hit = 11;
+ beam.damage = dice_def( 3, 7 + (power / 15) );
+ beam.hit = 11 + power / 20;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
- beam.flavour = BEAM_FIRE; // fire - I think this is appropriate
- beam.isBeam = false;
+ beam.thrower = KILL_MON_MISSILE;
+ beam.flavour = BEAM_STEAM;
+ beam.is_beam = false;
break;
// 27 is summon devils
@@ -1421,11 +1567,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 14;
beam.type = 0;
beam.flavour = BEAM_PAIN; // pain
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
// beam.damage = dice_def( 1, 50 );
beam.damage = dice_def( 1, 7 + (power / 20) );
beam.ench_power = 50;
- beam.isBeam = true;
+ beam.is_beam = true;
break;
// 30 is smiting
@@ -1436,11 +1582,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.range = 6;
beam.rangeMax = 10;
beam.damage = dice_def( 3, 3 + power / 50 );
- beam.hit = 8 + power / 15;
+ beam.hit = 10 + power / 15;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_FIRE;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_POISON_BLAST: // demon
@@ -1450,10 +1596,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 3 + power / 25 );
beam.colour = LIGHTGREEN;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_POISON;
- beam.hit = 7 + random2(power) / 80;
- beam.isBeam = true;
+ beam.hit = 11 + power / 25;
+ beam.is_beam = true;
+ beam.is_big_cloud = true;
break;
case MS_PURPLE_BLAST: // purple bang thing
@@ -1462,11 +1609,12 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.range = 6;
beam.rangeMax = 10;
beam.damage = dice_def( 3, 10 + power / 15 );
- beam.hit = 10 + power / 20;
+ beam.hit = 11 + power / 25;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
- beam.flavour = BEAM_EXPLOSION; // an exploding magical missile
- beam.isBeam = false;
+ beam.thrower = KILL_MON_MISSILE;
+ beam.flavour = BEAM_MMISSILE;
+ beam.is_beam = false;
+ beam.is_explosion = true;
break;
case MS_ENERGY_BOLT: // eye of devastation
@@ -1475,11 +1623,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.range = 9;
beam.rangeMax = 23;
beam.damage = dice_def( 3, 20 );
- beam.hit = 9;
+ beam.hit = 11 + power / 30;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_NUKE; // a magical missile which destroys walls
- beam.isBeam = true;
+ beam.is_beam = true;
break;
case MS_STING: // sting
@@ -1490,9 +1638,9 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 1, 6 + power / 25 );
beam.hit = 60;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_POISON;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_IRON_BOLT:
@@ -1501,11 +1649,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.range = 4;
beam.rangeMax = 8;
beam.damage = dice_def( 3, 8 + (power / 9) );
- beam.hit = 6 + (power / 25);
+ beam.hit = 12 + (power / 25);
beam.type = SYM_MISSILE;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_MMISSILE; // similarly unresisted thing
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_STONE_ARROW:
@@ -1514,11 +1662,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.range = 8;
beam.rangeMax = 12;
beam.damage = dice_def( 3, 5 + (power / 10) );
- beam.hit = 5 + power / 47;
+ beam.hit = 8 + power / 35;
beam.type = SYM_MISSILE;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_MMISSILE; // similarly unresisted thing
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_POISON_SPLASH:
@@ -1527,11 +1675,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.range = 5;
beam.rangeMax = 10;
beam.damage = dice_def( 1, 4 + power / 10 );
- beam.hit = 9;
+ beam.hit = 9 + power / 20;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_POISON;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_DISINTEGRATE:
@@ -1540,11 +1688,11 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 14;
beam.type = 0;
beam.flavour = BEAM_DISINTEGRATION;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.ench_power = 50;
// beam.hit = 30 + (power / 10);
beam.damage = dice_def( 1, 30 + (power / 10) );
- beam.isBeam = true;
+ beam.is_beam = true;
break;
case MS_MARSH_GAS: // swamp drake
@@ -1554,23 +1702,37 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 2 + power / 25 );
beam.colour = GREEN;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_POISON;
- beam.hit = 7 + random2(power) / 80;
- beam.isBeam = false;
+ beam.hit = 12 + power / 30;
+ beam.is_beam = true;
+ beam.is_big_cloud = true;
break;
+ case MS_MIASMA: // death drake
+ beam.name = "foul vapour";
+ beam.damage = dice_def( 3, 5 + power / 24 );
+ beam.colour = DARKGREY;
+ beam.type = SYM_ZAP;
+ beam.thrower = KILL_MON;
+ beam.flavour = BEAM_MIASMA;
+ beam.hit = 12 + power / 20;
+ beam.is_beam = true;
+ beam.is_big_cloud = true;
+ beam.range = beam.rangeMax = 8;
+ break;
+
case MS_QUICKSILVER_BOLT: // Quicksilver dragon
beam.colour = random_colour();
beam.name = "bolt of energy";
beam.range = 9;
beam.rangeMax = 23;
beam.damage = dice_def( 3, 25 );
- beam.hit = 9;
+ beam.hit = 9 + power / 25;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON_MISSILE;
+ beam.thrower = KILL_MON_MISSILE;
beam.flavour = BEAM_MMISSILE;
- beam.isBeam = false;
+ beam.is_beam = false;
break;
case MS_HELLFIRE: // fiend's hellfire
@@ -1581,9 +1743,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 25 );
beam.hit = 20;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
- beam.flavour = BEAM_EXPLOSION; // hellfire - not BEAM_HELLFIRE? {dlb}
- beam.isBeam = true;
+ beam.thrower = KILL_MON;
+ beam.flavour = BEAM_HELLFIRE;
+ beam.is_beam = true;
+ beam.is_explosion = true;
break;
case MS_METAL_SPLINTERS:
@@ -1593,10 +1756,10 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.damage = dice_def( 3, 20 + power / 20 );
beam.colour = CYAN;
beam.type = SYM_ZAP;
- beam.thrown = KILL_MON;
+ beam.thrower = KILL_MON;
beam.flavour = BEAM_FRAG;
- beam.hit = 15 + random2(power) / 50;
- beam.isBeam = true;
+ beam.hit = 15 + power / 30;
+ beam.is_beam = true;
break;
case MS_BANISHMENT:
@@ -1605,8 +1768,19 @@ struct SBeam mons_spells( int spell_cast, int power )
beam.rangeMax = 9;
beam.type = 0;
beam.flavour = BEAM_BANISH;
- beam.thrown = KILL_MON_MISSILE;
- beam.isBeam = true;
+ beam.thrower = KILL_MON_MISSILE;
+ beam.is_beam = true;
+ break;
+
+ case MS_BLINK_OTHER:
+ beam.name = "0";
+ beam.type = 0;
+ beam.flavour = BEAM_BLINK;
+ beam.thrower = KILL_MON;
+ beam.is_beam = true;
+ beam.is_enchant = true;
+ beam.range = 8;
+ beam.rangeMax = 8;
break;
default:
@@ -1663,3 +1837,39 @@ static unsigned char monster_abjuration(int pow, bool test)
return result;
} // end monster_abjuration()
+
+bool silver_statue_effects(monsters *mons)
+{
+ if ((mons_player_visible(mons) || one_chance_in(3))
+ && !one_chance_in(3))
+ {
+ char wc[30];
+
+ weird_colours( random2(256), wc );
+ snprintf(info, INFO_SIZE, "'s eyes glow %s.", wc);
+ simple_monster_message(mons, info, MSGCH_WARN);
+
+ create_monster( summon_any_demon((coinflip() ? DEMON_COMMON
+ : DEMON_LESSER)),
+ ENCH_ABJ_V, BEH_HOSTILE,
+ you.x_pos, you.y_pos,
+ MHITYOU, 250 );
+ return (true);
+ }
+ return (false);
+}
+
+bool orange_statue_effects(monsters *mons)
+{
+ if ((mons_player_visible(mons) || one_chance_in(3))
+ && !one_chance_in(3))
+ {
+ mpr("A hostile presence attacks your mind!", MSGCH_WARN);
+
+ miscast_effect( SPTYP_DIVINATION, random2(15), random2(150), 100,
+ "an orange crystal statue" );
+ return (true);
+ }
+
+ return (false);
+}
diff --git a/crawl-ref/source/mstuff2.h b/crawl-ref/source/mstuff2.h
index 1bdd23232f..aedb2cdcd0 100644
--- a/crawl-ref/source/mstuff2.h
+++ b/crawl-ref/source/mstuff2.h
@@ -3,6 +3,8 @@
* Summary: Misc monster related functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> 4/24/99 JDJ mons_spells returns an
@@ -19,22 +21,6 @@
#include "externs.h"
-struct SBeam
-{
- std::string name;
- int colour;
- int range;
- int rangeMax;
- int hit;
- dice_def damage;
- int ench_power;
- int type;
- int flavour;
- int thrown;
- bool isBeam;
-};
-
-
/*
beam_colour = _pass[0];
beam_range = _pass[1];
@@ -50,7 +36,7 @@ struct SBeam
/* ***********************************************************************
* called from: monstuff - mstuff2
* *********************************************************************** */
-struct SBeam mons_spells(int spell_cast, int power);
+bolt mons_spells(int spell_cast, int power);
// last updated 12may2000 {dlb}
@@ -95,7 +81,8 @@ void mons_trap(struct monsters *monster);
/* ***********************************************************************
* called from: beam - fight - files - monstuff - mstuff2 - spells4
* *********************************************************************** */
-void monster_teleport(struct monsters *monster, bool instan);
+void monster_teleport(struct monsters *monster, bool instan,
+ bool silent = false);
// last updated Dec17,2000 -- gdl
@@ -113,5 +100,7 @@ void throw_type(int lnchClass, int lnchType, int wepClass, int wepType,
bool &launched, bool &thrown);
+bool orange_statue_effects(monsters *mons);
+bool silver_statue_effects(monsters *mons);
#endif
diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc
index 027a810432..a4deade186 100644
--- a/crawl-ref/source/mutation.cc
+++ b/crawl-ref/source/mutation.cc
@@ -35,7 +35,9 @@
#include "defines.h"
#include "effects.h"
+#include "itemprop.h"
#include "macro.h"
+#include "notes.h"
#include "ouch.h"
#include "player.h"
#include "skills2.h"
@@ -48,6 +50,12 @@ int how_mutated(void);
char body_covered(void);
bool perma_mutate(int which_mut, char how_much);
+const char* troll_claw_messages[3] = {
+ "Your claws sharpen.",
+ "Your claws sharpen.",
+ "Your claws steel!"
+};
+
const char *mutation_descrip[][3] = {
{"You have tough skin (AC +1).", "You have very tough skin (AC +2).",
"You have extremely tough skin (AC +3)."},
@@ -896,6 +904,20 @@ void display_mutations(void)
j++;
break;
+ case SP_SPRIGGAN:
+ cprintf("You can see invisible." EOL);
+ cprintf("You cover the ground extremely quickly." EOL);
+ j += 2;
+ break;
+
+ case SP_CENTAUR:
+ if (!you.mutation[MUT_FAST])
+ cprintf("You cover the ground quickly." EOL);
+ else
+ cprintf("You cover the ground extremely quickly." EOL);
+ j++;
+ break;
+
case SP_NAGA:
// breathe poison replaces spit poison:
if (!you.mutation[MUT_BREATHE_POISON])
@@ -905,7 +927,8 @@ void display_mutations(void)
cprintf("Your system is immune to poisons." EOL);
cprintf("You can see invisible." EOL);
- j += 3;
+ cprintf("You move rather slowly." EOL);
+ j += 4;
break;
case SP_GNOME:
@@ -915,7 +938,24 @@ void display_mutations(void)
case SP_TROLL:
cprintf("Your body regenerates quickly." EOL);
- j++;
+ switch ( you.mutation[MUT_CLAWS] ) {
+ case 0:
+ cprintf("You have claws for hands." EOL);
+ break;
+ case 1:
+ cprintf("You have sharp claws for hands." EOL);
+ break;
+ case 2:
+ cprintf("You have very sharp claws for hands." EOL);
+ break;
+ case 3:
+ // literally true
+ cprintf("Your claws are sharper than steel." EOL);
+ break;
+ default:
+ break;
+ }
+ j += 2;
break;
case SP_GHOUL:
@@ -1051,6 +1091,10 @@ void display_mutations(void)
// this is already handled above:
if (you.species == SP_NAGA && i == MUT_BREATHE_POISON)
continue;
+ if (you.species == SP_CENTAUR && i == MUT_FAST)
+ continue;
+ if (you.species == SP_TROLL && i == MUT_CLAWS)
+ continue;
j++;
textcolor(LIGHTGREY);
@@ -1100,9 +1144,6 @@ void display_mutations(void)
puttext(1, 1, 80, 25, buffer);
#endif
- //cprintf("xxxxxxxxxxxxx");
- //last_requested = 0;
-
return;
} // end display_mutations()
@@ -1110,8 +1151,17 @@ bool mutate(int which_mutation, bool failMsg)
{
int mutat = which_mutation;
bool force_mutation = false; // is mutation forced?
+ bool demonspawn = false; // demonspawn mutation?
int i;
+ if (which_mutation >= 2000)
+ {
+ demonspawn = true;
+ force_mutation = true;
+ mutat -= 2000;
+ which_mutation -= 2000;
+ }
+
if (which_mutation >= 1000) // must give mutation without failure
{
force_mutation = true;
@@ -1120,10 +1170,11 @@ bool mutate(int which_mutation, bool failMsg)
}
// Undead bodies don't mutate, they fall apart. -- bwr
- if (you.is_undead)
+ // except for demonspawn in lichform -- haranp
+ if (you.is_undead && !demonspawn)
{
- if (force_mutation
- || (wearing_amulet(AMU_RESIST_MUTATION) && coinflip()))
+ if ((!wearing_amulet(AMU_RESIST_MUTATION) && coinflip())
+ || one_chance_in(10))
{
mpr( "Your body decomposes!" );
@@ -1427,7 +1478,6 @@ bool mutate(int which_mutation, bool failMsg)
break;
case MUT_TELEPORT_CONTROL:
- you.attribute[ATTR_CONTROL_TELEPORT]++;
mpr(gain_mutation[mutat][you.mutation[mutat]], MSGCH_MUTATION);
break;
@@ -1449,7 +1499,10 @@ bool mutate(int which_mutation, bool failMsg)
break;
case MUT_CLAWS:
- mpr( gain_mutation[ mutat ][ you.mutation[mutat] ], MSGCH_MUTATION );
+
+ mpr((you.species == SP_TROLL ? troll_claw_messages
+ : gain_mutation[mutat])[you.mutation[mutat]],
+ MSGCH_MUTATION);
// gloves aren't prevented until level three
if (you.mutation[ mutat ] >= 3 && you.equip[ EQ_GLOVES ] != -1)
@@ -1470,8 +1523,9 @@ bool mutate(int which_mutation, bool failMsg)
{
mpr(gain_mutation[mutat][you.mutation[mutat]], MSGCH_MUTATION);
- if (you.equip[EQ_HELMET] != -1
- && you.inv[you.equip[EQ_HELMET]].plus2 > 1)
+ if (you.equip[EQ_HELMET] != -1 &&
+ (get_helmet_type(you.inv[you.equip[EQ_HELMET]]) == THELM_CAP ||
+ get_helmet_type(you.inv[you.equip[EQ_HELMET]]) == THELM_WIZARD_HAT))
{
break; // horns don't push caps/wizard hats off
}
@@ -1519,6 +1573,8 @@ bool mutate(int which_mutation, bool failMsg)
mpr(gain_mutation[mutat][you.mutation[mutat]], MSGCH_MUTATION);
you.mutation[mutat]++;
calc_hp();
+ /* special-case check */
+ take_note(Note(NOTE_GET_MUTATION, mutat, you.mutation[mutat]));
return true;
case MUT_ROBUST:
@@ -1530,6 +1586,8 @@ bool mutate(int which_mutation, bool failMsg)
mpr(gain_mutation[mutat][you.mutation[mutat]], MSGCH_MUTATION);
you.mutation[mutat]++;
calc_hp();
+ /* special-case check */
+ take_note(Note(NOTE_GET_MUTATION, mutat, you.mutation[mutat]));
return true;
case MUT_BLACK_SCALES:
@@ -1567,6 +1625,7 @@ bool mutate(int which_mutation, bool failMsg)
you.mutation[mutat]++;
+ take_note(Note(NOTE_GET_MUTATION, mutat, you.mutation[mutat]));
/* remember, some mutations don't get this far (eg frail) */
return true;
} // end mutation()
@@ -1678,7 +1737,6 @@ bool delete_mutation(int which_mutation)
break;
case MUT_TELEPORT_CONTROL:
- you.attribute[ATTR_CONTROL_TELEPORT]--;
mpr(lose_mutation[mutat][you.mutation[mutat] - 1], MSGCH_MUTATION);
break;
@@ -1699,6 +1757,8 @@ bool delete_mutation(int which_mutation)
if (you.mutation[mutat] > 0)
you.mutation[mutat]--;
calc_hp();
+ /* special-case check */
+ take_note(Note(NOTE_LOSE_MUTATION, mutat, you.mutation[mutat]));
return true;
case MUT_ROBUST:
@@ -1706,6 +1766,8 @@ bool delete_mutation(int which_mutation)
if (you.mutation[mutat] > 0)
you.mutation[mutat]--;
calc_hp();
+ /* special-case check */
+ take_note(Note(NOTE_LOSE_MUTATION, mutat, you.mutation[mutat]));
return true;
case MUT_BLACK_SCALES:
@@ -1766,6 +1828,7 @@ bool delete_mutation(int which_mutation)
if (you.mutation[mutat] > 0)
you.mutation[mutat]--;
+ take_note(Note(NOTE_LOSE_MUTATION, mutat, you.mutation[mutat]));
return true;
} // end delete_mutation()
@@ -1825,7 +1888,7 @@ const char *mutation_name(int which_mutat, int level )
// Some mutations only have one "level", and it's better
// to show the first level description than a blank description.
- if (mutation_descrip[ which_mutat ][ level - 1 ][0] == '\0')
+ if (mutation_descrip[ which_mutat ][ level - 1 ][0] == 0)
return (mutation_descrip[ which_mutat ][ 0 ]);
else
return (mutation_descrip[ which_mutat ][ level - 1 ]);
@@ -1956,7 +2019,7 @@ void demonspawn(void)
}
}
- // check here so we can see if we need to extent our options:
+ // check here so we can see if we need to extend our options:
if (whichm != -1 && you.mutation[whichm] != 0)
whichm = -1;
@@ -2148,13 +2211,13 @@ bool perma_mutate(int which_mut, char how_much)
{
char levels = 0;
- if (mutate(which_mut + 1000))
+ if (mutate(which_mut + 2000))
levels++;
- if (how_much >= 2 && mutate(which_mut + 1000))
+ if (how_much >= 2 && mutate(which_mut + 2000))
levels++;
- if (how_much >= 3 && mutate(which_mut + 1000))
+ if (how_much >= 3 && mutate(which_mut + 2000))
levels++;
you.demon_pow[which_mut] = levels;
diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc
index eca23d3815..c4ffc8cbd1 100644
--- a/crawl-ref/source/newgame.cc
+++ b/crawl-ref/source/newgame.cc
@@ -58,6 +58,7 @@
#ifdef DOS
#include <conio.h>
+#include <dos.h>
#endif
#ifdef UNIX
@@ -66,18 +67,6 @@
#include <unistd.h>
#endif
-#ifdef USE_EMX
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#endif
-
-#ifdef OS9
-#include <stat.h>
-#else
-#include <sys/stat.h>
-#endif
-
#include "externs.h"
#include "abl-show.h"
@@ -86,8 +75,10 @@
#include "fight.h"
#include "initfile.h"
#include "itemname.h"
+#include "itemprop.h"
#include "items.h"
#include "macro.h"
+#include "menu.h"
#include "player.h"
#include "randart.h"
#include "skills.h"
@@ -95,8 +86,9 @@
#include "spl-util.h"
#include "stuff.h"
#include "version.h"
-#include "wpn-misc.h"
+#include "view.h"
+extern std::string init_file_location;
#define MIN_START_STAT 1
@@ -136,6 +128,7 @@ static char ng_race, ng_cls;
static bool ng_random;
static int ng_ck, ng_dk, ng_pr;
static int ng_weapon;
+static int ng_book;
static void reset_newgame_options(void)
{
@@ -145,6 +138,7 @@ static void reset_newgame_options(void)
ng_dk = DK_NO_SELECTION;
ng_pr = GOD_NO_GOD;
ng_weapon = WPN_UNKNOWN;
+ ng_book = SBT_NO_SELECTION;
}
static void save_newgame_options(void)
@@ -158,6 +152,7 @@ static void save_newgame_options(void)
Options.prev_dk = ng_dk;
Options.prev_pr = ng_pr;
Options.prev_weapon = ng_weapon;
+ Options.prev_book = ng_book;
write_newgame_options_file();
}
@@ -170,6 +165,7 @@ static void set_startup_options(void)
Options.death_knight = Options.prev_dk;
Options.chaos_knight = Options.prev_ck;
Options.priest = Options.prev_pr;
+ Options.book = Options.prev_book;
}
static bool prev_startup_options_set(void)
@@ -251,7 +247,7 @@ static void pick_random_species_and_class( void )
{
// we only want draconians counted once in this loop...
// we'll add the variety lower down -- bwr
- if (sp >= SP_WHITE_DRACONIAN && sp <= SP_UNK2_DRACONIAN)
+ if (sp >= SP_WHITE_DRACONIAN && sp <= SP_BASE_DRACONIAN)
continue;
for (int cl = JOB_FIGHTER; cl < NUM_JOBS; cl++)
@@ -283,64 +279,35 @@ static void pick_random_species_and_class( void )
static bool check_saved_game(void)
{
FILE *handle;
- char char_fil[kFileNameSize];
-
-#ifdef LOAD_UNPACKAGE_CMD
- // Create the file name base
- char name_buff[kFileNameLen];
-
- snprintf( name_buff, sizeof(name_buff),
- SAVE_DIR_PATH "%s%d", you.your_name, (int) getuid() );
-
- char zip_buff[kFileNameLen];
- strcpy(zip_buff, name_buff);
- strcat(zip_buff, PACKAGE_SUFFIX);
+ std::string basename = get_savedir_filename( you.your_name, "", "");
+ std::string savename = basename + ".sav";
- // Create save dir name
- strcpy(char_fil, name_buff);
- strcat(char_fil, ".sav");
-
- handle = fopen(zip_buff, "rb+");
+#ifdef LOAD_UNPACKAGE_CMD
+ std::string zipname = basename + PACKAGE_SUFFIX;
+ handle = fopen(zipname.c_str(), "rb+");
if (handle != NULL)
{
+ fclose(handle);
cprintf(EOL "Loading game..." EOL);
// Create command
char cmd_buff[1024];
- snprintf( cmd_buff, sizeof(cmd_buff), LOAD_UNPACKAGE_CMD, name_buff );
+ snprintf( cmd_buff, sizeof(cmd_buff), LOAD_UNPACKAGE_CMD,
+ basename.c_str() );
if (system( cmd_buff ) != 0)
{
cprintf( EOL "Warning: Zip command (LOAD_UNPACKAGE_CMD) returned non-zero value!" EOL );
}
- fclose(handle);
-
// Remove save game package
- unlink(zip_buff);
+ unlink(zipname.c_str());
}
- else
- {
-#ifdef DO_ANTICHEAT_CHECKS
- // Simple security patch -- must have zip file otherwise invalidate
- // the character. Right now this just renames the .sav file to
- // .bak, allowing anyone with the appropriate permissions to
- // fix a character in the case of a bug. This could be changed
- // to unlinking the file(s) which would remove the character.
- strcat(name_buff, ".bak");
- rename(char_fil, name_buff);
-#endif
- }
-
-#else
- strcpy(char_fil, "");
- strncat(char_fil, you.your_name, kFileNameLen);
- strcat(char_fil, ".sav");
#endif
- handle = fopen(char_fil, "rb+");
+ handle = fopen(savename.c_str(), "rb+");
if (handle != NULL)
{
@@ -350,19 +317,45 @@ static bool check_saved_game(void)
return false;
}
+static unsigned char random_potion_description()
+{
+ int desc, nature, colour;
+
+ do {
+ desc = random2( PDQ_NQUALS * PDC_NCOLOURS );
+
+ if (coinflip())
+ desc %= PDC_NCOLOURS;
+
+ nature = PQUAL(desc);
+ colour = PCOLOUR(desc);
+
+ // nature and colour correspond to primary and secondary
+ // in itemname.cc; this check ensures clear potions don't
+ // get odd qualifiers.
+ } while ((colour == PDC_CLEAR && nature > PDQ_VISCOUS)
+ || desc == PDESCS(PDC_CLEAR)
+ || desc == PDESCQ(PDQ_GLUGGY, PDC_WHITE));
+
+ return (unsigned char) desc;
+}
+
bool new_game(void)
{
int i, j; // loop variables {dlb}
//jmf: NEW ASSERTS: we ought to do a *lot* of these
ASSERT(NUM_SPELLS < SPELL_NO_SPELL);
- ASSERT(NUM_DURATIONS > DUR_LAST_DUR);
ASSERT(NUM_JOBS < JOB_UNKNOWN);
- ASSERT(NUM_ATTRIBUTES < 30);
+ ASSERT(NUM_ATTRIBUTES >= 30);
init_player();
- you.exp_available = 25; // now why is this all the way up here? {dlb}
+ if (!Options.player_name.empty())
+ {
+ strncpy(you.your_name, Options.player_name.c_str(), kNameLen);
+ you.your_name[kNameLen - 1] = 0;
+ }
textcolor(LIGHTGREY);
@@ -372,21 +365,20 @@ bool new_game(void)
if (SysEnv.crawl_name)
{
strncpy( you.your_name, SysEnv.crawl_name, kNameLen );
- you.your_name[ kNameLen - 1 ] = '\0';
+ you.your_name[ kNameLen - 1 ] = 0;
}
openingScreen();
enterPlayerName(true);
- if (you.your_name[0] != '\0')
+ if (you.your_name[0] != 0)
{
if (check_saved_game())
{
textcolor( BROWN );
cprintf( EOL "Welcome back, " );
textcolor( YELLOW );
- cprintf( you.your_name );
- cprintf( "!" );
+ cprintf( "%s!", you.your_name );
textcolor( LIGHTGREY );
save_player_name();
@@ -408,7 +400,7 @@ bool new_game(void)
strcpy( you.class_name, get_class_name( you.char_class ) );
// new: pick name _after_ race and class choices
- if (you.your_name[0] == '\0')
+ if (you.your_name[0] == 0)
{
clrscr();
@@ -432,8 +424,7 @@ bool new_game(void)
textcolor( BROWN );
cprintf(EOL EOL "Welcome back, ");
textcolor( YELLOW );
- cprintf(you.your_name);
- cprintf("!");
+ cprintf("%s!", you.your_name);
textcolor( LIGHTGREY );
return (false);
@@ -449,8 +440,8 @@ bool new_game(void)
you.is_undead = ((you.species == SP_MUMMY) ? US_UNDEAD :
(you.species == SP_GHOUL) ? US_HUNGRY_DEAD : US_ALIVE);
- // before we get into the inventory init, set light radius based
- // on species vision. currently, all species see out to 8 squares.
+ // before we get into the inventory init, set light radius based
+ // on species vision. currently, all species see out to 8 squares.
you.normal_vision = 8;
you.current_vision = 8;
@@ -627,7 +618,7 @@ bool new_game(void)
// don't change object type modifier unless it starts plain
if (you.inv[i].base_type <= OBJ_ARMOUR
- && cmp_equip_race( you.inv[i], 0 )) // == DARM_PLAIN
+ && get_equip_race(you.inv[i]) == 0 ) // == DARM_PLAIN
{
// now add appropriate species type mod:
switch (you.species)
@@ -664,8 +655,11 @@ bool new_game(void)
}
}
- you.item_description[IDESC_POTIONS][POT_PORRIDGE] = 153; // "gluggy white"
- you.item_description[IDESC_POTIONS][POT_WATER] = 0; // "clear"
+ you.item_description[IDESC_POTIONS][POT_PORRIDGE] =
+ PDESCQ(PDQ_GLUGGY, PDC_WHITE);
+
+ you.item_description[IDESC_POTIONS][POT_WATER] =
+ PDESCS(PDC_CLEAR);
int passout;
@@ -689,9 +683,7 @@ bool new_game(void)
break;
case IDESC_POTIONS: // potions
- you.item_description[i][j] = random2( 15 * 14 );
- if (coinflip())
- you.item_description[i][j] %= 14;
+ you.item_description[i][j] = random_potion_description();
break;
case IDESC_SCROLLS: // scrolls
@@ -1422,6 +1414,7 @@ bool class_allowed( unsigned char speci, int char_class )
case SP_HUMAN:
case SP_DEMIGOD:
case SP_DEMONSPAWN:
+ case SP_GHOUL:
return true;
}
return false;
@@ -1432,6 +1425,88 @@ bool class_allowed( unsigned char speci, int char_class )
}
} // end class_allowed()
+
+static void choose_book( item_def& book, int firstbook, int numbooks )
+{
+ int keyin = 0;
+ clrscr();
+ book.base_type = OBJ_BOOKS;
+ book.quantity = 1;
+ book.plus = 0;
+ book.special = 1;
+ book.colour = CYAN;
+
+ // using the fact that CONJ_I and MINOR_MAGIC_I are both
+ // fire books, CONJ_II and MINOR_MAGIC_II are both ice books
+ if ( Options.book && Options.book <= numbooks )
+ {
+ book.sub_type = firstbook + Options.book - 1;
+ ng_book = Options.book;
+ return;
+ }
+
+ if ( Options.prev_book > numbooks && Options.prev_book != SBT_RANDOM )
+ Options.prev_book = SBT_NO_SELECTION;
+
+ if ( !Options.random_pick )
+ {
+ textcolor( CYAN );
+ cprintf(EOL " You have a choice of books:" EOL);
+ textcolor( LIGHTGREY );
+
+ for (int i=0; i < numbooks; ++i)
+ {
+ char buf[ITEMNAME_SIZE];
+ book.sub_type = firstbook + i;
+ item_name( book, DESC_PLAIN, buf );
+ cprintf("%c - %s" EOL, 'a' + i, buf);
+ }
+
+ textcolor(BROWN);
+ cprintf(EOL "? - Random" );
+ if ( Options.prev_book != SBT_NO_SELECTION ) {
+ cprintf("; Enter - %s",
+ Options.prev_book == SBT_FIRE ? "Fire" :
+ Options.prev_book == SBT_COLD ? "Cold" :
+ Options.prev_book == SBT_SUMM ? "Summoning" :
+ Options.prev_book == SBT_RANDOM ? "Random" :
+ "Buggy Book");
+ }
+ cprintf(EOL);
+
+ do
+ {
+ textcolor( CYAN );
+ cprintf(EOL "Which book? ");
+ textcolor( LIGHTGREY );
+
+ keyin = get_ch();
+ } while (keyin != '?' &&
+ ((keyin != '\r' && keyin != '\n') ||
+ Options.prev_book == SBT_NO_SELECTION ) &&
+ (keyin < 'a' || keyin > ('a' + numbooks)));
+
+ if ( keyin == '\r' || keyin == '\n' )
+ {
+ if ( Options.prev_book == SBT_RANDOM )
+ keyin = '?';
+ else
+ keyin = ('a' + Options.prev_book - 1);
+ }
+ }
+
+ if (Options.random_pick || Options.book == SBT_RANDOM || keyin == '?')
+ ng_book = SBT_RANDOM;
+ else
+ ng_book = keyin - 'a' + 1;
+
+ if ( Options.random_pick || keyin == '?' )
+ keyin = random2(numbooks) + 'a';
+
+ book.sub_type = firstbook + keyin - 'a';
+}
+
+
static char startwep[5] = { WPN_SHORT_SWORD, WPN_MACE,
WPN_HAND_AXE, WPN_SPEAR, WPN_TRIDENT };
@@ -1477,10 +1552,8 @@ void choose_weapon( void )
int x = effective_stat_bonus(startwep[i]);
standard_name_weap(startwep[i], wepName);
- snprintf( info, INFO_SIZE, "%c - %s%s" EOL, 'a' + i, wepName,
- (x <= -4) ? " (not ideal)" : "" );
-
- cprintf(info);
+ cprintf("%c - %s%s" EOL, 'a' + i, wepName,
+ (x <= -4) ? " (not ideal)" : "" );
if (Options.prev_weapon == startwep[i])
prevmatch = true;
@@ -1527,7 +1600,10 @@ void choose_weapon( void )
}
if (keyin != '?' && effective_stat_bonus(startwep[keyin-'a']) > -4)
+ {
cprintf(EOL "A fine choice. " EOL);
+ delay(1000);
+ }
}
if (Options.random_pick || Options.weapon == WPN_RANDOM || keyin == '?')
@@ -1553,167 +1629,7 @@ void choose_weapon( void )
void init_player(void)
{
- unsigned char i = 0; // loop variable
-
- you.birth_time = time( NULL );
- you.real_time = 0;
- you.num_turns = 0;
-
-#ifdef WIZARD
- you.wizard = (Options.wiz_mode == WIZ_YES) ? true : false;
-#else
- you.wizard = false;
-#endif
-
- you.activity = ACT_NONE;
- you.berserk_penalty = 0;
- you.berserker = 0;
- you.conf = 0;
- you.confusing_touch = 0;
- you.deaths_door = 0;
- you.disease = 0;
- you.elapsed_time = 0;
- you.exhausted = 0;
- you.haste = 0;
- you.invis = 0;
- you.levitation = 0;
- you.might = 0;
- you.paralysis = 0;
- you.poison = 0;
- you.rotting = 0;
- you.fire_shield = 0;
- you.slow = 0;
- you.special_wield = SPWLD_NONE;
- you.sure_blade = 0;
- you.synch_time = 0;
-
- you.base_hp = 5000;
- you.base_hp2 = 5000;
- you.base_magic_points = 5000;
- you.base_magic_points2 = 5000;
-
- you.magic_points_regeneration = 0;
- you.strength = 0;
- you.max_strength = 0;
- you.intel = 0;
- you.max_intel = 0;
- you.dex = 0;
- you.max_dex = 0;
- you.experience = 0;
- you.experience_level = 1;
- you.max_level = 1;
- you.char_class = JOB_UNKNOWN;
-
- you.hunger = 6000;
- you.hunger_state = HS_SATIATED;
-
- you.gold = 0;
- // you.speed = 10; // 0.75; // unused
-
- you.burden = 0;
- you.burden_state = BS_UNENCUMBERED;
-
- you.spell_no = 0;
-
- you.your_level = 0;
- you.level_type = LEVEL_DUNGEON;
- you.where_are_you = BRANCH_MAIN_DUNGEON;
- you.char_direction = DIR_DESCENDING;
-
- you.prev_targ = MHITNOT;
- you.pet_target = MHITNOT;
-
- you.x_pos = 0;
- you.y_pos = 0;
-
- you.running = 0;
- you.run_x = 0;
- you.run_y = 0;
- you.travel_x = 0;
- you.travel_y = 0;
-
- for (i = 0; i < 3; i++)
- {
- you.run_check[i].grid = 0;
- you.run_check[i].dx = 0;
- you.run_check[i].dy = 0;
- }
-
- you.religion = GOD_NO_GOD;
- you.piety = 0;
-
- you.gift_timeout = 0;
-
- for (i = 0; i < MAX_NUM_GODS; i++)
- {
- you.penance[i] = 0;
- you.worshipped[i] = 0;
- }
-
- ghost.name[0] = '\0';
-
- for (i = 0; i < NUM_GHOST_VALUES; i++)
- ghost.values[i] = 0;
-
- for (i = EQ_WEAPON; i < NUM_EQUIP; i++)
- you.equip[i] = -1;
-
- for (i = 0; i < 25; i++)
- you.spells[i] = SPELL_NO_SPELL;
-
- for (i = 0; i < 52; i++)
- {
- you.spell_letter_table[i] = -1;
- you.ability_letter_table[i] = ABIL_NON_ABILITY;
- }
-
- for (i = 0; i < 100; i++)
- you.mutation[i] = 0;
-
- for (i = 0; i < 100; i++)
- you.demon_pow[i] = 0;
-
- for (i = 0; i < 50; i++)
- you.had_book[i] = 0;
-
- for (i = 0; i < 50; i++)
- you.unique_items[i] = UNIQ_NOT_EXISTS;
-
- for (i = 0; i < NO_UNRANDARTS; i++)
- set_unrandart_exist(i, 0);
-
- for (i = 0; i < 50; i++)
- {
- you.skills[i] = 0;
- you.skill_points[i] = 0;
- you.skill_order[i] = MAX_SKILL_ORDER;
- you.practise_skill[i] = 1;
- }
-
- you.skill_cost_level = 1;
- you.total_skill_points = 0;
-
- for (i = 0; i < 30; i++)
- you.attribute[i] = 0;
-
- for (i = 0; i < ENDOFPACK; i++)
- {
- you.inv[i].quantity = 0;
- you.inv[i].base_type = OBJ_WEAPONS;
- you.inv[i].sub_type = WPN_CLUB;
- you.inv[i].plus = 0;
- you.inv[i].plus2 = 0;
- you.inv[i].special = 0;
- you.inv[i].colour = 0;
- set_ident_flags( you.inv[i], ISFLAG_IDENT_MASK );
-
- you.inv[i].x = -1;
- you.inv[i].y = -1;
- you.inv[i].link = i;
- }
-
- for (i = 0; i < NUM_DURATIONS; i++)
- you.duration[i] = 0;
+ you.init();
}
void give_last_paycheck(int which_job)
@@ -1803,7 +1719,7 @@ void species_stat_init(unsigned char which_species)
case SP_PALE_DRACONIAN:
case SP_UNK0_DRACONIAN:
case SP_UNK1_DRACONIAN:
- case SP_UNK2_DRACONIAN: sb = 9; ib = 6; db = 2; break; // 17
+ case SP_BASE_DRACONIAN: sb = 9; ib = 6; db = 2; break; // 17
}
modify_all_stats( sb, ib, db );
@@ -1993,116 +1909,202 @@ void give_basic_spells(int which_job)
// eventually, this should be something more grand {dlb}
void openingScreen(void)
{
-/* **********************************************
-// this does not work just yet ... {dlb}:
- cprintf(EOL "Hello, ");
-
- if ( you.your_name[0] != '\0' )
- {
- cprintf(you.your_name); // better be less than 31 characters :P {dlb}
- // of course, invalid names will appear {dlb}
- cprintf(", ");
- }
-********************************************** */
-
textcolor( YELLOW );
- cprintf("Hello, welcome to Dungeon Crawl " VERSION "!");
+ cprintf("Hello, welcome to " CRAWL " " VERSION "!");
textcolor( BROWN );
cprintf(EOL "(c) Copyright 1997-2002 Linley Henzell");
- cprintf(EOL "Please consult crawl.txt for instructions and legal details."
- EOL);
+ cprintf(EOL
+ "Please consult crawl_manual.txt for instructions and legal details."
+ EOL);
+
+ bool init_found = init_file_location.find("not found") == std::string::npos;
+ if (!init_found)
+ textcolor( LIGHTRED );
+ else
+ textcolor( LIGHTGREY );
+
+ cprintf("Init file %s%s" EOL,
+ init_found? "read: " : "",
+ init_file_location.c_str());
textcolor( LIGHTGREY );
return;
} // end openingScreen()
+static void show_name_prompt(int where, bool blankOK,
+ const std::vector<player> &existing_chars,
+ slider_menu &menu)
+{
+ gotoxy(1, where);
+ textcolor( CYAN );
+ if (blankOK)
+ {
+ if (Options.prev_name.length() && Options.remember_name)
+ cprintf(EOL "Press <Enter> for \"%s\"." EOL,
+ Options.prev_name.c_str());
+ else
+ cprintf(EOL
+ "Press <Enter> to answer this after race and "
+ "class are chosen." EOL);
+ }
-void enterPlayerName(bool blankOK)
+ cprintf(EOL "What is your name today? ");
+
+ if (!existing_chars.empty())
+ {
+ const int name_x = wherex(), name_y = wherey();
+ menu.set_limits(name_y + 3, get_number_of_lines());
+ menu.display();
+ gotoxy(name_x, name_y);
+ }
+
+ textcolor( LIGHTGREY );
+}
+
+static void preprocess_character_name(char *name, bool blankOK)
{
- // temporary 'til copyover to you.your_name {dlb}
- // made this rediculously long so that the game doesn't
- // crash if a really really long name is entered (argh). {gdl}
- char name_entered[200];
+ if (!*name && blankOK && Options.prev_name.length() &&
+ Options.remember_name)
+ {
+ strncpy(name, Options.prev_name.c_str(), kNameLen);
+ name[kNameLen - 1] = 0;
+ }
- // anything to avoid goto statements {dlb}
- bool acceptable_name = false;
- bool first_time = true;
+ // '.', '?' and '*' are blanked.
+ if (!name[1] && (*name == '.' ||
+ *name == '*' ||
+ *name == '?'))
+ *name = 0;
+}
- // first time -- names set through init.txt/environment assumed ok {dlb}
- if (you.your_name[0] != '\0')
- acceptable_name = true;
+static bool is_good_name(char *name, bool blankOK)
+{
+ preprocess_character_name(name, blankOK);
- do
+ // verification begins here {dlb}:
+ if (you.your_name[0] == 0)
{
- // prompt for a new name if current one unsatisfactory {dlb}:
- if (!acceptable_name)
+ if (blankOK)
+ return (true);
+
+ cprintf(EOL "That's a silly name!" EOL);
+ return (false);
+ }
+
+ // if MULTIUSER is defined, userid will be tacked onto the end
+ // of each character's files, making bones a valid player name.
+#ifndef MULTIUSER
+ // this would cause big probs with ghosts
+ // what would? {dlb}
+ // ... having the name "bones" of course! The problem comes from
+ // the fact that bones files would have the exact same filename
+ // as level files for a character named "bones". -- bwr
+ if (stricmp(you.your_name, "bones") == 0)
+ {
+ cprintf(EOL "That's a silly name!" EOL);
+ return (false);
+ }
+#endif
+ return (verifyPlayerName());
+}
+
+static int newname_keyfilter(int &ch)
+{
+ if (ch == CK_DOWN || ch == CK_PGDN || ch == '\t')
+ return -1;
+ return 1;
+}
+
+static bool read_player_name(
+ char *name,
+ int len,
+ const std::vector<player> &existing,
+ slider_menu &menu)
+{
+ const int name_x = wherex(), name_y = wherey();
+ int (*keyfilter)(int &) = newname_keyfilter;
+ if (existing.empty())
+ keyfilter = NULL;
+
+ line_reader reader(name, len);
+ reader.set_keyproc(keyfilter);
+
+ for (;;)
+ {
+ gotoxy(name_x, name_y);
+ if (name_x <= 80)
+ cprintf("%-*s", 80 - name_x + 1, "");
+
+ gotoxy(name_x, name_y);
+ int ret = reader.read_line(false);
+ if (!ret)
+ return (true);
+
+ if (ret == CK_ESCAPE)
+ return (false);
+
+ if (ret != CK_ESCAPE && existing.size())
{
- textcolor( CYAN );
- if (blankOK && first_time)
+ menu.set_search(name);
+ menu.show();
+ const MenuEntry *sel = menu.selected_entry();
+ if (sel)
{
- if (Options.prev_name.length() && Options.remember_name)
- cprintf(EOL "Press <Enter> for \"%s\"." EOL,
- Options.prev_name.c_str());
- else
- cprintf(EOL
- "Press <Enter> to answer this after race and "
- "class are chosen." EOL);
+ const player &p = *static_cast<player*>( sel->data );
+ strncpy(name, p.your_name, kNameLen);
+ name[kNameLen - 1] = 0;
+ return (true);
}
+ }
- first_time = false;
+ // Go back and prompt the user.
+ }
+}
- cprintf(EOL "What is your name today? ");
- textcolor( LIGHTGREY );
- get_input_line( name_entered, sizeof( name_entered ) );
-
- strncpy( you.your_name, name_entered, kNameLen );
- you.your_name[ kNameLen - 1 ] = '\0';
- }
+void enterPlayerName(bool blankOK)
+{
+ int prompt_start = wherey();
+ bool ask_name = true;
+ char *name = you.your_name;
+ std::vector<player> existing_chars;
+ slider_menu char_menu;
- if (!*you.your_name && blankOK && Options.prev_name.length() &&
- Options.remember_name)
- {
- strncpy(you.your_name, Options.prev_name.c_str(), kNameLen);
- you.your_name[kNameLen - 1] = 0;
- }
+ if (you.your_name[0] != 0)
+ ask_name = false;
- // '.', '?' and '*' are blanked.
- if (!you.your_name[1] && (*you.your_name == '.' ||
- *you.your_name == '*' ||
- *you.your_name == '?'))
- {
- *you.your_name = 0;
- }
-
- // verification begins here {dlb}:
- if (you.your_name[0] == '\0')
+ if (blankOK)
+ {
+ existing_chars = find_saved_characters();
+
+ MenuEntry *title = new MenuEntry("Or choose an existing character:");
+ title->colour = LIGHTCYAN;
+ char_menu.set_title( title );
+ for (int i = 0, size = existing_chars.size(); i < size; ++i)
{
- if (blankOK)
- return;
+ std::string desc = " " + existing_chars[i].short_desc();
+ if ((int) desc.length() >= get_number_of_cols())
+ desc = desc.substr(0, get_number_of_cols() - 1);
- cprintf(EOL "That's a silly name!" EOL);
- acceptable_name = false;
+ MenuEntry *me = new MenuEntry(desc);
+ me->data = &existing_chars[i];
+ char_menu.add_entry(me);
}
+ char_menu.set_flags(MF_EASY_EXIT | MF_SINGLESELECT);
+ }
- // if SAVE_DIR_PATH is defined, userid will be tacked onto the end
- // of each character's files, making bones a valid player name.
-#ifndef SAVE_DIR_PATH
- // this would cause big probs with ghosts
- // what would? {dlb}
- // ... having the name "bones" of course! The problem comes from
- // the fact that bones files would have the exact same filename
- // as level files for a character named "bones". -- bwr
- else if (stricmp(you.your_name, "bones") == 0)
+ do
+ {
+ // prompt for a new name if current one unsatisfactory {dlb}:
+ if (ask_name)
{
- cprintf(EOL "That's a silly name!" EOL);
- acceptable_name = false;
- }
-#endif
- else
- acceptable_name = verifyPlayerName();
+ show_name_prompt(prompt_start, blankOK, existing_chars, char_menu);
+ // If the player wants out, we bail out.
+ if (!read_player_name(name, kNameLen, existing_chars, char_menu))
+ end(0);
+ }
}
- while (!acceptable_name);
+ while (ask_name = !is_good_name(you.your_name, blankOK));
} // end enterPlayerName()
bool verifyPlayerName(void)
@@ -2117,7 +2119,7 @@ bool verifyPlayerName(void)
return (false);
}
- // quick check for LPTx -- thank you, Mr. Tanksley! ;-)
+ // quick check for LPTx -- thank you, Mr. Tanksley! ;-)
if (strnicmp(you.your_name, "LPT", 3) == 0)
{
switch (william_tanksley_asked_for_this)
@@ -2133,7 +2135,7 @@ bool verifyPlayerName(void)
return (true);
} // end switch
- william_tanksley_asked_for_this --;
+ william_tanksley_asked_for_this--;
return (false);
}
#endif
@@ -2141,14 +2143,6 @@ bool verifyPlayerName(void)
const size_t len = strlen( you.your_name );
for (unsigned int i = 0; i < len; i++)
{
-#if MAC
- // the only bad character on Macs is the path seperator
- if (you.your_name[i] == ':')
- {
- cprintf(EOL "No colons, please." EOL);
- return (false);
- }
-#else
// Note that this includes systems which may be using the
// packaging system. The packaging system is very simple
// and doesn't take the time to escape every characters that
@@ -2159,10 +2153,9 @@ bool verifyPlayerName(void)
cprintf( EOL "Alpha-numerics and underscores only, please." EOL );
return (false);
}
-#endif
}
-#ifdef SAVE_DIR_PATH
+#ifdef MULTIUSER
// Until we have a better way to handle the fact that this could lead
// to some confusion with where the name ends and the uid begins. -- bwr
if (isdigit( you.your_name[ len - 1 ] ))
@@ -2379,19 +2372,19 @@ static bool give_wanderer_weapon( int slot, int wpn_skill )
static void create_wanderer( void )
{
const int util_skills[] =
- { SK_DARTS, SK_THROWING, SK_ARMOUR, SK_DODGING, SK_STEALTH,
+ { SK_DARTS, SK_RANGED_COMBAT, SK_ARMOUR, SK_DODGING, SK_STEALTH,
SK_STABBING, SK_SHIELDS, SK_TRAPS_DOORS, SK_UNARMED_COMBAT,
SK_INVOCATIONS, SK_EVOCATIONS };
const int num_util_skills = sizeof(util_skills) / sizeof(int);
- // Long swords is missing to increae it's rarity because we
+ // Long swords is missing to increase its rarity because we
// can't give out a long sword to a starting character (they're
// all too good)... Staves is also removed because it's not
// one of the fighter options.-- bwr
const int fight_util_skills[] =
{ SK_FIGHTING, SK_SHORT_BLADES, SK_AXES,
SK_MACES_FLAILS, SK_POLEARMS,
- SK_DARTS, SK_THROWING, SK_ARMOUR, SK_DODGING, SK_STEALTH,
+ SK_DARTS, SK_RANGED_COMBAT, SK_ARMOUR, SK_DODGING, SK_STEALTH,
SK_STABBING, SK_SHIELDS, SK_TRAPS_DOORS, SK_UNARMED_COMBAT,
SK_INVOCATIONS, SK_EVOCATIONS };
const int num_fight_util_skills = sizeof(fight_util_skills) / sizeof(int);
@@ -2402,7 +2395,7 @@ static void create_wanderer( void )
SK_FIRE_MAGIC, SK_ICE_MAGIC, SK_AIR_MAGIC, SK_EARTH_MAGIC,
SK_FIGHTING, SK_SHORT_BLADES, SK_LONG_SWORDS, SK_AXES,
SK_MACES_FLAILS, SK_POLEARMS, SK_STAVES,
- SK_DARTS, SK_THROWING, SK_ARMOUR, SK_DODGING, SK_STEALTH,
+ SK_DARTS, SK_RANGED_COMBAT, SK_ARMOUR, SK_DODGING, SK_STEALTH,
SK_STABBING, SK_SHIELDS, SK_TRAPS_DOORS, SK_UNARMED_COMBAT,
SK_INVOCATIONS, SK_EVOCATIONS };
const int num_not_rare_skills = sizeof(not_rare_skills) / sizeof(int);
@@ -2415,7 +2408,7 @@ static void create_wanderer( void )
SK_FIRE_MAGIC, SK_ICE_MAGIC, SK_AIR_MAGIC, SK_EARTH_MAGIC,
SK_FIGHTING, SK_SHORT_BLADES, SK_LONG_SWORDS, SK_AXES,
SK_MACES_FLAILS, SK_POLEARMS, SK_STAVES,
- SK_DARTS, SK_THROWING, SK_ARMOUR, SK_DODGING, SK_STEALTH,
+ SK_DARTS, SK_RANGED_COMBAT, SK_ARMOUR, SK_DODGING, SK_STEALTH,
SK_STABBING, SK_SHIELDS, SK_TRAPS_DOORS, SK_UNARMED_COMBAT,
SK_INVOCATIONS, SK_EVOCATIONS };
const int num_all_skills = sizeof(all_skills) / sizeof(int);
@@ -2486,9 +2479,9 @@ static void create_wanderer( void )
you.skills[ skill ] = 1;
}
- int wpn_skill = SK_FIGHTING; // prefered weapon type
- int wpn_skill_size = 0; // level of skill in prefered weapon type
- int num_wpn_skills = 0; // used to choose prefered weapon
+ int wpn_skill = SK_FIGHTING; // preferred weapon type
+ int wpn_skill_size = 0; // level of skill in preferred weapon type
+ int num_wpn_skills = 0; // used to choose preferred weapon
int total_wpn_skills = 0; // used to choose template
// This algorithm is the same as the one used to pick a random
@@ -2638,14 +2631,14 @@ static void create_wanderer( void )
add_spell_to_memory( spell_list[ school ] );
}
}
- else if (you.skills[ SK_THROWING ] && one_chance_in(3)) // these are rare
+ else if (you.skills[ SK_RANGED_COMBAT ] && one_chance_in(3)) // these are rare
{
// Ranger style wanderer
// Rare since starting with a throwing weapon is very good
// Create a default launcher template, but the
// quantity may be reset to 0 if we don't want one -- bwr
- // thorwing weapons are lowered to -1 to make them
+ // throwing weapons are lowered to -1 to make them
// not as good as the one's hunters get, ammo is
// also much smaller -- bwr
you.inv[1].quantity = 1;
@@ -2844,10 +2837,10 @@ static char letter_to_species(int keyn)
static char species_to_letter(int spec)
{
- if (spec > SP_RED_DRACONIAN && spec <= SP_UNK2_DRACONIAN)
+ if (spec > SP_RED_DRACONIAN && spec <= SP_BASE_DRACONIAN)
spec = SP_RED_DRACONIAN;
- else if (spec > SP_UNK2_DRACONIAN)
- spec -= SP_UNK2_DRACONIAN - SP_RED_DRACONIAN;
+ else if (spec > SP_BASE_DRACONIAN)
+ spec -= SP_BASE_DRACONIAN - SP_RED_DRACONIAN;
return 'a' + spec - 1;
}
@@ -2891,12 +2884,12 @@ spec_query:
textcolor( YELLOW );
if (strlen(you.your_name) > 0)
{
- cprintf(you.your_name);
+ cprintf("%s", you.your_name);
if (you.char_class != JOB_UNKNOWN)
cprintf(" the ");
}
if (you.char_class != JOB_UNKNOWN)
- cprintf(get_class_name(you.char_class));
+ cprintf("%s", get_class_name(you.char_class));
if (!shortgreet)
cprintf(".");
@@ -2918,7 +2911,7 @@ spec_query:
*linebuf = 0;
for (int i = SP_HUMAN; i < NUM_SPECIES; ++i)
{
- if (i > SP_RED_DRACONIAN && i <= SP_UNK2_DRACONIAN)
+ if (i > SP_RED_DRACONIAN && i <= SP_BASE_DRACONIAN)
continue;
if (you.char_class != JOB_UNKNOWN &&
@@ -3051,7 +3044,7 @@ spec_query:
return true;
}
-// returns true if a class was chosen, false if we should go back to
+// returns true if a class was chosen, false if we should go back to
// race selection.
bool choose_class(void)
@@ -3089,12 +3082,12 @@ job_query:
textcolor( YELLOW );
if (strlen(you.your_name) > 0)
{
- cprintf(you.your_name);
+ cprintf("%s", you.your_name);
if (you.species)
cprintf(" the ");
}
if (you.species)
- cprintf(species_name(you.species,you.experience_level));
+ cprintf("%s", species_name(you.species,you.experience_level));
if (!shortgreet)
cprintf(".");
@@ -3126,7 +3119,7 @@ job_query:
putch( letter );
cprintf( " - " );
- cprintf( get_class_name(i) );
+ cprintf( "%s", get_class_name(i) );
if (j % 2)
cprintf(EOL);
@@ -3301,7 +3294,7 @@ void give_items_skills()
{
you.inv[0].quantity = 1;
you.inv[0].base_type = OBJ_WEAPONS;
- you.inv[0].sub_type = WPN_CLUB;
+ you.inv[0].sub_type = WPN_ANCUS;
you.inv[0].plus = 0;
you.inv[0].special = 0;
you.inv[0].colour = BROWN;
@@ -3399,7 +3392,7 @@ void give_items_skills()
if (you.species == SP_KOBOLD)
{
- you.skills[SK_THROWING] = 1;
+ you.skills[SK_RANGED_COMBAT] = 1;
you.skills[SK_DARTS] = 1;
you.skills[SK_DODGING] = 1;
you.skills[SK_STEALTH] = 1;
@@ -3419,13 +3412,13 @@ void give_items_skills()
else
{
// Players get dodging or armour skill depending on their
- // starting armour now (note: the armour has to be quiped
+ // starting armour now (note: the armour has to be equipped
// for this function to work)
you.skills[(player_light_armour()? SK_DODGING : SK_ARMOUR)] = 2;
you.skills[SK_SHIELDS] = 2;
- you.skills[SK_THROWING] = 2;
+ you.skills[SK_RANGED_COMBAT] = 2;
you.skills[(coinflip() ? SK_STABBING : SK_SHIELDS)]++;
}
break;
@@ -3485,12 +3478,7 @@ void give_items_skills()
you.equip[EQ_BODY_ARMOUR] = 1;
// extra items being tested:
- you.inv[2].base_type = OBJ_BOOKS;
- you.inv[2].sub_type = BOOK_MINOR_MAGIC_I + random2(3);
- you.inv[2].quantity = 1;
- you.inv[2].plus = 0; // = 127
- you.inv[2].special = 1;
- you.inv[2].colour = CYAN;
+ choose_book( you.inv[2], BOOK_MINOR_MAGIC_I, 3 );
you.skills[SK_DODGING] = 1;
you.skills[SK_STEALTH] = 1;
@@ -3652,7 +3640,7 @@ void give_items_skills()
you.skills[SK_STEALTH] = 2;
you.skills[SK_STABBING] = 1;
you.skills[SK_DODGING + random2(3)]++;
- you.skills[SK_THROWING] = 1;
+ you.skills[SK_RANGED_COMBAT] = 1;
you.skills[SK_DARTS] = 1;
you.skills[SK_TRAPS_DOORS] = 2;
break;
@@ -3856,12 +3844,12 @@ void give_items_skills()
you.skills[SK_DODGING] = 1;
you.skills[SK_STEALTH] = 3;
you.skills[SK_STABBING] = 2;
- you.skills[SK_THROWING] = 1;
+ you.skills[SK_RANGED_COMBAT] = 1;
you.skills[SK_DARTS] = 1;
if (you.species == SP_DEEP_ELF)
you.skills[SK_CROSSBOWS] = 1;
else
- you.skills[SK_THROWING] += 1;
+ you.skills[SK_RANGED_COMBAT] += 1;
break;
@@ -3874,7 +3862,7 @@ void give_items_skills()
{
you.inv[0].quantity = 1;
you.inv[0].base_type = OBJ_WEAPONS;
- you.inv[0].sub_type = WPN_CLUB;
+ you.inv[0].sub_type = WPN_ANCUS;
you.inv[0].plus = 0;
you.inv[0].plus2 = 0;
you.inv[0].special = 0;
@@ -3954,7 +3942,7 @@ void give_items_skills()
you.skills[SK_POLEARMS] = 1;
you.skills[SK_ARMOUR] = 2;
you.skills[SK_DODGING] = 2;
- you.skills[SK_THROWING] = 2;
+ you.skills[SK_RANGED_COMBAT] = 2;
}
break;
@@ -4017,7 +4005,7 @@ void give_items_skills()
you.equip[EQ_BODY_ARMOUR] = 4;
you.skills[SK_FIGHTING] = 2;
- you.skills[SK_THROWING] = 3;
+ you.skills[SK_RANGED_COMBAT] = 3;
// Removing spellcasting -- bwr
// you.skills[SK_SPELLCASTING] = 1;
@@ -4064,7 +4052,7 @@ void give_items_skills()
you.skills[SK_POLEARMS] = 2;
you.skills[SK_DODGING] = 2;
- you.skills[SK_THROWING] += 1;
+ you.skills[SK_RANGED_COMBAT] += 1;
break;
default:
@@ -4108,9 +4096,15 @@ void give_items_skills()
you.equip[EQ_WEAPON] = 0;
you.equip[EQ_BODY_ARMOUR] = 1;
- you.inv[2].base_type = OBJ_BOOKS;
- you.inv[2].sub_type = give_first_conjuration_book();
- you.inv[2].plus = 0;
+
+ if ( you.char_class == JOB_CONJURER )
+ choose_book( you.inv[2], BOOK_CONJURATIONS_I, 2 );
+ else
+ {
+ you.inv[2].base_type = OBJ_BOOKS;
+ // subtype will always be overridden
+ you.inv[2].plus = 0;
+ }
switch (you.char_class)
{
@@ -4283,7 +4277,7 @@ void give_items_skills()
you.skills[SK_STEALTH] = 1;
if (you.species == SP_GNOME && you.char_class == JOB_EARTH_ELEMENTALIST)
- you.skills[SK_THROWING]++;
+ you.skills[SK_RANGED_COMBAT]++;
else
you.skills[ coinflip() ? SK_DODGING : SK_STEALTH ]++;
break;
@@ -4332,7 +4326,7 @@ void give_items_skills()
you.skills[SK_FIGHTING] = 1;
you.skills[SK_UNARMED_COMBAT] = 3;
- you.skills[SK_THROWING] = 2;
+ you.skills[SK_RANGED_COMBAT] = 2;
you.skills[SK_DODGING] = 2;
you.skills[SK_SPELLCASTING] = 2;
you.skills[SK_TRANSMIGRATION] = 2;
@@ -4419,7 +4413,7 @@ void give_items_skills()
you.equip[EQ_WEAPON] = 0;
you.equip[EQ_BODY_ARMOUR] = 1;
- you.skills[SK_THROWING] = 1;
+ you.skills[SK_RANGED_COMBAT] = 1;
you.skills[SK_DARTS] = 2;
you.skills[SK_DODGING] = 2;
you.skills[SK_STEALTH] = 1;
@@ -4722,7 +4716,7 @@ void give_items_skills()
you.skills[SK_FIGHTING] = 2;
you.skills[SK_DODGING] = 1;
you.skills[SK_SHIELDS] = 1;
- you.skills[SK_THROWING] = 2;
+ you.skills[SK_RANGED_COMBAT] = 2;
you.skills[SK_STAVES] = 3;
you.skills[SK_INVOCATIONS] = 2;
break;
@@ -4806,7 +4800,7 @@ void give_items_skills()
you.skills[SK_STEALTH] = 2;
you.skills[SK_STABBING] = 2;
you.skills[SK_DODGING + random2(3)]++;
- //you.skills[SK_THROWING] = 1; //jmf: removed these, added magic below
+ //you.skills[SK_RANGED_COMBAT] = 1; //jmf: removed these, added magic below
//you.skills[SK_DARTS] = 1;
you.skills[SK_SPELLCASTING] = 1;
you.skills[SK_ENCHANTMENTS] = 1;
diff --git a/crawl-ref/source/notes.cc b/crawl-ref/source/notes.cc
new file mode 100644
index 0000000000..0af29ec998
--- /dev/null
+++ b/crawl-ref/source/notes.cc
@@ -0,0 +1,405 @@
+/*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ */
+
+#include <vector>
+
+#include "AppHdr.h"
+#include "notes.h"
+
+#include "files.h"
+#include "Kills.h"
+#include "message.h"
+#include "misc.h"
+#include "mon-pick.h"
+#include "mutation.h"
+#include "religion.h"
+#include "skills2.h"
+#include "spl-util.h"
+
+#define NOTES_VERSION_NUMBER 1001
+
+std::vector<Note> note_list;
+
+/* I can't believe I'm writing code this bad */
+static int real_god_power( int religion, int idx ) {
+ switch ( religion ) {
+ case GOD_NO_GOD:
+ case GOD_XOM:
+ case GOD_NEMELEX_XOBEH:
+ return -1;
+ case GOD_ZIN:
+ case GOD_SHINING_ONE:
+ case GOD_YREDELEMNUL:
+ case GOD_MAKHLEB:
+ case GOD_ELYVILON:
+ return idx;
+ case GOD_KIKUBAAQUDGHA:
+ if ( idx < 3 )
+ return idx;
+ if ( idx == 3 )
+ return -1;
+ return idx-1;
+ case GOD_VEHUMET:
+ return ( idx > 3 ? -1 : idx );
+ case GOD_OKAWARU:
+ if ( idx < 2 )
+ return idx;
+ if ( idx == 2 || idx == 3 )
+ return -1;
+ return idx - 2;
+ case GOD_SIF_MUNA:
+ if ( idx == 2 || idx == 4 ) return -1;
+ if ( idx < 2 ) return idx;
+ if ( idx == 3 ) return 2;
+ case GOD_TROG:
+ if ( idx == 2 || idx == 4 ) return -1;
+ if ( idx < 2 ) return idx;
+ if ( idx == 3 ) return idx-1;
+ default:
+ return -1;
+ }
+}
+
+static bool is_noteworthy_skill_level( int level ) {
+ unsigned i;
+ for ( i = 0; i < Options.note_skill_levels.size(); ++i )
+ if ( level == Options.note_skill_levels[i] )
+ return true;
+ return false;
+}
+
+static bool is_highest_skill( int skill ) {
+ for ( int i = 0; i < NUM_SKILLS; ++i ) {
+ if ( i == skill )
+ continue;
+ if ( you.skills[i] >= you.skills[skill] )
+ return false;
+ }
+ return true;
+}
+
+static bool is_noteworthy_hp( int hp, int maxhp ) {
+ return (hp > 0 && Options.note_hp_percent &&
+ hp <= (maxhp * Options.note_hp_percent) / 100);
+}
+
+static int dungeon_branch_depth( unsigned char branch ) {
+ if ( branch > BRANCH_CAVERNS ) // last branch
+ return -1;
+ switch ( branch ) {
+ case BRANCH_MAIN_DUNGEON:
+ return 27;
+ case BRANCH_DIS:
+ case BRANCH_GEHENNA:
+ case BRANCH_COCYTUS:
+ case BRANCH_TARTARUS:
+ return 7;
+ case BRANCH_VESTIBULE_OF_HELL:
+ return 1;
+ case BRANCH_INFERNO:
+ case BRANCH_THE_PIT:
+ return -1;
+ default:
+ return branch_depth( branch - 10 );
+ }
+}
+
+static bool is_noteworthy_dlevel( unsigned short place ) {
+ unsigned const char branch = (unsigned char) ((place >> 8) & 0xFF);
+ const int lev = (place & 0xFF);
+
+ /* Special levels (Abyss, etc.) are always interesting */
+ if ( lev == 0xFF )
+ return true;
+
+ if ( lev == dungeon_branch_depth(branch) ||
+ (branch == BRANCH_MAIN_DUNGEON && (lev % 5) == 0) ||
+ (branch != BRANCH_MAIN_DUNGEON && lev == 1) )
+ return true;
+
+ return false;
+}
+
+/* Is a note worth taking?
+ This function assumes that game state has not changed since
+ the note was taken, e.g. you.* is valid.
+ */
+static bool is_noteworthy( const Note& note ) {
+
+ /* always noteworthy */
+ if ( note.type == NOTE_XP_LEVEL_CHANGE ||
+ note.type == NOTE_GET_GOD ||
+ note.type == NOTE_GOD_GIFT ||
+ note.type == NOTE_GET_MUTATION ||
+ note.type == NOTE_LOSE_MUTATION ||
+ note.type == NOTE_SEEN_MONSTER ||
+ note.type == NOTE_KILL_MONSTER ||
+ note.type == NOTE_POLY_MONSTER ||
+ note.type == NOTE_USER_NOTE ||
+ note.type == NOTE_MESSAGE ||
+ note.type == NOTE_LOSE_GOD )
+ return true;
+
+ /* never noteworthy, hooked up for fun or future use */
+ if ( note.type == NOTE_GET_ITEM ||
+ note.type == NOTE_MP_CHANGE ||
+ note.type == NOTE_MAXHP_CHANGE ||
+ note.type == NOTE_MAXMP_CHANGE )
+ return false;
+
+ /* god powers might be noteworthy if it's an actual power */
+ if ( note.type == NOTE_GOD_POWER &&
+ real_god_power(note.first, note.second) == -1 )
+ return false;
+
+ /* hp noteworthiness is handled in its own function */
+ if ( note.type == NOTE_HP_CHANGE &&
+ !is_noteworthy_hp(note.first, note.second) )
+ return false;
+
+ /* skills are noteworthy if in the skill value list or if
+ it's a new maximal skill (depending on options) */
+ if ( note.type == NOTE_GAIN_SKILL ) {
+ if ( is_noteworthy_skill_level(note.second) )
+ return true;
+ if ( Options.note_skill_max && is_highest_skill(note.first) )
+ return true;
+ return false;
+ }
+
+ if ( note.type == NOTE_DUNGEON_LEVEL_CHANGE &&
+ !is_noteworthy_dlevel(note.packed_place) )
+ return false;
+
+ /* Learning a spell is always noteworthy if note_all_spells is set */
+ if ( note.type == NOTE_LEARN_SPELL && Options.note_all_spells )
+ return true;
+
+ for ( unsigned i = 0; i < note_list.size(); ++i ) {
+ if ( note_list[i].type != note.type )
+ continue;
+ const Note& rnote( note_list[i] );
+ switch ( note.type ) {
+ case NOTE_DUNGEON_LEVEL_CHANGE:
+ if ( rnote.packed_place == note.packed_place )
+ return false;
+ break;
+ case NOTE_LEARN_SPELL:
+ if (spell_difficulty(rnote.first) >= spell_difficulty(note.first))
+ return false;
+ break;
+ case NOTE_GOD_POWER:
+ if ( rnote.first == note.first && rnote.second == note.second )
+ return false;
+ break;
+ case NOTE_ID_ITEM:
+ /* re-id'ing an item, e.g. second copy of book, isn't
+ noteworthy */
+ if ( rnote.name == note.name )
+ return false;
+ break;
+ case NOTE_HP_CHANGE:
+ /* not if we have a recent warning */
+ if ( (note.turn - rnote.turn < 5) &&
+ /* unless we've lost half our HP since then */
+ (note.first * 2 >= rnote.first) )
+ return false;
+ break;
+ default:
+ mpr("Buggy note passed: unknown note type");
+ // Return now, rather than give a "Buggy note passed" message
+ // for each note of the matching type in the note list.
+ return true;
+ }
+ }
+ return true;
+}
+
+const char* number_to_ordinal( int number ) {
+ const char* ordinals[5] = { "first", "second", "third", "fourth",
+ "fifth" };
+ if ( number < 1)
+ return "[unknown ordinal (too small)]";
+ if ( number > 5 )
+ return "[unknown ordinal (too big)]";
+ return ordinals[number-1];
+}
+
+std::string describe_note( const Note& note ) {
+ char buf[200], buf2[50];
+
+ switch ( note.type ) {
+ case NOTE_HP_CHANGE:
+ // [ds] Shortened HP change note from "Had X hitpoints" to accommodate
+ // the cause for the loss of hitpoints.
+ snprintf(buf, sizeof buf, "HP: %d/%d [%s]",
+ note.first, note.second, note.name.c_str());
+ break;
+ case NOTE_MP_CHANGE:
+ snprintf(buf, sizeof buf, "Mana: %d/%d", note.first, note.second);
+ break;
+ case NOTE_MAXHP_CHANGE:
+ snprintf(buf, sizeof buf, "Reached %d max hit points", note.first);
+ break;
+ case NOTE_MAXMP_CHANGE:
+ snprintf(buf, sizeof buf, "Reached %d max mana", note.first);
+ break;
+ case NOTE_XP_LEVEL_CHANGE:
+ snprintf(buf, sizeof buf, "Reached XP level %d. %s", note.first,
+ note.name.c_str());
+ break;
+ case NOTE_DUNGEON_LEVEL_CHANGE:
+ snprintf(buf, sizeof buf, "Entered %s",
+ place_name(note.packed_place, true, true).c_str());
+ break;
+ case NOTE_LEARN_SPELL:
+ snprintf(buf, sizeof buf, "Learned a level %d spell: %s",
+ spell_difficulty(note.first), spell_title(note.first));
+ break;
+ case NOTE_GET_GOD:
+ snprintf(buf, sizeof buf, "Became a worshipper of %s",
+ god_name(note.first, true));
+ break;
+ case NOTE_LOSE_GOD:
+ snprintf(buf, sizeof buf, "Fell from the grace of %s",
+ god_name(note.first));
+ break;
+ case NOTE_GOD_GIFT:
+ snprintf(buf, sizeof buf, "Received a gift from %s",
+ god_name(note.first));
+ break;
+ case NOTE_ID_ITEM:
+ if (note.desc.length() > 0)
+ snprintf(buf, sizeof buf, "Identified %s (%s)", note.name.c_str(),
+ note.desc.c_str());
+ else
+ snprintf(buf, sizeof buf, "Identified %s", note.name.c_str());
+ break;
+ case NOTE_GET_ITEM:
+ snprintf(buf, sizeof buf, "Got %s", note.name.c_str());
+ break;
+ case NOTE_GAIN_SKILL:
+ snprintf(buf, sizeof buf, "Reached skill %d in %s",
+ note.second, skill_name(note.first));
+ break;
+ case NOTE_SEEN_MONSTER:
+ snprintf(buf, sizeof buf, "Noticed %s", note.name.c_str() );
+ break;
+ case NOTE_KILL_MONSTER:
+ snprintf(buf, sizeof buf, "Defeated %s", note.name.c_str());
+ break;
+ case NOTE_POLY_MONSTER:
+ snprintf(buf, sizeof buf, "%s changed form", note.name.c_str() );
+ break;
+ case NOTE_GOD_POWER:
+ snprintf(buf, sizeof buf, "Acquired %s's %s power",
+ god_name(note.first),
+ number_to_ordinal(real_god_power(note.first, note.second)+1));
+ break;
+ case NOTE_GET_MUTATION:
+ snprintf(buf, sizeof buf, "Gained mutation: %s",
+ mutation_name(note.first, note.second == 0 ? 1 : note.second));
+ break;
+ case NOTE_LOSE_MUTATION:
+ snprintf(buf, sizeof buf, "Lost mutation: %s",
+ mutation_name(note.first,
+ note.second == 3 ? 3 : note.second+1));
+ break;
+ case NOTE_USER_NOTE:
+ snprintf(buf, sizeof buf, "%s", note.name.c_str());
+ break;
+ case NOTE_MESSAGE:
+ snprintf(buf, sizeof buf, "%s", note.name.c_str());
+ break;
+ default:
+ snprintf(buf, sizeof buf, "Buggy note description: unknown note type");
+ break;
+ }
+ snprintf(buf2, sizeof buf2, "| %5ld | ", note.turn );
+ std::string placename = short_place_name(note.packed_place);
+ while ( placename.length() < 7 )
+ placename += ' ';
+ return std::string(buf2) + placename + std::string(" | ") +
+ std::string(buf);
+}
+
+Note::Note() {
+ turn = you.num_turns;
+ packed_place = get_packed_place();
+}
+
+Note::Note( NOTE_TYPES t, int f, int s, const char* n, const char* d ) :
+ type(t), first(f), second(s) {
+ if (n)
+ name = std::string(n);
+ if (d)
+ desc = std::string(d);
+ turn = you.num_turns;
+ packed_place = get_packed_place();
+}
+
+void Note::save( FILE* fp ) const {
+ writeLong( fp, type );
+ writeLong( fp, turn );
+ writeShort( fp, packed_place );
+ writeLong( fp, first );
+ writeLong( fp, second );
+ writeString( fp, name );
+ writeString( fp, desc );
+}
+
+void Note::load( FILE* fp ) {
+ type = (NOTE_TYPES)(readLong( fp ));
+ turn = readLong( fp );
+ packed_place = readShort( fp );
+ first = readLong( fp );
+ second = readLong( fp );
+ name = readString( fp );
+ desc = readString( fp );
+}
+
+bool notes_active = false;
+
+bool notes_are_active() {
+ return notes_active;
+}
+
+void take_note( const Note& note ) {
+ if ( notes_active && is_noteworthy( note ) )
+ note_list.push_back( note );
+}
+
+void activate_notes( bool active ) {
+ notes_active = active;
+}
+
+void save_notes( FILE* fp ) {
+ writeLong( fp, NOTES_VERSION_NUMBER );
+ writeLong( fp, note_list.size() );
+ for ( unsigned i = 0; i < note_list.size(); ++i )
+ note_list[i].save(fp);
+}
+
+void load_notes( FILE* fp ) {
+ if ( readLong(fp) != NOTES_VERSION_NUMBER )
+ return;
+
+ const long num_notes = readLong(fp);
+ for ( long i = 0; i < num_notes; ++i ) {
+ Note new_note;
+ new_note.load(fp);
+ note_list.push_back(new_note);
+ }
+}
+
+void make_user_note() {
+ mpr("Enter note: ", MSGCH_PROMPT);
+ char buf[400];
+ bool validline = !cancelable_get_line(buf, sizeof(buf));
+ if ( !validline || (!*buf) )
+ return;
+ Note unote(NOTE_USER_NOTE);
+ unote.name = std::string(buf);
+ take_note(unote);
+}
diff --git a/crawl-ref/source/notes.h b/crawl-ref/source/notes.h
new file mode 100644
index 0000000000..882fe81250
--- /dev/null
+++ b/crawl-ref/source/notes.h
@@ -0,0 +1,67 @@
+/*
+ * File: notes.cc
+ * Summary: Notetaking stuff
+ * Written by: Haran Pilpel
+ *
+ * Change History (most recent first):
+ *
+ * <1> -/--/-- PH Created
+ */
+
+#ifndef NOTES_H
+#define NOTES_H
+
+#include <string>
+#include <vector>
+#include <stdio.h>
+
+enum NOTE_TYPES {
+ NOTE_HP_CHANGE = 0, /* needs: new hp, max hp */
+ NOTE_MAXHP_CHANGE, /* needs: new maxhp */
+ NOTE_MP_CHANGE, /* needs: new mp, max mp */
+ NOTE_MAXMP_CHANGE, /* needs: new maxmp */
+ NOTE_XP_LEVEL_CHANGE, /* needs: new xplevel */
+ NOTE_DUNGEON_LEVEL_CHANGE, /* needs: branch, subdepth */
+ NOTE_LEARN_SPELL, /* needs: spell idx */
+ NOTE_GET_GOD, /* needs: god id */
+ NOTE_GOD_GIFT, /* needs: god id */
+ NOTE_GOD_POWER, /* needs: god id, idx */
+ NOTE_GET_MUTATION, /* needs: mutation idx */
+ NOTE_LOSE_MUTATION, /* needs: mutation idx */
+ NOTE_ID_ITEM, /* needs: item name (string) */
+ /* NOT HOOKED YET */
+ NOTE_GET_ITEM, /* needs: item name (string) */
+ NOTE_GAIN_SKILL, /* needs: skill id, level */
+ NOTE_SEEN_MONSTER, /* needs: monster name (string) */
+ NOTE_KILL_MONSTER, /* needs: monster name (string) */
+ NOTE_POLY_MONSTER, /* needs: monster name (string) */
+ NOTE_USER_NOTE, /* needs: description string */
+ NOTE_MESSAGE, /* needs: message string */
+ NOTE_LOSE_GOD, /* needs: god id */
+ NOTE_NUM_TYPES
+};
+
+struct Note {
+ Note();
+ Note( NOTE_TYPES t, int f = 0, int s = 0, const char* n = 0,
+ const char* d = 0);
+ NOTE_TYPES type;
+ int first, second;
+ long turn;
+ unsigned short packed_place;
+ std::string name;
+ std::string desc;
+ void load( FILE* fp );
+ void save( FILE* fp ) const;
+};
+
+extern std::vector<Note> note_list;
+std::string describe_note( const Note& note );
+void activate_notes( bool active );
+bool notes_are_active();
+void take_note( const Note& note );
+void save_notes( FILE* fp );
+void load_notes( FILE* fp );
+void make_user_note();
+
+#endif
diff --git a/crawl-ref/source/ouch.cc b/crawl-ref/source/ouch.cc
index f9a5f514dd..4cc78e65d8 100644
--- a/crawl-ref/source/ouch.cc
+++ b/crawl-ref/source/ouch.cc
@@ -44,18 +44,6 @@
#include <unistd.h>
#endif
-#ifdef USE_EMX
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#endif
-
-#ifdef OS9
-#include <stat.h>
-#else
-#include <sys/stat.h>
-#endif
-
#include "ouch.h"
#ifdef __MINGW32__
@@ -70,9 +58,11 @@
#include "hiscores.h"
#include "invent.h"
#include "itemname.h"
+#include "itemprop.h"
#include "items.h"
#include "macro.h"
#include "mon-util.h"
+#include "notes.h"
#include "player.h"
#include "randart.h"
#include "religion.h"
@@ -98,8 +88,7 @@ int check_your_resists(int hurted, int flavour)
#endif
if (flavour == BEAM_FIRE || flavour == BEAM_LAVA
- || flavour == BEAM_HELLFIRE || flavour == BEAM_EXPLOSION
- || flavour == BEAM_FRAG)
+ || flavour == BEAM_HELLFIRE || flavour == BEAM_FRAG)
{
if (you.duration[DUR_CONDENSATION_SHIELD] > 0)
{
@@ -111,6 +100,21 @@ int check_your_resists(int hurted, int flavour)
switch (flavour)
{
+ case BEAM_STEAM:
+ resist = player_res_steam();
+ if (resist > 0)
+ {
+ canned_msg(MSG_YOU_RESIST);
+ hurted /= (1 + (resist * resist));
+ }
+ else if (resist < 0)
+ {
+ // We could use a superior message.
+ mpr("It burns terribly!");
+ hurted = hurted * 15 / 10;
+ }
+ break;
+
case BEAM_FIRE:
resist = player_res_fire();
if (resist > 0)
@@ -169,6 +173,9 @@ int check_your_resists(int hurted, int flavour)
break;
case BEAM_POISON_ARROW:
+ // [dshaligram] NOT importing uber-poison arrow from 4.1. Giving no
+ // bonus to poison resistant players seems strange and unnecessarily
+ // arbitrary.
resist = player_res_poison();
if (!resist)
@@ -179,7 +186,7 @@ int check_your_resists(int hurted, int flavour)
hurted /= 2;
if (!you.is_undead)
- poison_player( coinflip() ? 2 : 3, true );
+ poison_player( 2 + random2(3), true );
}
break;
@@ -225,6 +232,30 @@ int check_your_resists(int hurted, int flavour)
hurted /= 10;
}
break;
+
+ case BEAM_ACID:
+ if (player_res_acid())
+ {
+ canned_msg( MSG_YOU_RESIST );
+ hurted = hurted * player_acid_resist_factor() / 100;
+ }
+ break;
+
+ case BEAM_MIASMA:
+ if (player_prot_life() > random2(3))
+ {
+ canned_msg( MSG_YOU_RESIST );
+ hurted = 0;
+ }
+ break;
+
+ case BEAM_HOLY:
+ if (!you.is_undead && you.species != SP_DEMONSPAWN)
+ {
+ canned_msg( MSG_YOU_RESIST );
+ hurted = 0;
+ }
+ break;
} /* end switch */
return (hurted);
@@ -232,14 +263,10 @@ int check_your_resists(int hurted, int flavour)
void splash_with_acid( char acid_strength )
{
- /* affects equip only?
- assume that a message has already been sent, also that damage has
- already been done
- */
char splc = 0;
int dam = 0;
- const bool wearing_cloak = (you.equip[EQ_CLOAK] == -1);
+ const bool wearing_cloak = (you.equip[EQ_CLOAK] != -1);
for (splc = EQ_CLOAK; splc <= EQ_BODY_ARMOUR; splc++)
{
@@ -255,10 +282,19 @@ void splash_with_acid( char acid_strength )
item_corrode( you.equip[splc] );
}
- if (dam)
+ if (dam > 0)
{
- mpr( "The acid burns!" );
- ouch( dam, 0, KILLED_BY_ACID );
+ const int post_res_dam = dam * player_acid_resist_factor() / 100;
+
+ if (post_res_dam > 0)
+ {
+ mpr( "The acid burns!" );
+
+ if (post_res_dam < dam)
+ canned_msg(MSG_YOU_RESIST);
+
+ ouch( post_res_dam, 0, KILLED_BY_ACID );
+ }
}
} // end splash_with_acid()
@@ -313,7 +349,7 @@ void item_corrode( char itco )
suppress_msg = true;
}
else if ((you.inv[itco].sub_type == ARM_CRYSTAL_PLATE_MAIL
- || cmp_equip_race( you.inv[itco], ISFLAG_DWARVEN ))
+ || get_equip_race(you.inv[itco]) == ISFLAG_DWARVEN)
&& !one_chance_in(5))
{
it_resists = true;
@@ -328,7 +364,7 @@ void item_corrode( char itco )
it_resists = true;
suppress_msg = true;
}
- else if (cmp_equip_race( you.inv[itco], ISFLAG_DWARVEN )
+ else if (get_equip_race(you.inv[itco]) == ISFLAG_DWARVEN
&& !one_chance_in(5))
{
it_resists = true;
@@ -337,12 +373,17 @@ void item_corrode( char itco )
break;
case OBJ_MISSILES:
- if (cmp_equip_race( you.inv[itco], ISFLAG_DWARVEN ) && !one_chance_in(5))
+ if (get_equip_race(you.inv[itco]) == ISFLAG_DWARVEN
+ && !one_chance_in(5))
{
it_resists = true;
suppress_msg = false;
}
break;
+ default:
+ /* items which aren't missiles, etc...Could happen
+ if we're wielding a deck, say */
+ return;
}
// determine chance of corrosion {dlb}:
@@ -397,65 +438,145 @@ void item_corrode( char itco )
return;
} // end item_corrode()
-void scrolls_burn(char burn_strength, char target_class)
+// Helper function for the expose functions below.
+// This currently works because elements only target a single type each.
+static int get_target_class( beam_type flavour )
{
+ int target_class = OBJ_UNASSIGNED;
- unsigned char burnc;
- unsigned char burn2;
- unsigned char burn_no = 0;
-
- if (wearing_amulet(AMU_CONSERVATION) && !one_chance_in(10))
+ switch (flavour)
{
-#if DEBUG_DIAGNOSTICS
- mpr( "Amulet conserves.", MSGCH_DIAGNOSTICS );
-#endif
- return;
+ case BEAM_FIRE:
+ case BEAM_LAVA:
+ case BEAM_NAPALM:
+ case BEAM_HELLFIRE:
+ target_class = OBJ_SCROLLS;
+ break;
+
+ case BEAM_COLD:
+ case BEAM_FRAG:
+ target_class = OBJ_POTIONS;
+ break;
+
+ case BEAM_SPORE:
+ target_class = OBJ_FOOD;
+ break;
+
+ default:
+ break;
}
- for (burnc = 0; burnc < ENDOFPACK; burnc++)
+ return (target_class);
+}
+
+// XXX: These expose functions could use being reworked into a real system...
+// the usage and implementation is currently very hacky.
+// Handles the destruction of inventory items from the elements.
+static void expose_invent_to_element( beam_type flavour, int strength )
+{
+ int i, j;
+ int num_dest = 0;
+
+ const int target_class = get_target_class( flavour );
+ if (target_class == OBJ_UNASSIGNED)
+ return;
+
+ // Currently we test against each stack (and item in the stack)
+ // independantly at strength%... perhaps we don't want that either
+ // because it makes the system very fair and removes the protection
+ // factor of junk (which might be more desirable for game play).
+ for (i = 0; i < ENDOFPACK; i++)
{
- if (!you.inv[burnc].quantity)
- continue;
- if (you.inv[burnc].base_type != target_class)
+ if (!is_valid_item( you.inv[i] ))
continue;
- for (burn2 = 0; burn2 < you.inv[burnc].quantity; burn2++)
+ if (is_valid_item( you.inv[i] )
+ && (you.inv[i].base_type == target_class
+ || (target_class == OBJ_FOOD
+ && you.inv[i].base_type == OBJ_CORPSES)))
{
- if (random2(70) < burn_strength)
+ if (player_item_conserve() && !one_chance_in(10))
+ continue;
+
+ for (j = 0; j < you.inv[i].quantity; j++)
{
- burn_no++;
+ if (random2(100) < strength)
+ {
+ num_dest++;
- if (burnc == you.equip[EQ_WEAPON])
- you.wield_change = true;
+ if (i == you.equip[EQ_WEAPON])
+ you.wield_change = true;
- if (dec_inv_item_quantity( burnc, 1 ))
- break;
+ if (dec_inv_item_quantity( i, 1 ))
+ break;
+ }
}
}
}
- if (burn_no == 1)
+ if (num_dest > 0)
{
- if (target_class == OBJ_SCROLLS)
- mpr("A scroll you are carrying catches fire!");
- else if (target_class == OBJ_POTIONS)
- mpr("A potion you are carrying freezes and shatters!");
- else if (target_class == OBJ_FOOD)
- mpr("Some of your food is covered with spores!");
+ switch (target_class)
+ {
+ case OBJ_SCROLLS:
+ snprintf( info, INFO_SIZE, "%s you are carrying %s fire!",
+ (num_dest > 1) ? "Some of the scrolls" : "A scroll",
+ (num_dest > 1) ? "catch" : "catches" );
+ break;
+
+ case OBJ_POTIONS:
+ snprintf( info, INFO_SIZE, "%s you are carrying %s and %s!",
+ (num_dest > 1) ? "Some of the potions" : "A potion",
+ (num_dest > 1) ? "freeze" : "freezes",
+ (num_dest > 1) ? "shatter" : "shatters" );
+ break;
+
+ case OBJ_FOOD:
+ snprintf( info, INFO_SIZE, "Some of your food is covered with spores!" );
+ break;
+
+ default:
+ snprintf( info, INFO_SIZE, "%s you are carrying %s destroyed!",
+ (num_dest > 1) ? "Some items" : "An item",
+ (num_dest > 1) ? "were" : "was" );
+ break;
+ }
+
+ mpr( info ); // XXX: should this be in a channel?
}
- else if (burn_no > 1)
+}
+
+
+// Handle side-effects for exposure to element other than damage.
+// This function exists because some code calculates its own damage
+// instead of using check_resists and we want to isolate all the special
+// code they keep having to do... namely condensation shield checks,
+// you really can't expect this function to even be called for much else.
+//
+// This function now calls expose_invent_to_element if strength > 0.
+//
+// XXX: this function is far from perfect and a work in progress.
+void expose_player_to_element( beam_type flavour, int strength )
+{
+ // Note that BEAM_TELEPORT is sent here when the player
+ // blinks or teleports.
+ if (flavour == BEAM_FIRE || flavour == BEAM_LAVA
+ || flavour == BEAM_HELLFIRE || flavour == BEAM_FRAG
+ || flavour == BEAM_TELEPORT || flavour == BEAM_NAPALM
+ || flavour == BEAM_STEAM)
{
- if (target_class == OBJ_SCROLLS)
- mpr("Some of the scrolls you are carrying catch fire!");
- else if (target_class == OBJ_POTIONS)
- mpr("Some of the potions you are carrying freeze and shatter!");
- else if (target_class == OBJ_FOOD)
- mpr("Some of your food is covered with spores!");
+ if (you.duration[DUR_CONDENSATION_SHIELD] > 0)
+ {
+ mprf(MSGCH_DURATION, "Your icy shield dissipates!");
+ you.duration[DUR_CONDENSATION_SHIELD] = 0;
+ you.redraw_armour_class = true;
+ }
}
- /* burn_no could be 0 */
+
+ if (strength)
+ expose_invent_to_element( flavour, strength );
}
- // end scrolls_burn()
void lose_level(void)
{
// because you.experience is unsigned long, if it's going to be -ve
@@ -481,6 +602,11 @@ void lose_level(void)
calc_hp();
calc_mp();
+ char buf[200];
+ sprintf(buf, "HP: %d/%d MP: %d/%d",
+ you.hp, you.hp_max, you.magic_points, you.max_magic_points);
+ take_note(Note(NOTE_XP_LEVEL_CHANGE, you.experience_level, 0, buf));
+
you.redraw_experience = 1;
} // end lose_level()
@@ -548,9 +674,6 @@ void drain_exp(void)
// death_source should be set to zero for non-monsters {dlb}
void ouch( int dam, int death_source, char death_type, const char *aux )
{
- int d = 0;
- int e = 0;
-
ait_hp_loss hpl(dam, death_type);
interrupt_activity( AI_HP_LOSS, &hpl );
@@ -569,11 +692,6 @@ void ouch( int dam, int death_source, char death_type, const char *aux )
return;
}
- if (you_are_delayed())
- {
- stop_delay();
- }
-
if (dam > -9000) // that is, a "death" caused by hp loss {dlb}
{
switch (you.religion)
@@ -590,7 +708,6 @@ void ouch( int dam, int death_source, char death_type, const char *aux )
case GOD_ZIN:
case GOD_SHINING_ONE:
case GOD_ELYVILON:
- case GOD_OKAWARU:
case GOD_YREDELEMNUL:
if (dam >= you.hp && you.duration[DUR_PRAYER]
&& random2(you.piety) >= 30)
@@ -614,6 +731,14 @@ void ouch( int dam, int death_source, char death_type, const char *aux )
{
mpr( "* * * LOW HITPOINT WARNING * * *", MSGCH_DANGER );
}
+ take_note(
+ Note(
+ NOTE_HP_CHANGE,
+ you.hp,
+ you.hp_max,
+ scorefile_entry(dam, death_source, death_type, aux, true)
+ .death_description(scorefile_entry::DDV_TERSE)
+ .c_str()) );
if (you.hp > 0)
return;
@@ -651,228 +776,11 @@ void ouch( int dam, int death_source, char death_type, const char *aux )
//okay, so you're dead:
- // do points first.
- long points = you.gold;
- points += (you.experience * 7) / 10;
-
- //if (death_type == KILLED_BY_WINNING) points += points / 2;
- //if (death_type == KILLED_BY_LEAVING) points += points / 10;
- // these now handled by giving player the value of their inventory
- char temp_id[4][50];
-
- for (d = 0; d < 4; d++)
- {
- for (e = 0; e < 50; e++)
- temp_id[d][e] = 1;
- }
+ // prevent bogus notes
+ activate_notes(false);
// CONSTRUCT SCOREFILE ENTRY
- struct scorefile_entry se;
-
- // Score file entry version:
- //
- // 4.0 - original versioned entry
- // 4.1 - added real_time and num_turn fields
- // 4.2 - stats and god info
-
- se.version = 4;
- se.release = 2;
-
- strncpy( se.name, you.your_name, kNameLen );
- se.name[ kNameLen - 1 ] = '\0';
-#ifdef MULTIUSER
- se.uid = (int) getuid();
-#else
- se.uid = 0;
-#endif
-
- FixedVector< int, NUM_RUNE_TYPES > rune_array;
-
- se.num_runes = 0;
- se.num_diff_runes = 0;
-
- for (int i = 0; i < NUM_RUNE_TYPES; i++)
- rune_array[i] = 0;
-
- // Calculate value of pack and runes when character leaves dungeon
- if (death_type == KILLED_BY_LEAVING || death_type == KILLED_BY_WINNING)
- {
- for (d = 0; d < ENDOFPACK; d++)
- {
- if (is_valid_item( you.inv[d] ))
- {
- points += item_value( you.inv[d], temp_id, true );
-
- if (you.inv[d].base_type == OBJ_MISCELLANY
- && you.inv[d].sub_type == MISC_RUNE_OF_ZOT)
- {
- if (rune_array[ you.inv[d].plus ] == 0)
- se.num_diff_runes++;
-
- se.num_runes += you.inv[d].quantity;
- rune_array[ you.inv[d].plus ] += you.inv[d].quantity;
- }
- }
- }
-
- // Bonus for exploring different areas, not for collecting a
- // huge stack of demonic runes in Pandemonium (gold value
- // is enough for those). -- bwr
- if (se.num_diff_runes >= 3)
- points += ((se.num_diff_runes + 2) * (se.num_diff_runes + 2) * 1000);
- }
-
- // Players will have a hard time getting 1/10 of this (see XP cap):
- if (points > 99999999)
- points = 99999999;
-
- se.points = points;
- se.race = you.species;
- se.cls = you.char_class;
-
- // strcpy(se.race_class_name, "");
- se.race_class_name[0] = '\0';
-
- se.lvl = you.experience_level;
- se.best_skill = best_skill( SK_FIGHTING, NUM_SKILLS - 1, 99 );
- se.best_skill_lvl = you.skills[ se.best_skill ];
- se.death_type = death_type;
-
- // for death by monster
-
- // Set the default aux data value...
- // If aux is passed in (ie for a trap), we'll default to that.
- if (aux == NULL)
- se.auxkilldata[0] = '\0';
- else
- {
- strncpy( se.auxkilldata, aux, ITEMNAME_SIZE );
- se.auxkilldata[ ITEMNAME_SIZE - 1 ] = '\0';
- }
-
- if ((death_type == KILLED_BY_MONSTER || death_type == KILLED_BY_BEAM)
- && death_source >= 0 && death_source < MAX_MONSTERS)
- {
- struct monsters *monster = &menv[death_source];
-
- if (monster->type > 0 || monster->type <= NUM_MONSTERS)
- {
- se.death_source = monster->type;
- se.mon_num = monster->number;
-
- // Previously the weapon was only used for dancing weapons,
- // but now we pass it in as a string through the scorefile
- // entry to be appended in hiscores_format_single in long or
- // medium scorefile formats.
- // It still isn't used in monam for anything but flying weapons
- // though
- if (death_type == KILLED_BY_MONSTER
- && monster->inv[MSLOT_WEAPON] != NON_ITEM)
- {
-#if HISCORE_WEAPON_DETAIL
- set_ident_flags( mitm[monster->inv[MSLOT_WEAPON]],
- ISFLAG_IDENT_MASK );
-#else
- // changing this to ignore the pluses to keep it short
- unset_ident_flags( mitm[monster->inv[MSLOT_WEAPON]],
- ISFLAG_IDENT_MASK );
-
- set_ident_flags( mitm[monster->inv[MSLOT_WEAPON]],
- ISFLAG_KNOW_TYPE );
-
- // clear "runed" description text to make shorter yet
- set_equip_desc( mitm[monster->inv[MSLOT_WEAPON]], 0 );
-#endif
-
- // Setting this is redundant for dancing weapons, however
- // we do care about the above indentification. -- bwr
- if (monster->type != MONS_DANCING_WEAPON)
- {
- it_name( monster->inv[MSLOT_WEAPON], DESC_NOCAP_A, info );
- strncpy( se.auxkilldata, info, ITEMNAME_SIZE );
- se.auxkilldata[ ITEMNAME_SIZE - 1 ] = '\0';
- }
- }
-
- strcpy( info,
- monam( monster->number, monster->type, true, DESC_NOCAP_A,
- monster->inv[MSLOT_WEAPON] ) );
-
- strncpy( se.death_source_name, info, 40 );
- se.death_source_name[39] = '\0';
- }
- }
- else
- {
- se.death_source = death_source;
- se.mon_num = 0;
- se.death_source_name[0] = '\0';
- }
-
- se.damage = dam;
- se.final_hp = you.hp;
- se.final_max_hp = you.hp_max;
- se.final_max_max_hp = you.hp_max + player_rotted();
- se.str = you.strength;
- se.intel = you.intel;
- se.dex = you.dex;
-
- se.god = you.religion;
- if (you.religion != GOD_NO_GOD)
- {
- se.piety = you.piety;
- se.penance = you.penance[you.religion];
- }
-
- // main dungeon: level is simply level
- se.dlvl = you.your_level + 1;
- switch (you.where_are_you)
- {
- case BRANCH_ORCISH_MINES:
- case BRANCH_HIVE:
- case BRANCH_LAIR:
- case BRANCH_SLIME_PITS:
- case BRANCH_VAULTS:
- case BRANCH_CRYPT:
- case BRANCH_HALL_OF_BLADES:
- case BRANCH_HALL_OF_ZOT:
- case BRANCH_ECUMENICAL_TEMPLE:
- case BRANCH_SNAKE_PIT:
- case BRANCH_ELVEN_HALLS:
- case BRANCH_TOMB:
- case BRANCH_SWAMP:
- se.dlvl = you.your_level - you.branch_stairs[you.where_are_you - 10];
- break;
-
- case BRANCH_DIS:
- case BRANCH_GEHENNA:
- case BRANCH_VESTIBULE_OF_HELL:
- case BRANCH_COCYTUS:
- case BRANCH_TARTARUS:
- case BRANCH_INFERNO:
- case BRANCH_THE_PIT:
- se.dlvl = you.your_level - 26;
- break;
- }
-
- se.branch = you.where_are_you; // no adjustments necessary.
- se.level_type = you.level_type; // pandemonium, labyrinth, dungeon..
-
- se.birth_time = you.birth_time; // start time of game
- se.death_time = time( NULL ); // end time of game
-
- if (you.real_time != -1)
- se.real_time = you.real_time + (se.death_time - you.start_time);
- else
- se.real_time = -1;
-
- se.num_turns = you.num_turns;
-
-#ifdef WIZARD
- se.wiz_mode = (you.wizard ? 1 : 0);
-#else
- se.wiz_mode = 0;
-#endif
+ scorefile_entry se(dam, death_source, death_type, aux);
#ifdef SCORE_WIZARD_CHARACTERS
// add this highscore to the score file.
@@ -897,7 +805,6 @@ void ouch( int dam, int death_source, char death_type, const char *aux )
void end_game( struct scorefile_entry &se )
{
int i;
- char del_file[300]; // massive overkill!
bool dead = true;
if (se.death_type == KILLED_BY_LEAVING ||
@@ -913,47 +820,34 @@ void end_game( struct scorefile_entry &se )
{
if (tmp_file_pairs[level][dungeon])
{
- make_filename( info, you.your_name, level, dungeon,
- false, false );
- unlink(info);
+ unlink(make_filename( you.your_name, level, dungeon,
+ false, false ).c_str());
}
}
}
// temp level, if any
- make_filename( info, you.your_name, 0, 0, true, false );
- unlink(info);
+ unlink( make_filename( you.your_name, 0, 0, true, false ).c_str() );
// create base file name
-#ifdef SAVE_DIR_PATH
- snprintf( info, INFO_SIZE, SAVE_DIR_PATH "%s%d", you.your_name, (int) getuid());
-#else
- strncpy(info, you.your_name, kFileNameLen);
- info[kFileNameLen] = '\0';
-#endif
+ std::string basename = get_savedir_filename( you.your_name, "", "" );
- // this is to catch the game package if it still exists.
+ const char* suffixes[] = {
+#ifdef CLUA_BINDINGS
+ ".lua",
+#endif
#ifdef PACKAGE_SUFFIX
- strcpy(del_file, info);
- strcat(del_file, "." PACKAGE_SUFFIX);
- unlink(del_file);
+ PACKAGE_SUFFIX ,
#endif
+ ".st", ".kil", ".tc", ".nts", ".sav"
+ };
- // last, but not least, delete player .sav file
- strcpy(del_file, info);
-
- std::string basefile = del_file;
+ const int num_suffixes = sizeof(suffixes) / sizeof(const char*);
- strcat(del_file, ".sav");
- unlink(del_file);
-
- // Delete record of stashes, kills, travel cache and lua save.
- unlink( (basefile + ".st").c_str() );
- unlink( (basefile + ".kil").c_str() );
- unlink( (basefile + ".tc").c_str() );
-#ifdef CLUA_BINDINGS
- unlink( (basefile + ".lua").c_str() );
-#endif
+ for ( i = 0; i < num_suffixes; ++i ) {
+ std::string tmpname = basename + suffixes[i];
+ unlink( tmpname.c_str() );
+ }
// death message
if (dead)
@@ -978,7 +872,7 @@ void end_game( struct scorefile_entry &se )
invent( -1, dead );
clrscr();
- if (!dump_char( "morgue.txt", !dead ))
+ if (!dump_char( "morgue", !dead, true ))
mpr("Char dump unsuccessful! Sorry about that.");
#if DEBUG_DIAGNOSTICS
//jmf: switched logic and moved "success" message to debug-only
@@ -994,17 +888,17 @@ void end_game( struct scorefile_entry &se )
#endif
clrscr();
- cprintf( "Goodbye, " );
- cprintf( you.your_name );
- cprintf( "." );
+ cprintf( "Goodbye, %s.", you.your_name );
cprintf( EOL EOL " " ); // Space padding where # would go in list format
char scorebuff[ HIGHSCORE_SIZE ];
- const int lines = hiscores_format_single_long( scorebuff, se, true );
-
+ hiscores_format_single_long( scorebuff, se, true );
// truncate
- scorebuff[ HIGHSCORE_SIZE - 1 ] = '\0';
+ scorebuff[ HIGHSCORE_SIZE - 1 ] = 0;
+
+ const int lines = count_occurrences(scorebuff, EOL) + 1;
+
cprintf( scorebuff );
cprintf( EOL "Best Crawlers -" EOL );
diff --git a/crawl-ref/source/ouch.h b/crawl-ref/source/ouch.h
index 23894dade5..451d17bdcf 100644
--- a/crawl-ref/source/ouch.h
+++ b/crawl-ref/source/ouch.h
@@ -19,6 +19,7 @@
#define DEATH_NAME_LENGTH 10
+#include "enum.h"
// last updated 12may2000 {dlb}
/* ***********************************************************************
@@ -70,5 +71,6 @@ void lose_level(void);
* *********************************************************************** */
void drain_exp(void);
+void expose_player_to_element( beam_type flavour, int strength = 0 );
#endif
diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc
index 415e970fc0..9d510e9216 100644
--- a/crawl-ref/source/output.cc
+++ b/crawl-ref/source/output.cc
@@ -245,11 +245,11 @@ void print_stats(void)
gotoxy(52, 11);
#if DEBUG_DIAGNOSTICS
- cprintf( "%d/%d (%d/%d)",
+ cprintf( "%d/%lu (%d/%d)",
you.experience_level, you.experience,
you.skill_cost_level, you.exp_available );
#else
- cprintf( "%d/%d (%d)",
+ cprintf( "%d/%lu (%d)",
you.experience_level, you.experience, you.exp_available );
#endif
@@ -283,9 +283,9 @@ void print_stats(void)
in_name( you.equip[EQ_WEAPON], DESC_INVENTORY, str_pass,
Options.terse_hand );
- str_pass[39] = '\0';
+ str_pass[39] = 0;
- cprintf(str_pass);
+ cprintf("%s", str_pass);
textcolor(LIGHTGREY);
}
else
@@ -511,7 +511,7 @@ void print_stats(void)
cprintf( "Rot " );
}
- if (you.magic_contamination > 5)
+ if (you.magic_contamination >= 5)
{
textcolor( bad_ench_colour( you.magic_contamination, 15, 25 ) );
cprintf( "Glow " );
@@ -559,10 +559,12 @@ unsigned char* itosym1(int stat)
unsigned char* itosym3(int stat)
{
return (unsigned char*)( (stat >= 3) ? "+ + +" :
- (stat == 2) ? "+ + ." :
- (stat == 1) ? "+ . ." :
- (stat == 0) ? ". . ." :
- "x . .");
+ (stat == 2) ? "+ + ." :
+ (stat == 1) ? "+ . ." :
+ (stat == 0) ? ". . ." :
+ (stat == -1) ? "x . ." :
+ (stat == -2) ? "x x ." :
+ "x x x");
}
static const char *s_equip_slot_names[] =
@@ -600,10 +602,9 @@ int equip_name_to_slot(const char *s)
void get_full_detail(char* buffer, bool calc_unid)
{
-#define FIR_AD buffer,44
#define CUR_AD &buffer[++lines*45],44
-#define BUF_SIZE 25*3*45
- int lines = 0;
+#define BUF_SIZE 24*3*45
+ int lines = -1;
memset(buffer, 0, BUF_SIZE);
@@ -642,7 +643,7 @@ void get_full_detail(char* buffer, bool calc_unid)
}
else
{
- snprintf(CUR_AD, "HP : %3d/%d (%d)",
+ snprintf(CUR_AD, "HP : %3d/%d (%d)",
you.hp, you.hp_max, you.hp_max + player_rotted() );
}
@@ -683,7 +684,7 @@ void get_full_detail(char* buffer, bool calc_unid)
snprintf(CUR_AD, "Turns : %10ld", you.num_turns );
}
- lines = 27;
+ lines = 24 + 1;
snprintf(CUR_AD, "Res.Fire : %s",
itosym3( player_res_fire(calc_unid) ) );
@@ -722,15 +723,14 @@ void get_full_detail(char* buffer, bool calc_unid)
const char *slot = equip_slot_to_name( eqslot );
if (eqslot == EQ_LEFT_RING || eqslot == EQ_RIGHT_RING)
slot = "Ring";
- else if (eqslot == EQ_BOOTS
- && (you.species == SP_CENTAUR
- || you.species == SP_NAGA))
+ else if (eqslot == EQ_BOOTS &&
+ (you.species == SP_CENTAUR || you.species == SP_NAGA))
slot = "Barding";
if ( you.equip[ e_order[i] ] != -1)
{
in_name( you.equip[ e_order[i] ], DESC_PLAIN,
- str_pass, Options.terse_hand );
+ str_pass, true );
snprintf(CUR_AD, "%-7s: %s", slot, str_pass);
}
else
@@ -752,7 +752,7 @@ void get_full_detail(char* buffer, bool calc_unid)
}
}
- lines = 52;
+ lines = 24 * 2 + 1;
snprintf(CUR_AD, "See Invis. : %s",
itosym1( player_see_invis(calc_unid) ) );
snprintf(CUR_AD, "Warding : %s",
@@ -783,11 +783,7 @@ void get_full_detail(char* buffer, bool calc_unid)
case SP_OGRE:
snprintf(CUR_AD, "Saprovore : %s", itosym3(1) );
break;
-#ifdef V_FIX
- case SP_OGRE_MAGE:
- snprintf(CUR_AD, "Voracious : %s", itosym1(1) );
- break;
-#endif
+
default:
snprintf(CUR_AD, "Gourmand : %s", itosym1(0) );
break;
@@ -808,7 +804,7 @@ void get_full_detail(char* buffer, bool calc_unid)
snprintf(CUR_AD, "Rnd.Telep. : %s",
itosym1( player_teleport(calc_unid) ) );
snprintf(CUR_AD, "Ctrl.Telep.: %s",
- itosym1( you.attribute[ATTR_CONTROL_TELEPORT] ) );
+ itosym1( player_control_teleport(calc_unid) ) );
snprintf(CUR_AD, "Levitation : %s", itosym1( player_is_levitating() ) );
snprintf(CUR_AD, "Ctrl.Flight: %s",
itosym1( wearing_amulet(AMU_CONTROLLED_FLIGHT, calc_unid) ) );
diff --git a/crawl-ref/source/output.h b/crawl-ref/source/output.h
index 1fa77fd34b..3025c8899d 100644
--- a/crawl-ref/source/output.h
+++ b/crawl-ref/source/output.h
@@ -3,6 +3,8 @@
* Summary: Functions used to print player related info.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
diff --git a/crawl-ref/source/overmap.cc b/crawl-ref/source/overmap.cc
index e271a25fdf..2e4a236156 100644
--- a/crawl-ref/source/overmap.cc
+++ b/crawl-ref/source/overmap.cc
@@ -6,6 +6,8 @@
* Summary: Records location of stairs etc
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <3> 30/7/00 MV Made Over-map full-screen
@@ -26,6 +28,7 @@
// for #definitions of MAX_BRANCHES & MAX_LEVELS
#include "files.h"
// for #definitions of MAX_BRANCHES & MAX_LEVELS
+#include "misc.h"
#include "religion.h"
#include "stuff.h"
#include "view.h"
@@ -64,6 +67,22 @@ void print_one_highlighted_line( const char *pre, const char *text,
static void print_level_name( int branch, int depth,
bool &printed_branch, bool &printed_level );
+void seen_notable_thing( int which_thing )
+{
+ // Don't record in temporary terrain
+ if (you.level_type != LEVEL_DUNGEON)
+ return;
+
+ const god_type god = grid_altar_god(which_thing);
+
+ if (god != GOD_NO_GOD)
+ seen_altar( god );
+ else if (grid_is_branch_stairs( which_thing ))
+ seen_staircase( which_thing );
+ else
+ seen_other_thing( which_thing );
+}
+
void init_overmap( void )
{
for (int i = 0; i < MAX_LEVELS; i++)
@@ -196,7 +215,7 @@ void display_overmap( void )
{
pr_lev = false;
// strcpy(info, " - a staircase leading to ");
- info[0] = '\0';
+ info[0] = 0;
if (stair_level[k] == j)
{
@@ -359,7 +378,7 @@ static void print_level_name( int branch, int depth,
}
// we need our own buffer in here (info is used):
- char buff[ INFO_SIZE ] = "\0";;
+ char buff[INFO_SIZE];
if (branch == BRANCH_MAIN_DUNGEON)
depth += 1;
@@ -424,10 +443,24 @@ void seen_staircase( unsigned char which_staircase )
case DNGN_ENTER_SWAMP:
which_branch = BRANCH_SWAMP;
break;
+ case DNGN_ENTER_DIS:
+ which_branch = BRANCH_DIS;
+ break;
+ case DNGN_ENTER_GEHENNA:
+ which_branch = BRANCH_GEHENNA;
+ break;
+ case DNGN_ENTER_COCYTUS:
+ which_branch = BRANCH_COCYTUS;
+ break;
+ case DNGN_ENTER_TARTARUS:
+ which_branch = BRANCH_TARTARUS;
+ break;
default:
- exit(-1); // shouldn't happen
+ break;
}
+ ASSERT(which_branch != BRANCH_MAIN_DUNGEON);
+
stair_level[which_branch] = you.your_level;
} // end seen_staircase()
@@ -486,7 +519,7 @@ void seen_other_thing( unsigned char which_thing )
* prints "More..." message, read key, clear screen and after that prints new
* line
*/
-void print_one_simple_line( const char *line , int colour)
+void print_one_simple_line( const char *line, int colour)
{
if (map_lines == (get_number_of_lines() - 2))
{
@@ -499,9 +532,7 @@ void print_one_simple_line( const char *line , int colour)
}
textcolor( colour );
- cprintf( line );
- cprintf( EOL );
-
+ cprintf( "%s" EOL, line );
map_lines++;
}
@@ -518,19 +549,19 @@ void print_one_highlighted_line( const char *pre, const char *text,
map_lines = 0;
}
- if (pre[0] != '\0')
+ if (pre[0] != 0)
{
textcolor( LIGHTGREY );
- cprintf( pre );
+ cprintf( "%s", pre );
}
textcolor( colour );
- cprintf( text );
+ cprintf( "%s", text );
- if (post[0] != '\0')
+ if (post[0] != 0)
{
textcolor( LIGHTGREY );
- cprintf( post );
+ cprintf( "%s", post );
}
cprintf( EOL );
diff --git a/crawl-ref/source/overmap.h b/crawl-ref/source/overmap.h
index 9d02b320e6..4ded4e4420 100644
--- a/crawl-ref/source/overmap.h
+++ b/crawl-ref/source/overmap.h
@@ -13,6 +13,8 @@
#define OVERMAP_H
+void seen_notable_thing( int which_thing );
+
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: view
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index c4d5d6c047..e44996d6f8 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -3,6 +3,8 @@
* Summary: Player related functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <6> 7/30/99 BWR Added player_spell_levels()
@@ -31,23 +33,28 @@
#include "externs.h"
#include "clua.h"
+#include "delay.h"
+#include "fight.h"
#include "itemname.h"
+#include "itemprop.h"
#include "items.h"
#include "macro.h"
#include "misc.h"
#include "mon-util.h"
#include "mutation.h"
+#include "notes.h"
+#include "ouch.h"
#include "output.h"
#include "randart.h"
#include "religion.h"
+#include "skills.h"
#include "skills2.h"
#include "spl-util.h"
#include "spells4.h"
#include "stuff.h"
+#include "transfor.h"
#include "travel.h"
#include "view.h"
-#include "wpn-misc.h"
-
/*
you.duration []: //jmf: obsolete, see enum.h instead
@@ -105,7 +112,194 @@
int species_exp_mod(char species);
void ability_increase(void);
-//void priest_spells(int priest_pass[10], char religious); // see actual function for reasoning here {dlb}
+// Use this function whenever the player enters (or lands and thus re-enters)
+// a grid.
+//
+// stepped - normal walking moves
+// allow_shift - allowed to scramble in any direction out of lava/water
+// force - ignore safety checks, move must happen (traps, lava/water).
+bool move_player_to_grid( int x, int y, bool stepped, bool allow_shift,
+ bool force )
+{
+ ASSERT( in_bounds( x, y ) );
+
+ int id;
+ // assuming that entering the same square means coming from above (levitate)
+ const bool from_above = (you.x_pos == x && you.y_pos == y);
+ const int old_grid = (from_above) ? static_cast<int>(DNGN_FLOOR)
+ : grd[you.x_pos][you.y_pos];
+ const int new_grid = grd[x][y];
+
+ // really must be clear
+ ASSERT( !grid_is_solid( new_grid ) );
+
+ // if (grid_is_solid( new_grid ))
+ // return (false);
+
+ // better not be an unsubmerged monster either:
+ ASSERT( mgrd[x][y] == NON_MONSTER
+ || mons_is_submerged( &menv[ mgrd[x][y] ] ));
+
+ // if (mgrd[x][y] != NON_MONSTER && !mons_is_submerged( &menv[ mgrd[x][y] ] ))
+ // return (false);
+
+ // if we're walking along, give a chance to avoid trap
+ if (stepped
+ && !force
+ && new_grid == DNGN_UNDISCOVERED_TRAP)
+ {
+ const int skill = 4 + you.skills[SK_TRAPS_DOORS]
+ + you.mutation[MUT_ACUTE_VISION]
+ - 2 * you.mutation[MUT_BLURRY_VISION];
+
+ if (random2( skill ) > 6)
+ {
+ mprf( MSGCH_WARN,
+ "Wait a moment, %s! Do you really want to step there?",
+ you.your_name );
+
+ more();
+
+ exercise( SK_TRAPS_DOORS, 3 );
+
+ you.turn_is_over = false;
+
+ id = trap_at_xy( x, y );
+ if (id != -1)
+ grd[x][y] = trap_category( env.trap[id].type );
+
+ return (false);
+ }
+ }
+
+ // only consider terrain if player is not levitating
+ if (!player_is_levitating())
+ {
+ // XXX: at some point we're going to need to fix the swimming
+ // code to handle burden states.
+ if (new_grid == DNGN_LAVA
+ || (new_grid == DNGN_DEEP_WATER && you.species != SP_MERFOLK))
+ {
+ // lava and dangerous deep water (ie not merfolk)
+ int entry_x = (stepped) ? you.x_pos : x;
+ int entry_y = (stepped) ? you.y_pos : y;
+
+ if (stepped && !force && !you.conf)
+ {
+ bool okay = yesno( "Do you really want to step there?",
+ false, 'n' );
+
+ if (!okay)
+ {
+ canned_msg(MSG_OK);
+ return (false);
+ }
+ }
+
+ // have to move now so fall_into_a_pool will work
+ you.x_pos = x;
+ you.y_pos = y;
+
+ viewwindow( true, false );
+
+ // if true, we were shifted and so we're done.
+ if (fall_into_a_pool( entry_x, entry_y, allow_shift, new_grid ))
+ return (true);
+ }
+ else if (new_grid == DNGN_SHALLOW_WATER || new_grid == DNGN_DEEP_WATER)
+ {
+ // safer water effects
+ if (you.species == SP_MERFOLK)
+ {
+ if (old_grid != DNGN_SHALLOW_WATER
+ && old_grid != DNGN_DEEP_WATER)
+ {
+ if (stepped)
+ mpr("Your legs become a tail as you enter the water.");
+ else
+ mpr("Your legs become a tail as you dive into the water.");
+
+ merfolk_start_swimming();
+ }
+ }
+ else
+ {
+ ASSERT( new_grid != DNGN_DEEP_WATER );
+
+ if (!stepped)
+ noisy(SL_SPLASH, you.x_pos, you.y_pos, "Splash!");
+
+ you.time_taken *= 13 + random2(8);
+ you.time_taken /= 10;
+
+ if (old_grid != DNGN_SHALLOW_WATER)
+ {
+ mprf( "You %s the shallow water.",
+ (stepped ? "enter" : "fall into") );
+
+ mpr("Moving in this stuff is going to be slow.");
+
+ if (you.invis)
+ mpr( "... and don't expect to remain undetected." );
+ }
+ }
+ }
+ }
+
+ // move the player to location
+ you.x_pos = x;
+ you.y_pos = y;
+
+ viewwindow( true, false );
+
+ // Other Effects:
+ // clouds -- do we need this? (always seems to double up with acr.cc call)
+ // if (is_cloud( you.x_pos, you.y_pos ))
+ // in_a_cloud();
+
+ // icy shield goes down over lava
+ if (new_grid == DNGN_LAVA)
+ expose_player_to_element( BEAM_LAVA );
+
+ // traps go off:
+ if (new_grid >= DNGN_TRAP_MECHANICAL && new_grid <= DNGN_UNDISCOVERED_TRAP)
+ {
+ id = trap_at_xy( you.x_pos, you.y_pos );
+
+ if (id != -1)
+ {
+ bool trap_known = true;
+
+ if (new_grid == DNGN_UNDISCOVERED_TRAP)
+ {
+ trap_known = false;
+
+ const int type = trap_category( env.trap[id].type );
+
+ grd[you.x_pos][you.y_pos] = type;
+ set_envmap_char(you.x_pos, you.y_pos, get_sightmap_char(type));
+ }
+
+ // not easy to blink onto a trap without setting it off:
+ if (!stepped)
+ trap_known = false;
+
+ if (!player_is_levitating()
+ || trap_category( env.trap[id].type ) != DNGN_TRAP_MECHANICAL)
+ {
+ handle_traps(env.trap[id].type, id, trap_known);
+ }
+ }
+ }
+
+ return (true);
+}
+
+bool player_in_mappable_area( void )
+{
+ return (you.level_type != LEVEL_LABYRINTH && you.level_type != LEVEL_ABYSS);
+}
+
bool player_in_branch( int branch )
{
return (you.level_type == LEVEL_DUNGEON && you.where_are_you == branch);
@@ -157,7 +351,7 @@ bool player_genus(unsigned char which_genus, unsigned char species)
case SP_PALE_DRACONIAN:
case SP_UNK0_DRACONIAN:
case SP_UNK1_DRACONIAN:
- case SP_UNK2_DRACONIAN:
+ case SP_BASE_DRACONIAN:
return (which_genus == GENPC_DRACONIAN);
case SP_ELF:
@@ -178,6 +372,58 @@ bool player_genus(unsigned char which_genus, unsigned char species)
return (false);
} // end player_genus()
+// Returns the item in the given equipment slot, NULL if the slot is empty.
+// eq must be in [EQ_WEAPON, EQ_AMULET], or bad things will happen.
+item_def *player_slot_item(equipment_type eq)
+{
+ ASSERT(eq >= EQ_WEAPON && eq <= EQ_AMULET);
+
+ const int item = you.equip[eq];
+ return (item == -1? NULL : &you.inv[item]);
+}
+
+// Returns the item in the player's weapon slot.
+item_def *player_weapon()
+{
+ return player_slot_item(EQ_WEAPON);
+}
+
+bool player_weapon_wielded()
+{
+ const int wpn = you.equip[EQ_WEAPON];
+
+ if (wpn == -1)
+ return (false);
+
+ if (you.inv[wpn].base_type != OBJ_WEAPONS
+ && you.inv[wpn].base_type != OBJ_STAVES)
+ {
+ return (false);
+ }
+
+ // FIXME: This needs to go in eventually.
+ /*
+ // should never have a bad "shape" weapon in hand
+ ASSERT( check_weapon_shape( you.inv[wpn], false ) );
+
+ if (!check_weapon_wieldable_size( you.inv[wpn], player_size() ))
+ return (false);
+ */
+
+ return (true);
+}
+
+// Returns the you.inv[] index of our wielded weapon or -1 (no item, not wield)
+int get_player_wielded_item()
+{
+ return (you.equip[EQ_WEAPON]);
+}
+
+int get_player_wielded_weapon()
+{
+ return (player_weapon_wielded()? get_player_wielded_item() : -1);
+}
+
// Looks in equipment "slot" to see if there is an equiped "sub_type".
// Returns number of matches (in the case of rings, both are checked)
int player_equip( int slot, int sub_type, bool calc_unid )
@@ -201,7 +447,7 @@ int player_equip( int slot, int sub_type, bool calc_unid )
if (you.equip[EQ_WEAPON] != -1
&& you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_STAVES
&& you.inv[you.equip[EQ_WEAPON]].sub_type == sub_type
- && (calc_unid ||
+ && (calc_unid ||
item_ident(you.inv[you.equip[EQ_WEAPON]], ISFLAG_KNOW_TYPE)))
{
ret++;
@@ -275,6 +521,8 @@ int player_equip( int slot, int sub_type, bool calc_unid )
// Looks in equipment "slot" to see if equiped item has "special" ego-type
// Returns number of matches (jewellery returns zero -- no ego type).
+// [ds] There's no equivalent of calc_unid or req_id because as of now, weapons
+// and armour type-id on wield/wear.
int player_equip_ego_type( int slot, int special )
{
int ret = 0;
@@ -337,13 +585,14 @@ int player_damage_type( void )
if (wpn != -1)
{
- return (damage_type( you.inv[wpn].base_type, you.inv[wpn].sub_type ));
+ return (get_vorpal_type(you.inv[wpn]));
}
- else if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS
+ else if (you.equip[EQ_GLOVES] == -1 &&
+ (you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS
|| you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON
|| you.mutation[MUT_CLAWS]
|| you.species == SP_TROLL
- || you.species == SP_GHOUL)
+ || you.species == SP_GHOUL))
{
return (DVORP_SLICING);
}
@@ -609,6 +858,20 @@ int player_res_magic(void)
return rm;
}
+int player_res_steam(bool calc_unid)
+{
+ int res = 0;
+
+ if (you.species == SP_PALE_DRACONIAN && you.experience_level > 5)
+ res += 2;
+
+ if (player_equip(EQ_BODY_ARMOUR, ARM_STEAM_DRAGON_ARMOUR))
+ res += 2;
+
+ return (res + player_res_fire(calc_unid) / 2);
+}
+
+
int player_res_fire(bool calc_unid)
{
int rf = 0;
@@ -735,6 +998,46 @@ int player_res_cold(bool calc_unid)
return (rc);
}
+int player_res_acid(bool consider_unidentified_gear)
+{
+ int res = 0;
+ if (!transform_changed_physiology())
+ {
+ if (you.species == SP_GOLDEN_DRACONIAN
+ && you.experience_level >= 7)
+ res += 2;
+
+ res += you.mutation[MUT_YELLOW_SCALES] * 2 / 3;
+ }
+
+ if (wearing_amulet(AMU_RESIST_CORROSION, consider_unidentified_gear))
+ res++;
+
+ return (res);
+}
+
+// Returns a factor X such that post-resistance acid damage can be calculated
+// as pre_resist_damage * X / 100.
+int player_acid_resist_factor()
+{
+ int res = player_res_acid();
+
+ int factor = 100;
+
+ if (res == 1)
+ factor = 50;
+ else if (res == 2)
+ factor = 34;
+ else if (res > 2)
+ {
+ factor = 30;
+ while (res-- > 2 && factor >= 20)
+ factor = factor * 90 / 100;
+ }
+
+ return (factor);
+}
+
int player_res_electricity(bool calc_unid)
{
int re = 0;
@@ -774,6 +1077,35 @@ int player_res_electricity(bool calc_unid)
return (re);
} // end player_res_electricity()
+// Does the player resist asphyxiation?
+bool player_res_asphyx()
+{
+ // The undead are immune to asphyxiation, or so we'll assume.
+ if (you.is_undead)
+ return (true);
+
+ switch (you.attribute[ATTR_TRANSFORMATION])
+ {
+ case TRAN_LICH:
+ case TRAN_STATUE:
+ case TRAN_SERPENT_OF_HELL:
+ case TRAN_AIR:
+ return (true);
+ }
+ return (false);
+}
+
+bool player_control_teleport(bool calc_unid) {
+ return ( you.duration[DUR_CONTROL_TELEPORT] ||
+ player_equip(EQ_RINGS, RING_TELEPORT_CONTROL, calc_unid) ||
+ you.mutation[MUT_TELEPORT_CONTROL] );
+}
+
+int player_res_torment(bool)
+{
+ return (you.is_undead || you.mutation[MUT_TORMENT_RESISTANCE]);
+}
+
// funny that no races are susceptible to poisons {dlb}
int player_res_poison(bool calc_unid)
{
@@ -999,6 +1331,9 @@ int player_prot_life(bool calc_unid)
{
int pl = 0;
+ if (wearing_amulet(AMU_WARDING, calc_unid))
+ ++pl;
+
// rings
pl += player_equip( EQ_RINGS, RING_LIFE_PROTECTION, calc_unid );
@@ -1167,20 +1502,13 @@ int player_AC(void)
// which uses "plus2"... since not all members have the same
// AC value, we use special cases. -- bwr
if (i == EQ_HELMET
- && (cmp_helmet_type( you.inv[ item ], THELM_CAP )
- || cmp_helmet_type( you.inv[ item ], THELM_WIZARD_HAT )
- || cmp_helmet_type( you.inv[ item ], THELM_SPECIAL )))
+ && (get_helmet_type(you.inv[ item ]) == THELM_CAP
+ || get_helmet_type(you.inv[ item ]) == THELM_WIZARD_HAT
+ || get_helmet_type(you.inv[ item ]) == THELM_SPECIAL))
{
continue;
}
- if (i == EQ_BOOTS
- && (you.inv[ item ].plus2 == TBOOT_NAGA_BARDING
- || you.inv[ item ].plus2 == TBOOT_CENTAUR_BARDING))
- {
- AC += 3;
- }
-
int racial_bonus = 0; // additional levels of armour skill
const unsigned long armour_race = get_equip_race( you.inv[ item ] );
const int ac_value = property( you.inv[ item ], PARM_AC );
@@ -1386,7 +1714,7 @@ int player_AC(void)
bool is_light_armour( const item_def &item )
{
- if (cmp_equip_race( item, ISFLAG_ELVEN ))
+ if (get_equip_race(item) == ISFLAG_ELVEN)
return (true);
switch (item.sub_type)
@@ -1434,6 +1762,56 @@ bool player_is_shapechanged(void)
return (true);
}
+// psize defaults to PSIZE_TORSO, which checks the part of the body
+// that wears armour and wields weapons (which is different for some hybrids).
+// base defaults to "false", meaning consider our current size, not our
+// natural one.
+size_type player_size( int psize, bool base )
+{
+ size_type ret = (base) ? SIZE_CHARACTER : transform_size( psize );
+
+ if (ret == SIZE_CHARACTER)
+ {
+ // transformation has size of character's species:
+ switch (you.species)
+ {
+ case SP_OGRE:
+ case SP_OGRE_MAGE:
+ case SP_TROLL:
+ ret = SIZE_LARGE;
+ break;
+
+ case SP_NAGA:
+ // Most of their body is on the ground giving them a low profile.
+ if (psize == PSIZE_TORSO || psize == PSIZE_PROFILE)
+ ret = SIZE_MEDIUM;
+ else
+ ret = SIZE_BIG;
+ break;
+
+ case SP_CENTAUR:
+ ret = (psize == PSIZE_TORSO) ? SIZE_MEDIUM : SIZE_BIG;
+ break;
+
+ case SP_SPRIGGAN:
+ ret = SIZE_LITTLE;
+ break;
+
+ case SP_HALFLING:
+ case SP_GNOME:
+ case SP_KOBOLD:
+ ret = SIZE_SMALL;
+ break;
+
+ default:
+ ret = SIZE_MEDIUM;
+ break;
+ }
+ }
+
+ return (ret);
+}
+
int player_evasion(void)
{
int ev = 10;
@@ -1550,6 +1928,12 @@ int player_mag_abil(bool is_weighted)
return ((is_weighted) ? ((ma * you.intel) / 10) : ma);
} // end player_mag_abil()
+// Returns the shield the player is wearing, or NULL if none.
+item_def *player_shield()
+{
+ return player_slot_item(EQ_SHIELD);
+}
+
int player_shield_class(void) //jmf: changes for new spell
{
int base_shield = 0;
@@ -1619,7 +2003,7 @@ unsigned char player_see_invis(bool calc_unid)
// This does NOT do line of sight! It checks the monster's visibility
// with repect to the players perception, but doesn't do walls or range...
// to find if the square the monster is in is visible see mons_near().
-bool player_monster_visible( struct monsters *mon )
+bool player_monster_visible( const monsters *mon )
{
if (mons_has_ench( mon, ENCH_SUBMERGED )
|| (mons_has_ench( mon, ENCH_INVIS ) && !player_see_invis()))
@@ -1670,7 +2054,7 @@ int burden_change(void)
}
else
{
- you.burden += mass_item( you.inv[bu] ) * you.inv[bu].quantity;
+ you.burden += item_mass( you.inv[bu] ) * you.inv[bu].quantity;
}
}
@@ -2072,7 +2456,7 @@ void level_change(void)
case SP_PALE_DRACONIAN:
case SP_UNK0_DRACONIAN:
case SP_UNK1_DRACONIAN:
- case SP_UNK2_DRACONIAN:
+ case SP_BASE_DRACONIAN:
if (you.experience_level == 7)
{
switch (you.species)
@@ -2108,7 +2492,7 @@ void level_change(void)
break;
case SP_UNK0_DRACONIAN:
case SP_UNK1_DRACONIAN:
- case SP_UNK2_DRACONIAN:
+ case SP_BASE_DRACONIAN:
mpr("");
break;
}
@@ -2346,6 +2730,11 @@ void level_change(void)
if (you.experience_level > you.max_level)
you.max_level = you.experience_level;
+
+ char buf[200];
+ sprintf(buf, "HP: %d/%d MP: %d/%d",
+ you.hp, you.hp_max, you.magic_points, you.max_magic_points);
+ take_note(Note(NOTE_XP_LEVEL_CHANGE, you.experience_level, 0, buf));
if (you.religion == GOD_XOM)
Xom_acts(true, you.experience_level, true);
@@ -2359,7 +2748,7 @@ void level_change(void)
// - 12mar2000 {dlb}
int check_stealth(void)
{
- if (you.special_wield == SPWLD_SHADOW)
+ if (you.special_wield == SPWLD_SHADOW || you.berserker)
return (0);
int stealth = you.dex * 3;
@@ -2408,9 +2797,9 @@ int check_stealth(void)
const int boots = you.equip[EQ_BOOTS];
if (arm != -1 && !player_light_armour())
- stealth -= (mass_item( you.inv[arm] ) / 10);
+ stealth -= (item_mass( you.inv[arm] ) / 10);
- if (cloak != -1 && cmp_equip_race( you.inv[cloak], ISFLAG_ELVEN ))
+ if (cloak != -1 && get_equip_race(you.inv[cloak]) == ISFLAG_ELVEN)
stealth += 20;
if (boots != -1)
@@ -2418,7 +2807,7 @@ int check_stealth(void)
if (get_armour_ego_type( you.inv[boots] ) == SPARM_STEALTH)
stealth += 50;
- if (cmp_equip_race( you.inv[boots], ISFLAG_ELVEN ))
+ if (get_equip_race(you.inv[boots]) == ISFLAG_ELVEN)
stealth += 20;
}
@@ -2435,7 +2824,7 @@ int check_stealth(void)
stealth /= 2; // splashy-splashy
}
- // Radiating silence is the negative compliment of shouting all the
+ // Radiating silence is the negative complement of shouting all the
// time... a sudden change from background noise to no noise is going
// to clue anything in to the fact that something is very wrong...
// a personal silence spell would naturally be different, but this
@@ -2580,9 +2969,6 @@ void display_char_status(void)
if (you.duration[DUR_SILENCE]) //jmf: added 27mar2000
mpr( "You radiate silence." );
- if (you.duration[DUR_INFECTED_SHUGGOTH_SEED]) //jmf: added 19mar2000
- mpr( "You are infected with a shuggoth parasite." );
-
if (you.duration[DUR_STONESKIN])
mpr( "Your skin is tough as stone." );
@@ -2604,9 +2990,9 @@ void display_char_status(void)
if (you.slow && you.haste)
mpr( "You are under both slowing and hasting effects." );
else if (you.slow)
- mpr( "You are moving very slowly." );
+ mpr( "You actions are slowed." );
else if (you.haste)
- mpr( "You are moving very quickly." );
+ mpr( "You actions are hasted." );
if (you.might)
mpr( "You are mighty." );
@@ -2668,6 +3054,92 @@ void display_char_status(void)
: "weak " );
mpr(info);
}
+
+ int move_cost = (player_speed() * player_movement_speed()) / 10;
+ if ( you.slow )
+ move_cost *= 2;
+
+ const bool water = player_in_water();
+ const bool swim = player_is_swimming();
+
+ const bool lev = player_is_levitating();
+ const bool fly = (lev && you.duration[DUR_CONTROLLED_FLIGHT]);
+ const bool swift = (you.duration[DUR_SWIFTNESS] > 0);
+ snprintf( info, INFO_SIZE,
+ "Your %s speed is %s%s%s.",
+ // order is important for these:
+ (swim) ? "swimming" :
+ (water) ? "wading" :
+ (fly) ? "flying" :
+ (lev) ? "levitating"
+ : "movement",
+
+ (water && !swim) ? "uncertain and " :
+ (!water && swift) ? "aided by the wind" : "",
+
+ (!water && swift) ? ((move_cost >= 10) ? ", but still "
+ : " and ")
+ : "",
+
+ (move_cost < 8) ? "very quick" :
+ (move_cost < 10) ? "quick" :
+ (move_cost == 10) ? "average" :
+ (move_cost < 13) ? "slow"
+ : "very slow" );
+ mpr(info);
+
+ // XXX Assumes no hand-and-a-half bonus. Oh well.
+ const int to_hit = calc_your_to_hit( calc_heavy_armour_penalty(false),
+ false, false, false ) * 2;
+ // Messages based largely on percentage chance of missing the
+ // average EV 10 humanoid, and very agile EV 30 (pretty much
+ // max EV for monsters currently).
+ //
+ // "awkward" - need lucky hit (less than EV)
+ // "difficult" - worse than 2 in 3
+ // "hard" - worse than fair chance
+ snprintf( info, INFO_SIZE,
+ "%s in your current equipment.",
+ (to_hit < 1) ? "You are completely incapable of fighting" :
+ (to_hit < 5) ? "Hitting even clumsy monsters is extremely awkward" :
+ (to_hit < 10) ? "Hitting average monsters is awkward" :
+ (to_hit < 15) ? "Hitting average monsters is difficult" :
+ (to_hit < 20) ? "Hitting average monsters is hard" :
+ (to_hit < 30) ? "Very agile monsters are a bit awkward to hit" :
+ (to_hit < 45) ? "Very agile monsters are a bit difficult to hit" :
+ (to_hit < 60) ? "Very agile monsters are a bit hard to hit" :
+ (to_hit < 100) ? "You feel comfortable with your ability to fight"
+ : "You feel confident with your ability to fight" );
+
+#if DEBUG_DIAGNOSTICS
+ char str_pass[INFO_SIZE];
+ snprintf( str_pass, INFO_SIZE, " (%d)", to_hit );
+ strncat( info, str_pass, INFO_SIZE );
+#endif
+ mpr(info);
+
+
+ // character evaluates their ability to sneak around:
+ const int ustealth = check_stealth();
+
+ // XXX: made these values up, probably could be better.
+ snprintf( info, INFO_SIZE, "You feel %sstealthy.",
+ (ustealth < 10) ? "extremely un" :
+ (ustealth < 20) ? "very un" :
+ (ustealth < 30) ? "un" :
+ (ustealth < 50) ? "fairly " :
+ (ustealth < 80) ? "" :
+ (ustealth < 120) ? "quite " :
+ (ustealth < 160) ? "very " :
+ (ustealth < 200) ? "extremely "
+ : "incredibly " );
+
+#if DEBUG_DIAGNOSTICS
+ snprintf( str_pass, INFO_SIZE, " (%d)", ustealth );
+ strncat( info, str_pass, INFO_SIZE );
+#endif
+
+ mpr( info );
} // end display_char_status()
void redraw_skill(const char your_name[kNameLen], const char class_name[80])
@@ -2686,11 +3158,11 @@ void redraw_skill(const char your_name[kNameLen], const char class_name[80])
char name_buff[kNameLen];
strncpy( name_buff, your_name, kNameLen );
- // squeeze name if required, the "- 8" is too not squueze too much
+ // squeeze name if required, the "- 8" is too not squeeze too much
if (in_len > 40 && (name_len - 8) > (in_len - 40))
- name_buff[ name_len - (in_len - 40) - 1 ] = '\0';
+ name_buff[ name_len - (in_len - 40) - 1 ] = 0;
else
- name_buff[ kNameLen - 1 ] = '\0';
+ name_buff[ kNameLen - 1 ] = 0;
snprintf( print_it, sizeof(print_it), "%s, %s", name_buff, class_name );
}
@@ -2698,7 +3170,7 @@ void redraw_skill(const char your_name[kNameLen], const char class_name[80])
for (int i = strlen(print_it); i < 41; i++)
print_it[i] = ' ';
- print_it[40] = '\0';
+ print_it[40] = 0;
#ifdef DOS_TERM
window(1, 1, 80, 25);
@@ -2706,7 +3178,7 @@ void redraw_skill(const char your_name[kNameLen], const char class_name[80])
gotoxy(40, 1);
textcolor( LIGHTGREY );
- cprintf( print_it );
+ cprintf( "%s", print_it );
} // end redraw_skill()
// Note that this function only has the one static buffer, so if you
@@ -2758,7 +3230,7 @@ char *species_name( int speci, int level, bool genus, bool adj, bool cap )
break;
case SP_UNK0_DRACONIAN:
case SP_UNK1_DRACONIAN:
- case SP_UNK2_DRACONIAN:
+ case SP_BASE_DRACONIAN:
default:
strcpy( species_buff, "Draconian" );
break;
@@ -2891,6 +3363,26 @@ char *species_name( int speci, int level, bool genus, bool adj, bool cap )
return (species_buff);
} // end species_name()
+bool player_res_corrosion(bool calc_unid)
+{
+ return (player_equip(EQ_AMULET, AMU_RESIST_CORROSION, calc_unid)
+ || player_equip_ego_type(EQ_CLOAK, SPARM_PRESERVATION));
+}
+
+bool player_item_conserve(bool calc_unid)
+{
+ return (player_equip(EQ_AMULET, AMU_CONSERVATION, calc_unid)
+ || player_equip_ego_type(EQ_CLOAK, SPARM_PRESERVATION));
+}
+
+int player_mental_clarity(bool calc_unid)
+{
+ const int ret = 3 * player_equip(EQ_AMULET, AMU_CLARITY, calc_unid)
+ + you.mutation[ MUT_CLARITY ];
+
+ return ((ret > 3) ? 3 : ret);
+}
+
bool wearing_amulet(char amulet, bool calc_unid)
{
if (amulet == AMU_CONTROLLED_FLIGHT
@@ -3154,7 +3646,7 @@ void modify_stat(unsigned char which_stat, char amount, bool suppress_msg)
if (amount == 0)
return;
- // Stop running/travel if a stat drops.
+ // Stop delays if a stat drops.
if (amount < 0)
interrupt_activity( AI_STAT_CHANGE );
@@ -3204,15 +3696,24 @@ void modify_stat(unsigned char which_stat, char amount, bool suppress_msg)
return;
} // end modify_stat()
-void dec_hp(int hp_loss, bool fatal)
+void dec_hp(int hp_loss, bool fatal, const char *aux)
{
+ if (!fatal && you.hp < 1)
+ you.hp = 1;
+
+ if (!fatal && hp_loss >= you.hp)
+ hp_loss = you.hp - 1;
+
if (hp_loss < 1)
return;
- you.hp -= hp_loss;
-
- if (!fatal && you.hp < 1)
- you.hp = 1;
+ // If it's not fatal, use ouch() so that notes can be taken. If it IS
+ // fatal, somebody else is doing the bookkeeping, and we don't want to mess
+ // with that.
+ if (!fatal && aux)
+ ouch(hp_loss, -1, KILLED_BY_SOMETHING, aux);
+ else
+ you.hp -= hp_loss;
you.redraw_hit_points = 1;
@@ -3229,6 +3730,7 @@ void dec_mp(int mp_loss)
if (you.magic_points < 0)
you.magic_points = 0;
+ take_note(Note(NOTE_MP_CHANGE, you.magic_points, you.max_magic_points));
you.redraw_magic_points = 1;
return;
@@ -3276,6 +3778,7 @@ void inc_mp(int mp_gain, bool max_too)
if (you.magic_points > you.max_magic_points)
you.magic_points = you.max_magic_points;
+ take_note(Note(NOTE_MP_CHANGE, you.magic_points, you.max_magic_points));
you.redraw_magic_points = 1;
return;
@@ -3296,6 +3799,9 @@ void inc_hp(int hp_gain, bool max_too)
if (you.hp > you.hp_max)
you.hp = you.hp_max;
+ // to avoid message spam, no information when HP increases
+ // take_note(Note(NOTE_HP_CHANGE, you.hp, you.hp_max));
+
you.redraw_hit_points = 1;
} // end inc_hp()
@@ -3337,6 +3843,7 @@ void inc_max_hp( int hp_gain )
you.base_hp2 += hp_gain;
calc_hp();
+ take_note(Note(NOTE_MAXHP_CHANGE, you.hp_max));
you.redraw_hit_points = 1;
}
@@ -3345,6 +3852,7 @@ void dec_max_hp( int hp_loss )
you.base_hp2 -= hp_loss;
calc_hp();
+ take_note(Note(NOTE_MAXHP_CHANGE, you.hp_max));
you.redraw_hit_points = 1;
}
@@ -3353,6 +3861,7 @@ void inc_max_mp( int mp_gain )
you.base_magic_points2 += mp_gain;
calc_mp();
+ take_note(Note(NOTE_MAXMP_CHANGE, you.max_magic_points));
you.redraw_magic_points = 1;
}
@@ -3361,6 +3870,7 @@ void dec_max_mp( int mp_loss )
you.base_magic_points2 -= mp_loss;
calc_mp();
+ take_note(Note(NOTE_MAXMP_CHANGE, you.max_magic_points));
you.redraw_magic_points = 1;
}
@@ -3372,6 +3882,7 @@ void deflate_hp(int new_level, bool floor)
else if (!floor && you.hp > new_level)
you.hp = new_level;
+ // take_note(Note(NOTE_HP_CHANGE, you.hp, you.hp_max));
// must remain outside conditional, given code usage {dlb}
you.redraw_hit_points = 1;
@@ -3394,6 +3905,9 @@ void set_hp(int new_amount, bool max_too)
if (you.hp > you.hp_max)
you.hp = you.hp_max;
+ // take_note(Note(NOTE_HP_CHANGE, you.hp, you.hp_max));
+ if ( max_too )
+ take_note(Note(NOTE_MAXHP_CHANGE, you.hp_max));
// must remain outside conditional, given code usage {dlb}
you.redraw_hit_points = 1;
@@ -3416,7 +3930,10 @@ void set_mp(int new_amount, bool max_too)
if (you.magic_points > you.max_magic_points)
you.magic_points = you.max_magic_points;
-
+
+ take_note(Note(NOTE_MP_CHANGE, you.magic_points, you.max_magic_points));
+ if ( max_too )
+ take_note(Note(NOTE_MAXMP_CHANGE, you.max_magic_points));
// must remain outside conditional, given code usage {dlb}
you.redraw_magic_points = 1;
@@ -3557,65 +4074,6 @@ const char *get_class_name( int which_job )
return (Class_Name_List[ which_job ]);
}
-/* ******************************************************************
-
-// this function is solely called by a commented out portion of
-// player::level_change() and is a bit outta whack with the
-// current codebase - probably should be struck as well 19may2000 {dlb}
-
-void priest_spells( int priest_pass[10], char religious )
-{
-
- switch ( religious )
- {
- case GOD_ZIN:
- priest_pass[1] = SPELL_LESSER_HEALING;
- priest_pass[2] = SPELL_REPEL_UNDEAD;
- priest_pass[3] = SPELL_HEAL_OTHER;
- priest_pass[4] = SPELL_PURIFICATION;
- priest_pass[5] = SPELL_GREATER_HEALING;
- priest_pass[6] = SPELL_SMITING;
- priest_pass[7] = SPELL_HOLY_WORD;
- priest_pass[8] = SPELL_REMOVE_CURSE;
- priest_pass[9] = SPELL_GUARDIAN;
- break;
-
- case GOD_SHINING_ONE:
- priest_pass[1] = SPELL_REPEL_UNDEAD;
- priest_pass[2] = SPELL_LESSER_HEALING;
- priest_pass[3] = SPELL_HEAL_OTHER;
- priest_pass[4] = SPELL_PURIFICATION;
- priest_pass[5] = SPELL_ABJURATION_II;
- priest_pass[6] = SPELL_THUNDERBOLT;
- priest_pass[7] = SPELL_SHINING_LIGHT;
- priest_pass[8] = SPELL_SUMMON_DAEVA;
- priest_pass[9] = SPELL_FLAME_OF_CLEANSING;
- break;
-
- case GOD_ELYVILON:
- priest_pass[1] = SPELL_LESSER_HEALING;
- priest_pass[2] = SPELL_HEAL_OTHER;
- priest_pass[3] = SPELL_PURIFICATION;
- priest_pass[4] = 93; // restore abilities
- priest_pass[5] = SPELL_GREATER_HEALING;
- priest_pass[6] = 94; // another healing spell
- priest_pass[7] = 95; // something else
- priest_pass[8] = -1; //
- priest_pass[9] = -1; //
- break;
- }
-
-}
-
-// Spells to be added: (+ renamed!)
-// holy berserker
-// 87 Pestilence
-// 93 Restore Abilities
-// 94 something else healing
-// 95 something else
-
-****************************************************************** */
-
void contaminate_player(int change, bool statusOnly)
{
// get current contamination level
@@ -3839,7 +4297,7 @@ void haste_player( int amount )
if (you.haste > 80 + 20 * amu_eff)
you.haste = 80 + 20 * amu_eff;
- naughty( NAUGHTY_STIMULANTS, 4 + random2(4) );
+ did_god_conduct( DID_STIMULANTS, 4 + random2(4) );
}
void dec_haste_player( void )
@@ -3911,161 +4369,198 @@ void rot_player( int amount )
}
}
-void run_macro(const char *macroname)
+//////////////////////////////////////////////////////////////////////////////
+// player
+
+player::player()
{
- if (you.activity != ACT_NONE && you.activity != ACT_MACRO)
- return;
+ init();
+}
-#ifdef CLUA_BINDINGS
- if (!clua)
- {
- mpr("Lua not initialized", MSGCH_DIAGNOSTICS);
- you.activity = ACT_NONE;
- return;
- }
+// player struct initialization
+void player::init()
+{
+ birth_time = time( NULL );
+ real_time = 0;
+ num_turns = 0;
- if (!clua.callbooleanfn(false, "c_macro", "s", macroname))
- {
- if (clua.error.length())
- mpr(clua.error.c_str());
- you.activity = ACT_NONE;
- }
- else
- {
- you.activity = ACT_MACRO;
- }
+#ifdef WIZARD
+ wizard = (Options.wiz_mode == WIZ_YES) ? true : false;
#else
- you.activity = ACT_NONE;
+ wizard = false;
#endif
-}
-void perform_activity()
-{
- switch (you.activity)
+ your_name[0] = 0;
+
+ berserk_penalty = 0;
+ berserker = 0;
+ conf = 0;
+ confusing_touch = 0;
+ deaths_door = 0;
+ disease = 0;
+ elapsed_time = 0;
+ exhausted = 0;
+ haste = 0;
+ invis = 0;
+ levitation = 0;
+ might = 0;
+ paralysis = 0;
+ poison = 0;
+ rotting = 0;
+ fire_shield = 0;
+ slow = 0;
+ special_wield = SPWLD_NONE;
+ sure_blade = 0;
+ synch_time = 0;
+
+ base_hp = 5000;
+ base_hp2 = 5000;
+ base_magic_points = 5000;
+ base_magic_points2 = 5000;
+
+ magic_points_regeneration = 0;
+ strength = 0;
+ max_strength = 0;
+ intel = 0;
+ max_intel = 0;
+ dex = 0;
+ max_dex = 0;
+ experience = 0;
+ experience_level = 1;
+ max_level = 1;
+ char_class = JOB_UNKNOWN;
+
+ hunger = 6000;
+ hunger_state = HS_SATIATED;
+
+ gold = 0;
+ // speed = 10; // 0.75; // unused
+
+ burden = 0;
+ burden_state = BS_UNENCUMBERED;
+
+ spell_no = 0;
+
+ your_level = 0;
+ level_type = LEVEL_DUNGEON;
+ where_are_you = BRANCH_MAIN_DUNGEON;
+ char_direction = DIR_DESCENDING;
+
+ prev_targ = MHITNOT;
+ pet_target = MHITNOT;
+
+ x_pos = 0;
+ y_pos = 0;
+
+ running.clear();
+ travel_x = 0;
+ travel_y = 0;
+
+ religion = GOD_NO_GOD;
+ piety = 0;
+
+ gift_timeout = 0;
+
+ for (int i = 0; i < MAX_NUM_GODS; i++)
{
- case ACT_MULTIDROP:
- drop();
- break;
- case ACT_MACRO:
- run_macro();
- break;
- default:
- break;
+ penance[i] = 0;
+ worshipped[i] = 0;
+ num_gifts[i] = 0;
}
-}
-#ifdef CLUA_BINDINGS
-static const char *activity_interrupt_name(ACT_INTERRUPT ai)
-{
- switch (ai)
+ ghost.name[0] = 0;
+
+ for (int i = 0; i < NUM_GHOST_VALUES; i++)
+ ghost.values[i] = 0;
+
+ for (int i = EQ_WEAPON; i < NUM_EQUIP; i++)
+ equip[i] = -1;
+
+ for (int i = 0; i < 25; i++)
+ spells[i] = SPELL_NO_SPELL;
+
+ for (int i = 0; i < 52; i++)
{
- case AI_FORCE_INTERRUPT: return "force";
- case AI_KEYPRESS: return "keypress";
- case AI_FULL_HP: return "full_hp";
- case AI_FULL_MP: return "full_mp";
- case AI_STATUE: return "statue";
- case AI_HUNGRY: return "hungry";
- case AI_MESSAGE: return "message";
- case AI_HP_LOSS: return "hp_loss";
- case AI_BURDEN_CHANGE: return "burden";
- case AI_STAT_CHANGE: return "stat";
- case AI_SEE_MONSTER: return "monster";
- case AI_TELEPORT: return "teleport";
- default: return "unknown";
+ spell_letter_table[i] = -1;
+ ability_letter_table[i] = ABIL_NON_ABILITY;
}
-}
-static const char *activity_names[] = {
- "",
- "multidrop",
- "run",
- "travel",
- "macro"
-};
+ for (int i = 0; i < 100; i++)
+ mutation[i] = 0;
-static const char *activity_name(int act)
-{
- if (act < ACT_NONE || act >= ACT_ACTIVITY_COUNT)
- return NULL;
- return activity_names[act];
-}
-#endif
+ for (int i = 0; i < 100; i++)
+ demon_pow[i] = 0;
-static void kill_activity()
-{
- if (you.running)
- stop_running();
- you.activity = ACT_NONE;
-}
+ for (int i = 0; i < 50; i++)
+ had_book[i] = 0;
-static bool userdef_interrupt_activity( ACT_INTERRUPT ai,
- const activity_interrupt_t &at )
-{
-#ifdef CLUA_BINDINGS
- lua_State *ls = clua.state();
- if (!ls || ai == AI_FORCE_INTERRUPT)
+ for (int i = 0; i < 50; i++)
+ unique_items[i] = UNIQ_NOT_EXISTS;
+
+ for (int i = 0; i < NO_UNRANDARTS; i++)
+ set_unrandart_exist(i, 0);
+
+ for (int i = 0; i < 50; i++)
{
- if (ai == AI_FORCE_INTERRUPT || you.activity == ACT_MACRO)
- kill_activity();
- return true;
+ skills[i] = 0;
+ skill_points[i] = 0;
+ skill_order[i] = MAX_SKILL_ORDER;
+ practise_skill[i] = 1;
}
-
- const char *interrupt_name = activity_interrupt_name(ai);
- const char *act_name = activity_name(you.activity);
- bool ran = clua.callfn("c_interrupt_activity", "1:ssA",
- act_name, interrupt_name, &at);
- if (ran)
- {
- // If the function returned nil, we want to cease processing.
- if (lua_isnil(ls, -1))
- {
- lua_pop(ls, 1);
- return false;
- }
+ skill_cost_level = 1;
+ total_skill_points = 0;
- bool stopact = lua_toboolean(ls, -1);
- lua_pop(ls, 1);
- if (stopact)
- {
- kill_activity();
- return true;
- }
- }
+ for (int i = 0; i < 30; i++)
+ attribute[i] = 0;
- if (you.activity == ACT_MACRO &&
- clua.callbooleanfn(true, "c_interrupt_macro",
- "sA", interrupt_name, &at))
+ for (int i = 0; i < ENDOFPACK; i++)
{
- kill_activity();
+ inv[i].quantity = 0;
+ inv[i].base_type = OBJ_WEAPONS;
+ inv[i].sub_type = WPN_CLUB;
+ inv[i].plus = 0;
+ inv[i].plus2 = 0;
+ inv[i].special = 0;
+ inv[i].colour = 0;
+ set_ident_flags( inv[i], ISFLAG_IDENT_MASK );
+
+ inv[i].x = -1;
+ inv[i].y = -1;
+ inv[i].link = i;
}
-#else
- if (you.activity == ACT_MACRO)
- kill_activity();
-#endif
- return true;
+ for (int i = 0; i < NUM_DURATIONS; i++)
+ duration[i] = 0;
+
+ exp_available = 25;
}
-void interrupt_activity( ACT_INTERRUPT ai, const activity_interrupt_t &at )
+bool player::is_valid() const
{
- if (you.running && !you.activity)
- you.activity = you.running > 0? ACT_RUNNING : ACT_TRAVELING;
+ // Check if there's a name.
+ return (your_name[0] != 0);
+}
- if (!you.activity)
- return;
+std::string player::short_desc() const
+{
+ std::string desc;
+ desc += your_name;
+ desc += ", a level ";
- if (!userdef_interrupt_activity(ai, at) || !you.activity)
- {
- if (you.activity == ACT_RUNNING || you.activity == ACT_TRAVELING)
- you.activity = ACT_NONE;
- return;
- }
-
- if (!ai || (Options.activity_interrupts[ you.activity ] & ai)) {
- kill_activity();
- }
+ char st_prn[20];
+ itoa(experience_level, st_prn, 10);
+ desc += st_prn;
- if (you.activity == ACT_RUNNING || you.activity == ACT_TRAVELING)
- you.activity = ACT_NONE;
+ desc += " ";
+ desc += species_name(species, experience_level);
+ desc += " ";
+ desc += class_name;
+
+ return (desc);
+}
+
+bool player::operator < (const player &p) const
+{
+ return (strcmp(your_name, p.your_name) < 0);
}
diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h
index 1d99d6b154..656a7b1faf 100644
--- a/crawl-ref/source/player.h
+++ b/crawl-ref/source/player.h
@@ -3,6 +3,8 @@
* Summary: Player related functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -14,9 +16,14 @@
#include "externs.h"
+bool move_player_to_grid( int x, int y, bool stepped, bool allow_shift,
+ bool force );
+
+bool player_in_mappable_area(void);
bool player_in_branch( int branch );
bool player_in_hell( void );
+int get_player_wielded_weapon();
int player_equip( int slot, int sub_type, bool calc_unid = true );
int player_equip_ego_type( int slot, int sub_type );
int player_damage_type( void );
@@ -48,6 +55,7 @@ bool player_is_levitating(void);
* *********************************************************************** */
bool player_under_penance(void);
+int player_wielded_item();
/* ***********************************************************************
* called from: ability - acr - fight - food - it_use2 - item_use - items -
@@ -106,13 +114,6 @@ unsigned char player_energy(void);
int player_evasion(void);
-#if 0
-/* ***********************************************************************
- * called from: acr - spells1
- * *********************************************************************** */
-unsigned char player_fast_run(void);
-#endif
-
/* ***********************************************************************
* called from: acr - spells1
* *********************************************************************** */
@@ -147,6 +148,14 @@ int player_regen(void);
* called from: fight - files - it_use2 - misc - ouch - spells - spells2
* *********************************************************************** */
int player_res_cold(bool calc_unid = true);
+int player_res_acid(bool consider_unidentified_gear = true);
+int player_acid_resist_factor();
+
+int player_res_torment(bool calc_unid = true);
+
+bool player_res_corrosion(bool calc_unid = true);
+bool player_item_conserve(bool calc_unid = true);
+int player_mental_clarity(bool calc_unid = true);
/* ***********************************************************************
@@ -159,6 +168,7 @@ int player_res_electricity(bool calc_unid = true);
* called from: acr - fight - misc - ouch - spells
* *********************************************************************** */
int player_res_fire(bool calc_unid = true);
+int player_res_steam(bool calc_unid = true);
/* ***********************************************************************
@@ -167,8 +177,12 @@ int player_res_fire(bool calc_unid = true);
* *********************************************************************** */
int player_res_poison(bool calc_unid = true);
+bool player_control_teleport(bool calc_unid = true);
+
int player_res_magic(void);
+bool player_res_asphyx();
+
/* ***********************************************************************
* called from: beam - chardump - fight - misc - output
* *********************************************************************** */
@@ -278,7 +292,7 @@ int slaying_bonus(char which_affected);
* spells3
* *********************************************************************** */
unsigned char player_see_invis(bool calc_unid = true);
-bool player_monster_visible( struct monsters *mon );
+bool player_monster_visible( const monsters *mon );
/* ***********************************************************************
@@ -339,7 +353,7 @@ bool player_genus( unsigned char which_genus,
* called from: ability - effects - fight - it_use3 - ouch - spell -
* spells - spells2 - spells3 - spells4
* *********************************************************************** */
-void dec_hp(int hp_loss, bool fatal);
+void dec_hp(int hp_loss, bool fatal, const char *aux = NULL);
/* ***********************************************************************
@@ -436,16 +450,12 @@ void dec_disease_player();
void rot_player( int amount );
-void perform_activity();
-
-void interrupt_activity( ACT_INTERRUPT ai,
- const activity_interrupt_t &a = activity_interrupt_t() );
-
-// last updated 15sep2001 {bwr}
-/* ***********************************************************************
- * called from:
- * *********************************************************************** */
bool player_has_spell( int spell );
+size_type player_size( int psize = PSIZE_TORSO, bool base = false );
+
+bool player_weapon_wielded();
+item_def *player_weapon();
+item_def *player_shield();
void run_macro(const char *macroname = NULL);
diff --git a/crawl-ref/source/prebuilt/levcomp.lex.cc b/crawl-ref/source/prebuilt/levcomp.lex.cc
new file mode 100644
index 0000000000..07ad28b7ac
--- /dev/null
+++ b/crawl-ref/source/prebuilt/levcomp.lex.cc
@@ -0,0 +1,2522 @@
+#line 2 "levcomp.lex.cc"
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+#include <errno.h>
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator). This
+ * avoids problems with code like:
+ *
+ * if ( condition_holds )
+ * yyless( 5 );
+ * else
+ * do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ *yy_cp = yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+ };
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+
+#define YY_USES_REJECT
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern int yylineno;
+int yylineno = 1;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yytext_ptr = yy_bp; \
+ yyleng = (int) (yy_cp - yy_bp); \
+ yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 43
+#define YY_END_OF_BUFFER 44
+static yyconst short int yy_acclist[944] =
+ { 0,
+ 3, 3, 44, 42, 43, 41, 42, 43, 41, 43,
+ 37, 42, 43, 36, 42, 43, 38, 42, 43, 42,
+ 43, 42, 43, 42, 43, 42, 43, 42, 43, 42,
+ 43, 42, 43, 42, 43, 42, 43, 42, 43, 42,
+ 43, 42, 43, 42, 43, 42, 43, 42, 43, 5,
+ 42, 43, 42, 43, 42, 43, 3, 42, 43, 3,
+ 36, 42, 43, 3, 38, 42, 43, 3, 42, 43,
+ 3, 42, 43, 3, 42, 43, 3, 42, 43, 3,
+ 42, 43, 3, 42, 43, 3, 42, 43, 3, 42,
+ 43, 3, 42, 43, 3, 42, 43, 3, 42, 43,
+
+ 3, 42, 43, 3, 42, 43, 3, 42, 43, 3,
+ 42, 43, 3, 42, 43, 3, 5, 42, 43, 3,
+ 42, 43, 3, 42, 43, 42, 43, 40, 41, 43,
+ 41, 42, 43, 37, 42, 43, 36, 42, 43, 38,
+ 42, 43, 42, 43, 42, 43, 42, 43, 42, 43,
+ 42, 43, 42, 43, 42, 43, 42, 43, 42, 43,
+ 42, 43, 42, 43, 42, 43, 42, 43, 42, 43,
+ 42, 43, 5, 42, 43, 42, 43, 42, 43, 42,
+ 43, 22, 41, 42, 43, 21, 41, 43, 41, 42,
+ 43, 20, 37, 42, 43, 36, 42, 43, 38, 42,
+
+ 43, 42, 43, 42, 43, 42, 43, 42, 43, 42,
+ 43, 42, 43, 42, 43, 42, 43, 42, 43, 42,
+ 43, 42, 43, 42, 43, 42, 43, 42, 43, 42,
+ 43, 5, 42, 43, 42, 43, 42, 43, 17, 41,
+ 42, 43, 18, 41, 43, 41, 42, 43, 16, 36,
+ 42, 43, 16, 38, 42, 43, 16, 42, 43, 16,
+ 42, 43, 16, 42, 43, 16, 42, 43, 16, 42,
+ 43, 16, 42, 43, 16, 42, 43, 16, 42, 43,
+ 16, 42, 43, 16, 42, 43, 16, 42, 43, 16,
+ 42, 43, 16, 42, 43, 16, 42, 43, 16, 42,
+
+ 43, 16, 42, 43, 16, 42, 43, 16, 42, 43,
+ 41, 38, 5, 5, 3, 3, 38, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 5, 2, 5, 3, 5, 3,
+ 3, 5, 3, 39, 40, 41, 38, 39, 39, 39,
+ 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
+ 39, 39, 39, 39, 5, 39, 5, 39, 5, 39,
+ 39, 41, 21, 41, 41, 38, 5, 5, 17, 41,
+ 18, 41, 41, 16, 16, 38, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+
+ 16, 16, 16, 16, 4, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 4, 3, 5, 39, 39, 39,
+ 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
+ 39, 39, 39, 39, 4, 39, 19, 19, 38, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 5, 19, 4, 19,
+ 5, 19, 19, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 4, 16, 30, 31, 3, 3, 3, 3, 3, 3,
+
+ 3, 3, 3, 3, 3, 3, 30, 3, 3, 3,
+ 3, 3, 3, 3, 3, 31, 39, 39, 39, 39,
+ 39, 39, 39, 39, 39, 39, 30, 39, 39, 39,
+ 39, 39, 39, 39, 39, 31, 39, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 30, 19,
+ 19, 19, 19, 19, 19, 19, 19, 31, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 30,
+ 16, 16, 16, 16, 16, 16, 16, 16, 31, 15,
+ 6, 13, 28, 29, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 28, 3, 3,
+
+ 29, 39, 39, 39, 15, 39, 6, 39, 39, 39,
+ 39, 13, 39, 39, 39, 39, 39, 39, 28, 39,
+ 39, 29, 39, 19, 19, 19, 15, 19, 6, 19,
+ 19, 19, 19, 13, 19, 19, 19, 19, 19, 19,
+ 19, 28, 19, 19, 29, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 28, 16, 16,
+ 29, 8, 12, 10, 3, 1, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 39,
+ 8, 39, 12, 39, 39, 10, 39, 39, 39, 39,
+ 39, 39, 39, 39, 39, 39, 39, 39, 19, 8,
+
+ 19, 12, 19, 19, 10, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 11, 9, 14, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 11, 39, 9, 39, 14, 39, 39,
+ 39, 39, 39, 39, 39, 39, 39, 39, 39, 11,
+ 19, 9, 19, 14, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 39, 39, 39, 39, 39,
+
+ 39, 39, 39, 39, 39, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 27, 26, 32, 33, 34,
+ 35, 3, 3, 27, 3, 3, 26, 3, 3, 32,
+ 3, 33, 3, 3, 34, 3, 35, 39, 27, 39,
+ 39, 26, 39, 39, 32, 39, 33, 39, 39, 34,
+ 39, 35, 39, 19, 19, 27, 19, 19, 26, 19,
+ 19, 32, 19, 33, 19, 19, 34, 19, 35, 16,
+ 16, 27, 16, 16, 26, 16, 16, 32, 16, 33,
+ 16, 16, 34, 16, 35, 24, 25, 23, 3, 3,
+
+ 24, 3, 25, 3, 23, 39, 24, 39, 25, 39,
+ 23, 39, 19, 19, 24, 19, 25, 19, 23, 16,
+ 16, 24, 16, 25, 16, 23, 3, 39, 19, 16,
+ 3, 39, 19, 16, 3, 39, 19, 16, 7, 7,
+ 39, 7, 19
+ } ;
+
+static yyconst short int yy_accept[798] =
+ { 0,
+ 1, 1, 1, 2, 3, 3, 3, 3, 3, 3,
+ 3, 4, 6, 9, 11, 14, 17, 20, 22, 24,
+ 26, 28, 30, 32, 34, 36, 38, 40, 42, 44,
+ 46, 48, 50, 53, 55, 57, 60, 64, 68, 71,
+ 74, 77, 80, 83, 86, 89, 92, 95, 98, 101,
+ 104, 107, 110, 113, 116, 120, 123, 126, 128, 131,
+ 134, 137, 140, 143, 145, 147, 149, 151, 153, 155,
+ 157, 159, 161, 163, 165, 167, 169, 171, 173, 176,
+ 178, 180, 182, 186, 189, 192, 196, 199, 202, 204,
+ 206, 208, 210, 212, 214, 216, 218, 220, 222, 224,
+
+ 226, 228, 230, 232, 235, 237, 239, 243, 246, 249,
+ 253, 257, 260, 263, 266, 269, 272, 275, 278, 281,
+ 284, 287, 290, 293, 296, 299, 302, 305, 308, 311,
+ 312, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 314, 314,
+ 315, 315, 316, 318, 319, 320, 321, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
+ 335, 336, 337, 338, 340, 341, 343, 344, 345, 345,
+ 347, 349, 350, 351, 352, 353, 354, 355, 356, 357,
+ 358, 359, 360, 361, 362, 363, 364, 365, 367, 368,
+
+ 369, 371, 372, 372, 373, 375, 376, 377, 377, 377,
+ 377, 377, 377, 377, 377, 377, 377, 377, 377, 377,
+ 377, 377, 377, 377, 378, 378, 379, 379, 381, 383,
+ 384, 385, 387, 388, 389, 390, 391, 392, 393, 394,
+ 395, 396, 397, 398, 399, 400, 401, 402, 403, 404,
+ 405, 405, 405, 405, 405, 405, 405, 405, 405, 405,
+ 405, 405, 405, 405, 405, 405, 405, 405, 406, 407,
+ 408, 409, 410, 411, 412, 413, 414, 415, 416, 417,
+ 418, 419, 420, 421, 422, 423, 424, 426, 428, 429,
+ 430, 431, 432, 433, 434, 435, 436, 437, 438, 439,
+
+ 440, 441, 442, 443, 444, 445, 447, 448, 450, 451,
+ 452, 453, 454, 455, 456, 457, 458, 459, 460, 461,
+ 462, 463, 464, 465, 466, 467, 469, 471, 473, 474,
+ 475, 476, 477, 478, 479, 480, 481, 482, 483, 484,
+ 485, 486, 487, 488, 489, 490, 491, 493, 493, 493,
+ 493, 493, 493, 493, 493, 493, 493, 493, 494, 494,
+ 494, 494, 494, 494, 494, 494, 495, 496, 497, 498,
+ 499, 500, 501, 502, 503, 504, 505, 506, 508, 509,
+ 510, 511, 512, 513, 514, 515, 517, 518, 519, 520,
+ 521, 522, 523, 524, 525, 526, 527, 529, 530, 531,
+
+ 532, 533, 534, 535, 536, 538, 539, 540, 541, 542,
+ 543, 544, 545, 546, 547, 548, 550, 551, 552, 553,
+ 554, 555, 556, 557, 559, 560, 561, 562, 563, 564,
+ 565, 566, 567, 568, 569, 571, 572, 573, 574, 575,
+ 576, 577, 578, 580, 580, 580, 580, 581, 582, 582,
+ 582, 582, 583, 583, 583, 583, 583, 583, 584, 584,
+ 585, 586, 587, 588, 589, 590, 591, 592, 593, 594,
+ 595, 596, 597, 599, 600, 602, 603, 604, 605, 607,
+ 609, 610, 611, 612, 614, 615, 616, 617, 618, 619,
+ 621, 622, 624, 625, 626, 627, 629, 631, 632, 633,
+
+ 634, 636, 637, 638, 639, 640, 641, 643, 644, 646,
+ 647, 648, 649, 650, 651, 652, 653, 654, 655, 656,
+ 657, 659, 660, 662, 662, 663, 664, 664, 665, 665,
+ 665, 665, 665, 665, 665, 665, 665, 665, 665, 665,
+ 666, 668, 669, 670, 671, 672, 673, 674, 675, 676,
+ 677, 678, 679, 680, 681, 683, 685, 686, 688, 689,
+ 690, 691, 692, 693, 694, 695, 696, 697, 698, 699,
+ 700, 702, 704, 705, 707, 708, 709, 710, 711, 712,
+ 713, 714, 715, 716, 717, 718, 719, 720, 721, 722,
+ 723, 724, 725, 726, 727, 728, 729, 730, 731, 732,
+
+ 733, 734, 734, 734, 734, 734, 734, 734, 734, 734,
+ 734, 734, 735, 736, 737, 738, 739, 740, 741, 742,
+ 743, 744, 746, 748, 750, 751, 752, 753, 754, 755,
+ 756, 757, 758, 759, 760, 762, 764, 766, 767, 768,
+ 769, 770, 771, 772, 773, 774, 775, 776, 777, 778,
+ 779, 780, 781, 782, 783, 784, 785, 786, 786, 786,
+ 786, 786, 786, 786, 786, 786, 786, 786, 787, 788,
+ 789, 790, 791, 792, 793, 794, 795, 796, 797, 798,
+ 799, 800, 801, 802, 803, 804, 805, 806, 807, 808,
+ 809, 810, 811, 812, 813, 814, 815, 816, 817, 818,
+
+ 819, 820, 821, 822, 823, 824, 825, 826, 826, 827,
+ 827, 828, 828, 829, 830, 830, 831, 832, 833, 835,
+ 836, 838, 839, 841, 843, 844, 846, 848, 849, 851,
+ 852, 854, 855, 857, 859, 860, 862, 864, 865, 867,
+ 868, 870, 871, 873, 875, 876, 878, 880, 881, 883,
+ 884, 886, 887, 889, 891, 892, 894, 896, 896, 897,
+ 898, 899, 900, 902, 904, 906, 907, 909, 911, 913,
+ 914, 916, 918, 920, 921, 923, 925, 927, 927, 928,
+ 929, 930, 931, 931, 932, 933, 934, 935, 935, 936,
+ 937, 938, 939, 940, 942, 944, 944
+
+ } ;
+
+static yyconst int yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 1, 5, 6, 6, 6, 1, 6,
+ 6, 6, 6, 7, 8, 6, 1, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 10, 1, 6,
+ 6, 6, 6, 6, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 20, 21, 22, 23, 24, 25,
+ 20, 26, 27, 28, 20, 20, 20, 20, 29, 20,
+ 6, 1, 6, 6, 30, 1, 31, 20, 32, 33,
+
+ 34, 35, 20, 36, 37, 20, 20, 38, 39, 40,
+ 41, 42, 20, 43, 44, 45, 46, 47, 48, 20,
+ 20, 20, 6, 6, 6, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst int yy_meta[49] =
+ { 0,
+ 1, 1, 2, 3, 4, 4, 3, 5, 5, 1,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5
+ } ;
+
+static yyconst short int yy_base[809] =
+ { 0,
+ 0, 44, 88, 132, 176, 220, 264, 308, 352, 396,
+ 1529, 1530, 48, 51, 1530, 1530, 1519, 1509, 1511, 1504,
+ 1500, 1512, 1496, 1500, 1491, 1508, 1484, 25, 1476, 1485,
+ 1474, 1480, 0, 46, 397, 0, 0, 1504, 1494, 1496,
+ 1487, 1488, 1484, 1496, 1480, 1484, 1475, 1492, 1468, 27,
+ 1460, 1469, 1458, 1464, 70, 51, 398, 57, 79, 82,
+ 74, 136, 137, 140, 141, 145, 146, 149, 224, 153,
+ 225, 157, 228, 403, 404, 229, 407, 312, 160, 232,
+ 408, 0, 169, 235, 242, 1530, 0, 1488, 1478, 1480,
+ 1473, 1469, 1481, 1465, 1469, 1460, 1477, 1453, 29, 1445,
+
+ 1454, 1443, 1449, 244, 141, 409, 255, 315, 318, 0,
+ 1473, 0, 1463, 1465, 1458, 1454, 1466, 1450, 1454, 1445,
+ 1462, 1438, 209, 1430, 1439, 1428, 1434, 304, 410, 321,
+ 1458, 1455, 1440, 1453, 1440, 1440, 1442, 1449, 1437, 1441,
+ 1422, 1412, 1423, 296, 1414, 1407, 1408, 0, 1426, 0,
+ 411, 0, 1441, 1438, 1423, 1433, 1435, 1422, 1422, 1424,
+ 1431, 1419, 1423, 1404, 1394, 1405, 297, 1396, 1389, 1390,
+ 60, 1530, 249, 331, 1408, 341, 412, 165, 259, 417,
+ 327, 420, 421, 424, 455, 425, 456, 459, 460, 463,
+ 464, 428, 469, 472, 477, 481, 482, 345, 485, 486,
+
+ 489, 490, 1430, 494, 501, 504, 335, 498, 508, 510,
+ 512, 233, 511, 514, 516, 520, 402, 475, 518, 521,
+ 522, 526, 527, 537, 529, 538, 541, 545, 553, 556,
+ 0, 1422, 1419, 1404, 1417, 1404, 1404, 1406, 1413, 1401,
+ 1405, 1386, 1376, 1387, 522, 1378, 1371, 1372, 1390, 531,
+ 1391, 1385, 1395, 1384, 1395, 1394, 1395, 1395, 1379, 1374,
+ 1359, 1362, 527, 1357, 1368, 1355, 1354, 1530, 1375, 1369,
+ 1374, 1378, 1367, 1378, 1377, 1378, 1378, 1362, 1357, 1342,
+ 1345, 530, 1340, 1351, 1338, 1337, 0, 577, 565, 578,
+ 587, 588, 592, 593, 596, 599, 608, 612, 615, 616,
+
+ 619, 620, 623, 624, 627, 628, 1379, 559, 530, 574,
+ 631, 442, 584, 632, 66, 581, 611, 637, 634, 603,
+ 635, 638, 640, 639, 643, 647, 1378, 657, 648, 1356,
+ 1350, 1360, 1349, 1360, 1359, 1360, 1360, 1344, 1339, 1324,
+ 1327, 627, 1322, 1333, 1320, 1319, 0, 1350, 1344, 1334,
+ 1350, 1349, 1335, 1342, 1332, 1345, 1308, 1530, 1314, 1313,
+ 1310, 1311, 1313, 1314, 1311, 1530, 1333, 1327, 1333, 1316,
+ 1332, 1331, 1317, 1324, 1314, 1327, 1290, 0, 1296, 1295,
+ 1292, 1293, 1295, 1296, 1293, 0, 673, 683, 687, 692,
+ 693, 696, 702, 703, 706, 707, 711, 716, 719, 720,
+
+ 724, 728, 731, 732, 727, 735, 723, 740, 736, 737,
+ 644, 678, 688, 741, 738, 1326, 742, 743, 747, 748,
+ 750, 755, 754, 1325, 1313, 1307, 1297, 1313, 1312, 1298,
+ 1305, 1295, 1308, 1271, 0, 1277, 1276, 1273, 1274, 1276,
+ 1277, 1274, 0, 1294, 1298, 1297, 1530, 1530, 1278, 1295,
+ 1283, 1530, 1265, 1260, 1264, 1255, 1262, 725, 1259, 726,
+ 1282, 1286, 1270, 1284, 1265, 1282, 1270, 1252, 1247, 1251,
+ 1242, 1249, 728, 1246, 732, 768, 767, 789, 790, 793,
+ 794, 798, 799, 802, 803, 807, 808, 811, 814, 819,
+ 815, 823, 822, 824, 826, 1282, 1281, 812, 828, 827,
+
+ 1280, 830, 831, 829, 833, 837, 841, 840, 842, 1266,
+ 1270, 1269, 1250, 1267, 1255, 1237, 1232, 1236, 1227, 1234,
+ 812, 1231, 813, 1259, 1530, 1530, 1258, 1530, 1257, 1221,
+ 1234, 1221, 1232, 1219, 1230, 1226, 1218, 1227, 1223, 1246,
+ 0, 1245, 1244, 1208, 1221, 1208, 1219, 1206, 1217, 1213,
+ 1205, 1214, 1210, 848, 860, 861, 878, 868, 881, 882,
+ 890, 891, 894, 895, 898, 899, 902, 905, 906, 867,
+ 1241, 1240, 903, 1239, 909, 879, 650, 656, 885, 910,
+ 913, 912, 915, 916, 918, 1230, 1229, 1228, 1192, 1205,
+ 1192, 1203, 1190, 1201, 1197, 1189, 1198, 1194, 1530, 1530,
+
+ 1530, 1219, 1182, 1182, 1179, 1180, 1178, 1177, 1180, 1175,
+ 1174, 1209, 1172, 1172, 1169, 1170, 1168, 1167, 1170, 1165,
+ 1164, 924, 928, 933, 937, 946, 953, 947, 956, 957,
+ 960, 963, 964, 967, 1205, 1204, 1203, 239, 929, 920,
+ 940, 952, 968, 970, 973, 972, 974, 1196, 1159, 1159,
+ 1156, 1157, 1155, 1154, 1157, 1152, 1151, 1161, 1149, 1151,
+ 1157, 1149, 1144, 1143, 1150, 1141, 1140, 1151, 1139, 1141,
+ 1144, 1133, 1128, 1123, 1121, 1109, 1108, 976, 975, 979,
+ 987, 982, 996, 1003, 1013, 1020, 1023, 752, 985, 991,
+ 992, 995, 986, 1000, 1026, 1004, 1008, 1115, 1099, 1090,
+
+ 1094, 1086, 1080, 1079, 1086, 1077, 1076, 1086, 1530, 1076,
+ 1530, 1075, 1530, 1530, 1085, 1530, 1530, 1082, 0, 1072,
+ 0, 1071, 0, 0, 1081, 0, 0, 1033, 1036, 1040,
+ 1050, 1053, 1054, 1057, 1058, 1062, 1067, 1041, 1110, 1031,
+ 1109, 1037, 1107, 1106, 1044, 1105, 1104, 1071, 0, 1061,
+ 0, 1060, 0, 0, 1070, 0, 0, 1057, 1530, 1530,
+ 1530, 1036, 0, 0, 0, 1068, 1075, 1080, 1083, 1049,
+ 1032, 980, 921, 817, 0, 0, 0, 810, 734, 1084,
+ 1028, 733, 739, 640, 1090, 1045, 400, 423, 340, 1091,
+ 1087, 165, 1530, 1096, 161, 1530, 1129, 1131, 1136, 1141,
+
+ 1146, 1151, 1156, 82, 1161, 1166, 1171, 1176
+ } ;
+
+static yyconst short int yy_def[809] =
+ { 0,
+ 796, 1, 796, 3, 796, 5, 796, 7, 796, 9,
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,
+ 796, 796, 797, 796, 796, 798, 798, 798, 798, 798,
+ 798, 798, 798, 798, 798, 798, 798, 798, 798, 798,
+ 798, 798, 798, 798, 799, 798, 798, 800, 796, 796,
+ 800, 800, 800, 800, 800, 800, 800, 800, 800, 800,
+ 800, 800, 800, 800, 800, 800, 800, 800, 801, 800,
+ 800, 802, 796, 796, 796, 796, 802, 802, 802, 802,
+ 802, 802, 802, 802, 802, 802, 802, 802, 802, 802,
+
+ 802, 802, 802, 803, 802, 802, 796, 796, 796, 804,
+ 804, 804, 804, 804, 804, 804, 804, 804, 804, 804,
+ 804, 804, 804, 804, 804, 804, 804, 804, 804, 796,
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 797, 796, 797,
+ 796, 798, 798, 798, 798, 798, 798, 798, 798, 798,
+ 798, 798, 798, 798, 798, 798, 798, 798, 798, 798,
+ 805, 796, 805, 799, 798, 806, 798, 800, 800, 796,
+ 800, 800, 800, 800, 800, 800, 800, 800, 800, 800,
+ 800, 800, 800, 800, 800, 800, 800, 801, 801, 800,
+
+ 801, 800, 807, 796, 796, 796, 807, 807, 807, 807,
+ 807, 807, 807, 807, 807, 807, 807, 807, 807, 807,
+ 807, 807, 807, 808, 807, 808, 807, 796, 796, 796,
+ 804, 804, 804, 804, 804, 804, 804, 804, 804, 804,
+ 804, 804, 804, 804, 804, 804, 804, 804, 804, 804,
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 796, 798, 798,
+ 798, 798, 798, 798, 798, 798, 798, 798, 798, 798,
+ 798, 798, 798, 798, 798, 798, 798, 806, 800, 800,
+ 800, 800, 800, 800, 800, 800, 800, 800, 800, 800,
+
+ 800, 800, 800, 800, 800, 800, 807, 807, 807, 807,
+ 807, 807, 807, 807, 807, 807, 807, 807, 807, 807,
+ 807, 807, 807, 807, 807, 808, 807, 808, 807, 804,
+ 804, 804, 804, 804, 804, 804, 804, 804, 804, 804,
+ 804, 804, 804, 804, 804, 804, 804, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 798, 798, 798, 798,
+ 798, 798, 798, 798, 798, 798, 798, 798, 798, 798,
+ 798, 798, 798, 798, 798, 798, 800, 800, 800, 800,
+ 800, 800, 800, 800, 800, 800, 800, 800, 800, 800,
+
+ 800, 800, 800, 800, 800, 807, 807, 807, 807, 807,
+ 807, 807, 807, 807, 807, 807, 807, 807, 807, 807,
+ 807, 807, 807, 807, 804, 804, 804, 804, 804, 804,
+ 804, 804, 804, 804, 804, 804, 804, 804, 804, 804,
+ 804, 804, 804, 796, 796, 796, 796, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,
+ 798, 798, 798, 798, 798, 798, 798, 798, 798, 798,
+ 798, 798, 798, 798, 798, 800, 800, 800, 800, 800,
+ 800, 800, 800, 800, 800, 800, 800, 800, 800, 800,
+ 800, 800, 807, 807, 807, 807, 807, 807, 807, 807,
+
+ 807, 807, 807, 807, 807, 807, 807, 807, 807, 804,
+ 804, 804, 804, 804, 804, 804, 804, 804, 804, 804,
+ 804, 804, 804, 796, 796, 796, 796, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 798,
+ 798, 798, 798, 798, 798, 798, 798, 798, 798, 798,
+ 798, 798, 798, 800, 800, 800, 800, 800, 800, 800,
+ 800, 800, 800, 800, 800, 800, 800, 800, 800, 807,
+ 807, 807, 807, 807, 807, 807, 807, 807, 807, 807,
+ 807, 807, 807, 807, 807, 804, 804, 804, 804, 804,
+ 804, 804, 804, 804, 804, 804, 804, 804, 796, 796,
+
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,
+ 796, 798, 798, 798, 798, 798, 798, 798, 798, 798,
+ 798, 800, 800, 800, 800, 800, 800, 800, 800, 800,
+ 800, 800, 800, 800, 807, 807, 807, 807, 807, 807,
+ 807, 807, 807, 807, 807, 807, 807, 804, 804, 804,
+ 804, 804, 804, 804, 804, 804, 804, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 798, 798, 798,
+ 798, 798, 798, 798, 798, 798, 798, 800, 800, 800,
+ 800, 800, 800, 800, 800, 800, 800, 807, 807, 807,
+ 807, 807, 807, 807, 807, 807, 807, 804, 804, 804,
+
+ 804, 804, 804, 804, 804, 804, 804, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 798, 798, 798,
+ 798, 798, 798, 798, 798, 798, 798, 800, 800, 800,
+ 800, 800, 800, 800, 800, 800, 800, 807, 807, 807,
+ 807, 807, 807, 807, 807, 807, 807, 804, 804, 804,
+ 804, 804, 804, 804, 804, 804, 804, 796, 796, 796,
+ 796, 798, 798, 798, 798, 800, 800, 800, 800, 807,
+ 807, 807, 807, 804, 804, 804, 804, 796, 798, 800,
+ 807, 804, 796, 798, 800, 807, 804, 796, 798, 800,
+ 807, 804, 796, 800, 807, 0, 796, 796, 796, 796,
+
+ 796, 796, 796, 796, 796, 796, 796, 796
+ } ;
+
+static yyconst short int yy_nxt[1579] =
+ { 0,
+ 12, 13, 14, 13, 12, 12, 15, 16, 17, 12,
+ 12, 12, 18, 19, 12, 20, 12, 12, 12, 12,
+ 12, 21, 22, 23, 24, 12, 25, 26, 12, 12,
+ 12, 12, 27, 28, 12, 12, 12, 12, 12, 29,
+ 12, 30, 12, 31, 12, 12, 12, 32, 33, 130,
+ 130, 130, 130, 130, 130, 142, 149, 165, 179, 218,
+ 179, 175, 172, 173, 143, 34, 166, 203, 219, 135,
+ 171, 171, 172, 173, 158, 179, 171, 179, 412, 171,
+ 130, 130, 130, 130, 180, 130, 231, 35, 12, 13,
+ 14, 13, 36, 36, 15, 37, 38, 12, 36, 36,
+
+ 39, 40, 41, 42, 36, 36, 36, 36, 36, 43,
+ 44, 45, 46, 36, 47, 48, 36, 36, 36, 36,
+ 49, 50, 36, 36, 36, 36, 36, 51, 36, 52,
+ 36, 53, 36, 36, 36, 54, 55, 179, 179, 179,
+ 179, 179, 179, 179, 179, 181, 179, 179, 179, 179,
+ 179, 225, 179, 56, 179, 183, 179, 182, 179, 186,
+ 179, 199, 203, 199, 211, 184, 179, 190, 179, 185,
+ 204, 205, 206, 188, 793, 57, 58, 13, 59, 60,
+ 58, 58, 61, 62, 63, 58, 58, 58, 64, 65,
+ 58, 66, 58, 58, 58, 58, 58, 67, 68, 69,
+
+ 70, 58, 71, 72, 58, 58, 58, 58, 73, 74,
+ 58, 58, 58, 58, 58, 75, 58, 76, 58, 77,
+ 58, 58, 58, 78, 79, 179, 179, 179, 179, 179,
+ 179, 179, 179, 179, 203, 179, 130, 130, 130, 243,
+ 203, 80, 200, 130, 205, 130, 688, 148, 244, 187,
+ 148, 172, 173, 189, 313, 185, 228, 229, 230, 195,
+ 179, 191, 179, 81, 82, 83, 84, 85, 82, 82,
+ 86, 87, 88, 82, 82, 82, 89, 90, 82, 91,
+ 82, 82, 82, 82, 82, 92, 93, 94, 95, 82,
+ 96, 97, 82, 82, 82, 82, 98, 99, 82, 82,
+
+ 82, 82, 82, 100, 82, 101, 82, 102, 82, 82,
+ 82, 103, 104, 179, 249, 179, 130, 130, 130, 130,
+ 229, 130, 130, 130, 130, 263, 282, 236, 179, 105,
+ 179, 171, 171, 172, 173, 181, 203, 171, 264, 283,
+ 171, 148, 148, 308, 148, 197, 199, 148, 199, 793,
+ 148, 106, 12, 107, 108, 109, 12, 12, 15, 110,
+ 111, 12, 112, 112, 113, 114, 112, 115, 112, 112,
+ 112, 112, 112, 116, 117, 118, 119, 112, 120, 121,
+ 112, 112, 112, 112, 122, 123, 112, 112, 112, 112,
+ 112, 124, 112, 125, 112, 126, 112, 112, 112, 127,
+
+ 33, 150, 176, 203, 179, 179, 179, 179, 179, 179,
+ 179, 179, 201, 226, 150, 150, 176, 128, 130, 130,
+ 130, 179, 179, 179, 179, 179, 179, 179, 179, 179,
+ 289, 179, 793, 192, 291, 792, 318, 146, 169, 129,
+ 151, 177, 193, 203, 194, 290, 293, 196, 196, 222,
+ 247, 202, 227, 250, 151, 177, 179, 179, 179, 179,
+ 179, 179, 179, 179, 179, 179, 179, 179, 409, 295,
+ 179, 299, 179, 179, 294, 179, 203, 292, 179, 297,
+ 179, 296, 179, 179, 179, 179, 199, 179, 199, 179,
+ 199, 179, 199, 179, 201, 204, 205, 206, 298, 203,
+
+ 300, 301, 130, 130, 130, 130, 205, 130, 309, 203,
+ 306, 203, 203, 203, 302, 203, 303, 203, 319, 203,
+ 311, 203, 203, 203, 315, 305, 304, 203, 203, 314,
+ 203, 203, 310, 202, 312, 150, 317, 316, 224, 224,
+ 148, 148, 203, 148, 148, 328, 228, 229, 230, 320,
+ 321, 342, 406, 327, 130, 130, 130, 130, 229, 130,
+ 203, 323, 360, 322, 343, 380, 179, 308, 179, 361,
+ 325, 324, 381, 362, 250, 203, 382, 148, 148, 179,
+ 148, 179, 203, 148, 329, 203, 148, 387, 179, 179,
+ 179, 179, 413, 179, 179, 179, 179, 179, 410, 179,
+
+ 179, 407, 179, 389, 203, 388, 391, 392, 393, 179,
+ 394, 179, 203, 179, 390, 179, 179, 179, 179, 179,
+ 179, 179, 179, 179, 179, 179, 179, 179, 179, 179,
+ 179, 179, 203, 203, 395, 203, 203, 414, 203, 203,
+ 203, 203, 396, 417, 203, 203, 411, 408, 224, 203,
+ 148, 203, 328, 148, 399, 403, 398, 203, 224, 397,
+ 148, 400, 437, 148, 402, 401, 498, 415, 404, 438,
+ 418, 405, 422, 439, 179, 789, 179, 419, 416, 203,
+ 639, 420, 421, 423, 179, 476, 179, 424, 179, 203,
+ 179, 329, 499, 179, 179, 179, 179, 179, 640, 179,
+
+ 477, 479, 480, 179, 179, 179, 179, 179, 179, 179,
+ 179, 500, 179, 478, 179, 484, 482, 179, 481, 179,
+ 179, 179, 179, 179, 203, 179, 483, 179, 179, 179,
+ 179, 179, 179, 179, 179, 179, 203, 203, 203, 203,
+ 494, 203, 203, 203, 203, 496, 497, 493, 203, 203,
+ 501, 203, 485, 203, 486, 203, 203, 487, 535, 538,
+ 488, 549, 489, 490, 491, 552, 495, 492, 179, 179,
+ 179, 179, 536, 539, 788, 550, 555, 787, 784, 553,
+ 503, 504, 554, 502, 738, 507, 506, 505, 508, 509,
+ 179, 179, 179, 179, 179, 179, 179, 179, 556, 179,
+
+ 179, 179, 179, 179, 179, 179, 179, 558, 179, 179,
+ 179, 179, 179, 203, 179, 179, 179, 179, 179, 559,
+ 179, 557, 179, 203, 179, 203, 179, 203, 203, 203,
+ 203, 203, 203, 571, 203, 572, 570, 574, 203, 573,
+ 560, 203, 203, 203, 562, 594, 597, 575, 561, 179,
+ 564, 179, 565, 567, 783, 563, 568, 622, 782, 595,
+ 598, 179, 179, 179, 179, 578, 566, 576, 203, 179,
+ 569, 179, 577, 580, 581, 584, 635, 579, 583, 179,
+ 203, 179, 179, 179, 179, 179, 203, 623, 582, 585,
+ 624, 179, 179, 179, 179, 179, 179, 179, 179, 179,
+
+ 179, 179, 179, 179, 203, 179, 179, 179, 179, 179,
+ 203, 203, 636, 203, 203, 641, 203, 203, 637, 203,
+ 626, 203, 203, 638, 628, 179, 625, 179, 630, 179,
+ 203, 179, 631, 627, 179, 633, 179, 629, 179, 634,
+ 179, 203, 632, 643, 678, 644, 646, 179, 179, 179,
+ 179, 647, 642, 203, 179, 645, 179, 179, 179, 179,
+ 179, 179, 690, 179, 179, 179, 179, 179, 179, 203,
+ 179, 203, 689, 203, 203, 203, 179, 179, 179, 179,
+ 179, 203, 179, 179, 691, 179, 203, 203, 179, 679,
+ 179, 681, 203, 203, 692, 680, 203, 179, 682, 179,
+
+ 683, 203, 685, 684, 179, 203, 179, 686, 728, 203,
+ 687, 693, 695, 694, 179, 696, 179, 697, 729, 730,
+ 731, 179, 732, 179, 179, 741, 179, 203, 739, 203,
+ 743, 740, 203, 203, 179, 742, 179, 179, 203, 179,
+ 733, 179, 203, 179, 744, 203, 203, 734, 746, 735,
+ 203, 179, 747, 179, 179, 179, 179, 179, 179, 179,
+ 179, 179, 745, 179, 736, 179, 766, 737, 179, 179,
+ 179, 179, 786, 771, 770, 773, 179, 779, 179, 772,
+ 791, 179, 767, 179, 179, 179, 179, 179, 203, 769,
+ 781, 179, 179, 179, 179, 768, 795, 179, 778, 179,
+
+ 794, 777, 776, 775, 774, 203, 203, 203, 203, 780,
+ 203, 203, 765, 764, 763, 762, 761, 760, 759, 758,
+ 757, 756, 755, 754, 753, 790, 752, 751, 785, 148,
+ 750, 148, 148, 148, 152, 152, 174, 174, 174, 174,
+ 174, 178, 749, 178, 178, 178, 198, 748, 198, 198,
+ 198, 203, 727, 726, 203, 203, 224, 725, 224, 224,
+ 224, 171, 171, 171, 171, 171, 288, 724, 288, 288,
+ 288, 307, 723, 722, 307, 307, 326, 721, 326, 326,
+ 326, 720, 719, 718, 717, 716, 715, 714, 713, 712,
+ 711, 710, 709, 708, 707, 706, 705, 704, 703, 702,
+
+ 701, 700, 699, 698, 203, 203, 203, 677, 676, 675,
+ 674, 673, 672, 671, 670, 669, 668, 667, 666, 665,
+ 664, 663, 662, 661, 660, 659, 658, 657, 656, 655,
+ 654, 653, 652, 651, 650, 649, 648, 601, 600, 599,
+ 203, 203, 203, 621, 620, 619, 618, 617, 616, 615,
+ 614, 613, 612, 601, 600, 599, 611, 610, 609, 608,
+ 607, 606, 605, 604, 603, 602, 601, 600, 599, 596,
+ 593, 592, 591, 590, 589, 588, 528, 587, 526, 525,
+ 586, 203, 203, 203, 551, 548, 547, 546, 545, 544,
+ 543, 528, 542, 526, 541, 525, 540, 537, 534, 533,
+
+ 532, 531, 530, 529, 528, 527, 526, 525, 524, 523,
+ 522, 521, 520, 519, 518, 517, 516, 452, 515, 514,
+ 513, 448, 447, 512, 511, 510, 203, 203, 475, 474,
+ 473, 472, 471, 470, 469, 468, 452, 467, 466, 465,
+ 448, 447, 464, 463, 462, 461, 460, 459, 458, 457,
+ 456, 455, 454, 453, 452, 451, 450, 449, 448, 447,
+ 446, 445, 444, 443, 442, 441, 440, 436, 435, 434,
+ 433, 432, 431, 430, 429, 428, 427, 426, 425, 203,
+ 203, 386, 385, 384, 383, 379, 378, 377, 376, 375,
+ 374, 373, 372, 371, 370, 369, 368, 367, 366, 365,
+
+ 364, 363, 359, 358, 357, 356, 355, 354, 353, 352,
+ 351, 350, 349, 348, 347, 346, 345, 344, 341, 340,
+ 339, 338, 337, 336, 335, 334, 333, 332, 331, 330,
+ 232, 203, 287, 286, 285, 284, 281, 280, 279, 278,
+ 277, 276, 275, 274, 273, 272, 271, 270, 269, 153,
+ 268, 267, 266, 265, 262, 261, 260, 259, 258, 257,
+ 256, 255, 254, 253, 252, 251, 131, 248, 247, 246,
+ 245, 242, 241, 240, 239, 238, 237, 236, 235, 234,
+ 233, 232, 223, 222, 221, 220, 217, 216, 215, 214,
+ 213, 212, 211, 210, 209, 208, 207, 170, 169, 168,
+
+ 167, 164, 163, 162, 161, 160, 159, 158, 157, 156,
+ 155, 154, 153, 147, 146, 145, 144, 141, 140, 139,
+ 138, 137, 136, 135, 134, 133, 132, 131, 796, 11,
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 796
+ } ;
+
+static yyconst short int yy_chk[1579] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 13,
+ 13, 13, 14, 14, 14, 28, 34, 50, 58, 99,
+ 58, 56, 171, 171, 28, 2, 50, 315, 99, 34,
+ 55, 55, 55, 55, 56, 61, 55, 61, 315, 55,
+ 59, 59, 59, 60, 60, 60, 804, 2, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 4, 62, 63, 62,
+ 63, 64, 65, 64, 65, 63, 66, 67, 66, 67,
+ 68, 105, 68, 4, 70, 65, 70, 64, 72, 68,
+ 72, 79, 795, 79, 105, 66, 178, 72, 178, 67,
+ 83, 83, 83, 70, 792, 4, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 6, 69, 71, 69, 71, 73,
+ 76, 73, 76, 80, 212, 80, 84, 84, 84, 123,
+ 638, 6, 80, 85, 85, 85, 638, 104, 123, 69,
+ 104, 173, 173, 71, 212, 80, 107, 107, 107, 76,
+ 179, 73, 179, 6, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 8, 78, 128, 78, 108, 108, 108, 109,
+ 109, 109, 130, 130, 130, 144, 167, 128, 181, 8,
+ 181, 174, 174, 174, 174, 181, 207, 174, 144, 167,
+ 174, 176, 176, 207, 176, 78, 198, 176, 198, 789,
+ 176, 8, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+
+ 10, 35, 57, 217, 74, 75, 74, 75, 77, 81,
+ 77, 81, 81, 106, 129, 151, 177, 10, 180, 180,
+ 180, 182, 183, 182, 183, 184, 186, 184, 186, 192,
+ 182, 192, 788, 74, 184, 787, 217, 35, 57, 10,
+ 35, 57, 74, 312, 75, 183, 186, 77, 81, 106,
+ 129, 81, 106, 129, 151, 177, 185, 187, 185, 187,
+ 188, 189, 188, 189, 190, 191, 190, 191, 312, 188,
+ 193, 192, 193, 194, 187, 194, 218, 185, 195, 190,
+ 195, 189, 196, 197, 196, 197, 199, 200, 199, 200,
+ 201, 202, 201, 202, 202, 204, 204, 204, 191, 208,
+
+ 193, 194, 205, 205, 205, 206, 206, 206, 208, 209,
+ 200, 210, 213, 211, 194, 214, 195, 215, 218, 219,
+ 210, 216, 220, 221, 214, 197, 196, 222, 223, 213,
+ 225, 309, 209, 202, 211, 250, 216, 215, 224, 226,
+ 224, 226, 227, 224, 226, 227, 228, 228, 228, 219,
+ 220, 245, 309, 225, 229, 229, 229, 230, 230, 230,
+ 308, 221, 263, 220, 245, 282, 289, 308, 289, 263,
+ 223, 222, 282, 263, 250, 310, 282, 288, 288, 290,
+ 288, 290, 316, 288, 227, 313, 288, 289, 291, 292,
+ 291, 292, 316, 293, 294, 293, 294, 295, 313, 295,
+
+ 296, 310, 296, 291, 320, 290, 293, 294, 295, 297,
+ 296, 297, 317, 298, 292, 298, 299, 300, 299, 300,
+ 301, 302, 301, 302, 303, 304, 303, 304, 305, 306,
+ 305, 306, 311, 314, 297, 319, 321, 317, 318, 322,
+ 324, 323, 298, 320, 325, 411, 314, 311, 326, 329,
+ 326, 577, 329, 326, 301, 303, 300, 578, 328, 299,
+ 328, 301, 342, 328, 302, 301, 411, 318, 304, 342,
+ 321, 305, 323, 342, 387, 784, 387, 321, 319, 412,
+ 577, 321, 322, 324, 388, 387, 388, 325, 389, 413,
+ 389, 329, 412, 390, 391, 390, 391, 392, 578, 392,
+
+ 388, 390, 391, 393, 394, 393, 394, 395, 396, 395,
+ 396, 413, 397, 389, 397, 395, 393, 398, 392, 398,
+ 399, 400, 399, 400, 407, 401, 394, 401, 405, 402,
+ 405, 402, 403, 404, 403, 404, 406, 409, 410, 415,
+ 407, 408, 414, 417, 418, 409, 410, 406, 419, 420,
+ 414, 421, 396, 688, 398, 423, 422, 399, 458, 460,
+ 400, 473, 401, 402, 403, 475, 408, 404, 477, 476,
+ 477, 476, 458, 460, 783, 473, 477, 782, 779, 475,
+ 417, 418, 476, 415, 688, 421, 420, 419, 422, 423,
+ 478, 479, 478, 479, 480, 481, 480, 481, 478, 482,
+
+ 483, 482, 483, 484, 485, 484, 485, 482, 486, 487,
+ 486, 487, 488, 498, 488, 489, 491, 489, 491, 483,
+ 490, 481, 490, 493, 492, 494, 492, 495, 500, 499,
+ 504, 502, 503, 494, 505, 495, 493, 499, 506, 498,
+ 485, 508, 507, 509, 487, 521, 523, 500, 486, 554,
+ 489, 554, 490, 491, 778, 488, 492, 554, 774, 521,
+ 523, 555, 556, 555, 556, 504, 490, 502, 570, 558,
+ 492, 558, 503, 506, 507, 509, 570, 505, 508, 557,
+ 576, 557, 559, 560, 559, 560, 579, 557, 507, 509,
+ 559, 561, 562, 561, 562, 563, 564, 563, 564, 565,
+
+ 566, 565, 566, 567, 573, 567, 568, 569, 568, 569,
+ 575, 580, 573, 582, 581, 579, 583, 584, 575, 585,
+ 561, 640, 773, 576, 563, 622, 560, 622, 565, 623,
+ 639, 623, 566, 562, 624, 568, 624, 564, 625, 569,
+ 625, 641, 567, 581, 625, 582, 584, 626, 628, 626,
+ 628, 585, 580, 642, 627, 583, 627, 629, 630, 629,
+ 630, 631, 640, 631, 632, 633, 632, 633, 634, 643,
+ 634, 644, 639, 646, 645, 647, 679, 678, 679, 678,
+ 680, 772, 680, 682, 641, 682, 689, 693, 681, 626,
+ 681, 628, 690, 691, 642, 627, 692, 683, 629, 683,
+
+ 630, 694, 632, 631, 684, 696, 684, 633, 678, 697,
+ 634, 643, 645, 644, 685, 646, 685, 647, 679, 680,
+ 681, 686, 682, 686, 687, 691, 687, 695, 689, 781,
+ 693, 690, 740, 771, 728, 692, 728, 729, 742, 729,
+ 683, 730, 738, 730, 694, 745, 786, 684, 696, 685,
+ 770, 731, 697, 731, 732, 733, 732, 733, 734, 735,
+ 734, 735, 695, 736, 686, 736, 728, 687, 737, 766,
+ 737, 766, 781, 740, 738, 745, 767, 762, 767, 742,
+ 786, 768, 730, 768, 769, 780, 769, 780, 791, 735,
+ 770, 785, 790, 785, 790, 732, 791, 794, 758, 794,
+
+ 790, 755, 752, 750, 748, 747, 746, 744, 743, 766,
+ 741, 739, 725, 722, 720, 718, 715, 712, 710, 708,
+ 707, 706, 705, 704, 703, 785, 702, 701, 780, 797,
+ 700, 797, 797, 797, 798, 798, 799, 799, 799, 799,
+ 799, 800, 699, 800, 800, 800, 801, 698, 801, 801,
+ 801, 802, 677, 676, 802, 802, 803, 675, 803, 803,
+ 803, 805, 805, 805, 805, 805, 806, 674, 806, 806,
+ 806, 807, 673, 672, 807, 807, 808, 671, 808, 808,
+ 808, 670, 669, 668, 667, 666, 665, 664, 663, 662,
+ 661, 660, 659, 658, 657, 656, 655, 654, 653, 652,
+
+ 651, 650, 649, 648, 637, 636, 635, 621, 620, 619,
+ 618, 617, 616, 615, 614, 613, 612, 611, 610, 609,
+ 608, 607, 606, 605, 604, 603, 602, 598, 597, 596,
+ 595, 594, 593, 592, 591, 590, 589, 588, 587, 586,
+ 574, 572, 571, 553, 552, 551, 550, 549, 548, 547,
+ 546, 545, 544, 543, 542, 540, 539, 538, 537, 536,
+ 535, 534, 533, 532, 531, 530, 529, 527, 524, 522,
+ 520, 519, 518, 517, 516, 515, 514, 513, 512, 511,
+ 510, 501, 497, 496, 474, 472, 471, 470, 469, 468,
+ 467, 466, 465, 464, 463, 462, 461, 459, 457, 456,
+
+ 455, 454, 453, 451, 450, 449, 446, 445, 444, 442,
+ 441, 440, 439, 438, 437, 436, 434, 433, 432, 431,
+ 430, 429, 428, 427, 426, 425, 424, 416, 385, 384,
+ 383, 382, 381, 380, 379, 377, 376, 375, 374, 373,
+ 372, 371, 370, 369, 368, 367, 365, 364, 363, 362,
+ 361, 360, 359, 357, 356, 355, 354, 353, 352, 351,
+ 350, 349, 348, 346, 345, 344, 343, 341, 340, 339,
+ 338, 337, 336, 335, 334, 333, 332, 331, 330, 327,
+ 307, 286, 285, 284, 283, 281, 280, 279, 278, 277,
+ 276, 275, 274, 273, 272, 271, 270, 269, 267, 266,
+
+ 265, 264, 262, 261, 260, 259, 258, 257, 256, 255,
+ 254, 253, 252, 251, 249, 248, 247, 246, 244, 243,
+ 242, 241, 240, 239, 238, 237, 236, 235, 234, 233,
+ 232, 203, 175, 170, 169, 168, 166, 165, 164, 163,
+ 162, 161, 160, 159, 158, 157, 156, 155, 154, 153,
+ 149, 147, 146, 145, 143, 142, 141, 140, 139, 138,
+ 137, 136, 135, 134, 133, 132, 131, 127, 126, 125,
+ 124, 122, 121, 120, 119, 118, 117, 116, 115, 114,
+ 113, 111, 103, 102, 101, 100, 98, 97, 96, 95,
+ 94, 93, 92, 91, 90, 89, 88, 54, 53, 52,
+
+ 51, 49, 48, 47, 46, 45, 44, 43, 42, 41,
+ 40, 39, 38, 32, 31, 30, 29, 27, 26, 25,
+ 24, 23, 22, 21, 20, 19, 18, 17, 11, 796,
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,
+ 796, 796, 796, 796, 796, 796, 796, 796
+ } ;
+
+static yy_state_type yy_state_buf[YY_BUF_SIZE + 2], *yy_state_ptr;
+static char *yy_full_match;
+static int yy_lp;
+#define REJECT \
+{ \
+*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ \
+yy_cp = yy_full_match; /* restore poss. backed-over text */ \
+++yy_lp; \
+goto find_rule; \
+}
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "levcomp.lpp"
+#define INITIAL 0
+#line 2 "levcomp.lpp"
+
+// levcomp.l:
+// Level compiler lexer for Dungeon Crawl Stone Soup.
+//
+// Based loosely on NetHack's lev_comp.l
+
+#include "AppHdr.h"
+#include "levcomp.tab.h"
+#include <cstring>
+
+static bool alloced = false;
+
+static void clean()
+{
+ if (yylval.text && alloced)
+ free( (void*) yylval.text);
+ yylval.text = NULL;
+ alloced = false;
+}
+
+static void settext()
+{
+ clean();
+ if ((yylval.text = strdup(yytext)))
+ alloced = true;
+}
+
+#define MAPDEF 1
+
+#define ARGUMENT 2
+
+#define MNAME 3
+
+#define KEYWORDS 4
+
+#define YY_NEVER_INTERACTIVE 1
+#line 1130 "levcomp.lex.cc"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines. This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( yy_current_buffer->yy_is_interactive ) \
+ { \
+ int c = '*', n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ if ( yyleng > 0 ) \
+ yy_current_buffer->yy_at_bol = \
+ (yytext[yyleng - 1] == '\n'); \
+ YY_USER_ACTION
+
+YY_DECL
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 41 "levcomp.lpp"
+
+
+#line 1298 "levcomp.lex.cc"
+
+ if ( yy_init )
+ {
+ yy_init = 0;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yy_start )
+ yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! yy_current_buffer )
+ yy_current_buffer =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_load_buffer_state();
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yy_start;
+ yy_current_state += YY_AT_BOL();
+ yy_state_ptr = yy_state_buf;
+ *yy_state_ptr++ = yy_current_state;
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 797 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ *yy_state_ptr++ = yy_current_state;
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 1530 );
+
+yy_find_action:
+ yy_current_state = *--yy_state_ptr;
+ yy_lp = yy_accept[yy_current_state];
+find_rule: /* we branch to this label when backing up */
+ for ( ; ; ) /* until we find what rule we matched */
+ {
+ if ( yy_lp && yy_lp < yy_accept[yy_current_state + 1] )
+ {
+ yy_act = yy_acclist[yy_lp];
+ {
+ yy_full_match = yy_cp;
+ break;
+ }
+ }
+ --yy_cp;
+ yy_current_state = *--yy_state_ptr;
+ yy_lp = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+ if ( yy_act != YY_END_OF_BUFFER )
+ {
+ int yyl;
+ for ( yyl = 0; yyl < yyleng; ++yyl )
+ if ( yytext[yyl] == '\n' )
+ ++yylineno;
+ }
+
+do_action: /* This label is used only to access EOF actions. */
+
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+case 1:
+YY_RULE_SETUP
+#line 43 "levcomp.lpp"
+{ BEGIN(INITIAL); }
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 45 "levcomp.lpp"
+;
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 47 "levcomp.lpp"
+{
+ settext();
+ return MAP_LINE;
+ }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 52 "levcomp.lpp"
+{ BEGIN(MAPDEF); }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 54 "levcomp.lpp"
+;
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 56 "levcomp.lpp"
+{ BEGIN(ARGUMENT); return NAME; }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 57 "levcomp.lpp"
+return DEFAULT_DEPTH;
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 58 "levcomp.lpp"
+return DEPTH;
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 59 "levcomp.lpp"
+return ORIENT;
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 60 "levcomp.lpp"
+{ BEGIN(ARGUMENT); return PLACE; }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 61 "levcomp.lpp"
+return CHANCE;
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 62 "levcomp.lpp"
+return FLAGS;
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 63 "levcomp.lpp"
+{ BEGIN(KEYWORDS); return TAGS; }
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 64 "levcomp.lpp"
+{ BEGIN(ARGUMENT); return SYMBOL; }
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 65 "levcomp.lpp"
+{ BEGIN(MNAME); return MONS; }
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 67 "levcomp.lpp"
+{
+ settext();
+ return STRING;
+ }
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 72 "levcomp.lpp"
+;
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 73 "levcomp.lpp"
+{ BEGIN(INITIAL); }
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 75 "levcomp.lpp"
+{
+ settext();
+ return MONSTER_NAME;
+ }
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 80 "levcomp.lpp"
+return COMMA;
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 81 "levcomp.lpp"
+{ BEGIN(INITIAL); }
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 82 "levcomp.lpp"
+;
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 84 "levcomp.lpp"
+return PANDEMONIC;
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 85 "levcomp.lpp"
+return NO_HMIRROR;
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 86 "levcomp.lpp"
+return NO_VMIRROR;
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 87 "levcomp.lpp"
+return NO_ROTATE;
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 89 "levcomp.lpp"
+return ENCOMPASS;
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 90 "levcomp.lpp"
+return NORTH;
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 91 "levcomp.lpp"
+return SOUTH;
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 92 "levcomp.lpp"
+return EAST;
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 93 "levcomp.lpp"
+return WEST;
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 94 "levcomp.lpp"
+return NORTHEAST;
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 95 "levcomp.lpp"
+return NORTHWEST;
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 96 "levcomp.lpp"
+return SOUTHEAST;
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 97 "levcomp.lpp"
+return SOUTHWEST;
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 99 "levcomp.lpp"
+return DASH;
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 100 "levcomp.lpp"
+return COMMA;
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 102 "levcomp.lpp"
+{
+ clean();
+ yylval.i = atoi(yytext);
+ return INTEGER;
+ }
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 108 "levcomp.lpp"
+{
+ BEGIN(INITIAL);
+ settext();
+ return STRING;
+ }
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 114 "levcomp.lpp"
+{ BEGIN(INITIAL); }
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 116 "levcomp.lpp"
+;
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 118 "levcomp.lpp"
+return BAD_CHARACTER;
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 120 "levcomp.lpp"
+ECHO;
+ YY_BREAK
+#line 1622 "levcomp.lex.cc"
+ case YY_STATE_EOF(INITIAL):
+ case YY_STATE_EOF(MAPDEF):
+ case YY_STATE_EOF(ARGUMENT):
+ case YY_STATE_EOF(MNAME):
+ case YY_STATE_EOF(KEYWORDS):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between yy_current_buffer and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yy_current_buffer->yy_input_file = yyin;
+ yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap() )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p =
+ yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yy_c_buf_p =
+ &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+ } /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+ {
+ register char *dest = yy_current_buffer->yy_ch_buf;
+ register char *source = yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( yy_current_buffer->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+ YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = yy_current_buffer;
+
+ int yy_c_buf_p_offset =
+ (int) (yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yy_flex_realloc( (void *) b->yy_ch_buf,
+ b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = yy_current_buffer->yy_buf_size -
+ number_to_move - 1;
+#endif
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+ yy_n_chars, num_to_read );
+
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ if ( yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart( yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ yy_current_buffer->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ yy_n_chars += number_to_move;
+ yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+ return ret_val;
+ }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = yy_start;
+ yy_current_state += YY_AT_BOL();
+ yy_state_ptr = yy_state_buf;
+ *yy_state_ptr++ = yy_current_state;
+
+ for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 797 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ *yy_state_ptr++ = yy_current_state;
+ }
+
+ return yy_current_state;
+ }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+ {
+ register int yy_is_jam;
+
+ register YY_CHAR yy_c = 1;
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 797 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 796);
+ if ( ! yy_is_jam )
+ *yy_state_ptr++ = yy_current_state;
+
+ return yy_is_jam ? 0 : yy_current_state;
+ }
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+ {
+ register char *yy_cp = yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yy_hold_char;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = yy_n_chars + 2;
+ register char *dest = &yy_current_buffer->yy_ch_buf[
+ yy_current_buffer->yy_buf_size + 2];
+ register char *source =
+ &yy_current_buffer->yy_ch_buf[number_to_move];
+
+ while ( source > yy_current_buffer->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ yy_current_buffer->yy_n_chars =
+ yy_n_chars = yy_current_buffer->yy_buf_size;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ if ( c == '\n' )
+ --yylineno;
+
+ yytext_ptr = yy_bp;
+ yy_hold_char = *yy_cp;
+ yy_c_buf_p = yy_cp;
+ }
+#endif /* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+ {
+ int c;
+
+ *yy_c_buf_p = yy_hold_char;
+
+ if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ /* This was really a NUL. */
+ *yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yy_c_buf_p - yytext_ptr;
+ ++yy_c_buf_p;
+
+ switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart( yyin );
+
+ /* fall through */
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap() )
+ return EOF;
+
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */
+ *yy_c_buf_p = '\0'; /* preserve yytext */
+ yy_hold_char = *++yy_c_buf_p;
+
+ yy_current_buffer->yy_at_bol = (c == '\n');
+ if ( yy_current_buffer->yy_at_bol )
+ ++yylineno;
+
+ return c;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+ {
+ if ( ! yy_current_buffer )
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_init_buffer( yy_current_buffer, input_file );
+ yy_load_buffer_state();
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+ {
+ if ( yy_current_buffer == new_buffer )
+ return;
+
+ if ( yy_current_buffer )
+ {
+ /* Flush out information for old buffer. */
+ *yy_c_buf_p = yy_hold_char;
+ yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ yy_current_buffer = new_buffer;
+ yy_load_buffer_state();
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yy_did_buffer_switch_on_eof = 1;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+ {
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+ yyin = yy_current_buffer->yy_input_file;
+ yy_hold_char = *yy_c_buf_p;
+ }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer( b, file );
+
+ return b;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+ {
+ if ( ! b )
+ return;
+
+ if ( b == yy_current_buffer )
+ yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yy_flex_free( (void *) b->yy_ch_buf );
+
+ yy_flex_free( (void *) b );
+ }
+
+
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+ {
+ yy_flush_buffer( b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+ b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+ b->yy_is_interactive = 0;
+#else
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+ {
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == yy_current_buffer )
+ yy_load_buffer_state();
+ }
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer( b );
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+ {
+ int len;
+ for ( len = 0; yy_str[len]; ++len )
+ ;
+
+ return yy_scan_bytes( yy_str, len );
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+ {
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = len + 2;
+ buf = (char *) yy_flex_alloc( n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < len; ++i )
+ buf[i] = bytes[i];
+
+ buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer( buf, n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+ {
+ if ( yy_start_stack_ptr >= yy_start_stack_depth )
+ {
+ yy_size_t new_size;
+
+ yy_start_stack_depth += YY_START_STACK_INCR;
+ new_size = yy_start_stack_depth * sizeof( int );
+
+ if ( ! yy_start_stack )
+ yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+ else
+ yy_start_stack = (int *) yy_flex_realloc(
+ (void *) yy_start_stack, new_size );
+
+ if ( ! yy_start_stack )
+ YY_FATAL_ERROR(
+ "out of memory expanding start-condition stack" );
+ }
+
+ yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+ BEGIN(new_state);
+ }
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+ {
+ if ( --yy_start_stack_ptr < 0 )
+ YY_FATAL_ERROR( "start-condition stack underflow" );
+
+ BEGIN(yy_start_stack[yy_start_stack_ptr]);
+ }
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+ {
+ return yy_start_stack[yy_start_stack_ptr - 1];
+ }
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+ {
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+ }
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ yytext[yyleng] = yy_hold_char; \
+ yy_c_buf_p = yytext + n; \
+ yy_hold_char = *yy_c_buf_p; \
+ *yy_c_buf_p = '\0'; \
+ yyleng = n; \
+ } \
+ while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+ {
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+ }
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+ {
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+ }
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+ {
+ return (void *) malloc( size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+ {
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+ {
+ free( ptr );
+ }
+
+#if YY_MAIN
+int main()
+ {
+ yylex();
+ return 0;
+ }
+#endif
+#line 120 "levcomp.lpp"
+
+
+int yywrap()
+{
+ clean();
+ return 1;
+}
diff --git a/crawl-ref/source/prebuilt/levcomp.tab.cc b/crawl-ref/source/prebuilt/levcomp.tab.cc
new file mode 100644
index 0000000000..4b4d9dc3f3
--- /dev/null
+++ b/crawl-ref/source/prebuilt/levcomp.tab.cc
@@ -0,0 +1,1907 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ DEFAULT_DEPTH = 258,
+ SYMBOL = 259,
+ TAGS = 260,
+ NAME = 261,
+ DEPTH = 262,
+ ORIENT = 263,
+ PLACE = 264,
+ CHANCE = 265,
+ FLAGS = 266,
+ MONS = 267,
+ ENCOMPASS = 268,
+ NORTH = 269,
+ EAST = 270,
+ SOUTH = 271,
+ WEST = 272,
+ NORTHEAST = 273,
+ SOUTHEAST = 274,
+ SOUTHWEST = 275,
+ NORTHWEST = 276,
+ BAD_CHARACTER = 277,
+ NO_HMIRROR = 278,
+ NO_VMIRROR = 279,
+ NO_ROTATE = 280,
+ PANDEMONIC = 281,
+ DASH = 282,
+ COMMA = 283,
+ INTEGER = 284,
+ STRING = 285,
+ MAP_LINE = 286,
+ MONSTER_NAME = 287
+ };
+#endif
+/* Tokens. */
+#define DEFAULT_DEPTH 258
+#define SYMBOL 259
+#define TAGS 260
+#define NAME 261
+#define DEPTH 262
+#define ORIENT 263
+#define PLACE 264
+#define CHANCE 265
+#define FLAGS 266
+#define MONS 267
+#define ENCOMPASS 268
+#define NORTH 269
+#define EAST 270
+#define SOUTH 271
+#define WEST 272
+#define NORTHEAST 273
+#define SOUTHEAST 274
+#define SOUTHWEST 275
+#define NORTHWEST 276
+#define BAD_CHARACTER 277
+#define NO_HMIRROR 278
+#define NO_VMIRROR 279
+#define NO_ROTATE 280
+#define PANDEMONIC 281
+#define DASH 282
+#define COMMA 283
+#define INTEGER 284
+#define STRING 285
+#define MAP_LINE 286
+#define MONSTER_NAME 287
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 1 "levcomp.ypp"
+
+
+#include "AppHdr.h"
+#include "libutil.h"
+#include "levcomp.h"
+
+int yylex();
+
+extern int yylineno;
+
+void yyerror(const char *e)
+{
+ fprintf(stderr, "%s:%d: %s\n", lc_desfile.c_str(), yylineno, e);
+ // Bail bail bail.
+ exit(1);
+}
+
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 21 "levcomp.ypp"
+{
+ int i;
+ const char *text;
+}
+/* Line 193 of yacc.c. */
+#line 184 "levcomp.tab.c"
+ YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 216 of yacc.c. */
+#line 197 "levcomp.tab.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+ int i;
+#endif
+{
+ return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss;
+ YYSTYPE yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 13
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 41
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 33
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 28
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 57
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 70
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 287
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint8 yyprhs[] =
+{
+ 0, 0, 3, 5, 6, 9, 11, 13, 15, 18,
+ 23, 26, 27, 30, 32, 34, 36, 38, 40, 42,
+ 44, 46, 49, 50, 53, 55, 58, 60, 63, 67,
+ 69, 71, 74, 76, 79, 83, 85, 88, 90, 93,
+ 95, 97, 99, 101, 103, 105, 107, 109, 111, 114,
+ 115, 118, 120, 122, 124, 126, 128, 131
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 34, 0, -1, 35, -1, -1, 36, 35, -1, 37,
+ -1, 39, -1, 38, -1, 3, 51, -1, 40, 41,
+ 58, 41, -1, 6, 30, -1, -1, 42, 41, -1,
+ 49, -1, 50, -1, 52, -1, 53, -1, 55, -1,
+ 46, -1, 45, -1, 43, -1, 5, 44, -1, -1,
+ 30, 44, -1, 4, -1, 4, 30, -1, 12, -1,
+ 12, 47, -1, 48, 28, 47, -1, 48, -1, 32,
+ -1, 9, 30, -1, 7, -1, 7, 51, -1, 29,
+ 27, 29, -1, 29, -1, 10, 29, -1, 8, -1,
+ 8, 54, -1, 13, -1, 14, -1, 15, -1, 16,
+ -1, 17, -1, 18, -1, 19, -1, 20, -1, 21,
+ -1, 11, 56, -1, -1, 57, 56, -1, 23, -1,
+ 24, -1, 25, -1, 59, -1, 60, -1, 60, 59,
+ -1, 31, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint8 yyrline[] =
+{
+ 0, 46, 46, 49, 50, 53, 54, 57, 60, 66,
+ 72, 80, 81, 84, 85, 86, 87, 88, 89, 90,
+ 91, 94, 97, 98, 106, 107, 113, 114, 117, 118,
+ 121, 134, 140, 141, 147, 152, 158, 164, 165, 171,
+ 172, 173, 174, 175, 176, 177, 178, 179, 182, 185,
+ 186, 202, 203, 204, 207, 210, 211, 214
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "DEFAULT_DEPTH", "SYMBOL", "TAGS",
+ "NAME", "DEPTH", "ORIENT", "PLACE", "CHANCE", "FLAGS", "MONS",
+ "ENCOMPASS", "NORTH", "EAST", "SOUTH", "WEST", "NORTHEAST", "SOUTHEAST",
+ "SOUTHWEST", "NORTHWEST", "BAD_CHARACTER", "NO_HMIRROR", "NO_VMIRROR",
+ "NO_ROTATE", "PANDEMONIC", "DASH", "COMMA", "INTEGER", "STRING",
+ "MAP_LINE", "MONSTER_NAME", "$accept", "file", "definitions",
+ "definition", "def", "defdepth", "level", "name", "metalines",
+ "metaline", "tags", "tagstrings", "symbol", "mons", "mnames", "mname",
+ "place", "depth", "depth_range", "chance", "orientation", "orient_name",
+ "flags", "flagnames", "flagname", "map_def", "map_lines", "map_line", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 33, 34, 35, 35, 36, 36, 37, 38, 39,
+ 40, 41, 41, 42, 42, 42, 42, 42, 42, 42,
+ 42, 43, 44, 44, 45, 45, 46, 46, 47, 47,
+ 48, 49, 50, 50, 51, 51, 52, 53, 53, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 55, 56,
+ 56, 57, 57, 57, 58, 59, 59, 60
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 0, 2, 1, 1, 1, 2, 4,
+ 2, 0, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 0, 2, 1, 2, 1, 2, 3, 1,
+ 1, 2, 1, 2, 3, 1, 2, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 0,
+ 2, 1, 1, 1, 1, 1, 2, 1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 3, 0, 0, 0, 2, 3, 5, 7, 6, 11,
+ 35, 8, 10, 1, 4, 24, 22, 32, 37, 0,
+ 0, 49, 26, 0, 11, 20, 19, 18, 13, 14,
+ 15, 16, 17, 0, 25, 22, 21, 33, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 38, 31, 36,
+ 51, 52, 53, 48, 49, 30, 27, 29, 57, 11,
+ 54, 55, 12, 34, 23, 50, 0, 9, 56, 28
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int8 yydefgoto[] =
+{
+ -1, 3, 4, 5, 6, 7, 8, 9, 23, 24,
+ 25, 36, 26, 27, 56, 57, 28, 29, 11, 30,
+ 31, 47, 32, 53, 54, 59, 60, 61
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -29
+static const yytype_int8 yypact[] =
+{
+ 16, -17, -10, 21, -29, 16, -29, -29, -29, 6,
+ -1, -29, -29, -29, -29, -3, -2, -17, -12, 1,
+ 3, 0, 2, 5, 6, -29, -29, -29, -29, -29,
+ -29, -29, -29, 4, -29, -2, -29, -29, -29, -29,
+ -29, -29, -29, -29, -29, -29, -29, -29, -29, -29,
+ -29, -29, -29, -29, 0, -29, -29, 9, -29, 6,
+ -29, 5, -29, -29, -29, -29, 2, -29, -29, -29
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -29, -29, 24, -29, -29, -29, -29, -29, -24, -29,
+ -29, -5, -29, -29, -28, -29, -29, -29, 22, -29,
+ -29, -29, -29, -14, -29, -29, -20, -29
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+ 62, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 15, 16, 10, 17, 18, 19, 20, 21, 22, 1,
+ 12, 13, 2, 50, 51, 52, 33, 34, 35, 14,
+ 64, 48, 49, 63, 55, 67, 58, 66, 69, 37,
+ 65, 68
+};
+
+static const yytype_uint8 yycheck[] =
+{
+ 24, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 4, 5, 29, 7, 8, 9, 10, 11, 12, 3,
+ 30, 0, 6, 23, 24, 25, 27, 30, 30, 5,
+ 35, 30, 29, 29, 32, 59, 31, 28, 66, 17,
+ 54, 61
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 3, 6, 34, 35, 36, 37, 38, 39, 40,
+ 29, 51, 30, 0, 35, 4, 5, 7, 8, 9,
+ 10, 11, 12, 41, 42, 43, 45, 46, 49, 50,
+ 52, 53, 55, 27, 30, 30, 44, 51, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 54, 30, 29,
+ 23, 24, 25, 56, 57, 32, 47, 48, 31, 58,
+ 59, 60, 41, 29, 44, 56, 28, 41, 59, 47
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ yytype_int16 *bottom;
+ yytype_int16 *top;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+ YYSTYPE *yyvsp;
+ int yyrule;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ fprintf (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
+ fprintf (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ YYUSE (yyvaluep);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The look-ahead symbol. */
+int yychar;
+
+/* The semantic value of the look-ahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+ int yystate;
+ int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Look-ahead token as an internal (translated) token number. */
+ int yytoken = 0;
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss = yyssa;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ look-ahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to look-ahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a look-ahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the look-ahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+#line 46 "levcomp.ypp"
+ { }
+ break;
+
+ case 3:
+#line 49 "levcomp.ypp"
+ {}
+ break;
+
+ case 4:
+#line 50 "levcomp.ypp"
+ {}
+ break;
+
+ case 5:
+#line 53 "levcomp.ypp"
+ {}
+ break;
+
+ case 6:
+#line 54 "levcomp.ypp"
+ {}
+ break;
+
+ case 8:
+#line 61 "levcomp.ypp"
+ {
+ lc_default_depth = lc_range;
+ }
+ break;
+
+ case 9:
+#line 67 "levcomp.ypp"
+ {
+ add_parsed_map( lc_map );
+ }
+ break;
+
+ case 10:
+#line 73 "levcomp.ypp"
+ {
+ lc_map.init();
+ lc_map.depth = lc_default_depth;
+ lc_map.name = (yyvsp[(2) - (2)].text);
+ }
+ break;
+
+ case 21:
+#line 94 "levcomp.ypp"
+ {}
+ break;
+
+ case 23:
+#line 99 "levcomp.ypp"
+ {
+ lc_map.tags += " ";
+ lc_map.tags += (yyvsp[(1) - (2)].text);
+ lc_map.tags += " ";
+ }
+ break;
+
+ case 24:
+#line 106 "levcomp.ypp"
+ {}
+ break;
+
+ case 25:
+#line 108 "levcomp.ypp"
+ {
+ lc_map.random_symbols = (yyvsp[(2) - (2)].text);
+ }
+ break;
+
+ case 26:
+#line 113 "levcomp.ypp"
+ {}
+ break;
+
+ case 27:
+#line 114 "levcomp.ypp"
+ {}
+ break;
+
+ case 30:
+#line 122 "levcomp.ypp"
+ {
+ bool recognised = lc_map.mons.add_mons((yyvsp[(1) - (1)].text));
+ if (!recognised)
+ {
+ char buf[300];
+ snprintf(buf, sizeof buf, "unknown monster '%s'",
+ (yyvsp[(1) - (1)].text));
+ yyerror(buf);
+ }
+ }
+ break;
+
+ case 31:
+#line 135 "levcomp.ypp"
+ {
+ lc_map.place = (yyvsp[(2) - (2)].text);
+ }
+ break;
+
+ case 32:
+#line 140 "levcomp.ypp"
+ {}
+ break;
+
+ case 33:
+#line 142 "levcomp.ypp"
+ {
+ lc_map.depth = lc_range;
+ }
+ break;
+
+ case 34:
+#line 148 "levcomp.ypp"
+ {
+ lc_range.set((yyvsp[(1) - (3)].i), (yyvsp[(3) - (3)].i));
+ }
+ break;
+
+ case 35:
+#line 153 "levcomp.ypp"
+ {
+ lc_range.set((yyvsp[(1) - (1)].i));
+ }
+ break;
+
+ case 36:
+#line 159 "levcomp.ypp"
+ {
+ lc_map.chance = (yyvsp[(2) - (2)].i);
+ }
+ break;
+
+ case 37:
+#line 164 "levcomp.ypp"
+ {}
+ break;
+
+ case 38:
+#line 166 "levcomp.ypp"
+ {
+ lc_map.orient = (map_section_type) (yyvsp[(2) - (2)].i);
+ }
+ break;
+
+ case 39:
+#line 171 "levcomp.ypp"
+ { (yyval.i) = MAP_ENCOMPASS; }
+ break;
+
+ case 40:
+#line 172 "levcomp.ypp"
+ { (yyval.i) = MAP_NORTH; }
+ break;
+
+ case 41:
+#line 173 "levcomp.ypp"
+ { (yyval.i) = MAP_EAST; }
+ break;
+
+ case 42:
+#line 174 "levcomp.ypp"
+ { (yyval.i) = MAP_SOUTH; }
+ break;
+
+ case 43:
+#line 175 "levcomp.ypp"
+ { (yyval.i) = MAP_WEST; }
+ break;
+
+ case 44:
+#line 176 "levcomp.ypp"
+ { (yyval.i) = MAP_NORTHEAST; }
+ break;
+
+ case 45:
+#line 177 "levcomp.ypp"
+ { (yyval.i) = MAP_SOUTHEAST; }
+ break;
+
+ case 46:
+#line 178 "levcomp.ypp"
+ { (yyval.i) = MAP_SOUTHWEST; }
+ break;
+
+ case 47:
+#line 179 "levcomp.ypp"
+ { (yyval.i) = MAP_NORTHWEST; }
+ break;
+
+ case 48:
+#line 182 "levcomp.ypp"
+ {}
+ break;
+
+ case 50:
+#line 187 "levcomp.ypp"
+ {
+ switch ((yyvsp[(1) - (2)].i)) {
+ case NO_HMIRROR:
+ lc_map.flags &= ~MAPF_MIRROR_HORIZONTAL;
+ break;
+ case NO_VMIRROR:
+ lc_map.flags &= ~MAPF_MIRROR_VERTICAL;
+ break;
+ case NO_ROTATE:
+ lc_map.flags &= ~MAPF_ROTATE;
+ break;
+ }
+ }
+ break;
+
+ case 51:
+#line 202 "levcomp.ypp"
+ { (yyval.i) = NO_HMIRROR; }
+ break;
+
+ case 52:
+#line 203 "levcomp.ypp"
+ { (yyval.i) = NO_VMIRROR; }
+ break;
+
+ case 53:
+#line 204 "levcomp.ypp"
+ { (yyval.i) = NO_ROTATE; }
+ break;
+
+ case 57:
+#line 215 "levcomp.ypp"
+ {
+ lc_map.map.add_line((yyvsp[(1) - (1)].text));
+ }
+ break;
+
+
+/* Line 1267 of yacc.c. */
+#line 1692 "levcomp.tab.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse look-ahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse look-ahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ *++yyvsp = yylval;
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEOF && yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+#line 220 "levcomp.ypp"
+
+
diff --git a/crawl-ref/source/prebuilt/levcomp.tab.h b/crawl-ref/source/prebuilt/levcomp.tab.h
new file mode 100644
index 0000000000..64857e6606
--- /dev/null
+++ b/crawl-ref/source/prebuilt/levcomp.tab.h
@@ -0,0 +1,125 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ DEFAULT_DEPTH = 258,
+ SYMBOL = 259,
+ TAGS = 260,
+ NAME = 261,
+ DEPTH = 262,
+ ORIENT = 263,
+ PLACE = 264,
+ CHANCE = 265,
+ FLAGS = 266,
+ MONS = 267,
+ ENCOMPASS = 268,
+ NORTH = 269,
+ EAST = 270,
+ SOUTH = 271,
+ WEST = 272,
+ NORTHEAST = 273,
+ SOUTHEAST = 274,
+ SOUTHWEST = 275,
+ NORTHWEST = 276,
+ BAD_CHARACTER = 277,
+ NO_HMIRROR = 278,
+ NO_VMIRROR = 279,
+ NO_ROTATE = 280,
+ PANDEMONIC = 281,
+ DASH = 282,
+ COMMA = 283,
+ INTEGER = 284,
+ STRING = 285,
+ MAP_LINE = 286,
+ MONSTER_NAME = 287
+ };
+#endif
+/* Tokens. */
+#define DEFAULT_DEPTH 258
+#define SYMBOL 259
+#define TAGS 260
+#define NAME 261
+#define DEPTH 262
+#define ORIENT 263
+#define PLACE 264
+#define CHANCE 265
+#define FLAGS 266
+#define MONS 267
+#define ENCOMPASS 268
+#define NORTH 269
+#define EAST 270
+#define SOUTH 271
+#define WEST 272
+#define NORTHEAST 273
+#define SOUTHEAST 274
+#define SOUTHWEST 275
+#define NORTHWEST 276
+#define BAD_CHARACTER 277
+#define NO_HMIRROR 278
+#define NO_VMIRROR 279
+#define NO_ROTATE 280
+#define PANDEMONIC 281
+#define DASH 282
+#define COMMA 283
+#define INTEGER 284
+#define STRING 285
+#define MAP_LINE 286
+#define MONSTER_NAME 287
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 21 "levcomp.ypp"
+{
+ int i;
+ const char *text;
+}
+/* Line 1529 of yacc.c. */
+#line 118 "levcomp.tab.h"
+ YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYSTYPE yylval;
+
diff --git a/crawl-ref/source/randart.cc b/crawl-ref/source/randart.cc
index b0486fe02f..2aa804e957 100644
--- a/crawl-ref/source/randart.cc
+++ b/crawl-ref/source/randart.cc
@@ -3,6 +3,8 @@
* Summary: Random and unrandom artifact functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <8> 19 Jun 99 GDL added IBMCPP support
@@ -20,8 +22,8 @@
#include "externs.h"
#include "itemname.h"
+#include "itemprop.h"
#include "stuff.h"
-#include "wpn-misc.h"
/*
The initial generation of a randart is very simple - it occurs
@@ -608,7 +610,7 @@ const char *rand_armour_names[] = {
not randart.h because they're only used in this code module.
*/
-#if defined(MAC) || defined(__IBMCPP__) || defined(__BCPLUSPLUS__)
+#if defined(__IBMCPP__)
#define PACKED
#else
#ifndef PACKED
@@ -814,7 +816,7 @@ void randart_wpn_properties( const item_def &item,
if (proprt[RAP_BRAND] == SPWPN_SPEED && atype == WPN_QUICK_BLADE)
proprt[RAP_BRAND] = SPWPN_NORMAL;
- if (launches_things(atype))
+ if (is_range_weapon(item))
{
proprt[RAP_BRAND] = SPWPN_NORMAL;
@@ -825,12 +827,14 @@ void randart_wpn_properties( const item_def &item,
proprt[RAP_BRAND] = (tmp >= 18) ? SPWPN_SPEED :
(tmp >= 14) ? SPWPN_PROTECTION :
(tmp >= 10) ? SPWPN_VENOM
- : SPWPN_FLAME + (tmp % 2);
+ : SPWPN_VORPAL + random2(3);
+ if (proprt[RAP_BRAND] == SPWPN_VORPAL && atype == WPN_BLOWGUN)
+ proprt[RAP_BRAND] = SPWPN_VENOM;
}
}
- if (is_demonic(atype))
+ if (is_demonic(item))
{
switch (random5(9))
{
@@ -1182,11 +1186,11 @@ finished_curses:
if (random5(10) == 0
&& (aclass != OBJ_ARMOUR
|| atype != ARM_CLOAK
- || !cmp_equip_race( item, ISFLAG_ELVEN ))
+ || get_equip_race(item) != ISFLAG_ELVEN)
&& (aclass != OBJ_ARMOUR
|| atype != ARM_BOOTS
- || !cmp_equip_race( item, ISFLAG_ELVEN )
- && get_armour_ego_type( item ) != SPARM_STEALTH))
+ || get_equip_race(item) != ISFLAG_ELVEN)
+ && get_armour_ego_type( item ) != SPARM_STEALTH)
{
power_level++;
proprt[RAP_STEALTH] = 10 + random5(70);
@@ -1239,7 +1243,7 @@ const char *randart_name( const item_def &item )
push_rng_state();
seed_rng( seed );
- if (item_not_ident( item, ISFLAG_KNOW_TYPE ))
+ if (!item_ident( item, ISFLAG_KNOW_TYPE ))
{
switch (random5(21))
{
@@ -1286,7 +1290,7 @@ const char *randart_name( const item_def &item )
{
char st_p2[ITEMNAME_SIZE];
- make_name(random5(250), random5(250), random5(250), 3, st_p);
+ make_name(random_int(), false, st_p);
standard_name_weap( item.sub_type, st_p2 );
strcat(art_n, st_p2);
@@ -1336,7 +1340,7 @@ const char *randart_armour_name( const item_def &item )
push_rng_state();
seed_rng( seed );
- if (item_not_ident( item, ISFLAG_KNOW_TYPE ))
+ if (!item_ident( item, ISFLAG_KNOW_TYPE ))
{
switch (random5(21))
{
@@ -1382,7 +1386,7 @@ const char *randart_armour_name( const item_def &item )
{
char st_p2[ITEMNAME_SIZE];
- make_name(random5(250), random5(250), random5(250), 3, st_p);
+ make_name(random_int(), false, st_p);
standard_name_armour(item, st_p2);
strcat(art_n, st_p2);
if (random5(3) == 0)
@@ -1432,7 +1436,7 @@ const char *randart_ring_name( const item_def &item )
push_rng_state();
seed_rng( seed );
- if (item_not_ident( item, ISFLAG_KNOW_TYPE ))
+ if (!item_ident( item, ISFLAG_KNOW_TYPE ))
{
temp_rand = random5(21);
@@ -1473,7 +1477,7 @@ const char *randart_ring_name( const item_def &item )
}
else
{
- make_name(random5(250), random5(250), random5(250), 3, st_p);
+ make_name(random_int(), false, st_p);
strcat(art_n, (item.sub_type < AMU_RAGE) ? "ring" : "amulet");
@@ -1773,6 +1777,7 @@ void standard_name_weap(unsigned char item_typ, char glorg[ITEMNAME_SIZE])
(item_typ == WPN_HALBERD) ? "halberd" :
(item_typ == WPN_SLING) ? "sling" :
(item_typ == WPN_BOW) ? "bow" :
+ (item_typ == WPN_LONGBOW) ? "longbow" :
(item_typ == WPN_BLOWGUN) ? "blowgun" :
(item_typ == WPN_CROSSBOW) ? "crossbow" :
(item_typ == WPN_HAND_CROSSBOW) ? "hand crossbow" :
@@ -1782,6 +1787,7 @@ void standard_name_weap(unsigned char item_typ, char glorg[ITEMNAME_SIZE])
(item_typ == WPN_EVENINGSTAR) ? "eveningstar" :
(item_typ == WPN_QUICK_BLADE) ? "quick blade" :
(item_typ == WPN_KATANA) ? "katana" :
+ (item_typ == WPN_LAJATANG) ? "lajatang" :
(item_typ == WPN_EXECUTIONERS_AXE) ? "executioner's axe" :
(item_typ == WPN_DOUBLE_SWORD) ? "double sword" :
(item_typ == WPN_TRIPLE_SWORD) ? "triple sword" :
@@ -1790,13 +1796,15 @@ void standard_name_weap(unsigned char item_typ, char glorg[ITEMNAME_SIZE])
(item_typ == WPN_WHIP) ? "whip" :
(item_typ == WPN_SABRE) ? "sabre" :
(item_typ == WPN_DEMON_BLADE) ? "demon blade" :
+ (item_typ == WPN_BLESSED_BLADE)? "blessed blade" :
+ (item_typ == WPN_LOCHABER_AXE) ? "lochaber axe" :
(item_typ == WPN_DEMON_WHIP) ? "demon whip" :
(item_typ == WPN_DEMON_TRIDENT) ? "demon trident" :
(item_typ == WPN_BROAD_AXE) ? "broad axe" :
(item_typ == WPN_WAR_AXE) ? "war axe" :
(item_typ == WPN_SPIKED_FLAIL) ? "spiked flail" :
(item_typ == WPN_GREAT_MACE) ? "great mace" :
- (item_typ == WPN_GREAT_FLAIL) ? "great flail" :
+ (item_typ == WPN_DIRE_FLAIL) ? "dire flail" :
(item_typ == WPN_FALCHION) ? "falchion" :
(item_typ == WPN_GIANT_CLUB)
@@ -1814,7 +1822,7 @@ void standard_name_armour( const item_def &item, char glorg[ITEMNAME_SIZE] )
{
short helm_type;
- glorg[0] = '\0';
+ glorg[0] = 0;
switch (item.sub_type)
{
@@ -1859,8 +1867,8 @@ void standard_name_armour( const item_def &item, char glorg[ITEMNAME_SIZE] )
break;
case ARM_HELMET:
- if (cmp_helmet_type( item, THELM_HELM )
- || cmp_helmet_type( item, THELM_HELMET ))
+ if (get_helmet_type(item) == THELM_HELM
+ || get_helmet_type(item) == THELM_HELMET)
{
short dhelm = get_helmet_desc( item );
@@ -1893,13 +1901,16 @@ void standard_name_armour( const item_def &item, char glorg[ITEMNAME_SIZE] )
strcat(glorg, "gloves");
break;
+ case ARM_NAGA_BARDING:
+ strcat(glorg, "naga barding");
+ break;
+
+ case ARM_CENTAUR_BARDING:
+ strcat(glorg, "centaur barding");
+ break;
+
case ARM_BOOTS:
- if (item.plus2 == TBOOT_NAGA_BARDING)
- strcat(glorg, "naga barding");
- else if (item.plus2 == TBOOT_CENTAUR_BARDING)
- strcat(glorg, "centaur barding");
- else
- strcat(glorg, "boots");
+ strcat(glorg, "boots");
break;
case ARM_BUCKLER:
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index fc51bc28bd..805c652d77 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -27,6 +27,10 @@
#include <string.h>
#include <stdio.h>
+#ifdef DOS
+#include <dos.h>
+#endif
+
#include "externs.h"
#include "abl-show.h"
@@ -39,13 +43,17 @@
#include "food.h"
#include "it_use2.h"
#include "itemname.h"
+#include "itemprop.h"
+#include "item_use.h"
#include "items.h"
#include "misc.h"
#include "monplace.h"
#include "mutation.h"
#include "newgame.h"
+#include "notes.h"
#include "ouch.h"
#include "player.h"
+#include "randart.h"
#include "shopping.h"
#include "skills2.h"
#include "spells1.h"
@@ -53,6 +61,7 @@
#include "spells3.h"
#include "spl-cast.h"
#include "stuff.h"
+#include "view.h"
const char *sacrifice[] = {
" glows silver and disappears.",
@@ -115,9 +124,25 @@ static void inc_gift_timeout(int val)
you.gift_timeout += val;
} // end inc_gift_timeout()
+static int random_undead_servant(int religion)
+{
+ // error trapping {dlb}
+ int thing_called = MONS_PROGRAM_BUG;
+ int temp_rand = random2(100);
+ thing_called = ((temp_rand > 66) ? MONS_WRAITH : // 33%
+ (temp_rand > 52) ? MONS_WIGHT : // 12%
+ (temp_rand > 40) ? MONS_SPECTRAL_WARRIOR : // 16%
+ (temp_rand > 31) ? MONS_ROTTING_HULK : // 9%
+ (temp_rand > 23) ? MONS_SKELETAL_WARRIOR : // 8%
+ (temp_rand > 16) ? MONS_VAMPIRE : // 7%
+ (temp_rand > 10) ? MONS_GHOUL : // 6%
+ (temp_rand > 4) ? MONS_MUMMY // 6%
+ : MONS_FLAYED_GHOST); // 5%
+ return (thing_called);
+}
+
void pray(void)
{
- int temp_rand = 0;
unsigned char was_praying = you.duration[DUR_PRAYER];
bool success = false;
@@ -128,7 +153,7 @@ void pray(void)
}
// all prayers take time
- you.turn_is_over = 1;
+ you.turn_is_over = true;
if (you.religion != GOD_NO_GOD
&& grd[you.x_pos][you.y_pos] == 179 + you.religion)
@@ -155,7 +180,7 @@ void pray(void)
strcat(info, "un");
strcat(info, "life.");
- mpr(info);
+ mpr(info, MSGCH_PRAY);
return;
}
else if (you.religion == GOD_XOM)
@@ -187,7 +212,7 @@ void pray(void)
strcpy( info, "You offer a prayer to " );
strcat( info, god_name( you.religion ) );
strcat( info, "." );
- mpr(info);
+ mpr(info, MSGCH_PRAY);
you.duration[DUR_PRAYER] = 9 + (random2(you.piety) / 20)
+ (random2(you.piety) / 20);
@@ -208,7 +233,7 @@ void pray(void)
: "displeased");
strcat(info, ".");
- god_speaks(you.religion, info);
+ mpr( info, MSGCH_PRAY, you.religion );
if (you.piety > 130)
you.duration[DUR_PRAYER] *= 3;
@@ -226,197 +251,222 @@ void pray(void)
if (!you.penance[you.religion] && !you.gift_timeout && !was_praying)
{
// Remember to check for water/lava
- //jmf: "good" god will sometimes feed you (a la Nethack)
- if (you.religion == GOD_ZIN
- && you.hunger_state == HS_STARVING
- && random2(250) <= you.piety)
- {
- god_speaks(you.religion, "Your stomach feels content.");
- set_hunger(6000, true);
- lose_piety(5 + random2avg(10, 2));
- inc_gift_timeout(30 + random2avg(10, 2));
- return;
- }
-
- if (you.religion == GOD_NEMELEX_XOBEH
- && random2(200) <= you.piety
- && (!you.attribute[ATTR_CARD_TABLE] || one_chance_in(3))
- && !you.attribute[ATTR_CARD_COUNTDOWN]
- && grd[you.x_pos][you.y_pos] != DNGN_LAVA
- && grd[you.x_pos][you.y_pos] != DNGN_DEEP_WATER)
+ switch (you.religion)
{
- int thing_created = NON_ITEM;
- unsigned char gift_type = MISC_DECK_OF_TRICKS;
-
- if (!you.attribute[ATTR_CARD_TABLE])
- {
- thing_created = items( 1, OBJ_MISCELLANY,
- MISC_PORTABLE_ALTAR_OF_NEMELEX,
- true, 1, 250 );
+ default:
+ break;
- if (thing_created != NON_ITEM)
- you.attribute[ATTR_CARD_TABLE] = 1;
- }
- else
+ case GOD_ZIN:
+ //jmf: "good" god will sometimes feed you (a la Nethack)
+ if (you.hunger_state == HS_STARVING
+ && random2(250) <= you.piety)
{
- if (random2(200) <= you.piety && one_chance_in(4))
- gift_type = MISC_DECK_OF_SUMMONINGS;
- if (random2(200) <= you.piety && coinflip())
- gift_type = MISC_DECK_OF_WONDERS;
- if (random2(200) <= you.piety && one_chance_in(4))
- gift_type = MISC_DECK_OF_POWER;
-
- thing_created = items( 1, OBJ_MISCELLANY, gift_type,
- true, 1, 250 );
+ god_speaks(you.religion, "Your stomach feels content.");
+ set_hunger(6000, true);
+ lose_piety(5 + random2avg(10, 2));
+ inc_gift_timeout(30 + random2avg(10, 2));
}
+ break;
- if (thing_created != NON_ITEM)
+ case GOD_NEMELEX_XOBEH:
+ if (random2(200) <= you.piety
+ && (!you.attribute[ATTR_CARD_TABLE] || one_chance_in(3))
+ && !you.attribute[ATTR_CARD_COUNTDOWN]
+ && !grid_destroys_items(grd[you.x_pos][you.y_pos]))
{
- move_item_to_grid( &thing_created, you.x_pos, you.y_pos );
- origin_acquired(mitm[thing_created], you.religion);
-
- simple_god_message(" grants you a gift!");
- more();
- canned_msg(MSG_SOMETHING_APPEARS);
+ int thing_created = NON_ITEM;
+ unsigned char gift_type = MISC_DECK_OF_TRICKS;
- you.attribute[ATTR_CARD_COUNTDOWN] = 10;
- inc_gift_timeout(5 + random2avg(9, 2));
- }
- }
+ if (!you.attribute[ATTR_CARD_TABLE])
+ {
+ thing_created = items( 1, OBJ_MISCELLANY,
+ MISC_PORTABLE_ALTAR_OF_NEMELEX,
+ true, 1, 250 );
- if ((you.religion == GOD_OKAWARU || you.religion == GOD_TROG)
- && you.piety > 130
- && random2(you.piety) > 120
- && grd[you.x_pos][you.y_pos] != DNGN_LAVA
- && grd[you.x_pos][you.y_pos] != DNGN_DEEP_WATER
- && one_chance_in(4))
- {
- if (you.religion == GOD_TROG
- || (you.religion == GOD_OKAWARU && coinflip()))
- {
- success = acquirement(OBJ_WEAPONS, you.religion);
- }
- else
- {
- success = acquirement(OBJ_ARMOUR, you.religion);
- }
+ if (thing_created != NON_ITEM)
+ you.attribute[ATTR_CARD_TABLE] = 1;
+ }
+ else
+ {
+ if (random2(200) <= you.piety && one_chance_in(4))
+ gift_type = MISC_DECK_OF_SUMMONINGS;
+ if (random2(200) <= you.piety && coinflip())
+ gift_type = MISC_DECK_OF_WONDERS;
+ if (random2(200) <= you.piety && one_chance_in(4))
+ gift_type = MISC_DECK_OF_POWER;
+
+ thing_created = items( 1, OBJ_MISCELLANY, gift_type,
+ true, 1, 250 );
+ }
- if (success)
- {
- simple_god_message(" has granted you a gift!");
- more();
+ if (thing_created != NON_ITEM)
+ {
+ move_item_to_grid( &thing_created, you.x_pos, you.y_pos );
+ origin_acquired(mitm[thing_created], you.religion);
+
+ simple_god_message(" grants you a gift!");
+ more();
+ canned_msg(MSG_SOMETHING_APPEARS);
- inc_gift_timeout(30 + random2avg(19, 2));
+ you.attribute[ATTR_CARD_COUNTDOWN] = 10;
+ inc_gift_timeout(5 + random2avg(9, 2));
+ you.num_gifts[you.religion]++;
+ take_note(Note(NOTE_GOD_GIFT, you.religion));
+ }
}
- }
-
- if (you.religion == GOD_YREDELEMNUL
- && random2(you.piety) > 80 && one_chance_in(5))
- {
- int thing_called = MONS_PROGRAM_BUG; // error trapping {dlb}
-
- temp_rand = random2(100);
- thing_called = ((temp_rand > 66) ? MONS_WRAITH : // 33%
- (temp_rand > 52) ? MONS_WIGHT : // 12%
- (temp_rand > 40) ? MONS_SPECTRAL_WARRIOR : // 16%
- (temp_rand > 31) ? MONS_ROTTING_HULK : // 9%
- (temp_rand > 23) ? MONS_SKELETAL_WARRIOR : // 8%
- (temp_rand > 16) ? MONS_VAMPIRE : // 7%
- (temp_rand > 10) ? MONS_GHOUL : // 6%
- (temp_rand > 4) ? MONS_MUMMY // 6%
- : MONS_FLAYED_GHOST); // 5%
-
- if (create_monster( thing_called, 0, BEH_FRIENDLY,
- you.x_pos, you.y_pos,
- you.pet_target, 250 ) != -1)
+ break;
+
+ case GOD_OKAWARU:
+ case GOD_TROG:
+ if (you.piety > 130
+ && random2(you.piety) > 120
+ && !grid_destroys_items(grd[you.x_pos][you.y_pos])
+ && one_chance_in(4))
{
- simple_god_message(" grants you an undead servant!");
- more();
- inc_gift_timeout(4 + random2avg(7, 2));
- }
- }
-
- if ((you.religion == GOD_KIKUBAAQUDGHA
- || you.religion == GOD_SIF_MUNA
- || you.religion == GOD_VEHUMET)
- && you.piety > 160 && random2(you.piety) > 100)
- {
- unsigned int gift = NUM_BOOKS;
+ if (you.religion == GOD_TROG
+ || (you.religion == GOD_OKAWARU && coinflip()))
+ {
+ success = acquirement(OBJ_WEAPONS, you.religion);
+ }
+ else
+ {
+ success = acquirement(OBJ_ARMOUR, you.religion);
+ }
- switch (you.religion)
- {
- case GOD_KIKUBAAQUDGHA: // gives death books
- if (!you.had_book[BOOK_NECROMANCY])
- gift = BOOK_NECROMANCY;
- else if (!you.had_book[BOOK_DEATH])
- gift = BOOK_DEATH;
- else if (!you.had_book[BOOK_UNLIFE])
- gift = BOOK_UNLIFE;
- else if (!you.had_book[BOOK_NECRONOMICON])
- gift = BOOK_NECRONOMICON;
- break;
+ if (success)
+ {
+ simple_god_message(" has granted you a gift!");
+ more();
- case GOD_SIF_MUNA:
- gift = OBJ_RANDOM; // Sif Muna - gives any
+ inc_gift_timeout(30 + random2avg(19, 2));
+ you.num_gifts[ you.religion ]++;
+ take_note(Note(NOTE_GOD_GIFT, you.religion));
+ }
break;
+ }
- // Vehumet - gives conj/summ. books (higher skill first)
- case GOD_VEHUMET:
- if (!you.had_book[BOOK_CONJURATIONS_I])
- gift = give_first_conjuration_book();
- else if (!you.had_book[BOOK_POWER])
- gift = BOOK_POWER;
- else if (!you.had_book[BOOK_ANNIHILATIONS])
- gift = BOOK_ANNIHILATIONS; // conj books
-
- if (you.skills[SK_CONJURATIONS] < you.skills[SK_SUMMONINGS]
- || gift == NUM_BOOKS)
+ if (you.religion == GOD_OKAWARU
+ && you.piety > 80
+ && random2( you.piety ) > 70
+ && !grid_destroys_items( grd[you.x_pos][you.y_pos] )
+ && one_chance_in(8)
+ && you.skills[ best_skill(SK_SLINGS, SK_RANGED_COMBAT) ] >= 9)
+ {
+ success = acquirement( OBJ_MISSILES, you.religion );
+ if (success)
{
- if (!you.had_book[BOOK_CALLINGS])
- gift = BOOK_CALLINGS;
- else if (!you.had_book[BOOK_SUMMONINGS])
- gift = BOOK_SUMMONINGS;
- else if (!you.had_book[BOOK_DEMONOLOGY])
- gift = BOOK_DEMONOLOGY; // summoning bks
+ simple_god_message( " has granted you a gift!" );
+ more();
+
+ inc_gift_timeout( 4 + roll_dice(2,4) );
+ you.num_gifts[ you.religion ]++;
+ take_note(Note(NOTE_GOD_GIFT, you.religion));
}
break;
}
+ break;
- if (gift != NUM_BOOKS
- && (grd[you.x_pos][you.y_pos] != DNGN_LAVA
- && grd[you.x_pos][you.y_pos] != DNGN_DEEP_WATER))
+ case GOD_YREDELEMNUL:
+ if (random2(you.piety) > 80 && one_chance_in(5))
{
- if (gift == OBJ_RANDOM)
- success = acquirement(OBJ_BOOKS, you.religion);
- else
+ int thing_called = random_undead_servant(GOD_YREDELEMNUL);
+ if (create_monster( thing_called, 0, BEH_FRIENDLY,
+ you.x_pos, you.y_pos,
+ you.pet_target, 250 ) != -1)
{
- int thing_created = items(1, OBJ_BOOKS, gift, true, 1, 250);
- if (thing_created == NON_ITEM)
- return;
+ simple_god_message(" grants you an undead servant!");
+ more();
+ inc_gift_timeout(4 + random2avg(7, 2));
+ you.num_gifts[you.religion]++;
+ take_note(Note(NOTE_GOD_GIFT, you.religion));
+ }
+ }
+ break;
- move_item_to_grid( &thing_created, you.x_pos, you.y_pos );
+ case GOD_KIKUBAAQUDGHA:
+ case GOD_SIF_MUNA:
+ case GOD_VEHUMET:
+ if (you.piety > 160 && random2(you.piety) > 100)
+ {
+ unsigned int gift = NUM_BOOKS;
- if (thing_created != NON_ITEM)
+ switch (you.religion)
+ {
+ case GOD_KIKUBAAQUDGHA: // gives death books
+ if (!you.had_book[BOOK_NECROMANCY])
+ gift = BOOK_NECROMANCY;
+ else if (!you.had_book[BOOK_DEATH])
+ gift = BOOK_DEATH;
+ else if (!you.had_book[BOOK_UNLIFE])
+ gift = BOOK_UNLIFE;
+ else if (!you.had_book[BOOK_NECRONOMICON])
+ gift = BOOK_NECRONOMICON;
+ break;
+
+ case GOD_SIF_MUNA:
+ gift = OBJ_RANDOM; // Sif Muna - gives any
+ break;
+
+ // Vehumet - gives conj/summ. books (higher skill first)
+ case GOD_VEHUMET:
+ if (!you.had_book[BOOK_CONJURATIONS_I])
+ gift = give_first_conjuration_book();
+ else if (!you.had_book[BOOK_POWER])
+ gift = BOOK_POWER;
+ else if (!you.had_book[BOOK_ANNIHILATIONS])
+ gift = BOOK_ANNIHILATIONS; // conj books
+
+ if (you.skills[SK_CONJURATIONS] <
+ you.skills[SK_SUMMONINGS]
+ || gift == NUM_BOOKS)
{
- success = true;
- origin_acquired(mitm[thing_created], you.religion);
+ if (!you.had_book[BOOK_CALLINGS])
+ gift = BOOK_CALLINGS;
+ else if (!you.had_book[BOOK_SUMMONINGS])
+ gift = BOOK_SUMMONINGS;
+ else if (!you.had_book[BOOK_DEMONOLOGY])
+ gift = BOOK_DEMONOLOGY; // summoning bks
}
+ break;
}
- if (success)
+ if (gift != NUM_BOOKS
+ && !(grid_destroys_items(grd[you.x_pos][you.y_pos])))
{
- simple_god_message(" has granted you a gift!");
- more();
+ if (gift == OBJ_RANDOM)
+ success = acquirement(OBJ_BOOKS, you.religion);
+ else
+ {
+ int thing_created = items(1, OBJ_BOOKS, gift, true, 1, 250);
+ if (thing_created == NON_ITEM)
+ return;
- inc_gift_timeout(40 + random2avg(19, 2));
- }
+ move_item_to_grid( &thing_created, you.x_pos, you.y_pos );
+
+ if (thing_created != NON_ITEM)
+ {
+ success = true;
+ origin_acquired(mitm[thing_created], you.religion);
+ }
+ }
+
+ if (success)
+ {
+ simple_god_message(" has granted you a gift!");
+ more();
+ inc_gift_timeout(40 + random2avg(19, 2));
+ you.num_gifts[ you.religion ]++;
+ take_note(Note(NOTE_GOD_GIFT, you.religion));
+ }
- // Vehumet gives books less readily
- if (you.religion == GOD_VEHUMET && success)
- inc_gift_timeout(10 + random2(10));
- } // end of giving book
- } // end of book gods
+ // Vehumet gives books less readily
+ if (you.religion == GOD_VEHUMET && success)
+ inc_gift_timeout(10 + random2(10));
+ } // end of giving book
+ } // end of book gods
+ break;
+ }
} // end of gift giving
} // end pray()
@@ -683,7 +733,7 @@ void Xom_acts(bool niceness, int sever, bool force_sever)
(temp_rand == 2) ? "\"Let's see if it's strong enough to survive yet.\""
: "You hear Xom's maniacal laughter.");
- if (one_chance_in(4))
+ if (one_chance_in(4) && (you.equip[EQ_WEAPON] != -1) )
dancing_weapon(100, true); // nasty, but fun
else
{
@@ -823,11 +873,10 @@ void Xom_acts(bool niceness, int sever, bool force_sever)
(temp_rand == 1) ? "Xom grants you a gift!"
: "Xom's generous nature manifests itself.");
- if (grd[you.x_pos][you.y_pos] == DNGN_LAVA
- || grd[you.x_pos][you.y_pos] == DNGN_DEEP_WATER)
- {
+ if (grid_destroys_items(grd[you.x_pos][you.y_pos])) {
// How unfortunate. I'll bet Xom feels sorry for you.
- mpr("You hear a splash.");
+ mprf(MSGCH_SOUND,
+ grid_item_destruction_message(grd[you.x_pos][you.y_pos]));
}
else
{
@@ -862,6 +911,10 @@ void Xom_acts(bool niceness, int sever, bool force_sever)
(temp_rand == 1) ? "Xom grants you a demonic servitor."
: "Xom opens a gate.");
}
+ else
+ {
+ god_speaks(GOD_XOM, "You hear Xom cackling.");
+ }
done_good = true; // well, for Xom, trying == doing {dlb}
}
@@ -914,12 +967,13 @@ void Xom_acts(bool niceness, int sever, bool force_sever)
beam.flavour = BEAM_ELECTRICITY;
beam.target_x = you.x_pos;
beam.target_y = you.y_pos;
- strcpy(beam.beam_name, "blast of lightning");
+ beam.name = "blast of lightning";
beam.colour = LIGHTCYAN;
- beam.thrower = KILL_YOU; // your explosion
+ beam.thrower = KILL_MISC;
beam.aux_source = "Xom's lightning strike";
beam.ex_size = 2;
- beam.isTracer = false;
+ beam.is_tracer = false;
+ beam.is_explosion = true;
explosion(beam);
@@ -933,160 +987,375 @@ void Xom_acts(bool niceness, int sever, bool force_sever)
}
} // end "Good Things"
- if (done_bad || done_good || one_chance_in(4))
- return;
- else
- goto okay_try_again;
+ if (done_bad || done_good )
+ return;
+ if ( one_chance_in(4) ) {
+ god_speaks(GOD_XOM, "Xom's attention is distracted from you.");
+ return;
+ }
+ goto okay_try_again;
} // end Xom_acts()
-void done_good(char thing_done, int pgain)
+// This function is the merger of done_good() and naughty().
+// Returns true if god was interested (good or bad) in conduct.
+bool did_god_conduct( int thing_done, int level )
{
- if (you.religion == GOD_NO_GOD)
- return;
+ bool ret = false;
+ int piety_change = 0;
+ int penance = 0;
+
+ if (you.religion == GOD_NO_GOD || you.religion == GOD_XOM)
+ return (false);
switch (thing_done)
{
- case GOOD_KILLED_LIVING:
+ case DID_NECROMANCY:
+ case DID_UNHOLY:
+ case DID_ATTACK_HOLY:
+ switch (you.religion)
+ {
+ case GOD_ZIN:
+ case GOD_SHINING_ONE:
+ case GOD_ELYVILON:
+ piety_change = -level;
+ penance = level * ((you.religion == GOD_ZIN) ? 2 : 1);
+ ret = true;
+ break;
+ }
+ break;
+
+ case DID_STABBING:
+ case DID_POISON:
+ if (you.religion == GOD_SHINING_ONE)
+ {
+ ret = true;
+ piety_change = -level;
+ penance = level * 2;
+ }
+ break;
+
+ case DID_ATTACK_FRIEND:
+ switch (you.religion)
+ {
+ case GOD_ZIN:
+ case GOD_SHINING_ONE:
+ case GOD_ELYVILON:
+ case GOD_OKAWARU:
+ piety_change = -level;
+ penance = level * 3;
+ ret = true;
+ break;
+ }
+ break;
+
+ case DID_FRIEND_DIES:
+ switch (you.religion)
+ {
+ case GOD_ELYVILON:
+ penance = level; // healer god cares more about this
+ // fall through
+ case GOD_ZIN:
+ case GOD_SHINING_ONE:
+ case GOD_OKAWARU:
+ piety_change = -level;
+ ret = true;
+ break;
+ }
+ break;
+
+ case DID_DEDICATED_BUTCHERY: // aka field sacrifice
switch (you.religion)
{
case GOD_ELYVILON:
simple_god_message(" did not appreciate that!");
- naughty(NAUGHTY_KILLING, 10);
+ ret = true;
+ piety_change = -10;
+ penance = 10;
break;
- case GOD_KIKUBAAQUDGHA:
- case GOD_YREDELEMNUL:
- case GOD_VEHUMET:
+
case GOD_OKAWARU:
case GOD_MAKHLEB:
case GOD_TROG:
- simple_god_message(" accepts your kill.");
- if (random2(18 + pgain) > 5)
- gain_piety(1);
+ simple_god_message(" accepts your offering.");
+ ret = true;
+ if (random2(level + 10) > 5)
+ piety_change = 1;
break;
}
break;
- case GOOD_KILLED_UNDEAD:
+ case DID_DEDICATED_KILL_LIVING:
switch (you.religion)
{
- case GOD_ZIN:
- case GOD_SHINING_ONE:
+ case GOD_ELYVILON:
+ simple_god_message(" did not appreciate that!");
+ ret = true;
+ piety_change = -level;
+ penance = level * 2;
+ break;
+
+ case GOD_KIKUBAAQUDGHA:
+ case GOD_YREDELEMNUL:
+ case GOD_OKAWARU:
case GOD_VEHUMET:
case GOD_MAKHLEB:
- case GOD_OKAWARU:
+ case GOD_TROG:
simple_god_message(" accepts your kill.");
- if (random2(18 + pgain) > 4)
- gain_piety(1);
+ ret = true;
+ if (random2(level + 18) > 5)
+ piety_change = 1;
break;
}
break;
- case GOOD_KILLED_DEMON:
+ case DID_DEDICATED_KILL_UNDEAD:
switch (you.religion)
{
case GOD_ZIN:
case GOD_SHINING_ONE:
+ case GOD_OKAWARU:
case GOD_VEHUMET:
case GOD_MAKHLEB:
- case GOD_OKAWARU:
simple_god_message(" accepts your kill.");
- if (random2(18 + pgain) > 3)
- gain_piety(1);
+ ret = true;
+ if (random2(level + 18) > 4)
+ piety_change = 1;
break;
}
break;
- case GOOD_KILLED_ANGEL_I:
- case GOOD_KILLED_ANGEL_II:
+ case DID_DEDICATED_KILL_DEMON:
switch (you.religion)
{
case GOD_ZIN:
case GOD_SHINING_ONE:
- case GOD_ELYVILON:
- simple_god_message(" did not appreciate that!");
- naughty(NAUGHTY_ATTACK_HOLY, (you.conf ? 3 : pgain * 3));
+ case GOD_OKAWARU:
+ simple_god_message(" accepts your kill.");
+ ret = true;
+ if (random2(level + 18) > 3)
+ piety_change = 1;
break;
}
break;
- case GOOD_KILLED_WIZARD:
- // hooking this up, but is it too good?
- // enjoy it while you can -- bwr
+ case DID_DEDICATED_KILL_WIZARD:
if (you.religion == GOD_TROG)
{
- simple_god_message( " appreciates your killing of a magic user." );
-
- if (random2( 5 + pgain ) > 5)
- gain_piety(1);
+ // hooking this up, but is it too good?
+ // enjoy it while you can -- bwr
+ simple_god_message(" appreciates your killing of a magic user.");
+ ret = true;
+ if (random2(level + 10) > 5)
+ piety_change = 1;
}
break;
- case GOOD_HACKED_CORPSE: // NB - pgain is you.experience_level (maybe)
+ // Note that Angel deaths are special, they are always noticed...
+ // if you or any friendly kills one you'll get the credit or the blame.
+ case DID_ANGEL_KILLED_BY_SERVANT:
+ case DID_KILL_ANGEL:
switch (you.religion)
{
- // case GOD_KIKUBAAQUDGHA:
- case GOD_OKAWARU:
- case GOD_MAKHLEB:
- case GOD_TROG:
- simple_god_message(" accepts your offering.");
- if (random2(10 + pgain) > 5)
- gain_piety(1);
+ case GOD_ZIN:
+ case GOD_SHINING_ONE:
+ case GOD_ELYVILON:
+ level *= 3;
+ piety_change = -level;
+ penance = level * ((you.religion == GOD_ZIN) ? 2 : 1);
+ ret = true;
break;
- // case GOD_ZIN:
- // case GOD_SHINING_ONE:
- case GOD_ELYVILON:
- simple_god_message(" did not appreciate that!");
+ case GOD_KIKUBAAQUDGHA:
+ case GOD_YREDELEMNUL:
+ case GOD_MAKHLEB:
+ snprintf( info, INFO_SIZE, " accepts your %skill.",
+ (thing_done == DID_KILL_ANGEL) ? "" : "collateral " );
+
+ simple_god_message( info );
- naughty(NAUGHTY_BUTCHER, 8);
+ ret = true;
+ if (random2(level + 18) > 2)
+ piety_change = 1;
break;
}
break;
- case GOOD_OFFER_STUFF:
- simple_god_message(" is pleased with your offering.");
-
- gain_piety(1);
- break;
-
- case GOOD_SLAVES_KILL_LIVING:
+ // Undead slave is any friendly undead... Kiku and Yred pay attention
+ // to the undead and both like the death of living things.
+ case DID_LIVING_KILLED_BY_UNDEAD_SLAVE:
switch (you.religion)
{
case GOD_KIKUBAAQUDGHA:
case GOD_YREDELEMNUL:
- case GOD_VEHUMET:
simple_god_message(" accepts your slave's kill.");
-
- if (random2(pgain + 18) > 5)
- gain_piety(1);
+ ret = true;
+ if (random2(level + 10) > 5)
+ piety_change = 1;
break;
}
break;
- case GOOD_SERVANTS_KILL:
+ // Servants are currently any friendly monster under Vehumet, or
+ // any god given pet for everyone else (excluding undead which are
+ // handled above).
+ case DID_LIVING_KILLED_BY_SERVANT:
switch (you.religion)
{
+ case GOD_KIKUBAAQUDGHA: // note: reapers aren't undead
case GOD_VEHUMET:
case GOD_MAKHLEB:
simple_god_message(" accepts your collateral kill.");
+ ret = true;
+ if (random2(level + 10) > 5)
+ piety_change = 1;
+ break;
+ }
+ break;
- if (random2(pgain + 18) > 5)
- gain_piety(1);
+ case DID_UNDEAD_KILLED_BY_SERVANT:
+ switch (you.religion)
+ {
+ case GOD_ZIN:
+ case GOD_SHINING_ONE:
+ case GOD_VEHUMET:
+ case GOD_MAKHLEB:
+ simple_god_message(" accepts your collateral kill.");
+ ret = true;
+ if (random2(level + 10) > 5)
+ piety_change = 1;
break;
}
break;
- case GOOD_CARDS:
+ case DID_DEMON_KILLED_BY_SERVANT:
switch (you.religion)
{
- case GOD_NEMELEX_XOBEH:
- gain_piety(pgain);
+ case GOD_ZIN:
+ case GOD_SHINING_ONE:
+ simple_god_message(" accepts your collateral kill.");
+ ret = true;
+ if (random2(level + 10) > 5)
+ piety_change = 1;
break;
}
break;
- // Offering at altars is covered in another function.
+
+ case DID_SPELL_MEMORISE:
+ if (you.religion == GOD_TROG)
+ {
+ penance = level * 10;
+ piety_change = -penance;
+ ret = true;
+ }
+ break;
+
+ case DID_SPELL_CASTING:
+ if (you.religion == GOD_TROG)
+ {
+ piety_change = -level;
+ penance = level * 5;
+ ret = true;
+ }
+ break;
+
+ case DID_SPELL_PRACTISE:
+ // Like CAST, but for skill advancement.
+ // Level is number of skill points gained... typically 10 * exerise,
+ // but may be more/less if the skill is at 0 (INT adjustment), or
+ // if the PC's pool is low and makes change.
+ if (you.religion == GOD_SIF_MUNA)
+ {
+ // Old curve: random2(12) <= spell-level, this is similar,
+ // but faster at low levels (to help ease things for low level
+ // Power averages about (level * 20 / 3) + 10 / 3 now. Also
+ // note that spell skill practise comes just after XP gain, so
+ // magical kills tend to do both at the same time (unlike melee).
+ // This means high level spells probably work pretty much like
+ // they used to (use spell, get piety).
+ piety_change = div_rand_round( level + 10, 80 );
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Spell practise, level: %d, dpiety: %d",
+ level, piety_change);
+#endif
+ ret = true;
+ }
+ break;
+
+ case DID_CARDS:
+ if (you.religion == GOD_NEMELEX_XOBEH)
+ {
+ piety_change = level;
+ ret = true;
+ }
+ break;
+
+ case DID_STIMULANTS: // unused
+ case DID_EAT_MEAT: // unused
+ case DID_CREATED_LIFE: // unused
+ case DID_DEDICATED_KILL_NATURAL_EVIL: // unused
+ case DID_NATURAL_EVIL_KILLED_BY_SERVANT: // unused
+ case DID_SPELL_NONUTILITY: // unused
+ default:
+ break;
+ }
+
+ if (piety_change > 0)
+ gain_piety( piety_change );
+ else
+ {
+ const int piety_loss = -piety_change;
+
+ if (piety_loss)
+ {
+ // output guilt message:
+ mprf( "You feel%sguilty.",
+ (piety_loss == 1) ? " a little " :
+ (piety_loss < 5) ? " " :
+ (piety_loss < 10) ? " very "
+ : " extremely " );
+
+ lose_piety( piety_loss );
+ }
+
+ if (you.piety < 1)
+ excommunication();
+ else if (penance) // only if still in religion
+ {
+ god_speaks( you.religion,
+ "\"You will pay for your transgression, mortal!\"" );
+
+ inc_penance( penance );
+ }
+ }
+
+#if DEBUG_DIAGNOSTICS
+ if (ret)
+ {
+ static const char *conducts[] =
+ {
+ "",
+ "Necromancy", "Unholy", "Attack Holy", "Attack Friend",
+ "Friend Died", "Stab", "Poison", "Field Sacrifice",
+ "Kill Living", "Kill Undead", "Kill Demon", "Kill Natural Evil",
+ "Kill Wizard",
+ "Kill Priest", "Kill Angel", "Undead Slave Kill Living",
+ "Servant Kill Living", "Servant Kill Undead",
+ "Servant Kill Demon", "Servant Kill Natural Evil",
+ "Servant Kill Angel",
+ "Spell Memorise", "Spell Cast", "Spell Practise", "Spell Nonutility",
+ "Cards", "Stimulants", "Eat Meat", "Create Life"
+ };
+
+ mprf( MSGCH_DIAGNOSTICS,
+ "conduct: %s; piety: %d (%+d); penance: %d (%+d)",
+ conducts[thing_done],
+ you.piety, piety_change, you.penance[you.religion], penance );
+
}
-} // end done_good()
+#endif
+
+ return (ret);
+}
void gain_piety(char pgn)
{
@@ -1110,10 +1379,20 @@ void gain_piety(char pgn)
}
// slow down gain at upper levels of piety
- if (you.piety > 199
- || (you.piety > 150 && one_chance_in(3))
- || (you.piety > 100 && one_chance_in(3)))
- return;
+ if (you.religion != GOD_SIF_MUNA)
+ {
+ if (you.piety > 199
+ || (you.piety > 150 && one_chance_in(3))
+ || (you.piety > 100 && one_chance_in(3)))
+ return;
+ }
+ else
+ {
+ // Sif Muna has a gentler taper off because training because
+ // naturally slower as the player gains in spell skills.
+ if (you.piety > 150 && one_chance_in(5))
+ return;
+ }
int old_piety = you.piety;
@@ -1121,19 +1400,20 @@ void gain_piety(char pgn)
if (you.piety >= 30 && old_piety < 30)
{
+ take_note(Note(NOTE_GOD_POWER, you.religion, 0));
switch (you.religion)
{
case GOD_NO_GOD:
case GOD_XOM:
case GOD_NEMELEX_XOBEH:
- case GOD_SIF_MUNA:
break;
default:
strcpy(info, "You can now ");
strcat(info,
(you.religion == GOD_ZIN || you.religion == GOD_SHINING_ONE)
? "repel the undead" :
-
+ (you.religion == GOD_SIF_MUNA)
+ ? "tap ambient magical fields" :
(you.religion == GOD_KIKUBAAQUDGHA)
? "recall your undead slaves" :
(you.religion == GOD_YREDELEMNUL)
@@ -1159,6 +1439,7 @@ void gain_piety(char pgn)
if (you.piety >= 50 && old_piety < 50)
{
+ take_note(Note(NOTE_GOD_POWER, you.religion, 1));
switch (you.religion)
{
case GOD_NO_GOD:
@@ -1204,6 +1485,7 @@ void gain_piety(char pgn)
if (you.piety >= 75 && old_piety < 75)
{
+ take_note(Note(NOTE_GOD_POWER, you.religion, 2));
switch (you.religion)
{
case GOD_NO_GOD:
@@ -1242,6 +1524,7 @@ void gain_piety(char pgn)
if (you.piety >= 100 && old_piety < 100)
{
+ take_note(Note(NOTE_GOD_POWER, you.religion, 3));
switch (you.religion)
{
case GOD_NO_GOD:
@@ -1249,6 +1532,7 @@ void gain_piety(char pgn)
case GOD_OKAWARU:
case GOD_NEMELEX_XOBEH:
case GOD_KIKUBAAQUDGHA:
+ case GOD_VEHUMET:
break;
case GOD_SIF_MUNA:
simple_god_message
@@ -1265,8 +1549,6 @@ void gain_piety(char pgn)
? "hurl bolts of divine anger" :
(you.religion == GOD_YREDELEMNUL)
? "drain ambient lifeforce" :
- (you.religion == GOD_VEHUMET)
- ? "tap ambient magical fields" :
(you.religion == GOD_MAKHLEB)
? "hurl Makhleb's greater destruction" :
(you.religion == GOD_TROG)
@@ -1284,6 +1566,7 @@ void gain_piety(char pgn)
if (you.piety >= 120 && old_piety < 120)
{
+ take_note(Note(NOTE_GOD_POWER, you.religion, 4));
switch (you.religion)
{
case GOD_NO_GOD:
@@ -1319,159 +1602,13 @@ void gain_piety(char pgn)
break;
}
}
-} // end gain_piety()
-
-void naughty(char type_naughty, int naughtiness)
-{
- int penance = 0;
- int piety_loss = 0;
-
- // if you currently worship no deity in particular, exit function {dlb}
- if (you.religion == GOD_NO_GOD)
- return;
-
- switch (you.religion)
- {
- case GOD_ZIN:
- switch (type_naughty)
- {
- case NAUGHTY_NECROMANCY:
- case NAUGHTY_UNHOLY:
- case NAUGHTY_ATTACK_HOLY:
- piety_loss = naughtiness;
- penance = piety_loss * 2;
- break;
- case NAUGHTY_ATTACK_FRIEND:
- piety_loss = naughtiness;
- penance = piety_loss * 3;
- break;
- case NAUGHTY_FRIEND_DIES:
- piety_loss = naughtiness;
- break;
- case NAUGHTY_BUTCHER:
- piety_loss = naughtiness;
- if (one_chance_in(3))
- penance = piety_loss;
- break;
- }
- break;
-
- case GOD_SHINING_ONE:
- switch (type_naughty)
- {
- case NAUGHTY_NECROMANCY:
- case NAUGHTY_UNHOLY:
- case NAUGHTY_ATTACK_HOLY:
- piety_loss = naughtiness;
- penance = piety_loss;
- break;
- case NAUGHTY_ATTACK_FRIEND:
- piety_loss = naughtiness;
- penance = piety_loss * 3;
- break;
- case NAUGHTY_FRIEND_DIES:
- piety_loss = naughtiness;
- break;
- case NAUGHTY_BUTCHER:
- piety_loss = naughtiness;
- if (one_chance_in(3))
- penance = piety_loss;
- break;
- case NAUGHTY_STABBING:
- piety_loss = naughtiness;
- if (one_chance_in(5)) // can be accidental so we're nice here
- penance = piety_loss;
- break;
- case NAUGHTY_POISON:
- piety_loss = naughtiness;
- penance = piety_loss * 2;
- break;
- }
- break;
-
- case GOD_ELYVILON:
- switch (type_naughty)
- {
- case NAUGHTY_NECROMANCY:
- case NAUGHTY_UNHOLY:
- case NAUGHTY_ATTACK_HOLY:
- piety_loss = naughtiness;
- penance = piety_loss;
- break;
- case NAUGHTY_KILLING:
- piety_loss = naughtiness;
- penance = piety_loss * 2;
- break;
- case NAUGHTY_ATTACK_FRIEND:
- piety_loss = naughtiness;
- penance = piety_loss * 3;
- break;
- // Healer god gets a bit more upset since you should have
- // used your healing powers to save them.
- case NAUGHTY_FRIEND_DIES:
- piety_loss = naughtiness;
- penance = piety_loss;
- break;
- case NAUGHTY_BUTCHER:
- piety_loss = naughtiness;
- if (one_chance_in(3))
- penance = piety_loss;
- break;
- }
- break;
-
- case GOD_OKAWARU:
- switch (type_naughty)
- {
- case NAUGHTY_ATTACK_FRIEND:
- piety_loss = naughtiness;
- penance = piety_loss * 3;
- break;
- case NAUGHTY_FRIEND_DIES:
- piety_loss = naughtiness;
- break;
- }
- break;
-
- case GOD_TROG:
- switch (type_naughty)
- {
- case NAUGHTY_SPELLCASTING:
- piety_loss = naughtiness;
- // This penance isn't so bad since its much easier to
- // gain piety with Trog than the other gods in this function.
- penance = piety_loss * 10;
- break;
- }
- break;
- }
-
- // exit function early iff piety loss is zero:
- if (piety_loss < 1)
- return;
- // output guilt message:
- strcpy(info, "You feel");
+ if ( you.piety > 160 && old_piety <= 160 &&
+ (you.religion == GOD_SHINING_ONE || you.religion == GOD_ZIN) &&
+ you.num_gifts[you.religion] == 0 )
+ simple_god_message( " will now bless your weapon at an altar...once.");
- strcat(info, (piety_loss == 1) ? " a little " :
- (piety_loss < 5) ? " " :
- (piety_loss < 10) ? " very "
- : " extremely ");
-
- strcat(info, "guilty.");
- mpr(info);
-
- lose_piety(piety_loss);
-
- if (you.piety < 1)
- excommunication();
- else if (penance) // Don't bother unless we're not kicking them out
- {
- //jmf: FIXME: add randomness to following message:
- god_speaks(you.religion, "\"You will pay for your transgression, mortal!\"");
- inc_penance(penance);
- }
-} // end naughty()
+} // end gain_piety()
void lose_piety(char pgn)
{
@@ -1487,6 +1624,11 @@ void lose_piety(char pgn)
// are withheld.
if (!player_under_penance() && you.piety != old_piety)
{
+ if (you.piety <= 160 && old_piety > 160 &&
+ (you.religion == GOD_SHINING_ONE || you.religion == GOD_ZIN) &&
+ you.num_gifts[you.religion] == 0)
+ simple_god_message(" is no longer ready to bless your weapon.");
+
if (you.piety < 120 && old_piety >= 120)
{
switch (you.religion)
@@ -1534,6 +1676,7 @@ void lose_piety(char pgn)
case GOD_OKAWARU:
case GOD_NEMELEX_XOBEH:
case GOD_KIKUBAAQUDGHA:
+ case GOD_VEHUMET:
break;
case GOD_SIF_MUNA:
god_speaks(you.religion,"Sif Muna is no longer protecting you from miscast magic.");
@@ -1549,8 +1692,6 @@ void lose_piety(char pgn)
? "hurl bolts of divine anger" :
(you.religion == GOD_YREDELEMNUL)
? "drain ambient life force" :
- (you.religion == GOD_VEHUMET)
- ? "tap ambient magical fields" :
(you.religion == GOD_MAKHLEB)
? "direct Makhleb's greater destructive powers" :
(you.religion == GOD_TROG)
@@ -1576,7 +1717,7 @@ void lose_piety(char pgn)
case GOD_TROG:
break;
case GOD_VEHUMET:
- simple_god_message(" will longer shield you from summoned creatures.");
+ simple_god_message(" will no longer shield you from summoned creatures.");
break;
default:
strcpy(info, "You can no longer ");
@@ -1654,7 +1795,6 @@ void lose_piety(char pgn)
case GOD_NO_GOD:
case GOD_XOM:
case GOD_NEMELEX_XOBEH:
- case GOD_SIF_MUNA:
break;
default:
strcpy(info, "You can no longer ");
@@ -1666,6 +1806,8 @@ void lose_piety(char pgn)
? "recall your undead slaves" :
(you.religion == GOD_YREDELEMNUL)
? "animate corpses" :
+ (you.religion == GOD_SIF_MUNA)
+ ? "tap ambient magical fields" :
(you.religion == GOD_VEHUMET)
? "gain power from killing in Vehumet's name" :
(you.religion == GOD_MAKHLEB)
@@ -1747,6 +1889,10 @@ void divine_retribution( int god )
{
simple_god_message( " sends the divine host to punish you for your evil ways!", god );
}
+ else
+ {
+ simple_god_message("'s divine host fails to appear.", god);
+ }
}
else
{
@@ -1768,8 +1914,9 @@ void divine_retribution( int god )
dec_penance( GOD_SHINING_ONE, 1 );
}
}
+ break;
}
- break;
+ return;
case GOD_ZIN:
// angels/creeping doom theme:
@@ -1795,6 +1942,10 @@ void divine_retribution( int god )
{
simple_god_message(" sends the divine host to punish you for your evil ways!", god);
}
+ else
+ {
+ simple_god_message("'s divine host fails to appear.", god);
+ }
}
else
{
@@ -1802,8 +1953,9 @@ void divine_retribution( int god )
summon_swarm( you.experience_level * 20, true, false );
simple_god_message(" sends a plague down upon you!", god);
}
+ break;
}
- break;
+ return;
case GOD_MAKHLEB:
// demonic servant theme
@@ -1816,6 +1968,10 @@ void divine_retribution( int god )
simple_god_message(" sends a greater servant after you!",
god);
}
+ else
+ {
+ simple_god_message("'s greater servant is unavoidably detained.", god);
+ }
}
else
{
@@ -1833,6 +1989,8 @@ void divine_retribution( int god )
if (success)
simple_god_message(" sends minions to punish you.", god);
+ else
+ simple_god_message("'s minions fail to arrive.", god);
}
break;
@@ -1854,6 +2012,8 @@ void divine_retribution( int god )
if (success)
simple_god_message(" unleashes Death upon you!", god);
+ else
+ god_speaks(god, "Death has been delayed...for now.");
}
else
{
@@ -1895,6 +2055,8 @@ void divine_retribution( int god )
if (success)
simple_god_message(" sends a servant to punish you.", god);
+ else
+ simple_god_message("'s servant fails to arrive.", god);
}
else
{
@@ -1978,6 +2140,8 @@ void divine_retribution( int god )
if (success)
simple_god_message(" sends monsters to punish you.", god);
+ else
+ simple_god_message(" has no time to punish you...now.", god);
}
break;
@@ -2064,20 +2228,22 @@ void divine_retribution( int god )
if (success)
simple_god_message(" sends forces against you!", god);
+ else
+ simple_god_message("'s forces are busy with other wars.", god);
}
break;
case GOD_VEHUMET:
// conjuration and summoning theme
- simple_god_message("'s vengence finds you.", god);
+ simple_god_message("'s vengeance finds you.", god);
miscast_effect( coinflip() ? SPTYP_CONJURATION : SPTYP_SUMMONING,
8 + you.experience_level, random2avg(98, 3), 100,
"the wrath of Vehumet" );
break;
case GOD_NEMELEX_XOBEH:
- // like Xom, this might actually help the player -- bwr`
- simple_god_message(" makes you to draw from the Deck of Punishment.",
+ // like Xom, this might actually help the player -- bwr
+ simple_god_message(" makes you draw from the Deck of Punishment.",
god);
deck_of_cards(DECK_OF_PUNISHMENT);
break;
@@ -2102,7 +2268,7 @@ void divine_retribution( int god )
case 5:
case 6:
- miscast_effect(SK_DIVINATIONS, 9, 90, 100, "the will of Sif Muna");
+ miscast_effect(SPTYP_DIVINATION, 9, 90, 100, "the will of Sif Muna");
break;
case 7:
@@ -2130,11 +2296,13 @@ void divine_retribution( int god )
return;
}
- // Sometimes divine experiences are overwelming...
+ // Sometimes divine experiences are overwhelming...
if (one_chance_in(5) && you.experience_level < random2(37))
{
- if (coinflip())
+ if (coinflip()) {
+ mpr( "The divine experience confuses you!", MSGCH_WARN);
confuse_player( 3 + random2(10) );
+ }
else
{
if (you.slow < 90)
@@ -2154,6 +2322,8 @@ void excommunication(void)
{
const int old_god = you.religion;
+ take_note(Note(NOTE_LOSE_GOD, old_god));
+
you.duration[DUR_PRAYER] = 0;
you.religion = GOD_NO_GOD;
you.piety = 0;
@@ -2222,6 +2392,44 @@ void excommunication(void)
}
} // end excommunication()
+static bool bless_weapon( int god, int brand, int colour )
+{
+ const int wpn = get_player_wielded_weapon();
+
+ // Assuming the type of weapon is correct, we only need to check
+ // to see if it's an artefact we can successfully clobber:
+ if (!is_fixed_artefact( you.inv[wpn] )
+ && !is_random_artefact( you.inv[wpn] ))
+ {
+ you.duration[DUR_WEAPON_BRAND] = 0; // just in case
+
+ set_equip_desc( you.inv[wpn], ISFLAG_GLOWING );
+ set_item_ego_type( you.inv[wpn], OBJ_WEAPONS, brand );
+ you.inv[wpn].colour = colour;
+
+ do_uncurse_item( you.inv[wpn] );
+ enchant_weapon( ENCHANT_TO_HIT, true );
+ enchant_weapon( ENCHANT_TO_DAM, true );
+
+ you.wield_change = true;
+ you.num_gifts[god]++;
+ take_note(Note(NOTE_GOD_GIFT, you.religion));
+
+ you.flash_colour = colour;
+ viewwindow( true, false );
+
+ mprf( MSGCH_GOD, "Your weapon shines brightly!" );
+ simple_god_message( " booms: Use this gift wisely!" );
+
+ // as currently only Zin and TSO do this is our permabrand effect:
+ holy_word( 100, true );
+ delay(1000);
+
+ return (true);
+ }
+
+ return (false);
+}
void altar_prayer(void)
{
@@ -2239,9 +2447,48 @@ void altar_prayer(void)
mpr( "You kneel at the altar and pray." );
- if (you.religion == GOD_SHINING_ONE || you.religion == GOD_XOM)
+ if (you.religion == GOD_XOM)
return;
+ // TSO blesses long swords with holy wrath
+ if (you.religion == GOD_SHINING_ONE
+ && !you.num_gifts[GOD_SHINING_ONE]
+ && !player_under_penance()
+ && you.piety > 160)
+ {
+ const int wpn = get_player_wielded_weapon();
+
+ if (wpn != -1
+ && weapon_skill( you.inv[wpn] ) == SK_LONG_SWORDS
+ && get_weapon_brand( you.inv[wpn] ) != SPWPN_HOLY_WRATH)
+ {
+ if (bless_weapon( GOD_SHINING_ONE, SPWPN_HOLY_WRATH, YELLOW ))
+ {
+ // convert those demon blades if blessed:
+ if (you.inv[wpn].sub_type == WPN_DEMON_BLADE)
+ you.inv[wpn].sub_type = WPN_BLESSED_BLADE;
+ }
+ }
+ }
+
+ // Zin blesses maces with disruption
+ if (you.religion == GOD_ZIN
+ && !you.num_gifts[GOD_ZIN]
+ && !player_under_penance()
+ && you.piety > 160)
+ {
+ const int wpn = get_player_wielded_weapon();
+
+ if (wpn != -1
+ && (you.inv[wpn].base_type == OBJ_WEAPONS
+ && (you.inv[wpn].sub_type == WPN_MACE
+ || you.inv[wpn].sub_type == WPN_GREAT_MACE))
+ && get_weapon_brand( you.inv[wpn] ) != SPWPN_DISRUPTION)
+ {
+ bless_weapon( GOD_ZIN, SPWPN_DISRUPTION, WHITE );
+ }
+ }
+
i = igrd[you.x_pos][you.y_pos];
while (i != NON_ITEM)
{
@@ -2263,8 +2510,12 @@ void altar_prayer(void)
strcat(info, sacrifice[you.religion - 1]);
mpr(info);
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Sacrifice item value: %d", value);
+#endif
if (mitm[i].base_type == OBJ_CORPSES
|| random2(value) >= 50
+ || (you.religion == GOD_NEMELEX_XOBEH && one_chance_in(50))
|| player_under_penance())
{
gain_piety(1);
@@ -2385,6 +2636,8 @@ void god_pitch(unsigned char which_god)
if (you.worshipped[you.religion] < 100)
you.worshipped[you.religion]++;
+ take_note(Note(NOTE_GET_GOD, you.religion));
+
// Currently penance is just zeroed, this could be much more interesting.
you.penance[you.religion] = 0;
@@ -2410,7 +2663,7 @@ void offer_corpse(int corpse)
strcat(info, sacrifice[you.religion - 1]);
mpr(info);
- done_good(GOOD_HACKED_CORPSE, 10);
+ did_god_conduct(DID_DEDICATED_BUTCHERY, 10);
} // end offer_corpse()
//jmf: moved stuff from items::handle_time()
@@ -2507,8 +2760,17 @@ void handle_god_time(void)
break;
case GOD_SIF_MUNA:
- if (one_chance_in(20))
+ // [dshaligram] Sif Muna is now very patient - has to be
+ // to make up for the new spell training requirements, else
+ // it's practically impossible to get Master of Arcane status.
+ if (one_chance_in(100))
+ {
lose_piety(1);
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS,
+ "Sif Muna piety decay (new piety = %d)", you.piety);
+#endif
+ }
if (you.piety < 1)
excommunication();
break;
diff --git a/crawl-ref/source/religion.h b/crawl-ref/source/religion.h
index 7ca62f4e03..0e4f65a7cf 100644
--- a/crawl-ref/source/religion.h
+++ b/crawl-ref/source/religion.h
@@ -3,6 +3,8 @@
* Summary: Misc religion related functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -14,103 +16,20 @@
#include "enum.h"
-// last updated 03jun2000 {dlb}
-/* ***********************************************************************
- * called from: ouch - religion
- * *********************************************************************** */
void simple_god_message( const char *event, int which_deity = GOD_NO_GOD );
-
-
-// last updated 11jan2001 {mv}
-/* ***********************************************************************
- * called from: chardump - overmap - religion
- * *********************************************************************** */
char *god_name(int which_god,bool long_name=false); //mv
-
-
-// last updated 24may2000 {dlb}
-/* ***********************************************************************
- * called from: religion - spell
- * *********************************************************************** */
void dec_penance(int val);
-
-
-// last updated 24may2000 {dlb}
-/* ***********************************************************************
- * called from: acr - decks - fight - player - religion - spell
- * *********************************************************************** */
+void dec_penance(int god, int val);
void Xom_acts(bool niceness, int sever, bool force_sever);
-
-
-// last updated 24may2000 {dlb}
-/* ***********************************************************************
- * called from: beam - decks - fight - religion
- * *********************************************************************** */
-void done_good(char thing_done, int pgain);
-
-
-// last updated 24may2000 {dlb}
-/* ***********************************************************************
- * called from: ability - religion
- * *********************************************************************** */
+bool did_god_conduct(int thing_done, int pgain);
void excommunication(void);
-
-
-// last updated 24may2000 {dlb}
-/* ***********************************************************************
- * called from: acr - religion - spell
- * *********************************************************************** */
void gain_piety(char pgn);
-
-
-// last updated 24may2000 {dlb}
-/* ***********************************************************************
- * called from: spell - religion
- * *********************************************************************** */
void god_speaks( int god, const char *mesg );
-
-
-// last updated 24may2000 {dlb}
-/* ***********************************************************************
- * called from: ability - religion
- * *********************************************************************** */
void lose_piety(char pgn);
-
-
-// last updated 24may2000 {dlb}
-/* ***********************************************************************
- * called from: acr - beam - fight - it_use2 - item_use - religion - spell -
- * spellbook - spells4
- * *********************************************************************** */
-void naughty(char type_naughty, int naughtiness);
-
-
-// last updated 24may2000 {dlb}
-/* ***********************************************************************
- * called from: food
- * *********************************************************************** */
void offer_corpse(int corpse);
-
-
-// last updated 24may2000 {dlb}
-/* ***********************************************************************
- * called from: acr
- * *********************************************************************** */
void pray(void);
-
-
-// last updated 24may2000 {dlb}
-/* ***********************************************************************
- * called from: items
- * *********************************************************************** */
void handle_god_time(void);
-
-// created 5jan2001 {mv}
-/* ***********************************************************************
- * called from: message, describe
- * *********************************************************************** */
char god_colour(char god);
-
void god_pitch(unsigned char which_god);
#endif
diff --git a/crawl-ref/source/shopping.cc b/crawl-ref/source/shopping.cc
index dee10a8d8c..6f80839df1 100644
--- a/crawl-ref/source/shopping.cc
+++ b/crawl-ref/source/shopping.cc
@@ -3,6 +3,8 @@
* Summary: Shop keeper functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <3> Jul 30 00 JDJ in_a_shop uses shoppy instead of i when calling shop_set_id.
@@ -28,7 +30,9 @@
#include "invent.h"
#include "items.h"
#include "itemname.h"
+#include "itemprop.h"
#include "macro.h"
+#include "notes.h"
#include "player.h"
#include "randart.h"
#include "spl-book.h"
@@ -44,6 +48,66 @@ static void shop_set_ident_type(int i, id_fix_arr &shop_id,
unsigned char base_type, unsigned char sub_type);
static void shop_uninit_id(int i, const id_fix_arr &shop_id);
+static std::string hyphenated_suffix(char prev, char last)
+{
+ std::string s;
+ if (prev > last + 2)
+ s += "</w>-<w>";
+ else if (prev == last + 2)
+ s += (char) (last + 1);
+
+ if (prev != last)
+ s += prev;
+ return (s);
+}
+
+static std::string purchase_keys(const std::string &s)
+{
+ if (s.empty())
+ return "";
+
+ std::string list = "<w>" + s.substr(0, 1);
+ char last = s[0];
+ for (int i = 1; i < (int) s.length(); ++i)
+ {
+ if (s[i] == s[i - 1] + 1)
+ continue;
+
+ char prev = s[i - 1];
+ list += hyphenated_suffix(prev, last);
+ list += (last = s[i]);
+ }
+
+ list += hyphenated_suffix( s[s.length() - 1], last );
+ list += "</w>";
+ return (list);
+}
+
+static void list_shop_keys(const std::string &purchasable)
+{
+ char buf[200];
+ gotoxy(1, 23);
+
+ std::string pkeys = purchase_keys(purchasable);
+ if (pkeys.length())
+ pkeys = "[" + pkeys + "] Buy Item";
+
+ snprintf(buf, sizeof buf,
+ "[<w>x</w>/<w>Esc</w>] Exit [<w>v</w>] Examine Items %s",
+ pkeys.c_str());
+
+ formatted_string fs = formatted_string::parse_string(buf);
+ fs.cprintf("%*s", get_number_of_cols() - fs.length(), "");
+ fs.display();
+ gotoxy(1, 24);
+
+ fs = formatted_string::parse_string(
+ "[<w>?</w>/<w>*</w>] Inventory "
+ "[<w>\\</w>] Known Items");
+ fs.cprintf("%*s", get_number_of_cols() - fs.length(), "");
+ fs.display();
+}
+
char in_a_shop( char shoppy, id_arr id )
{
// easier to work with {dlb}
@@ -56,6 +120,7 @@ char in_a_shop( char shoppy, id_arr id )
unsigned int gp_value = 0;
char i;
unsigned char ft;
+ std::string purchasable;
#ifdef DOS_TERM
char buffer[4800];
@@ -79,6 +144,8 @@ char in_a_shop( char shoppy, id_arr id )
shop_print(info, 20);
more3();
+
+ activate_notes(false); /* should do a better job here */
shop_init_id(shoppy, shop_id);
/* *************************************
@@ -119,22 +186,31 @@ char in_a_shop( char shoppy, id_arr id )
itty = igrd[0][5 + shoppy];
+ purchasable.clear();
for (i = 1; i < 18; i++)
{
- gotoxy(1, i);
+ const char c = i + 96;
- textcolor((i % 2) ? WHITE : LIGHTGREY);
-
- it_name(itty, DESC_NOCAP_A, st_pass);
- putch(i + 96);
- cprintf(" - ");
- cprintf(st_pass);
+ gotoxy(1, i);
gp_value = greedy * item_value( mitm[itty], id );
gp_value /= 10;
if (gp_value <= 1)
gp_value = 1;
+ bool can_afford = (you.gold >= gp_value);
+ textcolor( can_afford ? LIGHTGREEN : LIGHTRED );
+
+ if (can_afford)
+ purchasable += c;
+
+ cprintf("%c - ", c);
+
+ textcolor((i % 2) ? WHITE : LIGHTGREY);
+
+ it_name(itty, DESC_NOCAP_A, st_pass);
+ cprintf("%s", st_pass);
+
std::string desc;
if (is_dumpable_artifact(mitm[itty], Options.verbose_dump))
desc = munge_description(get_item_description(mitm[itty],
@@ -145,10 +221,9 @@ char in_a_shop( char shoppy, id_arr id )
# endif
gotoxy(60, i);
- // cdl - itoa(gp_value, st_pass, 10);
+ textcolor( can_afford ? LIGHTGREEN : LIGHTRED );
snprintf(st_pass, sizeof(st_pass), "%5d", gp_value);
- cprintf(st_pass);
- cprintf(" gold");
+ cprintf("%s gold", st_pass);
if (mitm[itty].link == NON_ITEM)
break;
@@ -157,7 +232,7 @@ char in_a_shop( char shoppy, id_arr id )
textcolor(LIGHTGREY);
- shop_print("Type letter to buy item, x/Esc to leave, ?/* for inventory, v to examine.", 23);
+ list_shop_keys(purchasable);
purchase:
snprintf( info, INFO_SIZE, "You have %d gold piece%s.", you.gold,
@@ -167,7 +242,11 @@ char in_a_shop( char shoppy, id_arr id )
shop_print(info, 19);
textcolor(CYAN);
- shop_print("What would you like to purchase?", 20);
+
+ snprintf(st_pass, sizeof st_pass,
+ "What would you like to %s?",
+ purchasable.length()? "purchase" : "do");
+ shop_print(st_pass, 20);
textcolor(LIGHTGREY);
ft = get_ch();
@@ -175,6 +254,15 @@ char in_a_shop( char shoppy, id_arr id )
if (ft == 'x' || ft == ESCAPE)
goto goodbye;
+ if (ft == '\\')
+ {
+ shop_uninit_id(shoppy, shop_id);
+ check_item_knowledge();
+ shop_init_id(shoppy, shop_id);
+
+ goto print_stock;
+ }
+
if (ft == 'v')
{
textcolor(CYAN);
@@ -262,6 +350,7 @@ char in_a_shop( char shoppy, id_arr id )
#endif
shop_uninit_id( shoppy, shop_id );
+ activate_notes(true);
return 0;
}
@@ -347,7 +436,7 @@ void shop_print( const char *shoppy, char sh_lines )
{
gotoxy(1, sh_lines);
- cprintf(shoppy);
+ cprintf("%s", shoppy);
for (int i = strlen(shoppy); i < 80; i++)
cprintf(" ");
@@ -371,6 +460,21 @@ static void purchase( int shop, int item_got, int cost )
you.gold -= cost;
origin_purchased(mitm[item_got]);
+
+ if ( fully_identified(mitm[item_got]) &&
+ is_interesting_item(mitm[item_got]) ) {
+
+ activate_notes(true);
+
+ char buf[ITEMNAME_SIZE];
+ char buf2[ITEMNAME_SIZE];
+ item_name( mitm[item_got], DESC_NOCAP_A, buf );
+ strcpy(buf2, origin_desc(mitm[item_got]).c_str());
+ take_note(Note(NOTE_ID_ITEM, 0, 0, buf, buf2));
+
+ activate_notes(false);
+ }
+
int num = move_item_to_player( item_got, mitm[item_got].quantity, true );
// Shopkeepers will now place goods you can't carry outside the shop.
@@ -498,7 +602,6 @@ unsigned int item_value( item_def item, id_arr id, bool ident )
item.flags = (ident) ? (item.flags | ISFLAG_IDENT_MASK) : (item.flags);
int valued = 0;
- int charge_value = 0;
switch (item.base_type)
{
@@ -618,6 +721,7 @@ unsigned int item_value( item_def item, id_arr id, bool ident )
break;
case WPN_LONG_SWORD:
+ case WPN_LONGBOW:
case WPN_SCIMITAR:
valued += 45;
break;
@@ -647,8 +751,9 @@ unsigned int item_value( item_def item, id_arr id, bool ident )
valued += 65;
break;
- case WPN_GREAT_FLAIL:
- valued += 75;
+ case WPN_DIRE_FLAIL:
+ case WPN_LOCHABER_AXE:
+ valued += 90;
break;
case WPN_EVENINGSTAR:
@@ -660,22 +765,24 @@ unsigned int item_value( item_def item, id_arr id, bool ident )
break;
case WPN_DOUBLE_SWORD:
- valued += 200;
+ valued += 100;
break;
case WPN_DEMON_WHIP:
- valued += 230;
+ valued += 130;
break;
case WPN_QUICK_BLADE:
case WPN_DEMON_TRIDENT:
- valued += 250;
+ valued += 150;
break;
case WPN_KATANA:
case WPN_TRIPLE_SWORD:
case WPN_DEMON_BLADE:
- valued += 300;
+ case WPN_BLESSED_BLADE:
+ case WPN_LAJATANG:
+ valued += 200;
break;
}
@@ -737,15 +844,15 @@ unsigned int item_value( item_def item, id_arr id, bool ident )
}
// elf/dwarf
- if (cmp_equip_race( item, ISFLAG_ELVEN )
- || cmp_equip_race( item, ISFLAG_DWARVEN ))
+ if (get_equip_race(item) == ISFLAG_ELVEN
+ || get_equip_race(item) == ISFLAG_DWARVEN)
{
valued *= 12;
valued /= 10;
}
// value was "6" but comment read "orc", so I went with comment {dlb}
- if (cmp_equip_race( item, ISFLAG_ORCISH ))
+ if (get_equip_race(item) == ISFLAG_ORCISH)
{
valued *= 8;
valued /= 10;
@@ -795,7 +902,7 @@ unsigned int item_value( item_def item, id_arr id, bool ident )
valued += 50;
}
else if (item_ident( item, ISFLAG_KNOW_TYPE )
- && !cmp_equip_desc( item, 0 ))
+ && get_equip_desc(item) != 0)
{
valued += 20;
}
@@ -823,7 +930,7 @@ unsigned int item_value( item_def item, id_arr id, bool ident )
case MI_DART:
case MI_LARGE_ROCK:
case MI_STONE:
- case MI_EGGPLANT:
+ case MI_NONE:
valued++;
break;
case MI_ARROW:
@@ -892,6 +999,8 @@ unsigned int item_value( item_def item, id_arr id, bool ident )
break;
case ARM_BANDED_MAIL:
+ case ARM_CENTAUR_BARDING:
+ case ARM_NAGA_BARDING:
valued += 150;
break;
@@ -1006,14 +1115,14 @@ unsigned int item_value( item_def item, id_arr id, bool ident )
valued /= 10;
}
- if (cmp_equip_race( item, ISFLAG_ELVEN )
- || cmp_equip_race( item, ISFLAG_DWARVEN ))
+ if (get_equip_race(item) == ISFLAG_ELVEN
+ || get_equip_race(item) == ISFLAG_DWARVEN)
{
valued *= 12;
valued /= 10;
}
- if (cmp_equip_race( item, ISFLAG_ORCISH ))
+ if (get_equip_race(item) == ISFLAG_ORCISH)
{
valued *= 8;
valued /= 10;
@@ -1046,7 +1155,7 @@ unsigned int item_value( item_def item, id_arr id, bool ident )
valued += 50;
}
else if (item_ident( item, ISFLAG_KNOW_TYPE )
- && !cmp_equip_desc( item, 0 ))
+ && get_equip_desc(item) != 0)
{
valued += 20;
}
@@ -1059,100 +1168,72 @@ unsigned int item_value( item_def item, id_arr id, bool ident )
break;
case OBJ_WANDS:
- charge_value = 0;
- if (id[0][item.sub_type])
+ if (!id[ IDTYPE_WANDS ][item.sub_type])
+ valued += 200;
+ else
{
switch (item.sub_type)
{
- case WAND_FIREBALL:
- case WAND_LIGHTNING:
- valued += 20;
- charge_value += 5;
- break;
-
- case WAND_DRAINING:
- valued += 20;
- charge_value += 4;
- break;
-
- case WAND_DISINTEGRATION:
- valued += 17;
- charge_value += 4;
+ case WAND_HASTING:
+ case WAND_HEALING:
+ valued += 300;
break;
- case WAND_POLYMORPH_OTHER:
- valued += 15;
- charge_value += 4;
+ case WAND_TELEPORTATION:
+ valued += 250;
break;
case WAND_COLD:
- case WAND_ENSLAVEMENT:
case WAND_FIRE:
- case WAND_HASTING:
- valued += 15;
- charge_value += 3;
+ case WAND_FIREBALL:
+ valued += 200;
break;
case WAND_INVISIBILITY:
- valued += 15;
- charge_value += 2;
- break;
-
- case WAND_RANDOM_EFFECTS:
- valued += 13;
- charge_value += 3;
- break;
-
- case WAND_PARALYSIS:
- valued += 12;
- charge_value += 3;
+ case WAND_DRAINING:
+ case WAND_LIGHTNING:
+ valued += 175;
break;
- case WAND_SLOWING:
- valued += 10;
- charge_value += 3;
+ case WAND_DISINTEGRATION:
+ valued += 120;
break;
- case WAND_CONFUSION:
case WAND_DIGGING:
- case WAND_TELEPORTATION:
- valued += 10;
- charge_value += 2;
- break;
-
- case WAND_HEALING:
- valued += 7;
- charge_value += 3;
+ valued += 100;
break;
case WAND_FLAME:
case WAND_FROST:
- valued += 5;
- charge_value += 2;
+ case WAND_PARALYSIS:
+ valued += 75;
break;
- case WAND_MAGIC_DARTS:
- valued += 3;
- charge_value++;
+ case WAND_ENSLAVEMENT:
+ case WAND_POLYMORPH_OTHER:
+ valued += 63;
break;
- default: // no default charge_value ??? 15jan2000 {dlb}
- valued += 10;
+ case WAND_SLOWING:
+ valued += 50;
+ break;
+
+ case WAND_CONFUSION:
+ case WAND_MAGIC_DARTS:
+ case WAND_RANDOM_EFFECTS:
+ default:
+ valued += 45;
break;
}
if (item_ident( item, ISFLAG_KNOW_PLUSES ))
{
- valued += item.plus * charge_value;
+ if (item.plus == 0)
+ valued -= 50;
+ else
+ valued = (valued * (item.plus + 45)) / 50;
}
-
- valued *= 3;
-
- if (item.plus == 0)
- valued = 3; // change if wands are rechargeable!
}
- else
- valued = 35; // = 10;
break;
case OBJ_POTIONS:
@@ -1382,6 +1463,7 @@ unsigned int item_value( item_def item, id_arr id, bool ident )
break;
case RING_SUSTAIN_ABILITIES:
case RING_SUSTENANCE:
+ case RING_TELEPORTATION: // usually cursed
valued += 25;
break;
case RING_SEE_INVISIBLE:
@@ -1394,9 +1476,6 @@ unsigned int item_value( item_def item, id_arr id, bool ident )
case RING_STRENGTH:
valued += 10;
break;
- case RING_TELEPORTATION:
- valued -= 10;
- break;
case RING_HUNGER:
valued -= 50;
break;
@@ -1503,7 +1582,7 @@ unsigned int item_value( item_def item, id_arr id, bool ident )
break;
case OBJ_STAVES:
- if (item_not_ident( item, ISFLAG_KNOW_TYPE ))
+ if (!item_ident( item, ISFLAG_KNOW_TYPE ))
valued = 120;
else if (item.sub_type == STAFF_SMITING
|| item.sub_type == STAFF_STRIKING
@@ -1514,6 +1593,10 @@ unsigned int item_value( item_def item, id_arr id, bool ident )
}
else
valued = 250;
+
+ if (item_is_rod( item ) && item_ident( item, ISFLAG_KNOW_PLUSES ))
+ valued += 50 * (item.plus2 / ROD_CHARGE_MULT);
+
break;
case OBJ_ORBS:
@@ -1593,8 +1676,10 @@ const char *shop_name(int sx, int sy)
char st_p[ITEMNAME_SIZE];
- make_name( cshop->keeper_name[0], cshop->keeper_name[1],
- cshop->keeper_name[2], 3, st_p );
+ unsigned long seed = static_cast<unsigned long>( cshop->keeper_name[0] )
+ | (static_cast<unsigned long>( cshop->keeper_name[1] ) << 8)
+ | (static_cast<unsigned long>( cshop->keeper_name[1] ) << 16);
+ make_name( seed, false, st_p );
strcpy(sh_name, st_p);
strcat(sh_name, "'s ");
@@ -1630,3 +1715,4 @@ const char *shop_name(int sx, int sy)
return (sh_name);
}
+
diff --git a/crawl-ref/source/shopping.h b/crawl-ref/source/shopping.h
index 8891f16eb9..0de4edb2bd 100644
--- a/crawl-ref/source/shopping.h
+++ b/crawl-ref/source/shopping.h
@@ -3,6 +3,8 @@
* Summary: Shop keeper functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
diff --git a/crawl-ref/source/skills.cc b/crawl-ref/source/skills.cc
index 9dc63d54f0..3bb6a54119 100644
--- a/crawl-ref/source/skills.cc
+++ b/crawl-ref/source/skills.cc
@@ -3,6 +3,8 @@
* Summary: Skill exercising functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <3> 8/08/99 BWR Increased skill cost in midgame
@@ -21,6 +23,7 @@
#include "externs.h"
#include "macro.h"
+#include "notes.h"
#include "player.h"
#include "skills2.h"
#include "stuff.h"
@@ -38,7 +41,7 @@
#define MAX_COST_LIMIT 250
#define MAX_SPENDING_LIMIT 250
-static void exercise2( char exsk );
+static int exercise2( int exsk );
// These values were calculated by running a simulation of gaining skills.
// The goal is to try and match the old cost system which used the player's
@@ -146,27 +149,37 @@ static int calc_skill_cost( int skill_cost_level, int skill_level )
return (ret);
}
-void exercise(char exsk, int deg)
+// returns total number of skill points gained
+int exercise(int exsk, int deg)
{
- if (you.exp_available > 0 && you.skills[exsk] < 27)
+ int ret = 0;
+
+ while (deg > 0)
{
- while (deg > 0)
- {
- if (!you.practise_skill[exsk] && !one_chance_in(4))
- break;
+ if (you.exp_available <= 0 || you.skills[exsk] >= 27)
+ break;
- if (you.skills[exsk] >= 27)
- break;
+ if (you.practise_skill[exsk] || one_chance_in(4))
+ ret += exercise2( exsk );
- exercise2( exsk );
- deg--;
- }
+ deg--;
}
- return;
+#ifdef DEBUG_DIAGNOSTICS
+ if (ret)
+ {
+ mprf(MSGCH_DIAGNOSTICS,
+ "Exercised %s (deg: %d) by %d",
+ skill_name(exsk),
+ deg,
+ ret);
+ }
+#endif
+
+ return (ret);
} // end exercise()
-static void exercise2( char exsk )
+static int exercise2( int exsk )
{
int deg = 1;
int bonus = 0;
@@ -237,7 +250,7 @@ static void exercise2( char exsk )
|| you.skills[SK_EARTH_MAGIC] > you.skills[exsk]))
{
if (one_chance_in(3))
- return;
+ return (0);
}
// some are direct opposites
@@ -247,7 +260,7 @@ static void exercise2( char exsk )
{
// of course, this is cumulative with the one above.
if (!one_chance_in(3))
- return;
+ return (0);
}
if ((exsk == SK_AIR_MAGIC || exsk == SK_EARTH_MAGIC)
@@ -255,7 +268,7 @@ static void exercise2( char exsk )
|| you.skills[SK_EARTH_MAGIC] > you.skills[exsk]))
{
if (!one_chance_in(3))
- return;
+ return (0);
}
// experimental restriction (too many spell schools) -- bwr
@@ -270,7 +283,7 @@ static void exercise2( char exsk )
// Things get progressively harder, but not harder than
// the Fire-Air or Ice-Earth level.
if (skill_rank > 3 && one_chance_in(10 - skill_rank))
- return;
+ return (0);
}
int fraction = 0;
@@ -351,6 +364,9 @@ static void exercise2( char exsk )
}
}
+ if (skill_inc <= 0)
+ return (0);
+
you.skill_points[exsk] += skill_inc;
you.exp_available -= skill_change;
@@ -379,15 +395,27 @@ static void exercise2( char exsk )
*/
if (you.skill_points[exsk] >
- (skill_exp_needed(you.skills[exsk] + 2)
- * species_skills(exsk, you.species) / 100))
+ (skill_exp_needed(you.skills[exsk] + 2)
+ * species_skills(exsk, you.species) / 100))
{
- strcpy(info, "Your ");
- strcat(info, skill_name(exsk));
- strcat(info, " skill increases!");
- mpr(info, MSGCH_INTRINSIC_GAIN);
-
+
you.skills[exsk]++;
+ take_note(Note(NOTE_GAIN_SKILL, exsk, you.skills[exsk]));
+
+ if (you.skills[exsk] == 27) {
+ snprintf( info, INFO_SIZE, "You have mastered %s!",
+ skill_name( exsk ) );
+ }
+ else if (you.skills[exsk] == 1) {
+ snprintf( info, INFO_SIZE, "You have gained %s skill!",
+ skill_name( exsk ) );
+ }
+ else {
+ snprintf( info, INFO_SIZE, "Your %s skill increases to level %d!",
+ skill_name( exsk ), you.skills[exsk] );
+ }
+
+ mpr( info, MSGCH_INTRINSIC_GAIN );
// Recalculate this skill's order for tie breaking skills
// at its new level. See skills2.cc::init_skill_order()
@@ -405,8 +433,7 @@ static void exercise2( char exsk )
if (exsk == SK_FIGHTING)
calc_hp();
- if (exsk == SK_INVOCATIONS || exsk == SK_EVOCATIONS
- || exsk == SK_SPELLCASTING)
+ if (exsk == SK_INVOCATIONS || exsk == SK_SPELLCASTING)
{
calc_mp();
}
@@ -438,4 +465,5 @@ static void exercise2( char exsk )
redraw_skill( you.your_name, player_title() );
}
}
+ return (skill_inc);
} // end exercise2()
diff --git a/crawl-ref/source/skills.h b/crawl-ref/source/skills.h
index 10afa1df8a..bdc8afb6c5 100644
--- a/crawl-ref/source/skills.h
+++ b/crawl-ref/source/skills.h
@@ -3,6 +3,8 @@
* Summary: Skill exercising functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -20,7 +22,7 @@ void calc_total_skill_points( void );
* called from: ability - bang - beam - debug - fight - it_use3 - item_use -
* items - misc - spell
* *********************************************************************** */
-void exercise(char exsk, int deg);
+int exercise(int exsk, int deg);
#endif
diff --git a/crawl-ref/source/skills2.cc b/crawl-ref/source/skills2.cc
index f4012d0462..42f42a1f85 100644
--- a/crawl-ref/source/skills2.cc
+++ b/crawl-ref/source/skills2.cc
@@ -30,11 +30,12 @@
#include "externs.h"
#include "fight.h"
+#include "itemprop.h"
+#include "menu.h"
#include "player.h"
#include "randart.h"
#include "religion.h"
#include "stuff.h"
-#include "wpn-misc.h"
#include "view.h"
/* jmf: some references for words I used below:
@@ -61,7 +62,7 @@ const char *skills[50][6] = {
{"Bows", "Shooter", "Yeoman", "Archer", "Merry %s", "Merry %s"},
{"Crossbows", "Shooter", "Sharpshooter", "Archer", "%s Ballista", "%s Ballista"}, // 10
{"Darts", "Dart Thrower", "Hurler", "Hurler, First Class", "%s Darts Champion", "Universal Darts Champion"},
- {"Throwing", "Chucker", "Thrower", "Deadly Accurate", "Hawkeye", "Sniper"},
+ {"Ranged Combat", "Chucker", "Thrower", "Deadly Accurate", "Hawkeye", "Sniper"},
{"Armour", "Covered", "Protected", "Tortoise", "Impregnable", "Invulnerable"},
{"Dodging", "Ducker", "Dodger", "Nimble", "Spry", "Acrobat"},
@@ -136,7 +137,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
100, // SK_BOWS
100, // SK_CROSSBOWS
100, // SK_DARTS
- 100, // SK_THROWING
+ 100, // SK_RANGED_COMBAT
100, // SK_ARMOUR
100, // SK_DODGING
100, // SK_STEALTH
@@ -179,7 +180,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
60, // SK_BOWS
100, // SK_CROSSBOWS
90, // SK_DARTS
- 80, // SK_THROWING
+ 80, // SK_RANGED_COMBAT
120, // SK_ARMOUR
80, // SK_DODGING
80, // SK_STEALTH
@@ -222,7 +223,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
60, // SK_BOWS
100, // SK_CROSSBOWS
90, // SK_DARTS
- 80, // SK_THROWING
+ 80, // SK_RANGED_COMBAT
110, // SK_ARMOUR
90, // SK_DODGING
90, // SK_STEALTH
@@ -265,7 +266,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
70, // SK_BOWS
100, // SK_CROSSBOWS
90, // SK_DARTS
- 80, // SK_THROWING
+ 80, // SK_RANGED_COMBAT
140, // SK_ARMOUR
75, // SK_DODGING
70, // SK_STEALTH
@@ -308,7 +309,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
74, // SK_BOWS
75, // SK_CROSSBOWS
75, // SK_DARTS
- 80, // SK_THROWING
+ 80, // SK_RANGED_COMBAT
140, // SK_ARMOUR
70, // SK_DODGING
65, // SK_STEALTH
@@ -351,7 +352,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
100, // SK_BOWS
100, // SK_CROSSBOWS
100, // SK_DARTS
- 70, // SK_THROWING
+ 70, // SK_RANGED_COMBAT
140, // SK_ARMOUR
70, // SK_DODGING
75, // SK_STEALTH
@@ -394,7 +395,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
150, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
- 120, // SK_THROWING
+ 120, // SK_RANGED_COMBAT
70, // SK_ARMOUR
120, // SK_DODGING
150, // SK_STEALTH
@@ -437,7 +438,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
140, // SK_BOWS
100, // SK_CROSSBOWS
120, // SK_DARTS
- 115, // SK_THROWING
+ 115, // SK_RANGED_COMBAT
60, // SK_ARMOUR
110, // SK_DODGING
140, // SK_STEALTH
@@ -480,7 +481,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
70, // SK_BOWS
90, // SK_CROSSBOWS
50, // SK_DARTS
- 60, // SK_THROWING
+ 60, // SK_RANGED_COMBAT
150, // SK_ARMOUR
70, // SK_DODGING
60, // SK_STEALTH
@@ -523,7 +524,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
120, // SK_BOWS
120, // SK_CROSSBOWS
130, // SK_DARTS
- 130, // SK_THROWING
+ 130, // SK_RANGED_COMBAT
90, // SK_ARMOUR
140, // SK_DODGING
150, // SK_STEALTH
@@ -566,7 +567,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
80, // SK_BOWS
90, // SK_CROSSBOWS
50, // SK_DARTS
- 60, // SK_THROWING
+ 60, // SK_RANGED_COMBAT
140, // SK_ARMOUR
70, // SK_DODGING
60, // SK_STEALTH
@@ -609,7 +610,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
140, // SK_BOWS
140, // SK_CROSSBOWS
140, // SK_DARTS
- 140, // SK_THROWING
+ 140, // SK_RANGED_COMBAT
140, // SK_ARMOUR
140, // SK_DODGING
140, // SK_STEALTH
@@ -652,7 +653,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
- 120, // SK_THROWING
+ 120, // SK_RANGED_COMBAT
150, // SK_ARMOUR
150, // SK_DODGING
40, // SK_STEALTH
@@ -695,7 +696,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
100, // SK_BOWS
90, // SK_CROSSBOWS
60, // SK_DARTS
- 100, // SK_THROWING
+ 100, // SK_RANGED_COMBAT
150, // SK_ARMOUR
70, // SK_DODGING
70, // SK_STEALTH
@@ -738,7 +739,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
150, // SK_BOWS
180, // SK_CROSSBOWS
150, // SK_DARTS
- 100, // SK_THROWING
+ 100, // SK_RANGED_COMBAT
140, // SK_ARMOUR
150, // SK_DODGING
200, // SK_STEALTH
@@ -781,7 +782,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
180, // SK_BOWS
180, // SK_CROSSBOWS
180, // SK_DARTS
- 130, // SK_THROWING
+ 130, // SK_RANGED_COMBAT
150, // SK_ARMOUR
130, // SK_DODGING
250, // SK_STEALTH
@@ -824,7 +825,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
150, // SK_BOWS
150, // SK_CROSSBOWS
150, // SK_DARTS
- 150, // SK_THROWING
+ 150, // SK_RANGED_COMBAT
170, // SK_ARMOUR
130, // SK_DODGING
100, // SK_STEALTH
@@ -867,7 +868,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
- 120, // SK_THROWING
+ 120, // SK_RANGED_COMBAT
200, // SK_ARMOUR
120, // SK_DODGING
120, // SK_STEALTH
@@ -889,7 +890,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
100, // SK_TRANSMIGRATION
100, // SK_DIVINATIONS
70, // SK_FIRE_MAGIC
- 150, // SK_ICE_MAGIC
+ 135, // SK_ICE_MAGIC
100, // SK_AIR_MAGIC
100, // SK_EARTH_MAGIC
100, // SK_POISON_MAGIC
@@ -910,7 +911,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
- 120, // SK_THROWING
+ 120, // SK_RANGED_COMBAT
200, // SK_ARMOUR
120, // SK_DODGING
120, // SK_STEALTH
@@ -931,7 +932,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
100, // SK_TRANSLOCATIONS
100, // SK_TRANSMIGRATION
100, // SK_DIVINATIONS
- 150, // SK_FIRE_MAGIC
+ 135, // SK_FIRE_MAGIC
70, // SK_ICE_MAGIC
100, // SK_AIR_MAGIC
100, // SK_EARTH_MAGIC
@@ -953,7 +954,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
- 120, // SK_THROWING
+ 120, // SK_RANGED_COMBAT
200, // SK_ARMOUR
120, // SK_DODGING
120, // SK_STEALTH
@@ -996,7 +997,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
- 120, // SK_THROWING
+ 120, // SK_RANGED_COMBAT
200, // SK_ARMOUR
120, // SK_DODGING
120, // SK_STEALTH
@@ -1039,7 +1040,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
- 120, // SK_THROWING
+ 120, // SK_RANGED_COMBAT
200, // SK_ARMOUR
120, // SK_DODGING
120, // SK_STEALTH
@@ -1082,7 +1083,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
- 120, // SK_THROWING
+ 120, // SK_RANGED_COMBAT
200, // SK_ARMOUR
120, // SK_DODGING
120, // SK_STEALTH
@@ -1106,7 +1107,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
100, // SK_FIRE_MAGIC
100, // SK_ICE_MAGIC
70, // SK_AIR_MAGIC
- 150, // SK_EARTH_MAGIC
+ 135, // SK_EARTH_MAGIC
100, // SK_POISON_MAGIC
100, // SK_INVOCATIONS
100, // SK_EVOCATIONS
@@ -1125,7 +1126,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
- 120, // SK_THROWING
+ 120, // SK_RANGED_COMBAT
200, // SK_ARMOUR
120, // SK_DODGING
120, // SK_STEALTH
@@ -1168,7 +1169,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
- 120, // SK_THROWING
+ 120, // SK_RANGED_COMBAT
200, // SK_ARMOUR
120, // SK_DODGING
120, // SK_STEALTH
@@ -1211,7 +1212,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
- 120, // SK_THROWING
+ 120, // SK_RANGED_COMBAT
200, // SK_ARMOUR
120, // SK_DODGING
120, // SK_STEALTH
@@ -1254,7 +1255,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
- 120, // SK_THROWING
+ 120, // SK_RANGED_COMBAT
200, // SK_ARMOUR
120, // SK_DODGING
120, // SK_STEALTH
@@ -1297,7 +1298,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
- 120, // SK_THROWING
+ 120, // SK_RANGED_COMBAT
200, // SK_ARMOUR
120, // SK_DODGING
120, // SK_STEALTH
@@ -1340,7 +1341,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
- 120, // SK_THROWING
+ 120, // SK_RANGED_COMBAT
200, // SK_ARMOUR
120, // SK_DODGING
120, // SK_STEALTH
@@ -1383,7 +1384,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
60, // SK_BOWS
85, // SK_CROSSBOWS
80, // SK_DARTS
- 60, // SK_THROWING
+ 60, // SK_RANGED_COMBAT
180, // SK_ARMOUR
170, // SK_DODGING
200, // SK_STEALTH
@@ -1426,7 +1427,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
110, // SK_BOWS
110, // SK_CROSSBOWS
110, // SK_DARTS
- 110, // SK_THROWING
+ 110, // SK_RANGED_COMBAT
110, // SK_ARMOUR
110, // SK_DODGING
110, // SK_STEALTH
@@ -1469,7 +1470,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
70, // SK_BOWS
100, // SK_CROSSBOWS
70, // SK_DARTS
- 90, // SK_THROWING
+ 90, // SK_RANGED_COMBAT
170, // SK_ARMOUR
50, // SK_DODGING
50, // SK_STEALTH
@@ -1512,7 +1513,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
90, // SK_BOWS
90, // SK_CROSSBOWS
90, // SK_DARTS
- 90, // SK_THROWING
+ 90, // SK_RANGED_COMBAT
80, // SK_ARMOUR
80, // SK_DODGING
130, // SK_STEALTH
@@ -1555,7 +1556,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
110, // SK_BOWS
110, // SK_CROSSBOWS
110, // SK_DARTS
- 110, // SK_THROWING
+ 110, // SK_RANGED_COMBAT
110, // SK_ARMOUR
110, // SK_DODGING
110, // SK_STEALTH
@@ -1598,7 +1599,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
130, // SK_BOWS
130, // SK_CROSSBOWS
130, // SK_DARTS
- 130, // SK_THROWING
+ 130, // SK_RANGED_COMBAT
110, // SK_ARMOUR
110, // SK_DODGING
80, // SK_STEALTH
@@ -1641,7 +1642,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
80, // SK_BOWS
80, // SK_CROSSBOWS
90, // SK_DARTS
- 90, // SK_THROWING
+ 90, // SK_RANGED_COMBAT
90, // SK_ARMOUR
90, // SK_DODGING
100, // SK_STEALTH
@@ -1684,7 +1685,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
140, // SK_BOWS
140, // SK_CROSSBOWS
100, // SK_DARTS
- 100, // SK_THROWING
+ 100, // SK_RANGED_COMBAT
160, // SK_ARMOUR
60, // SK_DODGING
90, // SK_STEALTH
@@ -1732,7 +1733,7 @@ const int spec_skills[ NUM_SPECIES ][40] = {
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
- 120, // SK_THROWING
+ 120, // SK_RANGED_COMBAT
200, // SK_ARMOUR
120, // SK_DODGING
120, // SK_STEALTH
@@ -1787,11 +1788,38 @@ JOB_PALADIN:
************************************************************* */
+static const int skill_display_order[] = {
+ SK_FIGHTING, SK_SHORT_BLADES, SK_LONG_SWORDS, SK_AXES,
+ SK_MACES_FLAILS, SK_POLEARMS, SK_STAVES, SK_UNARMED_COMBAT,
+
+ SK_BLANK_LINE,
+
+ SK_RANGED_COMBAT, SK_SLINGS, SK_BOWS, SK_CROSSBOWS, SK_DARTS,
+
+ SK_BLANK_LINE,
+
+ SK_ARMOUR, SK_DODGING, SK_STEALTH, SK_STABBING, SK_SHIELDS, SK_TRAPS_DOORS,
+
+ SK_BLANK_LINE,
+ SK_COLUMN_BREAK,
+
+ SK_SPELLCASTING, SK_CONJURATIONS, SK_ENCHANTMENTS, SK_SUMMONINGS,
+ SK_NECROMANCY, SK_TRANSLOCATIONS, SK_TRANSMIGRATION, SK_DIVINATIONS,
+ SK_FIRE_MAGIC, SK_ICE_MAGIC, SK_AIR_MAGIC, SK_EARTH_MAGIC, SK_POISON_MAGIC,
+
+ SK_BLANK_LINE,
+
+ SK_INVOCATIONS, SK_EVOCATIONS,
+};
+
+static const int ndisplayed_skills =
+ sizeof(skill_display_order) / sizeof(*skill_display_order);
+
void show_skills(void)
{
int i;
int x;
- char lcount;
+ menu_letter lcount;
const int num_lines = get_number_of_lines();
@@ -1823,21 +1851,30 @@ void show_skills(void)
// Don't want the help line to appear too far down a big window.
int bottom_line = ((num_lines > 30) ? 30 : num_lines);
- for (x = 0; x < NUM_SKILLS; x++)
+ for (i = 0; i < ndisplayed_skills; ++i)
{
- /* spells in second column */
- if ((x == SK_SPELLCASTING && scrcol != 40) || scrln > bottom_line - 3)
+ x = skill_display_order[i];
+
+ if (scrln > bottom_line - 3 || x == SK_COLUMN_BREAK)
{
- scrln = 3;
- scrcol = 40;
+ if (scrcol != 40)
+ {
+ scrln = 3;
+ scrcol = 40;
+ }
+ if (x == SK_COLUMN_BREAK)
+ continue;
+ }
+
+ if (x == SK_BLANK_LINE)
+ {
+ scrln++;
+ continue;
}
gotoxy(scrcol, scrln);
-#if DEBUG_DIAGNOSTICS
- // In diagnostic mode we show skills at 0, but only real skills
- if (x != SK_UNUSED_1 && (x <= SK_UNARMED_COMBAT || x >= SK_SPELLCASTING))
-#else
+#ifndef DEBUG_DIAGNOSTICS
if (you.skills[x] > 0)
#endif
{
@@ -1853,19 +1890,9 @@ void show_skills(void)
if (you.skills[x] == 0)
putch(' ');
else
- {
- putch(lcount);
- if (lcount == 'z')
- lcount = 'A';
- else
- lcount++;
- }
+ putch(lcount++);
#else
- putch(lcount);
- if (lcount == 'z')
- lcount = 'A';
- else
- lcount++;
+ putch(lcount++);
#endif
cprintf( " %c %-14s Skill %2d",
@@ -1885,18 +1912,19 @@ void show_skills(void)
const int prev_needed = skill_exp_needed(you.skills[x] + 1);
const int spec_abil = species_skills(x, you.species);
- cprintf( " (%d)",
- (((needed * spec_abil) / 100 - you.skill_points[x]) * 10) /
- (((needed - prev_needed) * spec_abil) / 100) );
- }
+ int percent_done = ((you.skill_points[x] - (prev_needed * spec_abil) / 100) * 100) / (((needed - prev_needed) * spec_abil) / 100);
- scrln++;
- }
+ if ( percent_done == 100 )
+ --percent_done;
+ if ( percent_done == 0 )
+ ++percent_done;
+
+ if ( !Options.increasing_skill_progress )
+ cprintf( " (%d)", (100 - percent_done) / 10 );
+ else
+ cprintf( " (%2d%%)", (percent_done / 5) * 5 );
+ }
- /* Extra CR between classes of weapons and such things */
- if (x == SK_STAVES || x == SK_THROWING || x == SK_TRAPS_DOORS
- || x == SK_UNARMED_COMBAT || x == SK_POISON_MAGIC)
- {
scrln++;
}
}
@@ -1919,21 +1947,22 @@ void show_skills(void)
{
lcount = 'a'; // toggle skill practise
- for (i = 0; i < 50; i++)
+ for (i = 0; i < ndisplayed_skills; i++)
{
- if (you.skills[i] == 0)
+ x = skill_display_order[i];
+ if (x == SK_BLANK_LINE || x == SK_COLUMN_BREAK)
+ continue;
+
+ if (you.skills[x] == 0)
continue;
if (get_thing == lcount)
{
- you.practise_skill[i] = (you.practise_skill[i]) ? 0 : 1;
+ you.practise_skill[x] = !you.practise_skill[x];
break;
}
- if (lcount == 'z')
- lcount = 'A';
- else
- lcount++;
+ ++lcount;
}
goto reprint_stuff;
@@ -1947,7 +1976,7 @@ void show_skills(void)
}
-const char *skill_name(unsigned char which_skill)
+const char *skill_name(int which_skill)
{
return (skills[which_skill][0]);
} // end skill_name()
@@ -2038,10 +2067,9 @@ const char *player_title( void )
return (skill_title( best, you.skills[ best ] ));
} // end player_title()
-unsigned char best_skill( unsigned char min_skill, unsigned char max_skill,
- unsigned char excl_skill )
+int best_skill( int min_skill, int max_skill, int excl_skill )
{
- unsigned char ret = SK_FIGHTING;
+ int ret = SK_FIGHTING;
unsigned int best_skill_level = 0;
unsigned int best_position = 1000;
@@ -2179,14 +2207,11 @@ int calc_mp(void)
int spell_extra = (you.experience_level * you.skills[SK_SPELLCASTING]) / 4;
int invoc_extra = (you.experience_level * you.skills[SK_INVOCATIONS]) / 6;
- int evoc_extra = (you.experience_level * you.skills[SK_EVOCATIONS]) / 6;
- if (spell_extra > invoc_extra && spell_extra > evoc_extra)
+ if (spell_extra > invoc_extra)
enp += spell_extra;
- else if (invoc_extra > evoc_extra)
- enp += invoc_extra;
else
- enp += evoc_extra;
+ enp += invoc_extra;
you.max_magic_points = stepdown_value( enp, 9, 18, 45, 100 );
@@ -2298,7 +2323,7 @@ void wield_warning(bool newWeapon)
strcat(wepstr, wepstr2);
// only warn about str/dex for non-launcher weapons
- if (!launches_things(wepType))
+ if (!is_range_weapon( you.inv[you.equip[EQ_WEAPON]] ))
{
#ifdef USE_NEW_COMBAT_STATS
const int stat_bonus = effective_stat_bonus();
@@ -2334,8 +2359,10 @@ void wield_warning(bool newWeapon)
return;
}
+ // [dshaligram] No more annoying throwing skill warnings.
+#ifdef OBSOLETE_THROW_SKILL_WARNING
// must be a launcher
- int effSkill = you.skills[SK_THROWING] * 2 + 1;
+ int effSkill = you.skills[SK_RANGED_COMBAT] * 2 + 1;
int shoot_skill = 0;
switch (wepType)
@@ -2364,4 +2391,5 @@ void wield_warning(bool newWeapon)
strcat( info, wepstr );
mpr( info, MSGCH_WARN );
}
+#endif
}
diff --git a/crawl-ref/source/skills2.h b/crawl-ref/source/skills2.h
index 05c5d03068..73658f31af 100644
--- a/crawl-ref/source/skills2.h
+++ b/crawl-ref/source/skills2.h
@@ -23,7 +23,7 @@
/* ***********************************************************************
* called from: chardump - it_use3 - itemname - skills
* *********************************************************************** */
-const char *skill_name(unsigned char which_skill);
+const char *skill_name(int which_skill);
// last_updated 24may2000 {dlb}
@@ -46,7 +46,7 @@ const char *player_title( void );
* called from: acr - chardump - effects - files - player - skills -
* skills2 - stuff
* *********************************************************************** */
-unsigned char best_skill(unsigned char min_skill, unsigned char max_skill, unsigned char excl_skill);
+int best_skill(int min_skill, int max_skill, int excl_skill = -1);
void init_skill_order( void );
diff --git a/crawl-ref/source/spells1.cc b/crawl-ref/source/spells1.cc
index 64bb5630f0..8e7eecc8e9 100644
--- a/crawl-ref/source/spells1.cc
+++ b/crawl-ref/source/spells1.cc
@@ -3,6 +3,8 @@
* Summary: Implementations of some additional spells.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <4> 06-mar-2000 bwr confusing_touch, sure_blade
@@ -29,6 +31,7 @@
#include "invent.h"
#include "it_use2.h"
#include "itemname.h"
+#include "itemprop.h"
#include "misc.h"
#include "monplace.h"
#include "monstuff.h"
@@ -40,9 +43,8 @@
#include "spl-util.h"
#include "stuff.h"
#include "view.h"
-#include "wpn-misc.h"
-void blink(void)
+int blink(void)
{
struct dist beam;
@@ -65,12 +67,12 @@ void blink(void)
{
mpr("Blink to where?", MSGCH_PROMPT);
- direction( beam, DIR_TARGET );
+ direction( beam, DIR_TARGET, TARG_ANY, true );
if (!beam.isValid)
{
- canned_msg(MSG_SPELL_FIZZLES);
- return; // early return {dlb}
+ canned_msg(MSG_OK);
+ return (-1); // early return {dlb}
}
if (see_grid(beam.tx, beam.ty))
@@ -82,7 +84,7 @@ void blink(void)
}
}
- if (grd[beam.tx][beam.ty] <= DNGN_LAST_SOLID_TILE
+ if (grid_is_solid(grd[beam.tx][beam.ty])
|| mgrd[beam.tx][beam.ty] != NON_MONSTER)
{
mpr("Oops! Maybe something was there already.");
@@ -109,7 +111,7 @@ void blink(void)
}
}
- return;
+ return (1);
} // end blink()
void random_blink(bool allow_partial_control)
@@ -130,7 +132,7 @@ void random_blink(bool allow_partial_control)
#ifdef USE_SEMI_CONTROLLED_BLINK
//jmf: add back control, but effect is cast_semi_controlled_blink(pow)
- else if (you.attribute[ATTR_CONTROL_TELEPORT] && !you.conf
+ else if (player_control_teleport() && !you.conf
&& allow_partial_control && allow_control_teleport())
{
mpr("You may select the general direction of your translocation.");
@@ -163,7 +165,7 @@ void random_blink(bool allow_partial_control)
return;
} // end random_blink()
-void fireball(int power)
+int fireball(int power)
{
struct dist fire_ball;
@@ -171,41 +173,42 @@ void fireball(int power)
message_current_target();
- direction( fire_ball, DIR_NONE, TARG_ENEMY );
+ direction( fire_ball, DIR_NONE, TARG_ENEMY, true );
if (!fire_ball.isValid)
- canned_msg(MSG_SPELL_FIZZLES);
+ {
+ canned_msg(MSG_OK);
+ return (-1);
+ }
else
{
struct bolt beam;
beam.source_x = you.x_pos;
beam.source_y = you.y_pos;
- beam.target_x = fire_ball.tx;
- beam.target_y = fire_ball.ty;
+ beam.set_target(fire_ball);
zapping(ZAP_FIREBALL, power, beam);
}
- return;
+ return (1);
} // end fireball()
-void cast_fire_storm(int powc)
+int cast_fire_storm(int powc)
{
struct bolt beam;
struct dist targ;
mpr("Where?");
- direction( targ, DIR_TARGET, TARG_ENEMY );
+ direction( targ, DIR_TARGET, TARG_ENEMY, true );
- beam.target_x = targ.tx;
- beam.target_y = targ.ty;
+ beam.set_target(targ);
if (!targ.isValid)
{
- canned_msg(MSG_SPELL_FIZZLES);
- return;
+ canned_msg(MSG_OK);
+ return (-1);
}
beam.ex_size = 2 + (random2(powc) > 75);
@@ -214,12 +217,13 @@ void cast_fire_storm(int powc)
beam.colour = RED;
beam.beam_source = MHITYOU;
beam.thrower = KILL_YOU_MISSILE;
- beam.aux_source = NULL;
- beam.obviousEffect = false;
- beam.isBeam = false;
- beam.isTracer = false;
+ beam.aux_source.clear();
+ beam.obvious_effect = false;
+ beam.is_beam = false;
+ beam.is_tracer = false;
+ beam.is_explosion = true;
beam.ench_power = powc; // used for radius
- strcpy( beam.beam_name, "great blast of fire" );
+ beam.name = "great blast of fire";
beam.hit = 20 + powc / 10;
beam.damage = calc_dice( 6, 15 + powc );
@@ -227,8 +231,164 @@ void cast_fire_storm(int powc)
mpr("A raging storm of fire appears!");
viewwindow(1, false);
+
+ return (1);
} // end cast_fire_storm()
+
+void cast_chain_lightning( int powc )
+{
+ struct bolt beam;
+
+ // initialize beam structure
+ beam.name = "lightning arc";
+ beam.aux_source = "chain lightning";
+ beam.beam_source = MHITYOU;
+ beam.thrower = KILL_YOU_MISSILE;
+ beam.range = 8;
+ beam.rangeMax = 8;
+ beam.hit = AUTOMATIC_HIT;
+ beam.type = SYM_ZAP;
+ beam.flavour = BEAM_ELECTRICITY;
+ beam.obvious_effect = true;
+ beam.is_beam = false; // since we want to stop at our target
+ beam.is_explosion = false;
+ beam.is_tracer = false;
+
+ int sx, sy;
+ int tx, ty;
+ int i;
+
+ for (sx = you.x_pos, sy = you.y_pos;
+ powc > 0;
+ powc -= 8 + random2(13), sx = tx, sy = ty)
+ {
+ // infinity as far as this spell is concerned
+ // (Range - 1) is used because the distance is randomized and
+ // may be shifted by one.
+ int min_dist = MONSTER_LOS_RANGE - 1;
+
+ int dist;
+ int count = 0;
+
+ tx = -1;
+ ty = -1;
+
+ for (i = 0; i < MAX_MONSTERS; i++)
+ {
+ struct monsters *monster = &menv[i];
+
+ if (monster->type == -1)
+ continue;
+
+ dist = grid_distance( sx, sy, monster->x, monster->y );
+
+ // check for the source of this arc
+ if (!dist)
+ continue;
+
+ // randomize distance (arcs don't care about a couple of feet)
+ dist += (random2(3) - 1);
+
+ // always ignore targets further than current one
+ if (dist > min_dist)
+ continue;
+
+ if (!check_line_of_sight( sx, sy, monster->x, monster->y ))
+ continue;
+
+ count++;
+
+ if (dist < min_dist)
+ {
+ // switch to looking for closer targets (but not always)
+ if (!one_chance_in(10))
+ {
+ min_dist = dist;
+ tx = monster->x;
+ ty = monster->y;
+ count = 0;
+ }
+ }
+ else if (tx == -1 || one_chance_in( count ))
+ {
+ // either first target, or new selected target at min_dist
+ tx = monster->x;
+ ty = monster->y;
+
+ // need to set min_dist for first target case
+ if (dist < min_dist)
+ min_dist = dist;
+ }
+ }
+
+ // now check if the player is a target:
+ dist = grid_distance( sx, sy, you.x_pos, you.y_pos );
+
+ if (dist) // ie player was not the source
+ {
+ // distance randomized (as above)
+ dist += (random2(3) - 1);
+
+ // select player if only, closest, or randomly selected
+ if ((tx == -1
+ || dist < min_dist
+ || (dist == min_dist && one_chance_in( count + 1 )))
+ && check_line_of_sight( sx, sy, you.x_pos, you.y_pos ))
+ {
+ tx = you.x_pos;
+ ty = you.y_pos;
+ }
+ }
+
+ const bool see_source = see_grid( sx, sy );
+ const bool see_targ = see_grid( tx, ty );
+
+ if (tx == -1)
+ {
+ if (see_source)
+ mpr( "The lightning grounds out." );
+
+ break;
+ }
+
+ // Trying to limit message spamming here so we'll only mention
+ // the thunder when it's out of LoS.
+ if (noisy( 25, sx, sy ) && !see_source)
+ mpr( "You hear a mighty clap of thunder!", MSGCH_SOUND );
+
+ if (see_source && !see_targ)
+ mpr( "The lightning arcs out of your line of sight!" );
+ else if (!see_source && see_targ)
+ mpr( "The lightning arc suddenly appears!" );
+
+ if (!see_targ)
+ {
+ // It's no longer in the caster's LOS and influence.
+ powc = powc / 2 + 1;
+ }
+
+ beam.source_x = sx;
+ beam.source_y = sy;
+ beam.target_x = tx;
+ beam.target_y = ty;
+ beam.colour = LIGHTBLUE;
+ beam.damage = calc_dice( 5, 12 + powc * 2 / 3 );
+
+ // Be kinder to the player
+ if (tx == you.x_pos && ty == you.y_pos)
+ {
+ if (!(beam.damage.num /= 2))
+ beam.damage.num = 1;
+ if ((beam.damage.size /= 2) < 3)
+ beam.damage.size = 3;
+ }
+ fire_beam( beam );
+ }
+
+ more();
+}
+
void identify(int power)
{
int id_used = 1;
@@ -241,8 +401,8 @@ void identify(int power)
do
{
- item_slot = prompt_invent_item( "Identify which item?", -1, true,
- false, false );
+ item_slot = prompt_invent_item( "Identify which item?", MT_INVSELECT,
+ -1, true, true, false );
if (item_slot == PROMPT_ABORT)
{
canned_msg( MSG_OK );
@@ -257,16 +417,18 @@ void identify(int power)
// output identified item
in_name( item_slot, DESC_INVENTORY_EQUIP, str_pass );
mpr( str_pass );
-
if (item_slot == you.equip[EQ_WEAPON])
you.wield_change = true;
id_used--;
+
+ if (Options.auto_list && id_used > 0)
+ more();
}
while (id_used > 0);
} // end identify()
-void conjure_flame(int pow)
+int conjure_flame(int pow)
{
struct dist spelld;
@@ -282,12 +444,12 @@ void conjure_flame(int pow)
done_first_message = true;
}
- direction( spelld, DIR_TARGET, TARG_ENEMY );
+ direction( spelld, DIR_TARGET, TARG_ENEMY, true );
if (!spelld.isValid)
{
- canned_msg(MSG_SPELL_FIZZLES);
- return;
+ canned_msg(MSG_OK);
+ return (-1);
}
if (!see_grid(spelld.tx, spelld.ty))
@@ -296,7 +458,7 @@ void conjure_flame(int pow)
continue;
}
- if (grd[ spelld.tx ][ spelld.ty ] <= DNGN_LAST_SOLID_TILE
+ if (grid_is_solid(grd[ spelld.tx ][ spelld.ty ])
|| mgrd[ spelld.tx ][ spelld.ty ] != NON_MONSTER
|| env.cgrid[ spelld.tx ][ spelld.ty ] != EMPTY_CLOUD)
{
@@ -313,9 +475,10 @@ void conjure_flame(int pow)
durat = 23;
place_cloud( CLOUD_FIRE, spelld.tx, spelld.ty, durat );
+ return (1);
} // end cast_conjure_flame()
-void stinking_cloud( int pow )
+int stinking_cloud( int pow )
{
struct dist spelld;
struct bolt beem;
@@ -324,21 +487,20 @@ void stinking_cloud( int pow )
message_current_target();
- direction( spelld, DIR_NONE, TARG_ENEMY );
+ direction( spelld, DIR_NONE, TARG_ENEMY, true );
if (!spelld.isValid)
{
- canned_msg(MSG_SPELL_FIZZLES);
- return;
+ canned_msg(MSG_OK);
+ return (-1);
}
- beem.target_x = spelld.tx;
- beem.target_y = spelld.ty;
+ beem.set_target(spelld);
beem.source_x = you.x_pos;
beem.source_y = you.y_pos;
- strcpy(beem.beam_name, "ball of vapour");
+ beem.name = "ball of vapour";
beem.colour = GREEN;
beem.range = 6;
beem.rangeMax = 6;
@@ -349,27 +511,30 @@ void stinking_cloud( int pow )
beem.ench_power = pow;
beem.beam_source = MHITYOU;
beem.thrower = KILL_YOU;
- beem.aux_source = NULL;
- beem.isBeam = false;
- beem.isTracer = false;
+ beem.aux_source.clear();
+ beem.is_beam = false;
+ beem.is_tracer = false;
fire_beam(beem);
+
+ return (1);
} // end stinking_cloud()
-void cast_big_c(int pow, char cty)
+int cast_big_c(int pow, char cty)
{
struct dist cdis;
mpr("Where do you want to put it?", MSGCH_PROMPT);
- direction( cdis, DIR_TARGET, TARG_ENEMY );
+ direction( cdis, DIR_TARGET, TARG_ENEMY, true );
if (!cdis.isValid)
{
- canned_msg(MSG_SPELL_FIZZLES);
- return;
+ canned_msg(MSG_OK);
+ return (-1);
}
big_cloud( cty, cdis.tx, cdis.ty, pow, 8 + random2(3) );
+ return (1);
} // end cast_big_c()
void big_cloud(char clouds, char cl_x, char cl_y, int pow, int size)
@@ -377,18 +542,18 @@ void big_cloud(char clouds, char cl_x, char cl_y, int pow, int size)
apply_area_cloud(make_a_normal_cloud, cl_x, cl_y, pow, size, clouds);
} // end big_cloud()
-static char healing_spell( int healed )
+static int healing_spell( int healed )
{
int mgr = 0;
struct monsters *monster = 0; // NULL {dlb}
struct dist bmove;
mpr("Which direction?", MSGCH_PROMPT);
- direction( bmove, DIR_DIR, TARG_FRIEND );
+ direction( bmove, DIR_DIR, TARG_FRIEND, true );
if (!bmove.isValid)
{
- canned_msg( MSG_HUH );
+ canned_msg( MSG_OK );
return 0;
}
@@ -446,7 +611,7 @@ char cast_greatest_healing( int pow )
} // end cast_greatest_healing()
#endif
-char cast_healing( int pow )
+int cast_healing( int pow )
{
if (pow > 50)
pow = 50;
@@ -880,11 +1045,7 @@ void cast_swiftness(int power)
if (player_in_water())
{
- if (you.species == SP_MERFOLK)
- mpr("This spell will not benefit you while you're swimming!");
- else
- mpr("This spell will not benefit you while you're in water!");
-
+ mpr("The water foams!");
return;
}
@@ -898,11 +1059,9 @@ void cast_swiftness(int power)
// dur_incr = random2(power) + random2(power) + 20;
dur_incr = 20 + random2( power );
- // Centaurs do have feet and shouldn't get here anyways -- bwr
- snprintf( info, INFO_SIZE, "You feel quick%s",
- (you.species == SP_NAGA) ? "." : " on your feet." );
-
- mpr(info);
+ // [dshaligram] Removed the on-your-feet bit. Sounds odd when you're
+ // levitating, for instance.
+ mpr("You feel quick.");
if (dur_incr + you.duration[DUR_SWIFTNESS] > 100)
you.duration[DUR_SWIFTNESS] = 100;
@@ -963,9 +1122,6 @@ void cast_teleport_control(int power)
{
int dur_incr = 10 + random2(power);
- if (you.duration[DUR_CONTROL_TELEPORT] == 0)
- you.attribute[ATTR_CONTROL_TELEPORT]++;
-
mpr("You feel in control.");
if (dur_incr + you.duration[DUR_CONTROL_TELEPORT] >= 50)
@@ -1047,7 +1203,7 @@ void manage_fire_shield(void)
//if ( one_chance_in(3) ) beam.range ++;
- if (grd[you.x_pos + stx][you.y_pos + sty] > DNGN_LAST_SOLID_TILE
+ if (!grid_is_solid(grd[you.x_pos + stx][you.y_pos + sty])
&& env.cgrid[you.x_pos + stx][you.y_pos + sty] == EMPTY_CLOUD)
{
place_cloud( CLOUD_FIRE, you.x_pos + stx, you.y_pos + sty,
diff --git a/crawl-ref/source/spells1.h b/crawl-ref/source/spells1.h
index dc98a1b133..64481d53bb 100644
--- a/crawl-ref/source/spells1.h
+++ b/crawl-ref/source/spells1.h
@@ -50,7 +50,7 @@ char cast_lesser_healing(void);
/* ***********************************************************************
* called from: ability - spell
* *********************************************************************** */
-char cast_healing(int power);
+int cast_healing(int power);
// last updated 24may2000 {dlb}
/* ***********************************************************************
@@ -63,25 +63,25 @@ void big_cloud(char clouds, char cl_x, char cl_y, int pow, int size);
/* ***********************************************************************
* called from: acr (WIZARD only) - item_use - spell
* *********************************************************************** */
-void blink(void);
+int blink(void);
/* ***********************************************************************
* called from: spell
* *********************************************************************** */
-void cast_big_c(int pow, char cty);
+int cast_big_c(int pow, char cty);
void cast_confusing_touch(int power);
void cast_cure_poison(int mabil);
int allowed_deaths_door_hp(void);
void cast_deaths_door(int pow);
-void cast_fire_storm(int powc);
+int cast_fire_storm(int powc);
bool cast_revivification(int power);
void cast_berserk(void);
void cast_ring_of_flames(int power);
-void conjure_flame(int pow);
+int conjure_flame(int pow);
void extension(int pow);
-void fireball(int power);
-void stinking_cloud(int pow);
+int fireball(int power);
+int stinking_cloud(int pow);
void abjuration(int pow);
// last updated 24may2000 {dlb}
diff --git a/crawl-ref/source/spells2.cc b/crawl-ref/source/spells2.cc
index dbd8f00f3b..8fbd11ac3d 100644
--- a/crawl-ref/source/spells2.cc
+++ b/crawl-ref/source/spells2.cc
@@ -29,8 +29,10 @@
#include "beam.h"
#include "cloud.h"
#include "direct.h"
+#include "dungeon.h"
#include "effects.h"
#include "itemname.h"
+#include "itemprop.h"
#include "items.h"
#include "misc.h"
#include "monplace.h"
@@ -43,7 +45,6 @@
#include "spl-cast.h"
#include "stuff.h"
#include "view.h"
-#include "wpn-misc.h"
int raise_corpse( int corps, int corx, int cory, int corps_beh,
int corps_hit, int actual );
@@ -73,7 +74,8 @@ unsigned char detect_traps( int pow )
traps_found++;
grd[ etx ][ ety ] = trap_category( env.trap[count_x].type );
- env.map[etx - 1][ety - 1] = '^';
+ set_envmap_char(etx, ety, get_magicmap_char(grd[etx][ety]));
+ set_terrain_mapped(etx, ety);
}
}
}
@@ -100,11 +102,8 @@ unsigned char detect_items( int pow )
if (igrd[i][j] != NON_ITEM)
{
- unsigned short flags = env.map[i - 1][j - 1];
- flags = !flags || (flags & ENVF_DETECTED)?
- ENVF_DETECTED
- : 0;
- env.map[i - 1][j - 1] = '~' | ENVF_DETECT_ITEM | flags;
+ set_envmap_char(i, j, get_magicmap_char(DNGN_ITEM_DETECTED));
+ set_envmap_detected_item(i, j);
}
}
}
@@ -112,14 +111,71 @@ unsigned char detect_items( int pow )
return (items_found);
} // end detect_items()
+static void fuzz_detect_creatures(int pow, int *fuzz_radius, int *fuzz_chance)
+{
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "dc_fuzz: Power is %d", pow);
+#endif
+
+ if (pow < 1)
+ pow = 1;
+
+ *fuzz_radius = pow >= 50? 1 : 2;
+
+ // Fuzz chance starts off at 100% and declines to a low of 10% for obscenely
+ // powerful castings (pow caps around the 60 mark).
+ *fuzz_chance = 100 - 90 * (pow - 1) / 59;
+ if (*fuzz_chance < 10)
+ *fuzz_chance = 10;
+}
+
+static void mark_detected_creature(int gridx, int gridy, const monsters *mon,
+ int fuzz_chance, int fuzz_radius)
+{
+ if (fuzz_radius && fuzz_chance > random2(100))
+ {
+ const int fuzz_diam = 2 * fuzz_radius + 1;
+
+ int gx, gy;
+ bool found_good = false;
+ for (int itry = 0; itry < 5; ++itry)
+ {
+ gx = gridx + random2(fuzz_diam) - fuzz_radius;
+ gy = gridy + random2(fuzz_diam) - fuzz_radius;
+
+ if (map_bounds(gx, gy) && !grid_is_solid(grd[gx][gy]))
+ {
+ found_good = true;
+ break;
+ }
+ }
+
+ if (found_good)
+ {
+ gridx = gx;
+ gridy = gy;
+ }
+ }
+
+ set_envmap_char(gridx, gridy, mons_char(mon->type));
+ set_envmap_detected_mons(gridx, gridy);
+}
+
unsigned char detect_creatures( int pow )
{
+ int fuzz_radius = 0, fuzz_chance = 0;
+ fuzz_detect_creatures(pow, &fuzz_radius, &fuzz_chance);
+
if (pow > 50)
pow = 50;
unsigned char creatures_found = 0;
const int map_radius = 8 + random2(8) + pow;
+ // Clear the map so detect creatures is more useful and the detection
+ // fuzz is harder to analyse by averaging.
+ clear_map();
+
mpr("You detect creatures!");
for (int i = you.x_pos - map_radius; i < you.x_pos + map_radius; i++)
@@ -132,19 +188,16 @@ unsigned char detect_creatures( int pow )
if (mgrd[i][j] != NON_MONSTER)
{
struct monsters *mon = &menv[ mgrd[i][j] ];
+ mark_detected_creature(i, j, mon, fuzz_chance, fuzz_radius);
- unsigned short flags = env.map[i - 1][j - 1];
- flags = !flags || (flags & ENVF_DETECTED)?
- ENVF_DETECTED
- : 0;
-
- env.map[i - 1][j - 1] =
- mons_char( mon->type ) | ENVF_DETECT_MONS | flags;
+ // [ds] Should we be doing this here? DC doesn't give away
+ // full monster identity, after all. XXX
+ seen_monster(mon);
// Assuming that highly intelligent spellcasters can
- // detect scyring. -- bwr
+ // detect scrying. -- bwr
if (mons_intel( mon->type ) == I_HIGH
- && mons_flag( mon->type, M_SPELLCASTER ))
+ && mons_class_flag( mon->type, M_SPELLCASTER ))
{
behaviour_event( mon, ME_DISTURB, MHITYOU,
you.x_pos, you.y_pos );
@@ -321,7 +374,7 @@ int animate_dead( int power, int corps_beh, int corps_hit, int actual )
return number_raised;
} // end animate_dead()
-int animate_a_corpse( int axps, int ayps, int corps_beh, int corps_hit,
+int animate_a_corpse( int axps, int ayps, int corps_beh, int corps_hit,
int class_allowed )
{
if (igrd[axps][ayps] == NON_ITEM)
@@ -495,7 +548,7 @@ bool brand_weapon(int which_brand, int power)
return false;
if (you.inv[wpn].base_type != OBJ_WEAPONS
- || launches_things(you.inv[wpn].sub_type))
+ || is_range_weapon(you.inv[wpn]))
{
return false;
}
@@ -511,8 +564,7 @@ bool brand_weapon(int which_brand, int power)
in_name( wpn, DESC_CAP_YOUR, str_pass );
strcpy( info, str_pass );
- const int wpn_type = damage_type( you.inv[wpn].base_type,
- you.inv[wpn].sub_type );
+ const int wpn_type = get_vorpal_type(you.inv[wpn]);
switch (which_brand) // use SPECIAL_WEAPONS here?
{
@@ -561,9 +613,16 @@ bool brand_weapon(int which_brand, int power)
strcat( info, coinflip() ? " oddly." : " strangely." );
duration_affected = 5;
+ // [dshaligram] Clamping power to 2.
+ power = 2;
+
// This brand is insanely powerful, this isn't even really
// a start to balancing it, but it needs something. -- bwr
- miscast_effect(SPTYP_TRANSLOCATION, 9, 90, 100, "a distortion effect");
+ // [dshaligram] At level 7 it's costly enough to experiment
+ // with removing the miscast effect. We may need to revise the spell
+ // to level 8 or 9. XXX.
+ // miscast_effect(SPTYP_TRANSLOCATION,
+ // 9, 90, 100, "a distortion effect");
break;
case SPWPN_DUMMY_CRUSHING: //jmf: added for Maxwell's Silver Hammer
@@ -682,7 +741,7 @@ void turn_undead(int pow)
// used to inflict random2(5) + (random2(pow) / 20) damage,
// in addition {dlb}
- if (mons_holiness(monster->type) == MH_UNDEAD)
+ if (mons_holiness(monster) == MH_UNDEAD)
{
if (check_mons_resist_magic( monster, pow ))
{
@@ -707,11 +766,12 @@ void turn_undead(int pow)
} // end "for tu"
} // end turn_undead()
-void holy_word(int pow)
+void holy_word(int pow, bool silent)
{
struct monsters *monster;
- mpr("You speak a Word of immense power!");
+ if (!silent)
+ mpr("You speak a Word of immense power!");
// doubt this will ever happen, but it's here as a safety -- bwr
if (pow > 300)
@@ -724,8 +784,8 @@ void holy_word(int pow)
if (monster->type == -1 || !mons_near(monster))
continue;
- if (mons_holiness(monster->type) == MH_UNDEAD
- || mons_holiness(monster->type) == MH_DEMONIC)
+ if (mons_holiness(monster) == MH_UNDEAD
+ || mons_holiness(monster) == MH_DEMONIC)
{
simple_monster_message(monster, " convulses!");
@@ -827,7 +887,7 @@ void cast_refrigeration(int pow)
// Note: this used to be 12!... and it was also applied even if
// the player didn't take damage from the cold, so we're being
// a lot nicer now. -- bwr
- scrolls_burn( 5, OBJ_POTIONS );
+ expose_player_to_element(BEAM_COLD, 5);
}
// Now do the monsters:
@@ -859,7 +919,7 @@ void cast_refrigeration(int pow)
print_wounds(monster);
//jmf: "slow snakes" finally available
- if (mons_flag( monster->type, M_COLD_BLOOD ) && coinflip())
+ if (mons_class_flag( monster->type, M_COLD_BLOOD ) && coinflip())
mons_add_ench(monster, ENCH_SLOW);
}
}
@@ -892,7 +952,7 @@ void drain_life(int pow)
if (monster->type == -1)
continue;
- if (mons_holiness( monster->type ) != MH_NATURAL)
+ if (mons_holiness(monster) != MH_NATURAL)
continue;
if (mons_res_negative_energy( monster ))
@@ -939,7 +999,7 @@ int vampiric_drain(int pow)
dirc:
mpr("Which direction?", MSGCH_PROMPT);
- direction( vmove, DIR_DIR, TARG_ENEMY );
+ direction( vmove, DIR_DIR, TARG_ENEMY, true );
if (!vmove.isValid)
{
@@ -963,12 +1023,12 @@ int vampiric_drain(int pow)
monster = &menv[mgr];
- const int holy = mons_holiness(monster->type);
+ const int holy = mons_holiness(monster);
if (holy == MH_UNDEAD || holy == MH_DEMONIC)
{
mpr("Aaaarggghhhhh!");
- dec_hp(random2avg(39, 2) + 10, false);
+ dec_hp(random2avg(39, 2) + 10, false, "vampiric drain backlash");
return -1;
}
@@ -1023,11 +1083,11 @@ char burn_freeze(int pow, char flavour)
while (mgr == NON_MONSTER)
{
mpr("Which direction?", MSGCH_PROMPT);
- direction( bmove, DIR_DIR, TARG_ENEMY );
+ direction( bmove, DIR_DIR, TARG_ENEMY, true );
if (!bmove.isValid)
{
- canned_msg(MSG_SPELL_FIZZLES);
+ canned_msg(MSG_OK);
return -1;
}
@@ -1043,7 +1103,7 @@ char burn_freeze(int pow, char flavour)
if (mgr == NON_MONSTER)
{
mpr("There isn't anything close enough!");
- return -1;
+ return 0;
}
}
@@ -1082,7 +1142,7 @@ char burn_freeze(int pow, char flavour)
if (flavour == BEAM_COLD)
{
- if (mons_flag( monster->type, M_COLD_BLOOD ) && coinflip())
+ if (mons_class_flag( monster->type, M_COLD_BLOOD ) && coinflip())
mons_add_ench(monster, ENCH_SLOW);
const int cold_res = mons_res_cold( monster );
@@ -1123,11 +1183,11 @@ int summon_elemental(int pow, int restricted_type,
{
mpr("Summon from material in which direction?", MSGCH_PROMPT);
- direction( smove, DIR_DIR );
+ direction( smove, DIR_DIR, TARG_ANY, true );
if (!smove.isValid)
{
- canned_msg(MSG_NOTHING_HAPPENS);
+ canned_msg(MSG_OK);
return (-1);
}
@@ -1183,7 +1243,7 @@ int summon_elemental(int pow, int restricted_type,
if (type_summoned == MONS_PROGRAM_BUG)
{
canned_msg(MSG_NOTHING_HAPPENS);
- return (-1);
+ return (0);
}
// silly - ice for water? 15jan2000 {dlb}
@@ -1314,10 +1374,10 @@ void summon_scorpions(int pow)
}
} // end summon_scorpions()
-void summon_ice_beast_etc(int pow, int ibc)
+void summon_ice_beast_etc(int pow, int ibc, bool divine_gift)
{
int numsc = ENCH_ABJ_II + (random2(pow) / 4);
- int beha = BEH_FRIENDLY;
+ int beha = divine_gift? BEH_GOD_GIFT : BEH_FRIENDLY;
if (numsc > ENCH_ABJ_VI)
numsc = ENCH_ABJ_VI;
diff --git a/crawl-ref/source/spells2.h b/crawl-ref/source/spells2.h
index 8c3bef71c5..409aff5a25 100644
--- a/crawl-ref/source/spells2.h
+++ b/crawl-ref/source/spells2.h
@@ -116,7 +116,7 @@ void drain_life(int pow);
/* ***********************************************************************
* called from: ability - spell
* *********************************************************************** */
-void holy_word(int pow);
+void holy_word(int pow, bool silent = false);
// last updated 24may2000 {dlb}
@@ -131,7 +131,7 @@ bool restore_stat(unsigned char which_stat, bool suppress_msg);
/* ***********************************************************************
* called from: ability - spell
* *********************************************************************** */
-void summon_ice_beast_etc(int pow, int ibc);
+void summon_ice_beast_etc(int pow, int ibc, bool divine_gift = false);
// last updated 24may2000 {dlb}
diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc
index e2a2bf325f..2d74e8a92f 100644
--- a/crawl-ref/source/spells3.cc
+++ b/crawl-ref/source/spells3.cc
@@ -3,6 +3,8 @@
* Summary: Implementations of some additional spells.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <2> 9/11/99 LRH Teleportation takes longer in the Abyss
@@ -26,6 +28,7 @@
#include "debug.h"
#include "delay.h"
#include "itemname.h"
+#include "itemprop.h"
#include "items.h"
#include "it_use2.h"
#include "misc.h"
@@ -36,15 +39,15 @@
#include "player.h"
#include "randart.h"
#include "spells1.h"
+#include "spells4.h"
#include "spl-cast.h"
#include "spl-util.h"
#include "stuff.h"
#include "view.h"
-#include "wpn-misc.h"
static bool monster_on_level(int monster);
-void cast_selective_amnesia(bool force)
+bool cast_selective_amnesia(bool force)
{
char ep_gain = 0;
unsigned char keyin = 0;
@@ -61,7 +64,7 @@ void cast_selective_amnesia(bool force)
keyin = (unsigned char) get_ch();
if (keyin == ESCAPE)
- return; // early return {dlb}
+ return (false); // early return {dlb}
if (keyin == '?' || keyin == '*')
{
@@ -108,7 +111,7 @@ void cast_selective_amnesia(bool force)
}
}
- return;
+ return (true);
} // end cast_selective_amnesia()
bool remove_curse(bool suppress_msg)
@@ -164,7 +167,7 @@ bool detect_curse(bool suppress_msg)
|| you.inv[loopy].base_type == OBJ_ARMOUR
|| you.inv[loopy].base_type == OBJ_JEWELLERY))
{
- if (item_not_ident( you.inv[loopy], ISFLAG_KNOW_CURSE ))
+ if (!item_ident( you.inv[loopy], ISFLAG_KNOW_CURSE ))
success = true;
set_ident_flags( you.inv[loopy], ISFLAG_KNOW_CURSE );
@@ -183,7 +186,7 @@ bool detect_curse(bool suppress_msg)
return (success);
} // end detect_curse()
-bool cast_smiting(int power)
+int cast_smiting(int power)
{
bool success = false;
struct dist beam;
@@ -191,10 +194,15 @@ bool cast_smiting(int power)
mpr("Smite whom?", MSGCH_PROMPT);
- direction( beam, DIR_TARGET, TARG_ENEMY );
+ direction( beam, DIR_TARGET, TARG_ENEMY, true );
- if (!beam.isValid
- || mgrd[beam.tx][beam.ty] == NON_MONSTER
+ if (!beam.isValid)
+ {
+ canned_msg(MSG_OK);
+ return (-1);
+ }
+
+ if (mgrd[beam.tx][beam.ty] == NON_MONSTER
|| beam.isMe)
{
canned_msg(MSG_SPELL_FIZZLES);
@@ -221,7 +229,7 @@ bool cast_smiting(int power)
return (success);
} // end cast_smiting()
-bool airstrike(int power)
+int airstrike(int power)
{
bool success = false;
struct dist beam;
@@ -230,10 +238,15 @@ bool airstrike(int power)
mpr("Strike whom?", MSGCH_PROMPT);
- direction( beam, DIR_TARGET, TARG_ENEMY );
+ direction( beam, DIR_TARGET, TARG_ENEMY, true );
- if (!beam.isValid
- || mgrd[beam.tx][beam.ty] == NON_MONSTER
+ if (!beam.isValid)
+ {
+ canned_msg(MSG_OK);
+ return (-1);
+ }
+
+ if (mgrd[beam.tx][beam.ty] == NON_MONSTER
|| beam.isMe)
{
canned_msg(MSG_SPELL_FIZZLES);
@@ -250,6 +263,10 @@ bool airstrike(int power)
hurted = random2( random2(12) + (random2(power) / 6)
+ (random2(power) / 7) );
hurted -= random2(1 + monster->armour_class);
+ if ( mons_flies(monster) ) {
+ hurted *= 3;
+ hurted /= 2;
+ }
if (hurted < 0)
hurted = 0;
@@ -269,7 +286,7 @@ bool airstrike(int power)
return (success);
} // end airstrike()
-bool cast_bone_shards(int power)
+int cast_bone_shards(int power)
{
bool success = false;
struct bolt beam;
@@ -282,8 +299,11 @@ bool cast_bone_shards(int power)
}
else if (you.inv[you.equip[EQ_WEAPON]].sub_type != CORPSE_SKELETON)
mpr("The corpse collapses into a mass of pulpy flesh.");
- else if (spell_direction(spelld, beam) != -1)
+ else
{
+ if (spell_direction(spelld, beam) == -1)
+ return (-1);
+
// practical max of 100 * 15 + 3000 = 4500
// actual max of 200 * 15 + 3000 = 6000
power *= 15;
@@ -430,10 +450,10 @@ void dancing_weapon(int pow, bool force_hostile)
const int wpn = you.equip[EQ_WEAPON];
- // See if weilded item is appropriate:
+ // See if wielded item is appropriate:
if (wpn == -1
|| you.inv[wpn].base_type != OBJ_WEAPONS
- || launches_things( you.inv[wpn].sub_type )
+ || is_range_weapon( you.inv[wpn] )
|| is_fixed_artefact( you.inv[wpn] ))
{
goto failed_spell;
@@ -478,12 +498,15 @@ void dancing_weapon(int pow, bool force_hostile)
you.equip[EQ_WEAPON] = -1;
menv[summs].inv[MSLOT_WEAPON] = i;
- menv[summs].number = mitm[i].colour;
+ menv[summs].colour = mitm[i].colour;
return;
failed_spell:
- mpr("Your weapon vibrates crazily for a second.");
+ if ( wpn != -1 )
+ mpr("Your weapon vibrates crazily for a second.");
+ else
+ mprf(MSGCH_PLAIN, "Your %s twitch.", your_hand(true));
} // end dancing_weapon()
static bool monster_on_level(int monster)
@@ -565,7 +588,7 @@ bool allow_control_teleport( bool silent )
}
// Tell the player why if they have teleport control.
- if (!ret && you.attribute[ATTR_CONTROL_TELEPORT] && !silent)
+ if (!ret && player_control_teleport() && !silent)
mpr("A powerful magic prevents control of your teleportation.");
return ret;
@@ -599,8 +622,8 @@ void you_teleport(void)
void you_teleport2( bool allow_control, bool new_abyss_area )
{
bool is_controlled = (allow_control && !you.conf
- && you.attribute[ATTR_CONTROL_TELEPORT]
- && allow_control_teleport());
+ && player_control_teleport()
+ && allow_control_teleport());
if (scan_randarts(RAP_PREVENT_TELEPORTATION))
{
@@ -608,11 +631,8 @@ void you_teleport2( bool allow_control, bool new_abyss_area )
return;
}
- // after this point, we're guaranteed to teleport. Turn off auto-butcher.
- // corpses still get butchered, but at least we don't get a silly message.
- if (current_delay_action() == DELAY_BUTCHER)
- stop_delay();
-
+ // after this point, we're guaranteed to teleport. Kill the appropriate
+ // delays.
interrupt_activity( AI_TELEPORT );
if (you.duration[DUR_CONDENSATION_SHIELD] > 0)
@@ -639,7 +659,7 @@ void you_teleport2( bool allow_control, bool new_abyss_area )
mpr("Expect minor deviation.");
more();
- show_map(plox);
+ show_map(plox, false);
redraw_screen();
@@ -854,7 +874,7 @@ bool project_noise(void)
mpr( "Choose the noise's source (press '.' or delete to select)." );
more();
- show_map(plox);
+ show_map(plox, false);
redraw_screen();
@@ -868,7 +888,7 @@ bool project_noise(void)
// player can use this spell to "sound out" the dungeon -- bwr
if (plox[0] > 1 && plox[0] < (GXM - 2)
&& plox[1] > 1 && plox[1] < (GYM - 2)
- && grd[ plox[0] ][ plox[1] ] > DNGN_LAST_SOLID_TILE)
+ && !grid_is_solid(grd[ plox[0] ][ plox[1] ]))
{
noisy( 30, plox[0], plox[1] );
success = true;
@@ -877,12 +897,12 @@ bool project_noise(void)
if (!silenced( you.x_pos, you.y_pos ))
{
if (!success)
- mpr("You hear a dull thud.");
+ mpr("You hear a dull thud.", MSGCH_SOUND);
else
{
snprintf( info, INFO_SIZE, "You hear a %svoice call your name.",
(see_grid( plox[0], plox[1] ) ? "distant " : "") );
- mpr( info );
+ mpr( info , MSGCH_SOUND );
}
}
}
@@ -926,7 +946,7 @@ bool recall(char type_recalled)
if (!mons_friendly(monster))
continue;
- if (monster_habitat(monster->type) != DNGN_FLOOR)
+ if (!monster_habitable_grid(monster, DNGN_FLOOR))
continue;
if (type_recalled == 1)
@@ -934,19 +954,19 @@ bool recall(char type_recalled)
/* abomin created by twisted res, although it gets others too */
if ( !((monster->type == MONS_ABOMINATION_SMALL
|| monster->type == MONS_ABOMINATION_LARGE)
- && (monster->number == BROWN
- || monster->number == RED
- || monster->number == LIGHTRED)) )
+ && (monster->colour == BROWN
+ || monster->colour == RED
+ || monster->colour == LIGHTRED)) )
{
if (monster->type != MONS_REAPER
- && mons_holiness(monster->type) != MH_UNDEAD)
+ && mons_holiness(monster) != MH_UNDEAD)
{
continue;
}
}
}
- if (empty_surrounds(you.x_pos, you.y_pos, DNGN_FLOOR, false, empty))
+ if (empty_surrounds(you.x_pos, you.y_pos, DNGN_FLOOR, 3, false, empty))
{
// clear old cell pointer -- why isn't there a function for moving a monster?
mgrd[monster->x][monster->y] = NON_MONSTER;
@@ -972,7 +992,7 @@ bool recall(char type_recalled)
return (success);
} // end recall()
-void portal(void)
+int portal(void)
{
char dir_sign = 0;
unsigned char keyi;
@@ -982,10 +1002,12 @@ void portal(void)
if (!player_in_branch( BRANCH_MAIN_DUNGEON ))
{
mpr("This spell doesn't work here.");
+ return (-1);
}
else if (grd[you.x_pos][you.y_pos] != DNGN_FLOOR)
{
mpr("You must find a clear area in which to cast this spell.");
+ return (-1);
}
else
{
@@ -1021,7 +1043,7 @@ void portal(void)
if (keyi == 'x')
{
canned_msg(MSG_OK);
- return; // an early return {dlb}
+ return (-1); // an early return {dlb}
}
}
@@ -1035,7 +1057,7 @@ void portal(void)
if (keyi == 'x')
{
canned_msg(MSG_OK);
- return; // another early return {dlb}
+ return (-1); // another early return {dlb}
}
if (!(keyi < '1' || keyi > '9'))
@@ -1065,7 +1087,7 @@ void portal(void)
untag_followers();
}
- return;
+ return (1);
} // end portal()
bool cast_death_channel(int power)
diff --git a/crawl-ref/source/spells3.h b/crawl-ref/source/spells3.h
index 5b10dd3026..9eea54e646 100644
--- a/crawl-ref/source/spells3.h
+++ b/crawl-ref/source/spells3.h
@@ -24,14 +24,14 @@ bool allow_control_teleport( bool silent = false );
/* ***********************************************************************
* called from: spell
* *********************************************************************** */
-bool airstrike(int power);
+int airstrike(int power);
// updated 24may2000 {dlb}
/* ***********************************************************************
* called from: spell
* *********************************************************************** */
-bool cast_bone_shards(int power);
+int cast_bone_shards(int power);
// updated 24may2000 {dlb}
@@ -52,14 +52,14 @@ void cast_poison_ammo(void);
/* ***********************************************************************
* called from: ability - spell
* *********************************************************************** */
-void cast_selective_amnesia(bool force);
+bool cast_selective_amnesia(bool force);
// updated 24may2000 {dlb}
/* ***********************************************************************
* called from: ability - spell
* *********************************************************************** */
-bool cast_smiting(int power);
+int cast_smiting(int power);
// updated 24may2000 {dlb}
@@ -94,7 +94,7 @@ bool entomb(void);
/* ***********************************************************************
* called from: spell
* *********************************************************************** */
-void portal(void);
+int portal(void);
// updated 24may2000 {dlb}
diff --git a/crawl-ref/source/spells4.cc b/crawl-ref/source/spells4.cc
index 26b09c3901..4f005c81ac 100644
--- a/crawl-ref/source/spells4.cc
+++ b/crawl-ref/source/spells4.cc
@@ -4,6 +4,8 @@
* other neglected areas of Crawl magic ;^)
* Written by: Copyleft Josh Fishman 1999-2000, All Rights Preserved
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <2> 29jul2000 jdj Made a zillion functions static.
@@ -28,6 +30,7 @@
#include "effects.h"
#include "it_use2.h"
#include "itemname.h"
+#include "itemprop.h"
#include "items.h"
#include "invent.h"
#include "misc.h"
@@ -57,7 +60,6 @@ enum DEBRIS // jmf: add for shatter, dig, and Giants to throw
NUM_DEBRIS
}; // jmf: ...and I'll actually implement the items Real Soon Now...
-static bool mons_can_host_shuggoth(int type);
// static int make_a_random_cloud(int x, int y, int pow, int ctype);
static int make_a_rot_cloud(int x, int y, int pow, int ctype);
static int quadrant_blink(int x, int y, int pow, int garbage);
@@ -189,6 +191,7 @@ static int shatter_monsters(int x, int y, int pow, int garbage)
case MONS_ICE_BEAST: // 3/2 damage
case MONS_SIMULACRUM_SMALL:
case MONS_SIMULACRUM_LARGE:
+ case MONS_SILVER_STATUE:
dam_dice.num = 4;
break;
@@ -199,6 +202,7 @@ static int shatter_monsters(int x, int y, int pow, int garbage)
case MONS_STONE_GOLEM:
case MONS_IRON_GOLEM:
case MONS_CRYSTAL_GOLEM:
+ case MONS_ORANGE_STATUE:
case MONS_EARTH_ELEMENTAL:
case MONS_GARGOYLE:
case MONS_SKELETAL_DRAGON:
@@ -298,7 +302,7 @@ static int shatter_items(int x, int y, int pow, int garbage)
if (broke_stuff)
{
if (!silenced(x, y) && !silenced(you.x_pos, you.y_pos))
- mpr("You hear glass break.");
+ mpr("You hear glass break.", MSGCH_SOUND);
return 1;
}
@@ -394,7 +398,7 @@ void cast_shatter(int pow)
noisy( 30, you.x_pos, you.y_pos );
snprintf(info, INFO_SIZE, "The dungeon %s!", (sil ? "shakes" : "rumbles"));
- mpr(info);
+ mpr(info, (sil? MSGCH_PLAIN : MSGCH_SOUND));
switch (you.attribute[ATTR_TRANSFORMATION])
{
@@ -434,7 +438,7 @@ void cast_shatter(int pow)
pow, rad, 0 );
if (dest && !sil)
- mpr("Ka-crash!");
+ mpr("Ka-crash!", MSGCH_SOUND);
} // end cast_shatter()
// cast_forescry: raises evasion (by 8 currently) via divination
@@ -492,7 +496,7 @@ static void cast_detect_magic(int pow)
}
mpr("Which direction?", MSGCH_PROMPT);
- direction( bmove, DIR_DIR );
+ direction( bmove, DIR_DIR, TARG_ANY, true );
if (!bmove.isValid)
{
@@ -708,6 +712,7 @@ void cast_sticks_to_snakes(int pow)
|| you.inv[ weapon ].sub_type == WPN_GIANT_CLUB
|| you.inv[ weapon ].sub_type == WPN_GIANT_SPIKED_CLUB
|| you.inv[ weapon ].sub_type == WPN_BOW
+ || you.inv[ weapon ].sub_type == WPN_LONGBOW
|| you.inv[ weapon ].sub_type == WPN_ANCUS
|| you.inv[ weapon ].sub_type == WPN_HALBERD
|| you.inv[ weapon ].sub_type == WPN_GLAIVE
@@ -720,7 +725,7 @@ void cast_sticks_to_snakes(int pow)
// ogres, and most importantly ogre magi). Still it's unlikely
// any character is strong enough to bother lugging a few of
// these around. -- bwr
- if (mass_item( you.inv[ weapon ] ) < 500)
+ if (item_mass( you.inv[ weapon ] ) < 300)
mon = MONS_SNAKE;
else
mon = MONS_BROWN_SNAKE;
@@ -851,7 +856,7 @@ static int sleep_monsters(int x, int y, int pow, int garbage)
int mnstr = mgrd[x][y];
if (mnstr == NON_MONSTER) return 0;
- if (mons_holiness( menv[mnstr].type ) != MH_NATURAL) return 0;
+ if (mons_holiness(&menv[mnstr]) != MH_NATURAL) return 0;
if (check_mons_resist_magic( &menv[mnstr], pow )) return 0;
// Why shouldn't we be able to sleep friendly monsters? -- bwr
@@ -864,7 +869,7 @@ static int sleep_monsters(int x, int y, int pow, int garbage)
menv[mnstr].behaviour = BEH_SLEEP;
mons_add_ench( &menv[mnstr], ENCH_SLEEP_WARY );
- if (mons_flag( menv[mnstr].type, M_COLD_BLOOD ) && coinflip())
+ if (mons_class_flag( menv[mnstr].type, M_COLD_BLOOD ) && coinflip())
mons_add_ench( &menv[mnstr], ENCH_SLOW );
return 1;
@@ -884,7 +889,7 @@ static int tame_beast_monsters(int x, int y, int pow, int garbage)
struct monsters *monster = &menv[which_mons];
- if (mons_holiness(monster->type) != MH_NATURAL) return 0;
+ if (mons_holiness(monster) != MH_NATURAL) return 0;
if (mons_intel_type(monster->type) != I_ANIMAL) return 0;
if (mons_friendly(monster)) return 0;
@@ -1012,7 +1017,7 @@ static int ignite_poison_monsters(int x, int y, int pow, int garbage)
struct monsters *const mon = &menv[ mon_index ];
// Monsters which have poison corpses or poisonous attacks:
- if (mons_corpse_thingy( mon->type ) == CE_POISONOUS
+ if (mons_corpse_effect( mon->type ) == CE_POISONOUS
|| mon->type == MONS_GIANT_ANT
|| mon->type == MONS_SMALL_SNAKE
|| mon->type == MONS_SNAKE
@@ -1259,6 +1264,8 @@ static int discharge_monsters( int x, int y, int pow, int garbage )
mpr( "You are struck by lightning." );
damage = 3 + random2( 5 + pow / 10 );
damage = check_your_resists( damage, BEAM_ELECTRICITY );
+ if ( player_is_levitating() )
+ damage /= 2;
ouch( damage, 0, KILLED_BY_WILD_MAGIC );
}
else if (mon == NON_MONSTER)
@@ -1707,7 +1714,7 @@ static int intoxicate_monsters(int x, int y, int pow, int garbage)
return 0;
if (mons_intel(menv[mon].type) < I_NORMAL)
return 0;
- if (mons_holiness(menv[mon].type) != MH_NATURAL)
+ if (mons_holiness(&menv[mon]) != MH_NATURAL)
return 0;
if (mons_res_poison(&menv[mon]) > 0)
return 0;
@@ -1746,7 +1753,7 @@ static int glamour_monsters(int x, int y, int pow, int garbage)
if (mons_intel(menv[mon].type) < I_NORMAL)
return (0);
- if (mons_holiness(mon) != MH_NATURAL)
+ if (mons_class_holiness(mon) != MH_NATURAL)
return (0);
if (!mons_is_humanoid( menv[mon].type ))
@@ -1893,7 +1900,8 @@ void cast_evaporate(int pow)
struct dist spelld;
struct bolt beem;
- const int potion = prompt_invent_item( "Throw which potion?", OBJ_POTIONS );
+ const int potion =
+ prompt_invent_item( "Throw which potion?", MT_INVSELECT, OBJ_POTIONS );
if (potion == -1)
{
@@ -1914,7 +1922,7 @@ void cast_evaporate(int pow)
message_current_target();
- direction( spelld, DIR_NONE, TARG_ENEMY );
+ direction( spelld, DIR_NONE, TARG_ENEMY, true );
if (!spelld.isValid)
{
@@ -1922,24 +1930,23 @@ void cast_evaporate(int pow)
return;
}
- beem.target_x = spelld.tx;
- beem.target_y = spelld.ty;
+ beem.set_target(spelld);
beem.source_x = you.x_pos;
beem.source_y = you.y_pos;
- strcpy( beem.beam_name, "potion" );
+ beem.name = "potion";
beem.colour = you.inv[potion].colour;
beem.range = 9;
beem.rangeMax = 9;
beem.type = SYM_FLASK;
beem.beam_source = MHITYOU;
beem.thrower = KILL_YOU_MISSILE;
- beem.aux_source = NULL;
- beem.isBeam = false;
- beem.isTracer = false;
+ beem.aux_source.clear();
+ beem.is_beam = false;
+ beem.is_tracer = false;
- beem.hit = you.dex / 2 + roll_dice( 2, you.skills[SK_THROWING] / 2 + 1 );
+ beem.hit = you.dex / 2 + roll_dice( 2, you.skills[SK_RANGED_COMBAT] / 2 + 1 );
beem.damage = dice_def( 1, 0 ); // no damage, just producing clouds
beem.ench_power = pow; // used for duration only?
@@ -2016,7 +2023,7 @@ void cast_evaporate(int pow)
}
if (coinflip())
- exercise( SK_THROWING, 1 );
+ exercise( SK_RANGED_COMBAT, 1 );
fire_beam(beem);
@@ -2103,7 +2110,7 @@ void cast_fulsome_distillation( int powc )
break;
default:
- switch (mons_corpse_thingy( mitm[corpse].plus ))
+ switch (mons_corpse_effect( mitm[corpse].plus ))
{
case CE_CLEAN:
potion_type = (power_up ? POT_CONFUSION : POT_WATER);
@@ -2208,7 +2215,7 @@ static int rot_living(int x, int y, int pow, int message)
if (mon == NON_MONSTER)
return 0;
- if (mons_holiness(menv[mon].type) != MH_NATURAL)
+ if (mons_holiness(&menv[mon]) != MH_NATURAL)
return 0;
if (check_mons_resist_magic(&menv[mon], pow))
@@ -2240,7 +2247,7 @@ static int rot_undead(int x, int y, int pow, int garbage)
if (mon == NON_MONSTER)
return 0;
- if (mons_holiness(menv[mon].type) != MH_UNDEAD)
+ if (mons_holiness(&menv[mon]) != MH_UNDEAD)
return 0;
if (check_mons_resist_magic(&menv[mon], pow))
@@ -2315,7 +2322,7 @@ void do_monster_rot(int mon)
{
int damage = 1 + random2(3);
- if (mons_holiness(menv[mon].type) == MH_UNDEAD && random2(5))
+ if (mons_holiness(&menv[mon]) == MH_UNDEAD && random2(5))
{
apply_area_cloud(make_a_normal_cloud, menv[mon].x, menv[mon].y,
10, 1, CLOUD_MIASMA);
@@ -2361,7 +2368,7 @@ void cast_fragmentation(int pow) // jmf: ripped idea from airstrike
const char *what = NULL;
mpr("Fragment what (e.g. a wall)?", MSGCH_PROMPT);
- direction( beam, DIR_TARGET, TARG_ENEMY );
+ direction( beam, DIR_TARGET, TARG_ENEMY, true );
if (!beam.isValid)
{
@@ -2372,13 +2379,12 @@ void cast_fragmentation(int pow) // jmf: ripped idea from airstrike
//FIXME: if (player typed '>' to attack floor) goto do_terrain;
blast.beam_source = MHITYOU;
blast.thrower = KILL_YOU;
- blast.aux_source = NULL;
+ blast.aux_source.clear();
blast.ex_size = 1; // default
blast.type = '#';
blast.colour = 0;
- blast.target_x = beam.tx;
- blast.target_y = beam.ty;
- blast.isTracer = false;
+ blast.set_target(beam);
+ blast.is_tracer = false;
blast.flavour = BEAM_FRAG;
// Number of dice vary... 3 is easy/common, but it can get as high as 6.
@@ -2405,7 +2411,7 @@ void cast_fragmentation(int pow) // jmf: ripped idea from airstrike
case MONS_SIMULACRUM_SMALL:
case MONS_SIMULACRUM_LARGE:
explode = true;
- strcpy(blast.beam_name, "icy blast");
+ blast.name = "icy blast";
blast.colour = WHITE;
blast.damage.num = 2;
blast.flavour = BEAM_ICE;
@@ -2421,7 +2427,7 @@ void cast_fragmentation(int pow) // jmf: ripped idea from airstrike
snprintf( info, INFO_SIZE, "The sk%s explodes into sharp fragments of bone!",
(menv[mon].type == MONS_FLYING_SKULL) ? "ull" : "eleton");
- strcpy(blast.beam_name, "blast of bone shards");
+ blast.name = "blast of bone shards";
blast.colour = LIGHTGREY;
@@ -2452,7 +2458,7 @@ void cast_fragmentation(int pow) // jmf: ripped idea from airstrike
case MONS_IRON_GOLEM:
case MONS_METAL_GARGOYLE:
explode = true;
- strcpy( blast.beam_name, "blast of metal fragments" );
+ blast.name = "blast of metal fragments";
blast.colour = CYAN;
blast.damage.num = 4;
if (player_hurt_monster(mon, roll_dice( blast.damage )))
@@ -2465,17 +2471,38 @@ void cast_fragmentation(int pow) // jmf: ripped idea from airstrike
case MONS_GARGOYLE:
explode = true;
blast.ex_size = 2;
- strcpy(blast.beam_name, "blast of rock fragments");
+ blast.name = "blast of rock fragments";
blast.colour = BROWN;
blast.damage.num = 3;
if (player_hurt_monster(mon, roll_dice( blast.damage )))
blast.damage.num += 1;
break;
+ case MONS_SILVER_STATUE:
+ case MONS_ORANGE_STATUE:
+ explode = true;
+ blast.ex_size = 2;
+ if (menv[mon].type == MONS_SILVER_STATUE)
+ {
+ blast.name = "blast of silver fragments";
+ blast.colour = WHITE;
+ blast.damage.num = 3;
+ }
+ else
+ {
+ blast.name = "blast of orange crystal shards";
+ blast.colour = LIGHTRED;
+ blast.damage.num = 6;
+ }
+
+ if (player_hurt_monster(mon, roll_dice( blast.damage )))
+ blast.damage.num += 2;
+ break;
+
case MONS_CRYSTAL_GOLEM:
explode = true;
blast.ex_size = 2;
- strcpy(blast.beam_name, "blast of crystal shards");
+ blast.name = "blast of crystal shards";
blast.colour = WHITE;
blast.damage.num = 4;
if (player_hurt_monster(mon, roll_dice( blast.damage )))
@@ -2524,7 +2551,7 @@ void cast_fragmentation(int pow) // jmf: ripped idea from airstrike
explode = true;
- strcpy(blast.beam_name, "blast of rock fragments");
+ blast.name = "blast of rock fragments";
blast.damage.num = 3;
if (blast.colour == 0)
blast.colour = LIGHTGREY;
@@ -2558,7 +2585,7 @@ void cast_fragmentation(int pow) // jmf: ripped idea from airstrike
}
explode = true;
- strcpy( blast.beam_name, "blast of metal fragments" );
+ blast.name = "blast of metal fragments";
blast.damage.num = 4;
if (okay_to_dest && pow >= 80 && random2(500) < pow / 5)
@@ -2586,7 +2613,7 @@ void cast_fragmentation(int pow) // jmf: ripped idea from airstrike
explode = true;
blast.ex_size = 2;
- strcpy(blast.beam_name, "blast of crystal shards");
+ blast.name = "blast of crystal shards";
blast.damage.num = 5;
if (okay_to_dest
@@ -2619,7 +2646,7 @@ void cast_fragmentation(int pow) // jmf: ripped idea from airstrike
explode = true;
hole = false; // to hit monsters standing on traps
- strcpy( blast.beam_name, "blast of fragments" );
+ blast.name = "blast of fragments";
blast.colour = env.floor_colour; // in order to blend in
blast.damage.num = 2;
@@ -2645,7 +2672,7 @@ void cast_fragmentation(int pow) // jmf: ripped idea from airstrike
case DNGN_STONE_ARCH: // floor -- small explosion
explode = true;
hole = false; // to hit monsters standing on doors
- strcpy( blast.beam_name, "blast of rock fragments" );
+ blast.name = "blast of rock fragments";
blast.colour = LIGHTGREY;
blast.damage.num = 2;
break;
@@ -2698,7 +2725,7 @@ void cast_twist(int pow)
if (pow > 25)
pow = 25;
- // Get target, using DIR_TARGET for targetting only,
+ // Get target, using DIR_TARGET for targetting only,
// since we don't use fire_beam() for this spell.
if (spell_direction(targ, tmp, DIR_TARGET) == -1)
return;
@@ -2750,7 +2777,7 @@ void cast_far_strike(int pow)
struct dist targ;
struct bolt tmp; // used, but ignored
- // Get target, using DIR_TARGET for targetting only,
+ // Get target, using DIR_TARGET for targetting only,
// since we don't use fire_beam() for this spell.
if (spell_direction(targ, tmp, DIR_TARGET) == -1)
return;
@@ -2863,34 +2890,34 @@ void cast_far_strike(int pow)
return;
} // end cast_far_strike()
-void cast_apportation(int pow)
+int cast_apportation(int pow)
{
struct dist beam;
mpr("Pull items from where?");
- direction( beam, DIR_TARGET );
+ direction( beam, DIR_TARGET, TARG_ANY, true );
if (!beam.isValid)
{
- canned_msg(MSG_SPELL_FIZZLES);
- return;
+ canned_msg(MSG_OK);
+ return (-1);
}
// it's already here!
if (beam.isMe)
{
mpr( "That's just silly." );
- return;
+ return (-1);
}
// Protect the player from destroying the item
const int grid = grd[ you.x_pos ][ you.y_pos ];
- if (grid == DNGN_LAVA || grid == DNGN_DEEP_WATER)
+ if (grid_destroys_items(grid))
{
mpr( "That would be silly while over this terrain!" );
- return;
+ return (0);
}
// If this is ever changed to allow moving objects that can't
@@ -2906,7 +2933,7 @@ void cast_apportation(int pow)
if (!see_grid( beam.tx, beam.ty ))
{
mpr( "You cannot see there!" );
- return;
+ return (0);
}
// Let's look at the top item in that square...
@@ -2926,11 +2953,11 @@ void cast_apportation(int pow)
else
mpr( "This spell does not work on creatures." );
- return;
+ return (0);
}
// mass of one unit
- const int unit_mass = mass_item( mitm[ item ] );
+ const int unit_mass = item_mass( mitm[ item ] );
// assume we can pull everything
int max_units = mitm[ item ].quantity;
@@ -2946,9 +2973,11 @@ void cast_apportation(int pow)
if (max_units <= 0)
{
mpr( "The mass is resisting your pull." );
- return;
+ return (0);
}
+ int done = 0;
+
// Failure should never really happen after all the above checking,
// but we'll handle it anyways...
if (move_top_item( beam.tx, beam.ty, you.x_pos, you.y_pos ))
@@ -2965,9 +2994,12 @@ void cast_apportation(int pow)
(mitm[ item ].quantity > 1) ? "s" : "" );
mpr( info );
}
+ done = 1;
}
else
mpr( "The spell fails." );
+
+ return (done);
}
void cast_sandblast(int pow)
@@ -3010,63 +3042,6 @@ void cast_sandblast(int pow)
}
} // end cast_sandblast()
-static bool mons_can_host_shuggoth(int type) //jmf: simplified
-{
- if (mons_holiness(type) != MH_NATURAL)
- return false;
- if (mons_flag(type, M_WARM_BLOOD))
- return true;
-
- return false;
-}
-
-void cast_shuggoth_seed(int powc)
-{
- struct dist beam;
- int i;
-
- mpr("Sow seed in whom?", MSGCH_PROMPT);
-
- direction( beam, DIR_TARGET, TARG_ENEMY );
-
- if (!beam.isValid)
- {
- mpr("You feel a distant frustration.");
- return;
- }
-
- if (beam.isMe)
- {
- if (!you.is_undead)
- {
- you.duration[DUR_INFECTED_SHUGGOTH_SEED] = 10;
- mpr("A deathly dread twitches in your chest.");
- }
- else
- mpr("You feel a distant frustration.");
- }
-
- i = mgrd[beam.tx][beam.ty];
-
- if (i == NON_MONSTER)
- {
- mpr("You feel a distant frustration.");
- return;
- }
-
- if (mons_can_host_shuggoth(menv[i].type))
- {
- if (random2(powc) > 100)
- mons_add_ench(&menv[i], ENCH_YOUR_SHUGGOTH_III);
- else
- mons_add_ench(&menv[i], ENCH_YOUR_SHUGGOTH_IV);
-
- simple_monster_message(&menv[i], " twitches.");
- }
-
- return;
-}
-
void cast_condensation_shield(int pow)
{
if (you.equip[EQ_SHIELD] != -1 || you.fire_shield)
@@ -3109,8 +3084,8 @@ static int quadrant_blink(int x, int y, int pow, int garbage)
// setup: Brent's new algorithm
// we are interested in two things: distance of a test point from
- // the ideal 'line', and the distance of a test point from two
- // actual points, one in the 'correct' direction and one in the
+ // the ideal 'line', and the distance of a test point from two
+ // actual points, one in the 'correct' direction and one in the
// 'incorrect' direction.
// scale distance by 10 for more interesting numbers.
@@ -3164,10 +3139,9 @@ static int quadrant_blink(int x, int y, int pow, int garbage)
return (1);
}
-void cast_semi_controlled_blink(int pow)
+int cast_semi_controlled_blink(int pow)
{
- apply_one_neighbouring_square(quadrant_blink, pow);
- return;
+ return apply_one_neighbouring_square(quadrant_blink, pow);
}
void cast_stoneskin(int pow)
diff --git a/crawl-ref/source/spells4.h b/crawl-ref/source/spells4.h
index 94cc74fcac..29580a7b29 100644
--- a/crawl-ref/source/spells4.h
+++ b/crawl-ref/source/spells4.h
@@ -3,6 +3,8 @@
* Summary: Yet More Spell Function Declarations
* Written by: Josh Fishman
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
* <2> 12jul2000 jmf Fixed random (undocumented) damage
* <1> 07jan2000 jmf Created
@@ -30,7 +32,7 @@ void cast_fragmentation(int powc);
void cast_twist(int powc);
void cast_far_strike(int powc);
void cast_swap(int powc);
-void cast_apportation(int powc);
+int cast_apportation(int powc);
void cast_glamour(int pow);
void cast_ignite_poison(int pow);
void cast_intoxicate(int pow);
@@ -45,6 +47,7 @@ void cast_silence(int pow);
void cast_sticks_to_snakes(int pow);
void cast_summon_butterflies(int pow);
void cast_summon_dragon(int pow);
+void cast_chain_lightning( int pow );
void cast_conjure_ball_lightning(int pow);
void cast_summon_large_mammal(int pow);
void cast_tame_beasts(int pow);
@@ -55,7 +58,7 @@ void cast_stoneskin(int pow);
void cast_shuggoth_seed(int powc);
void make_shuggoth(int x, int y, int hp);
-void cast_semi_controlled_blink(int pow);
+int cast_semi_controlled_blink(int pow);
#endif
diff --git a/crawl-ref/source/spl-book.cc b/crawl-ref/source/spl-book.cc
index c6efbae9cf..4f6e040563 100644
--- a/crawl-ref/source/spl-book.cc
+++ b/crawl-ref/source/spl-book.cc
@@ -3,6 +3,8 @@
* Summary: Spellbook/Staff contents array and management functions
* Written by: Josh Fishman
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* 24jun2000 jmf Changes to many books; addition of Assassinations;
@@ -26,8 +28,10 @@
#include "debug.h"
#include "delay.h"
+#include "food.h"
#include "invent.h"
#include "itemname.h"
+#include "itemprop.h"
#include "items.h"
#include "it_use3.h"
#include "player.h"
@@ -144,8 +148,8 @@ static int spellbook_template_array[NUMBER_SPELLBOOKS][SPELLBOOK_SIZE] =
SPELL_CONDENSATION_SHIELD,
SPELL_BOLT_OF_COLD,
SPELL_OZOCUBUS_REFRIGERATION,
- SPELL_MASS_SLEEP,
SPELL_SIMULACRUM,
+ SPELL_MASS_SLEEP,
SPELL_NO_SPELL,
},
@@ -331,15 +335,10 @@ static int spellbook_template_array[NUMBER_SPELLBOOKS][SPELLBOOK_SIZE] =
SPELL_BACKLIGHT,
SPELL_REPEL_MISSILES,
SPELL_SLEEP,
-#ifdef USE_SILENCE_CODE
- SPELL_SILENCE,
-#endif
SPELL_CONFUSE,
SPELL_ENSLAVEMENT,
+ SPELL_SILENCE,
SPELL_INVISIBILITY,
-#ifndef USE_SILENCE_CODE
- SPELL_NO_SPELL,
-#endif
SPELL_NO_SPELL,
},
// 27 - Book of Demonology -- Vehumet special
@@ -382,19 +381,14 @@ static int spellbook_template_array[NUMBER_SPELLBOOKS][SPELLBOOK_SIZE] =
// 29 - Book of the Sky
{0,
-#ifdef USE_SILENCE_CODE
- SPELL_SILENCE,
-#endif
SPELL_SUMMON_ELEMENTAL,
SPELL_INSULATION,
SPELL_AIRSTRIKE,
SPELL_FLY,
+ SPELL_SILENCE,
SPELL_DEFLECT_MISSILES,
SPELL_LIGHTNING_BOLT,
SPELL_CONJURE_BALL_LIGHTNING,
-#ifndef USE_SILENCE_CODE
- SPELL_NO_SPELL,
-#endif
},
// 30 - Book of Divinations
@@ -410,11 +404,11 @@ static int spellbook_template_array[NUMBER_SPELLBOOKS][SPELLBOOK_SIZE] =
},
// 31 - Book of the Warp
{0,
- SPELL_CONTROLLED_BLINK,
SPELL_BANISHMENT,
+ SPELL_WARP_BRAND,
SPELL_DISPERSAL,
SPELL_PORTAL,
- SPELL_NO_SPELL,
+ SPELL_CONTROLLED_BLINK,
SPELL_NO_SPELL,
SPELL_NO_SPELL,
SPELL_NO_SPELL,
@@ -434,7 +428,7 @@ static int spellbook_template_array[NUMBER_SPELLBOOKS][SPELLBOOK_SIZE] =
{0,
SPELL_ISKENDERUNS_MYSTIC_BLAST,
SPELL_POISON_ARROW,
- SPELL_ORB_OF_ELECTROCUTION, // XXX: chain lightning?
+ SPELL_CHAIN_LIGHTNING,
SPELL_LEHUDIBS_CRYSTAL_SPEAR,
SPELL_ICE_STORM,
SPELL_FIRE_STORM,
@@ -520,7 +514,7 @@ static int spellbook_template_array[NUMBER_SPELLBOOKS][SPELLBOOK_SIZE] =
SPELL_BOLT_OF_IRON,
SPELL_TOMB_OF_DOROKLOHE,
SPELL_SHATTER,
- SPELL_NO_SPELL,
+ SPELL_NO_SPELL
},
// 41 - manuals of all kinds
{0,
@@ -800,7 +794,7 @@ unsigned char spellbook_contents( item_def &book, int action,
char str_pass[ ITEMNAME_SIZE ];
item_name( book, DESC_CAP_THE, str_pass );
- out.cprintf( str_pass );
+ out.cprintf( "%s", str_pass );
out.cprintf( EOL EOL " Spells Type Level" EOL );
@@ -824,7 +818,9 @@ unsigned char spellbook_contents( item_def &book, int action,
if (action == RBOOK_USE_STAFF)
{
if (you.experience_level >= level_diff
- && you.magic_points >= level_diff)
+ && (book.base_type == OBJ_BOOKS?
+ you.magic_points >= level_diff
+ : book.plus >= level_diff * ROD_CHARGE_MULT))
{
colour = LIGHTGREY;
}
@@ -850,12 +846,12 @@ unsigned char spellbook_contents( item_def &book, int action,
char strng[2];
strng[0] = index_to_letter(spelcount);
- strng[1] = '\0';
+ strng[1] = 0;
out.cprintf(strng);
out.cprintf(" - ");
- out.cprintf( spell_title(spell_types[j]) );
+ out.cprintf( "%s", spell_title(spell_types[j]) );
out.gotoxy( 35, -1 );
@@ -872,7 +868,7 @@ unsigned char spellbook_contents( item_def &book, int action,
if (already)
out.cprintf( "/" );
- out.cprintf( spelltype_name( 1 << i ) );
+ out.cprintf( "%s", spelltype_name( 1 << i ) );
already = true;
}
}
@@ -897,7 +893,7 @@ unsigned char spellbook_contents( item_def &book, int action,
out.cprintf( "Select a spell to cast." EOL );
break;
- case RBOOK_MEMORIZE:
+ case RBOOK_MEMORISE:
out.cprintf( "Select a spell to memorise (%d level%s available)." EOL,
spell_levels, (spell_levels == 1) ? "" : "s" );
break;
@@ -1063,7 +1059,8 @@ static bool which_spellbook( int &book, int &spell )
mpr( info );
- book = prompt_invent_item( "Memorise from which spellbook?", OBJ_BOOKS );
+ book = prompt_invent_item("Memorise from which spellbook?", MT_INVSELECT,
+ OBJ_BOOKS );
if (book == PROMPT_ABORT)
{
canned_msg( MSG_OK );
@@ -1083,7 +1080,7 @@ static bool which_spellbook( int &book, int &spell )
return (false);
}
- spell = read_book( you.inv[book], RBOOK_MEMORIZE );
+ spell = read_book( you.inv[book], RBOOK_MEMORISE );
clrscr();
return (true);
@@ -1156,7 +1153,7 @@ unsigned char read_book( item_def &book, int action )
// reading spell descriptions doesn't take time:
if (action != RBOOK_READ_SPELL)
- you.turn_is_over = 1;
+ you.turn_is_over = true;
set_ident_flags( book, ISFLAG_KNOW_TYPE );
@@ -1225,7 +1222,6 @@ bool learn_spell(void)
{
int chance = 0;
int levels_needed = 0;
- unsigned char keyin;
int book, spell;
int index;
@@ -1247,45 +1243,47 @@ bool learn_spell(void)
if (!which_spellbook( book, spell ))
return (false);
+ mesclr(true);
+ redraw_screen();
+
if (spell < 'A' || (spell > 'Z' && spell < 'a') || spell > 'z')
{
- whatt:
- redraw_screen();
- mpr("What?");
+ canned_msg( MSG_HUH );
return (false);
}
index = letter_to_index( spell );
- if (index >= SPELLBOOK_SIZE)
- goto whatt;
-
- if (!is_valid_spell_in_book( book, index ))
- goto whatt;
+ if (index >= SPELLBOOK_SIZE ||
+ !is_valid_spell_in_book( book, index ))
+ {
+ canned_msg( MSG_HUH );
+ return (false);
+ }
unsigned int specspell = which_spell_in_book(you.inv[book].sub_type,index);
if (specspell == SPELL_NO_SPELL)
- goto whatt;
+ {
+ canned_msg( MSG_HUH );
+ return (false);
+ }
// You can always memorise selective amnesia:
if (you.spell_no == 21 && specspell != SPELL_SELECTIVE_AMNESIA)
{
- redraw_screen();
mpr("Your head is already too full of spells!");
return (false);
}
if (you.is_undead && spell_typematch(specspell, SPTYP_HOLY))
{
- redraw_screen();
mpr("You cannot use this type of magic!");
return (false);
}
if (undead_cannot_memorise(specspell, you.is_undead))
{
- redraw_screen();
mpr("You cannot use this spell.");
return (false);
}
@@ -1294,9 +1292,8 @@ bool learn_spell(void)
{
if (you.spells[i] == specspell)
{
- redraw_screen();
mpr("You already know that spell!");
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return (false);
}
}
@@ -1305,89 +1302,56 @@ bool learn_spell(void)
if (player_spell_levels() < levels_needed)
{
- redraw_screen();
mpr("You can't memorise that many levels of magic yet!");
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return (false);
}
if (you.experience_level < spell_difficulty(specspell))
{
- redraw_screen();
mpr("You're too inexperienced to learn that spell!");
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return (false);
}
- redraw_screen();
-
chance = spell_fail(specspell);
-
- strcpy(info, "This spell is ");
-
- strcat(info, (chance >= 80) ? "very" :
- (chance >= 60) ? "quite" :
- (chance >= 45) ? "rather" :
- (chance >= 30) ? "somewhat"
- : "not that");
-
- strcat(info, " ");
-
- int temp_rand = random2(3);
-
- strcat(info, (temp_rand == 0) ? "difficult" :
- (temp_rand == 1) ? "tricky" :
- (temp_rand == 2) ? "challenging"
- : "");
-
- strcat(info, " to ");
-
- temp_rand = random2(4);
-
- strcat(info, (temp_rand == 0) ? "memorise" :
- (temp_rand == 1) ? "commit to memory" :
- (temp_rand == 2) ? "learn" :
- (temp_rand == 3) ? "absorb"
- : "");
-
- strcat(info, ".");
-
+ int temp_rand1 = random2(3);
+ int temp_rand2 = random2(4);
+
+ snprintf(info, INFO_SIZE, "This spell is %s %s to %s.",
+ ((chance >= 80) ? "very" :
+ (chance >= 60) ? "quite" :
+ (chance >= 45) ? "rather" :
+ (chance >= 30) ? "somewhat"
+ : "not that"),
+ ((temp_rand1 == 0) ? "difficult" :
+ (temp_rand1 == 1) ? "tricky" :
+ "challenging"),
+ ((temp_rand2 == 0) ? "memorise" :
+ (temp_rand2 == 1) ? "commit to memory" :
+ (temp_rand2 == 2) ? "learn" :
+ "absorb"));
mpr(info);
- strcpy(info, "Memorise ");
- strcat(info, spell_title(specspell));
- strcat(info, "?");
- mpr(info);
-
- for (;;)
+ snprintf(info, INFO_SIZE, "Memorise %s?", spell_title(specspell));
+ if ( !yesno(info, true, 0, false) )
{
- keyin = getch();
-
- if (keyin == 'n' || keyin == 'N')
- {
- redraw_screen();
- return (false);
- }
-
- if (keyin == 'y' || keyin == 'Y')
- break;
+ canned_msg( MSG_OK );
+ return (false);
}
- mesclr( true );
-
if (you.mutation[MUT_BLURRY_VISION] > 0
- && random2(4) < you.mutation[MUT_BLURRY_VISION])
+ && random2(4) < you.mutation[MUT_BLURRY_VISION])
{
mpr("The writing blurs into unreadable gibberish.");
- you.turn_is_over = 1;
+ you.turn_is_over = true;
return (false);
}
if (random2(40) + random2(40) + random2(40) < chance)
{
- redraw_screen();
mpr("You fail to memorise the spell.");
- you.turn_is_over = 1;
+ you.turn_is_over = true;
if (you.inv[ book ].sub_type == BOOK_NECRONOMICON)
{
@@ -1411,19 +1375,17 @@ bool learn_spell(void)
#if WIZARD
if (!you.wizard)
return (false);
- else if (!yesno("Memorize anyway?"))
+ else if (!yesno("Memorise anyway?"))
return (false);
#else
return (false);
#endif
}
- start_delay( DELAY_MEMORIZE, spell_difficulty( specspell ), specspell );
-
- you.turn_is_over = 1;
- redraw_screen();
+ start_delay( DELAY_MEMORISE, spell_difficulty( specspell ), specspell );
+ you.turn_is_over = true;
- naughty( NAUGHTY_SPELLCASTING, 2 + random2(5) );
+ did_god_conduct( DID_SPELL_CASTING, 2 + random2(5) );
return (true);
} // end which_spell()
@@ -1433,7 +1395,7 @@ int count_staff_spells(const item_def &item, bool need_id)
if (item.base_type != OBJ_STAVES)
return (-1);
- if (need_id && item_not_ident( item, ISFLAG_KNOW_TYPE ))
+ if (need_id && !item_ident( item, ISFLAG_KNOW_TYPE ))
return (0);
const int stype = item.sub_type;
@@ -1453,11 +1415,29 @@ int count_staff_spells(const item_def &item, bool need_id)
return (num_spells);
}
+// Returns a measure of the rod spell power disrupted by a worn shield.
+int rod_shield_leakage()
+{
+ const item_def *shield = player_shield();
+ int leakage = 100;
+
+ if (shield)
+ {
+ const int shield_type = shield->sub_type;
+ leakage = shield_type == ARM_BUCKLER? 125 :
+ shield_type == ARM_SHIELD ? 150 :
+ 200;
+ // Adjust for shields skill.
+ leakage -= ((leakage - 100) * 5 / 10) * you.skills[SK_SHIELDS] / 27;
+ }
+ return (leakage);
+}
+
int staff_spell( int staff )
{
int spell;
unsigned char specspell;
- int mana, diff;
+ int mana, diff, food, energy;
FixedVector< int, SPELLBOOK_SIZE > spell_list;
// converting sub_type into book index type
@@ -1465,18 +1445,19 @@ int staff_spell( int staff )
// Spell staves are mostly for the benefit of non-spellcasters, so we're
// not going to involve INT or Spellcasting skills for power. -- bwr
- const int powc = 5 + you.skills[SK_EVOCATIONS]
- + roll_dice( 2, you.skills[SK_EVOCATIONS] );
+ int powc = (5 + you.skills[SK_EVOCATIONS]
+ + roll_dice( 2, you.skills[SK_EVOCATIONS] ))
+ * 100
+ / rod_shield_leakage();
- if (you.inv[staff].sub_type < STAFF_SMITING
- || you.inv[staff].sub_type >= STAFF_AIR)
+ const int staff_type = you.inv[staff].sub_type;
+ if (staff_type < STAFF_SMITING || staff_type >= STAFF_AIR)
{
- //mpr("That staff has no spells in it.");
canned_msg(MSG_NOTHING_HAPPENS);
- return (0);
+ return (-1);
}
- if (item_not_ident( you.inv[staff], ISFLAG_KNOW_TYPE ))
+ if (!item_ident( you.inv[staff], ISFLAG_KNOW_TYPE ))
{
set_ident_flags( you.inv[staff], ISFLAG_KNOW_TYPE );
you.wield_change = true;
@@ -1508,7 +1489,11 @@ int staff_spell( int staff )
spell = get_ch();
if (spell == '?' || spell == '*')
+ {
spell = read_book( you.inv[staff], RBOOK_USE_STAFF );
+ // [ds] read_book sets turn_is_over.
+ you.turn_is_over = false;
+ }
}
if (spell < 'A' || (spell > 'Z' && spell < 'a') || spell > 'z')
@@ -1524,39 +1509,74 @@ int staff_spell( int staff )
if (!is_valid_spell_in_book( staff, spell ))
goto whattt;
- specspell = which_spell_in_book( type, spell );
+ specspell = which_spell_in_book( type, spell );
if (specspell == SPELL_NO_SPELL)
goto whattt;
- mana = spell_mana( specspell );
+ mana = spell_mana( specspell ) * ROD_CHARGE_MULT;
diff = spell_difficulty( specspell );
+ food = spell_hunger( specspell );
- if (you.magic_points < mana || you.experience_level < diff)
+ if (food && (you.is_undead != US_UNDEAD
+ && (you.hunger_state < HS_HUNGRY || you.hunger <= food)))
{
- mpr("Your brain hurts!");
- confuse_player( 2 + random2(4) );
- you.turn_is_over = 1;
- return (0);
+ mpr("You don't have the energy to cast that spell.");
+ return (-1);
}
- // Exercising the spell skills doesn't make very much sense given
- // that spell staves are largely intended to supply spells to
- // non-spellcasters, and they don't use spell skills to determine
- // power in the same way that spellcasting does. -- bwr
- //
- // exercise_spell(specspell, true, true);
+ if (staff_type == STAFF_STRIKING)
+ mana /= ROD_CHARGE_MULT;
- your_spells(specspell, powc, false);
+ if ((staff_type == STAFF_STRIKING?
+ you.magic_points < mana
+ : you.inv[staff].plus < mana)
+ || you.experience_level < diff)
+ {
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS,
+ "Mana needed: %d, Staff plus: %d, Difficulty: %d, XP: %d",
+ mana, you.inv[staff].plus, diff, you.experience_level);
+#endif
+ if (you.experience_level < diff)
+ mprf("You need to be at least level %d to use that.", diff);
+ else
+ mprf("%s have enough magic points.",
+ staff_type == STAFF_STRIKING? "You don't" : "The rod doesn't");
- dec_mp(spell_mana(specspell));
+ // Don't lose a turn for trying to evoke without enough MP - that's
+ // needlessly cruel for an honest error.
+ return (-1);
+ }
+
+ if (your_spells(specspell, powc, false) == -1)
+ return (-1);
+
+ // dec_mp(spell_mana(specspell));
+ if (staff_type != STAFF_STRIKING)
+ you.inv[staff].plus -= mana;
+ else {
+ you.magic_points -= mana;
+ you.redraw_magic_points = true;
+ }
+
+ energy = player_energy();
+ if (energy <= 0 && you.is_undead != US_UNDEAD)
+ {
+ food -= 10 * you.skills[SK_EVOCATIONS];
+ if (food < diff * 5)
+ food = diff * 5;
+
+ make_hungry( food, true );
+ }
- you.turn_is_over = 1;
+ you.wield_change = true;
+ you.turn_is_over = true;
return (roll_dice( 1, 1 + spell_difficulty(specspell) / 2 ));
whattt:
mpr("What?");
- return (0);
+ return (-1);
} // end staff_spell()
diff --git a/crawl-ref/source/spl-book.h b/crawl-ref/source/spl-book.h
index d6aa2843bc..6c34a596e2 100644
--- a/crawl-ref/source/spl-book.h
+++ b/crawl-ref/source/spl-book.h
@@ -3,6 +3,8 @@
* Summary: Some spellbook related functions.
* Written by: Josh Fishman
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* 22mar2000 jmf Created
@@ -13,6 +15,7 @@
#define SPL_BOOK_H
#include "externs.h"
+#include "menu.h"
#include "FixVec.h"
@@ -64,5 +67,6 @@ unsigned char spellbook_contents( item_def &book, int action,
formatted_string *fs = NULL );
int count_staff_spells(const item_def &item, bool need_id);
+int rod_shield_leakage();
#endif
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index 6044904dc0..cc46f82a10 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -31,6 +31,7 @@
#include "food.h"
#include "it_use2.h"
#include "itemname.h"
+#include "itemprop.h"
#include "macro.h"
#include "monplace.h"
#include "monstuff.h"
@@ -39,6 +40,7 @@
#include "player.h"
#include "religion.h"
#include "skills.h"
+#include "skills2.h"
#include "spells1.h"
#include "spells2.h"
#include "spells3.h"
@@ -101,7 +103,7 @@ char list_spells(void)
clrscr();
- cprintf( " Your Spells Type Success Level" );
+ cprintf( " Your Spells Type Power Success Level" );
lines++;
for (j = 0; j < 52; j++)
@@ -162,13 +164,29 @@ char list_spells(void)
if (already)
cprintf( "/" );
- cprintf( spelltype_name( 1 << i ) );
+ cprintf( "%s", spelltype_short_name( 1 << i ) );
already = true;
}
}
char sval[16];
+ // 35--48 is the spell schools
+
+ gotoxy(51, wherey());
+ int spell_p = calc_spell_power( spell, true );
+ cprintf( (spell_p > 100) ? "Enormous" :
+ (spell_p > 90) ? "Huge" :
+ (spell_p > 80) ? "Massive" :
+ (spell_p > 70) ? "Major" :
+ (spell_p > 60) ? "Impressive" :
+ (spell_p > 50) ? "Reasonable" :
+ (spell_p > 40) ? "Moderate" :
+ (spell_p > 30) ? "Adequate" :
+ (spell_p > 20) ? "Mediocre" :
+ (spell_p > 10) ? "Minor"
+ : "Negligible");
+
//gotoxy(58, wherey());
gotoxy(65, wherey());
@@ -225,12 +243,44 @@ char list_spells(void)
return (ki);
} // end list_spells()
+static int apply_vehumet_wizardry_boost(int spell, int chance)
+{
+ int wizardry = player_mag_abil(false);
+ int fail_reduce = 100;
+ int wiz_factor = 86;
+
+ if (you.religion == GOD_VEHUMET
+ && you.duration[DUR_PRAYER]
+ && (!player_under_penance() && you.piety >= 50)
+ && (spell_typematch(spell, SPTYP_CONJURATION)
+ || spell_typematch(spell, SPTYP_SUMMONING)))
+ {
+ // [dshaligram] Fail rate multiplier used to be .5, scaled
+ // back to 60%.
+ fail_reduce = fail_reduce * 60 / 100;
+ }
+
+ // [dshaligram] Apply wizardry factor here, rather than mixed into the
+ // pre-scaling spell power.
+ while (wizardry-- > 0)
+ {
+ fail_reduce = fail_reduce * wiz_factor / 100;
+ wiz_factor += (100 - wiz_factor) / 5;
+ }
+
+ // Hard cap on fail rate reduction.
+ if (fail_reduce < 40)
+ fail_reduce = 40;
+
+ return (chance * fail_reduce / 100);
+}
+
int spell_fail(int spell)
{
int chance = 60;
int chance2 = 0, armour = 0;
- chance -= 6 * calc_spell_power( spell, false );
+ chance -= 6 * calc_spell_power( spell, false, true );
chance -= (you.intel * 2);
//chance -= (you.intel - 10) * abs(you.intel - 10);
@@ -396,15 +446,6 @@ int spell_fail(int spell)
if (chance < -180)
chance2 = 0;
- if (you.religion == GOD_VEHUMET
- && you.duration[DUR_PRAYER]
- && (!player_under_penance() && you.piety >= 50)
- && (spell_typematch(spell, SPTYP_CONJURATION)
- || spell_typematch(spell, SPTYP_SUMMONING)))
- {
- chance2 /= 2;
- }
-
if (you.duration[DUR_TRANSFORMATION] > 0)
{
switch (you.attribute[ATTR_TRANSFORMATION])
@@ -417,17 +458,28 @@ int spell_fail(int spell)
chance2 += 10;
break;
}
+
+ if (chance2 > 100)
+ chance2 = 100;
}
+ // Apply the effects of Vehumet prayer and items of wizardry.
+ chance2 = apply_vehumet_wizardry_boost(spell, chance2);
+
return (chance2);
} // end spell_fail()
-int calc_spell_power( int spell, bool apply_intel )
+int calc_spell_power( int spell, bool apply_intel, bool fail_rate_check )
{
unsigned int bit;
int ndx;
- int power = (you.skills[SK_SPELLCASTING] / 2) + player_mag_abil(false);
+
+ // When checking failure rates, wizardry is handled after the various
+ // stepping calulations.
+ int power =
+ (you.skills[SK_SPELLCASTING] / 2)
+ + (fail_rate_check? 0 : player_mag_abil(false));
int enhanced = 0;
unsigned int disciplines = spell_type( spell );
@@ -453,7 +505,10 @@ int calc_spell_power( int spell, bool apply_intel )
if (apply_intel)
power = (power * you.intel) / 10;
- enhanced = spell_enhancement( disciplines );
+ // [dshaligram] Enhancers don't affect fail rates any more, only spell
+ // power. Note that this does not affect Vehumet's boost in castability.
+ if (!fail_rate_check)
+ enhanced = spell_enhancement( disciplines );
if (enhanced > 0)
{
@@ -561,7 +616,7 @@ bool cast_a_spell(void)
if (unthing == 2)
return (false);
- if (unthing >= 'a' && unthing <= 'y')
+ if ( isalpha(unthing) )
{
keyin = unthing;
break;
@@ -611,6 +666,18 @@ bool cast_a_spell(void)
return (false);
}
+ if (you.conf)
+ random_uselessness( 2 + random2(7), 0 );
+ else
+ {
+ int cast_result = your_spells( spell );
+ if (cast_result == -1)
+ return (false);
+
+ exercise_spell( spell, true, cast_result );
+ did_god_conduct( DID_SPELL_CASTING, 1 + random2(5) );
+ }
+
dec_mp( spell_mana(spell) );
if (!player_energy() && you.is_undead != US_UNDEAD)
@@ -626,39 +693,32 @@ bool cast_a_spell(void)
make_hungry(spellh, true);
}
- you.turn_is_over = 1;
+ you.turn_is_over = true;
alert_nearby_monsters();
- if (you.conf)
- random_uselessness( 2 + random2(7), 0 );
- else
- {
- exercise_spell( spell, true, your_spells( spell ) );
- naughty( NAUGHTY_SPELLCASTING, 1 + random2(5) );
- }
-
return (true);
} // end cast_a_spell()
-// returns true if spell if spell is successfully cast for purposes of
-// exercising and false otherwise (note: false == less exercise, not none).
-bool your_spells( int spc2, int powc, bool allow_fail )
+// "Utility" spells for the sake of simplicity are currently ones with
+// enchantments, translocations, or divinations.
+bool spell_is_utility_spell( int spell_id )
{
- int dem_hor = 0;
- int dem_hor2 = 0;
- int total_skill = 0;
- struct dist spd;
- struct bolt beam;
+ return (spell_typematch( spell_id,
+ SPTYP_ENCHANTMENT | SPTYP_TRANSLOCATION | SPTYP_DIVINATION ));
+}
- alert_nearby_monsters();
+bool spell_is_unholy( int spell_id )
+{
+ return (testbits( get_spell_flags( spell_id ), SPFLAG_UNHOLY ));
+}
- // Added this so that the passed in powc can have meaning -- bwr
- if (powc == 0)
- powc = calc_spell_power( spc2, true );
+void spellcasting_side_effects(int spc2, bool idonly = false)
+{
+ int total_skill = 0;
if (you.equip[EQ_WEAPON] != -1
&& item_is_staff( you.inv[you.equip[EQ_WEAPON]] )
- && item_not_ident( you.inv[you.equip[EQ_WEAPON]], ISFLAG_KNOW_TYPE ))
+ && !item_ident( you.inv[you.equip[EQ_WEAPON]], ISFLAG_KNOW_TYPE ))
{
switch (you.inv[you.equip[EQ_WEAPON]].sub_type)
{
@@ -719,7 +779,8 @@ bool your_spells( int spc2, int powc, bool allow_fail )
{
char str_pass[ ITEMNAME_SIZE ];
- set_ident_flags( you.inv[you.equip[EQ_WEAPON]], ISFLAG_KNOW_TYPE );
+ // changed from ISFLAG_KNOW_TYPE
+ set_ident_flags( you.inv[you.equip[EQ_WEAPON]], ISFLAG_IDENT_MASK);
strcpy(info, "You are wielding ");
in_name(you.equip[EQ_WEAPON], DESC_NOCAP_A, str_pass);
@@ -733,6 +794,53 @@ bool your_spells( int spc2, int powc, bool allow_fail )
}
}
+ if (idonly)
+ return;
+
+ if (!spell_is_utility_spell(spc2))
+ did_god_conduct( DID_SPELL_NONUTILITY, 10 + spell_difficulty(spc2) );
+
+ if (spell_is_unholy( spc2 ))
+ did_god_conduct( DID_UNHOLY, 10 + spell_difficulty(spc2) );
+
+ // Linley says: Condensation Shield needs some disadvantages to keep
+ // it from being a no-brainer... this isn't much, but its a start -- bwr
+ if (spell_typematch(spc2, SPTYP_FIRE))
+ expose_player_to_element(BEAM_FIRE, 0);
+
+ if (spell_typematch( spc2, SPTYP_NECROMANCY ))
+ {
+ did_god_conduct( DID_NECROMANCY, 10 + spell_difficulty(spc2) );
+
+ if (spc2 == SPELL_NECROMUTATION
+ && (you.religion == GOD_ELYVILON
+ || you.religion == GOD_SHINING_ONE
+ || you.religion == GOD_ZIN))
+ {
+ excommunication();
+ }
+ }
+
+ alert_nearby_monsters();
+}
+
+// returns 1 if spell is successfully cast for purposes of exercising and 0
+// otherwise (note: false == less exercise, not none). If the player aborts the
+// spell, returns -1.
+int your_spells( int spc2, int powc, bool allow_fail )
+{
+ int dem_hor = 0;
+ int dem_hor2 = 0;
+ struct dist spd;
+ struct bolt beam;
+
+ // [dshaligram] Any action that depends on the spellcasting attempt to have
+ // succeeded must be performed after the switch()
+
+ // Added this so that the passed in powc can have meaning -- bwr
+ if (powc == 0)
+ powc = calc_spell_power( spc2, true );
+
surge_power(spc2);
if (allow_fail)
@@ -740,21 +848,23 @@ bool your_spells( int spc2, int powc, bool allow_fail )
int spfl = random2avg(100, 3);
if (you.religion != GOD_SIF_MUNA
- && you.penance[GOD_SIF_MUNA] && one_chance_in(40))
+ && you.penance[GOD_SIF_MUNA] && one_chance_in(20))
{
god_speaks(GOD_SIF_MUNA, "You feel a surge of divine spite.");
// This will cause failure and increase the miscast effect.
spfl = -you.penance[GOD_SIF_MUNA];
- // Reduced penenance reduction here because casting spells
+ // Reduced penance reduction here because casting spells
// is a player controllable act. -- bwr
- if (one_chance_in(7))
- dec_penance(1);
+ if (one_chance_in(12))
+ dec_penance(GOD_SIF_MUNA, 1);
}
if (spfl < spell_fail(spc2))
{
+ spellcasting_side_effects(spc2, true);
+
mpr( "You miscast the spell." );
flush_input_buffer( FLUSH_ON_FAILURE );
@@ -763,7 +873,7 @@ bool your_spells( int spc2, int powc, bool allow_fail )
&& you.piety >= 100 && random2(150) <= you.piety))
{
canned_msg(MSG_NOTHING_HAPPENS);
- return (false);
+ return (0);
}
unsigned int sptype = 0;
@@ -793,14 +903,14 @@ bool your_spells( int spc2, int powc, bool allow_fail )
if (you.religion == GOD_XOM && random2(75) < spell_mana(spc2))
Xom_acts(coinflip(), spell_mana(spc2), false);
- return (false);
+ return (0);
}
}
if (you.is_undead && spell_typematch( spc2, SPTYP_HOLY ))
{
mpr( "You can't use this type of magic!" );
- return (false); // XXX: still gets trained!
+ return (-1);
}
// Normally undead can't memorize these spells, so this check is
@@ -810,43 +920,7 @@ bool your_spells( int spc2, int powc, bool allow_fail )
&& undead_cannot_memorise( spc2, you.is_undead ))
{
mpr( "You cannot cast that spell in your current form!" );
- return (false); // XXX: still gets trained!
- }
-
- // Linley says: Condensation Shield needs some disadvantages to keep
- // it from being a no-brainer... this isn't much, but its a start -- bwr
- if (you.duration[DUR_CONDENSATION_SHIELD] > 0
- && spell_typematch( spc2, SPTYP_FIRE ))
- {
- mpr( "Your icy shield dissipates!", MSGCH_DURATION );
- you.duration[DUR_CONDENSATION_SHIELD] = 0;
- you.redraw_armour_class = 1;
- }
-
- if (spc2 == SPELL_SUMMON_HORRIBLE_THINGS
- || spc2 == SPELL_CALL_IMP
- || spc2 == SPELL_SUMMON_DEMON
- || spc2 == SPELL_DEMONIC_HORDE
- || spc2 == SPELL_SUMMON_GREATER_DEMON || spc2 == SPELL_HELLFIRE)
- {
- naughty(NAUGHTY_UNHOLY, 10 + spell_difficulty(spc2));
- }
-
- if (spell_typematch( spc2, SPTYP_NECROMANCY ))
- naughty( NAUGHTY_NECROMANCY, 10 + spell_difficulty(spc2) );
-
- if (spc2 == SPELL_NECROMUTATION
- && (you.religion == GOD_ELYVILON
- || you.religion == GOD_SHINING_ONE
- || you.religion == GOD_ZIN))
- {
- excommunication();
- }
-
- if (you.religion == GOD_SIF_MUNA
- && you.piety < 200 && random2(12) <= spell_difficulty(spc2))
- {
- gain_piety(1);
+ return (-1);
}
#if DEBUG_DIAGNOSTICS
@@ -854,6 +928,9 @@ bool your_spells( int spc2, int powc, bool allow_fail )
mpr( info, MSGCH_DIAGNOSTICS );
#endif
+#define SPELL_DIR(s, b) if (spell_direction(spd, beam) == -1) return -1; \
+ else
+
switch (spc2)
{
case SPELL_IDENTIFY:
@@ -871,7 +948,7 @@ bool your_spells( int spc2, int powc, bool allow_fail )
case SPELL_CREATE_NOISE: // unused, the player can shout to do this - bwr
if (!silenced(you.x_pos, you.y_pos))
{
- mpr("You hear a voice call your name!");
+ mpr("You hear a voice call your name!", MSGCH_SOUND);
noisy( 25, you.x_pos, you.y_pos );
}
break;
@@ -881,14 +958,14 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_MAGIC_DART:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_MAGIC_DARTS, powc, beam);
break;
case SPELL_FIREBALL:
- fireball(powc);
+ if (fireball(powc) == -1)
+ return (-1);
break;
case SPELL_DELAYED_FIREBALL:
@@ -931,20 +1008,17 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_STRIKING:
- if (spell_direction( spd, beam ) == -1)
- return (false);
-
+ SPELL_DIR(spd, beam);
zapping( ZAP_STRIKING, powc, beam );
break;
case SPELL_CONJURE_FLAME:
- conjure_flame(powc);
+ if (conjure_flame(powc) == -1)
+ return (-1);
break;
case SPELL_DIG:
- if (spell_direction(spd, beam) == -1)
- return (false);
-
+ SPELL_DIR(spd, beam);
if (spd.isMe)
{
canned_msg(MSG_UNTHINKING_ACT);
@@ -954,62 +1028,53 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_BOLT_OF_FIRE:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_FIRE, powc, beam);
break;
case SPELL_BOLT_OF_COLD:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_COLD, powc, beam);
break;
case SPELL_LIGHTNING_BOLT:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_LIGHTNING, powc, beam);
break;
case SPELL_BOLT_OF_MAGMA:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_MAGMA, powc, beam);
break;
case SPELL_POLYMORPH_OTHER:
- if (spell_direction(spd, beam) == -1)
- return (false);
-
+ SPELL_DIR(spd, beam);
if (spd.isMe)
{
mpr("Sorry, it doesn't work like that.");
- return (false);
+ return (-1);
}
zapping(ZAP_POLYMORPH_OTHER, powc, beam);
break;
case SPELL_SLOW:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_SLOWING, powc, beam);
break;
case SPELL_HASTE:
if (spell_direction(spd, beam, DIR_NONE, TARG_FRIEND) == -1)
- return (false);
+ return (-1);
zapping(ZAP_HASTING, powc, beam);
break;
case SPELL_PARALYZE:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_PARALYSIS, powc, beam);
break;
case SPELL_CONFUSE:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_CONFUSION, powc, beam);
break;
@@ -1023,32 +1088,33 @@ bool your_spells( int spc2, int powc, bool allow_fail )
case SPELL_INVISIBILITY:
if (spell_direction(spd, beam, DIR_NONE, TARG_FRIEND) == -1)
- return (false);
+ return (-1);
zapping(ZAP_INVISIBILITY, powc, beam);
break;
case SPELL_THROW_FLAME:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_FLAME, powc, beam);
break;
case SPELL_THROW_FROST:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_FROST, powc, beam);
break;
case SPELL_CONTROLLED_BLINK:
- blink();
+ if (blink() == -1)
+ return (-1);
break;
case SPELL_FREEZING_CLOUD:
- cast_big_c(powc, CLOUD_COLD);
+ if (cast_big_c(powc, CLOUD_COLD) == -1)
+ return (-1);
break;
case SPELL_MEPHITIC_CLOUD:
- stinking_cloud(powc);
+ if (stinking_cloud(powc) == -1)
+ return (-1);
break;
case SPELL_RING_OF_FLAMES:
@@ -1068,8 +1134,7 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_VENOM_BOLT:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_VENOM_BOLT, powc, beam);
break;
@@ -1078,24 +1143,25 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_TELEPORT_OTHER:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
if (spd.isMe)
{
mpr("Sorry, it doesn't work like that.");
- return (false);
+ return (-1);
}
// teleport creature (I think)
zapping(ZAP_TELEPORTATION, powc, beam);
break;
case SPELL_LESSER_HEALING:
- cast_healing(5);
+ if (!cast_healing(5))
+ return (-1);
break;
case SPELL_GREATER_HEALING:
- cast_healing(25);
+ if (!cast_healing(25))
+ return (-1);
break;
case SPELL_CURE_POISON_I: //jmf: `healing' version? group w/ S_C_P_II?
@@ -1111,7 +1177,8 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_SELECTIVE_AMNESIA:
- cast_selective_amnesia(false);
+ if (!cast_selective_amnesia(false))
+ return (-1);
break; // Sif Muna power calls with true
case SPELL_MASS_CONFUSION:
@@ -1119,7 +1186,8 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_SMITING:
- cast_smiting(powc);
+ if (cast_smiting(powc) == -1)
+ return (-1);
break;
case SPELL_REPEL_UNDEAD:
@@ -1135,7 +1203,7 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_SUMMON_SMALL_MAMMAL:
- summon_small_mammals(powc); //jmf: hmm, that's definately *plural* ;-)
+ summon_small_mammals(powc); //jmf: hmm, that's definitely *plural* ;-)
break;
case SPELL_ABJURATION_I: //jmf: why not group with SPELL_ABJURATION_II?
@@ -1151,36 +1219,34 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_BOLT_OF_DRAINING:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_NEGATIVE_ENERGY, powc, beam);
break;
case SPELL_LEHUDIBS_CRYSTAL_SPEAR:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_CRYSTAL_SPEAR, powc, beam);
break;
case SPELL_BOLT_OF_INACCURACY:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_BEAM_OF_ENERGY, powc, beam);
break;
case SPELL_POISONOUS_CLOUD:
- cast_big_c(powc, CLOUD_POISON);
+ if (cast_big_c(powc, CLOUD_POISON) == -1)
+ return (-1);
break;
case SPELL_POISON_ARROW:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping( ZAP_POISON_ARROW, powc, beam );
break;
case SPELL_FIRE_STORM:
- cast_fire_storm(powc);
+ if (cast_fire_storm(powc) == -1)
+ return (-1);
break;
case SPELL_DETECT_TRAPS:
@@ -1194,9 +1260,7 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_ISKENDERUNS_MYSTIC_BLAST:
- if (spell_direction(spd, beam) == -1)
- return (false);
-
+ SPELL_DIR(spd, beam);
zapping( ZAP_MYSTIC_BLAST, powc, beam );
break;
@@ -1209,12 +1273,11 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_ENSLAVEMENT:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
if (spd.isMe)
{
canned_msg(MSG_UNTHINKING_ACT);
- return (false);
+ return (-1);
}
zapping(ZAP_ENSLAVEMENT, powc, beam);
break;
@@ -1234,12 +1297,12 @@ bool your_spells( int spc2, int powc, bool allow_fail )
case SPELL_HEAL_OTHER:
if (spell_direction(spd, beam, DIR_NONE, TARG_FRIEND) == -1)
- return (false);
+ return (-1);
if (spd.isMe)
{
mpr("Sorry, it doesn't work like that.");
- return (false);
+ return (-1);
}
zapping(ZAP_HEALING, powc, beam);
break;
@@ -1250,8 +1313,7 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_PAIN:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
dec_hp(1, false);
zapping(ZAP_PAIN, powc, beam);
break;
@@ -1287,15 +1349,18 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_BURN:
- burn_freeze(powc, BEAM_FIRE);
+ if (burn_freeze(powc, BEAM_FIRE) == -1)
+ return (-1);
break;
case SPELL_FREEZE:
- burn_freeze(powc, BEAM_COLD);
+ if (burn_freeze(powc, BEAM_COLD) == -1)
+ return (-1);
break;
case SPELL_SUMMON_ELEMENTAL:
- summon_elemental(powc, 0, 2);
+ if (summon_elemental(powc, 0, 2) == -1)
+ return (-1);
break;
case SPELL_OZOCUBUS_REFRIGERATION:
@@ -1303,8 +1368,7 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_STICKY_FLAME:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_STICKY_FLAME, powc, beam);
break;
@@ -1334,8 +1398,7 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_DISPEL_UNDEAD:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_DISPEL_UNDEAD, powc, beam);
break;
@@ -1343,22 +1406,16 @@ bool your_spells( int spc2, int powc, bool allow_fail )
summon_ice_beast_etc(powc, MONS_ANGEL);
break;
- //jmf: FIXME: SPELL_PESTILENCE?
-
case SPELL_THUNDERBOLT:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_LIGHTNING, powc, beam);
break;
case SPELL_FLAME_OF_CLEANSING:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_CLEANSING_FLAME, powc, beam);
break;
- //jmf: FIXME: SPELL_SHINING_LIGHT?
-
case SPELL_SUMMON_DAEVA:
summon_ice_beast_etc(powc, MONS_DAEVA);
break;
@@ -1378,18 +1435,17 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_BONE_SHARDS:
- cast_bone_shards(powc);
+ if (cast_bone_shards(powc) == -1)
+ return (-1);
break;
case SPELL_BANISHMENT:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_BANISHMENT, powc, beam);
break;
case SPELL_CIGOTUVIS_DEGENERATION:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
if (spd.isMe)
{
@@ -1400,8 +1456,7 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_STING:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_STING, powc, beam);
break;
@@ -1416,9 +1471,7 @@ bool your_spells( int spc2, int powc, bool allow_fail )
case SPELL_HELLFIRE:
// should only be available from:
// staff of Dispater & Sceptre of Asmodeus
- if (spell_direction(spd, beam) == -1)
- return (false);
-
+ SPELL_DIR(spd, beam);
zapping(ZAP_HELLFIRE, powc, beam);
break;
@@ -1488,14 +1541,12 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_BOLT_OF_IRON:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_IRON_BOLT, powc, beam);
break;
case SPELL_STONE_ARROW:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_STONE_ARROW, powc, beam);
break;
@@ -1508,8 +1559,7 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_SHOCK:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_ELECTRICITY, powc, beam);
break;
@@ -1526,8 +1576,7 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_ORB_OF_ELECTROCUTION:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_ORB_OF_ELECTRICITY, powc, beam);
break;
@@ -1583,17 +1632,16 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_PORTAL:
- portal();
+ if (portal() == -1)
+ return (-1);
break;
case SPELL_AGONY:
- if (spell_direction(spd, beam) == -1)
- return (false);
-
+ SPELL_DIR(spd, beam);
if (spd.isMe)
{
canned_msg(MSG_UNTHINKING_ACT);
- return (false);
+ return (-1);
}
zapping(ZAP_AGONY, powc, beam);
break;
@@ -1603,20 +1651,16 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_DISRUPT:
- if (spell_direction(spd, beam) == -1)
- return (false);
-
+ SPELL_DIR(spd, beam);
zapping(ZAP_DISRUPTION, powc, beam);
break;
case SPELL_DISINTEGRATE:
- if (spell_direction(spd, beam) == -1)
- return (false);
-
+ SPELL_DIR(spd, beam);
if (spd.isMe)
{
canned_msg(MSG_UNTHINKING_ACT);
- return (false);
+ return (-1);
}
zapping(ZAP_DISINTEGRATION, powc, beam);
break;
@@ -1649,9 +1693,9 @@ bool your_spells( int spc2, int powc, bool allow_fail )
if (you.is_undead || you.mutation[MUT_TORMENT_RESISTANCE])
{
mpr("To torment others, one must first know what torment means. ");
- return (false);
+ return (-1);
}
- torment(you.x_pos, you.y_pos);
+ torment(TORMENT_SPELL, you.x_pos, you.y_pos);
break;
case SPELL_DEFLECT_MISSILES:
@@ -1659,28 +1703,27 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_ORB_OF_FRAGMENTATION:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_ORB_OF_FRAGMENTATION, powc, beam);
break;
case SPELL_ICE_BOLT:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_ICE_BOLT, powc, beam);
break;
case SPELL_ARC:
- burn_freeze(powc, BEAM_ELECTRICITY);
+ if (burn_freeze(powc, BEAM_ELECTRICITY) == -1)
+ return (-1);
break;
case SPELL_AIRSTRIKE:
- airstrike(powc);
+ if (airstrike(powc) == -1)
+ return (-1);
break;
case SPELL_ICE_STORM:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
zapping(ZAP_ICE_STORM, powc, beam);
break;
@@ -1692,22 +1735,13 @@ bool your_spells( int spc2, int powc, bool allow_fail )
//jmf: new spells 19mar2000
case SPELL_FLAME_TONGUE:
- if (spell_direction(spd, beam) == -1)
- return (false);
-
+ SPELL_DIR(spd, beam);
if (spd.isMe)
{
canned_msg(MSG_UNTHINKING_ACT);
- return (false);
+ return (-1);
}
zapping(ZAP_FLAME_TONGUE, powc, beam);
-
- /*
- // This is not the place for this sort of power adjustment,
- // it just makes it harder to balance -- bwr
- zapping(ZAP_FLAME_TONGUE, 2 + random2(4) + random2(4)
- + random2(powc) / 25, beam);
- */
break;
case SPELL_PASSWALL:
@@ -1735,15 +1769,12 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_SLEEP:
- if (spell_direction(spd, beam) == -1)
- return (false);
-
+ SPELL_DIR(spd, beam);
if (spd.isMe)
{
canned_msg(MSG_UNTHINKING_ACT);
- return (false);
+ return (-1);
}
-
zapping(ZAP_SLEEP, powc, beam);
break;
@@ -1797,12 +1828,11 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_BACKLIGHT:
- if (spell_direction(spd, beam) == -1)
- return (false);
+ SPELL_DIR(spd, beam);
if (spd.isMe)
{
canned_msg(MSG_UNTHINKING_ACT);
- return (false);
+ return (-1);
}
zapping(ZAP_BACKLIGHT, powc + 10, beam);
break;
@@ -1839,16 +1869,14 @@ bool your_spells( int spc2, int powc, bool allow_fail )
cast_rotting(powc);
break;
- case SPELL_SHUGGOTH_SEED:
- cast_shuggoth_seed(powc);
- break;
-
case SPELL_CONDENSATION_SHIELD:
cast_condensation_shield(powc);
break;
case SPELL_SEMI_CONTROLLED_BLINK:
- cast_semi_controlled_blink(powc); //jmf: powc is ignored
+ //jmf: powc is ignored
+ if (cast_semi_controlled_blink(powc) == -1)
+ return (-1);
break;
case SPELL_STONESKIN:
@@ -1863,6 +1891,10 @@ bool your_spells( int spc2, int powc, bool allow_fail )
cast_conjure_ball_lightning(powc);
break;
+ case SPELL_CHAIN_LIGHTNING:
+ cast_chain_lightning(powc);
+ break;
+
case SPELL_TWIST:
cast_twist(powc);
break;
@@ -1876,7 +1908,8 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
case SPELL_APPORTATION:
- cast_apportation(powc);
+ if (cast_apportation(powc) == -1)
+ return (-1);
break;
default:
@@ -1884,6 +1917,8 @@ bool your_spells( int spc2, int powc, bool allow_fail )
break;
} // end switch
+ spellcasting_side_effects(spc2);
+
return (true);
} // end you_spells()
@@ -1892,8 +1927,16 @@ void exercise_spell( int spell, bool spc, bool success )
// (!success) reduces skill increase for miscast spells
int ndx = 0;
int skill;
+ int exer = 0;
+ int exer_norm = 0;
int workout = 0;
+ // This is used as a reference level to normalise spell skill training
+ // (for Sif Muna piety). Normalised skill training is worked out as:
+ // norm = actual_amount_trained * species_aptitude / ref_skill. This was
+ // set at 50 in stone_soup 0.1.1 (which is bad).
+ const int ref_skill = 80;
+
unsigned int disciplines = spell_type(spell);
//jmf: evil evil evil -- exclude HOLY bit
@@ -1904,18 +1947,22 @@ void exercise_spell( int spell, bool spc, bool success )
if (!success)
skillcount += 4 + random2(10);
+ const int diff = spell_difficulty(spell);
for (ndx = 0; ndx <= SPTYP_LAST_EXPONENT; ndx++)
{
if (!spell_typematch( spell, 1 << ndx ))
continue;
skill = spell_type2skill( 1 << ndx );
- workout = (random2(1 + spell_difficulty(spell)) / skillcount);
+ workout = (random2(1 + diff) / skillcount);
if (!one_chance_in(5))
workout++; // most recently, this was an automatic add {dlb}
- exercise( skill, workout );
+ const int exercise_amount = exercise( skill, workout );
+ exer += exercise_amount;
+ exer_norm +=
+ exercise_amount * species_skills(skill, you.species) / ref_skill;
}
/* ******************************************************************
@@ -1932,21 +1979,16 @@ void exercise_spell( int spell, bool spc, bool success )
if (spc)
{
- exercise(SK_SPELLCASTING, one_chance_in(3) ? 1
- : random2(1 + random2(spell_difficulty(spell))));
+ const int exercise_amount =
+ exercise(SK_SPELLCASTING, one_chance_in(3) ? 1
+ : random2(1 + random2(diff)));
+ exer += exercise_amount;
+ exer_norm += exercise_amount *
+ species_skills(SK_SPELLCASTING, you.species) / ref_skill;
}
- //+ (coinflip() ? 1 : 0) + (skillcount ? 1 : 0));
-
-/* ******************************************************************
- 3.02 was:
-
- if ( spc && spellsy )
- exercise(SK_SPELLCASTING, random2(random2(spell_difficulty(spell_ex) + 1) / spellsy)); // + 1);
- else if ( spc )
- exercise(SK_SPELLCASTING, random2(random2(spell_difficulty(spell_ex)))); // + 1);
-****************************************************************** */
-
+ if (exer_norm)
+ did_god_conduct( DID_SPELL_PRACTISE, exer_norm );
} // end exercise_spell()
static bool send_abyss()
@@ -1999,7 +2041,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
}
// setup beam
- beam.isTracer = false;
+ beam.is_tracer = false;
spec_effect = spec_effect / 100;
@@ -2107,12 +2149,15 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
beam.target_x = you.x_pos;
beam.target_y = you.y_pos;
- strcpy(beam.beam_name, "explosion");
+ beam.name = "explosion";
beam.colour = random_colour();
beam.beam_source = NON_MONSTER;
beam.thrower = (cause) ? KILL_MISC : KILL_YOU;
- beam.aux_source = cause;
+ beam.aux_source.clear();
+ if (cause)
+ beam.aux_source = cause;
beam.ex_size = 1;
+ beam.is_explosion = true;
explosion(beam);
break;
@@ -2134,13 +2179,16 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
// BEAM_EXPLOSION instead? {dlb}
beam.target_x = you.x_pos;
beam.target_y = you.y_pos;
- strcpy(beam.beam_name, "explosion");
+ beam.name = "explosion";
beam.colour = random_colour();
beam.beam_source = NON_MONSTER;
beam.thrower = (cause) ? KILL_MISC : KILL_YOU;
- beam.aux_source = cause;
+ beam.aux_source.clear();
+ if (cause)
+ beam.aux_source = cause;
beam.ex_size = coinflip()?1:2;
-
+ beam.is_explosion = true;
+
explosion(beam);
break;
}
@@ -2185,7 +2233,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
break;
case 9:
if (!silenced(you.x_pos, you.y_pos))
- mpr("You hear something strange.");
+ mpr("You hear something strange.", MSGCH_SOUND);
else if (you.attribute[ATTR_TRANSFORMATION] != TRAN_AIR)
mpr("Your skull vibrates slightly.");
else
@@ -2391,7 +2439,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
break;
case 1:
if (!silenced(you.x_pos, you.y_pos))
- mpr("You hear strange voices.");
+ mpr("You hear strange voices.", MSGCH_SOUND);
else
mpr("You feel momentarily dizzy.");
break;
@@ -2560,7 +2608,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
break;
case 1:
if (!silenced(you.x_pos, you.y_pos))
- mpr("You hear strange voices.");
+ mpr("You hear strange voices.", MSGCH_SOUND);
else
mpr("Your nose twitches.");
break;
@@ -2671,7 +2719,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
break;
case 1:
if (!silenced(you.x_pos, you.y_pos))
- mpr("You hear strange and distant voices.");
+ mpr("You hear strange and distant voices.", MSGCH_SOUND);
else
mpr("You feel homesick.");
break;
@@ -2779,9 +2827,8 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
mpr("Something just walked over your grave. No, really!");
break;
}
- mpr("Your body is wracked with pain!");
- dec_hp((you.hp / 2) - 1, false);
+ torment_monsters(you.x_pos, you.y_pos, 0, TORMENT_GENERIC);
break;
case 1:
@@ -2974,7 +3021,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
break;
case 9:
if (!silenced(you.x_pos, you.y_pos))
- mpr("You hear a sizzling sound.");
+ mpr("You hear a sizzling sound.", MSGCH_SOUND);
else
mpr("You feel like you have heartburn.");
break;
@@ -2995,7 +3042,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
case 1:
mpr("Flames sear your flesh.");
- scrolls_burn(3, OBJ_SCROLLS);
+ expose_player_to_element(BEAM_FIRE, 3);
if (player_res_fire() < 0)
{
@@ -3014,7 +3061,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
ouch( check_your_resists( 5 + random2avg(29, 2), 2 ), 0,
KILLED_BY_WILD_MAGIC, cause );
- scrolls_burn( 5, OBJ_SCROLLS );
+ expose_player_to_element(BEAM_FIRE, 5);
break;
case 1:
@@ -3025,12 +3072,15 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
beam.flavour = BEAM_FIRE;
beam.target_x = you.x_pos;
beam.target_y = you.y_pos;
- strcpy(beam.beam_name, "explosion");
+ beam.name = "explosion";
beam.colour = RED;
beam.beam_source = NON_MONSTER;
beam.thrower = (cause) ? KILL_MISC : KILL_YOU;
- beam.aux_source = cause;
+ beam.aux_source.clear();
+ if (cause)
+ beam.aux_source = cause;
beam.ex_size = 1;
+ beam.is_explosion = true;
explosion(beam);
break;
@@ -3046,7 +3096,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
ouch( check_your_resists( 9 + random2avg(33, 2), 2 ), 0,
KILLED_BY_WILD_MAGIC, cause );
- scrolls_burn( 10, OBJ_SCROLLS );
+ expose_player_to_element(BEAM_FIRE, 10);
break;
case 1:
mpr("There is a sudden and violent explosion of flames!");
@@ -3056,12 +3106,15 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
beam.flavour = BEAM_FIRE;
beam.target_x = you.x_pos;
beam.target_y = you.y_pos;
- strcpy( beam.beam_name, "fireball" );
+ beam.name = "fireball";
beam.colour = RED;
beam.beam_source = NON_MONSTER;
beam.thrower = (cause) ? KILL_MISC : KILL_YOU;
- beam.aux_source = cause;
+ beam.aux_source.clear();
+ if (cause)
+ beam.aux_source = cause;
beam.ex_size = coinflip()?1:2;
+ beam.is_explosion = true;
explosion(beam);
break;
@@ -3114,7 +3167,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
break;
case 9:
if (!silenced(you.x_pos, you.y_pos))
- mpr("You hear a crackling sound.");
+ mpr("You hear a crackling sound.", MSGCH_SOUND);
else
mpr("A snowflake lands on your nose.");
break;
@@ -3129,7 +3182,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
break;
case 1:
mpr("You are covered in a thin layer of ice");
- scrolls_burn(2, OBJ_POTIONS);
+ expose_player_to_element(BEAM_COLD, 2);
if (player_res_cold() < 0)
ouch(4 + random2avg(5, 2), 0, KILLED_BY_WILD_MAGIC, cause);
@@ -3146,7 +3199,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
ouch(check_your_resists(5 + random2(6) + random2(7), 3), 0,
KILLED_BY_WILD_MAGIC, cause);
- scrolls_burn(4, OBJ_POTIONS);
+ expose_player_to_element(BEAM_COLD, 4);
break;
case 1:
@@ -3157,12 +3210,15 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
beam.flavour = BEAM_COLD;
beam.target_x = you.x_pos;
beam.target_y = you.y_pos;
- strcpy(beam.beam_name, "explosion");
+ beam.name = "explosion";
beam.colour = WHITE;
beam.beam_source = NON_MONSTER;
beam.thrower = (cause) ? KILL_MISC : KILL_YOU;
- beam.aux_source = cause;
+ beam.aux_source.clear();
+ if (cause)
+ beam.aux_source = cause;
beam.ex_size = 1;
+ beam.is_explosion = true;
explosion(beam);
break;
@@ -3178,7 +3234,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
ouch(check_your_resists(9 + random2avg(23, 2), 3), 0,
KILLED_BY_WILD_MAGIC, cause);
- scrolls_burn(9, OBJ_POTIONS);
+ expose_player_to_element(BEAM_COLD, 9);
break;
case 1:
snprintf( info, INFO_SIZE,"Freezing gasses pour from your %s!",
@@ -3216,7 +3272,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
break;
case 4:
if (!silenced(you.x_pos, you.y_pos))
- mpr("You hear a distant rumble.");
+ mpr("You hear a distant rumble.", MSGCH_SOUND);
else
mpr("You sympathise with the stones.");
break;
@@ -3279,7 +3335,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
beam.flavour = BEAM_FRAG;
beam.target_x = you.x_pos;
beam.target_y = you.y_pos;
- strcpy(beam.beam_name, "explosion");
+ beam.name = "explosion";
beam.colour = CYAN;
if (one_chance_in(5))
@@ -3289,8 +3345,11 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
beam.beam_source = NON_MONSTER;
beam.thrower = (cause) ? KILL_MISC : KILL_YOU;
- beam.aux_source = cause;
+ beam.aux_source.clear();
+ if (cause)
+ beam.aux_source = cause;
beam.ex_size = 1;
+ beam.is_explosion = true;
explosion(beam);
break;
@@ -3333,7 +3392,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
case 7:
// mummies cannot smell
if (!silenced(you.x_pos, you.y_pos))
- mpr("You hear a whooshing sound.");
+ mpr("You hear a whooshing sound.", MSGCH_SOUND);
else if (you.species != SP_MUMMY)
mpr("You smell ozone.");
break;
@@ -3343,7 +3402,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
case 9:
// mummies cannot smell
if (!silenced(you.x_pos, you.y_pos))
- mpr("You hear a crackling sound.");
+ mpr("You hear a crackling sound.", MSGCH_SOUND);
else if (you.species != SP_MUMMY)
mpr("You smell something musty.");
break;
@@ -3394,12 +3453,15 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
beam.flavour = BEAM_ELECTRICITY;
beam.target_x = you.x_pos;
beam.target_y = you.y_pos;
- strcpy(beam.beam_name, "explosion");
+ beam.name = "explosion";
beam.colour = LIGHTBLUE;
beam.beam_source = NON_MONSTER;
beam.thrower = (cause) ? KILL_MISC : KILL_YOU;
- beam.aux_source = cause;
+ beam.aux_source.clear();
+ if (cause)
+ beam.aux_source = cause;
beam.ex_size = one_chance_in(4)?1:2;
+ beam.is_explosion = true;
explosion(beam);
break;
@@ -3453,7 +3515,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
break;
case 9:
if (!silenced(you.x_pos, you.y_pos))
- mpr("You hear a slurping sound.");
+ mpr("You hear a slurping sound.", MSGCH_SOUND);
else if (you.species != SP_MUMMY)
mpr("You taste almonds.");
break;
diff --git a/crawl-ref/source/spl-cast.h b/crawl-ref/source/spl-cast.h
index f517a5ff3f..b5e97d8b38 100644
--- a/crawl-ref/source/spl-cast.h
+++ b/crawl-ref/source/spl-cast.h
@@ -3,6 +3,8 @@
* Summary: Spell casting functions.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -14,7 +16,7 @@
char list_spells( void );
int spell_fail( int spell );
-int calc_spell_power( int spell, bool apply_intel );
+int calc_spell_power( int spell, bool apply_intel, bool fail_rate_chk = false );
int spell_enhancement( unsigned int typeflags );
// last updaetd 12may2000 {dlb}
@@ -35,7 +37,7 @@ bool cast_a_spell( void );
/* ***********************************************************************
* called from: ability - debug - it_use3 - spell
* *********************************************************************** */
-bool your_spells( int spc2, int powc = 0, bool allow_fail = true );
+int your_spells( int spc2, int powc = 0, bool allow_fail = true );
// last updated 12may2000 {dlb}
/* ***********************************************************************
diff --git a/crawl-ref/source/spl-data.h b/crawl-ref/source/spl-data.h
index aee5e09bc0..ef275fccfe 100644
--- a/crawl-ref/source/spl-data.h
+++ b/crawl-ref/source/spl-data.h
@@ -1,4 +1,8 @@
/*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ */
+
+/*
In case anyone ever wants to add new spells, or just understand my reasons
for putting a particular spell into a particular type, read on:
@@ -135,114 +139,133 @@
{
SPELL_IDENTIFY, "Identify",
SPTYP_DIVINATION,
+ SPFLAG_NONE,
6
},
{
SPELL_TELEPORT_SELF, "Teleport Self",
SPTYP_TRANSLOCATION,
+ SPFLAG_NONE,
5
},
{
SPELL_CAUSE_FEAR, "Cause Fear",
SPTYP_ENCHANTMENT,
+ SPFLAG_NONE,
5
},
{
SPELL_CREATE_NOISE, "Create Noise",
SPTYP_ENCHANTMENT,
+ SPFLAG_NONE,
1
},
{
SPELL_REMOVE_CURSE, "Remove Curse",
SPTYP_ENCHANTMENT,
+ SPFLAG_NONE,
5
},
{
SPELL_MAGIC_DART, "Magic Dart",
SPTYP_CONJURATION,
+ SPFLAG_DIR_OR_TARGET,
1
},
{
SPELL_FIREBALL, "Fireball",
SPTYP_CONJURATION | SPTYP_FIRE,
+ SPFLAG_DIR_OR_TARGET,
6
},
{
SPELL_SWAP, "Swap",
SPTYP_TRANSLOCATION,
- 3
+ SPFLAG_NONE,
+ 4
},
{
SPELL_APPORTATION, "Apportation",
SPTYP_TRANSLOCATION,
+ SPFLAG_NONE,
1
},
{
SPELL_TWIST, "Twist",
SPTYP_TRANSLOCATION,
+ SPFLAG_DIR_OR_TARGET,
1
},
{
SPELL_CONJURE_FLAME, "Conjure Flame",
SPTYP_CONJURATION | SPTYP_FIRE,
+ SPFLAG_GRID | SPFLAG_NOT_SELF,
3
},
{
SPELL_DIG, "Dig",
SPTYP_TRANSMIGRATION | SPTYP_EARTH,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF,
4
},
{
SPELL_BOLT_OF_FIRE, "Bolt of Fire",
SPTYP_CONJURATION | SPTYP_FIRE,
+ SPFLAG_DIR_OR_TARGET,
5
},
{
SPELL_BOLT_OF_COLD, "Bolt of Cold",
SPTYP_CONJURATION | SPTYP_ICE,
+ SPFLAG_DIR_OR_TARGET,
5
},
{
SPELL_LIGHTNING_BOLT, "Lightning Bolt",
SPTYP_CONJURATION | SPTYP_AIR,
+ SPFLAG_DIR_OR_TARGET,
6
},
{
SPELL_BOLT_OF_MAGMA, "Bolt of Magma",
SPTYP_CONJURATION | SPTYP_FIRE | SPTYP_EARTH,
+ SPFLAG_DIR_OR_TARGET,
5
},
{
SPELL_POLYMORPH_OTHER, "Polymorph Other",
SPTYP_TRANSMIGRATION, // removed enchantment, wasn't needed -- bwr
+ SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF,
5
},
{
SPELL_SLOW, "Slow",
SPTYP_ENCHANTMENT,
+ SPFLAG_DIR_OR_TARGET,
3
},
{
SPELL_HASTE, "Haste",
SPTYP_ENCHANTMENT,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_HELPFUL,
6 // lowered to 6 from 8, since its easily available from various items
// and Swiftness is level 2 (and gives a similar effect). Its also
// not that much better than Invisibility. -- bwr
@@ -251,204 +274,238 @@
{
SPELL_PARALYZE, "Paralyze",
SPTYP_ENCHANTMENT,
+ SPFLAG_DIR_OR_TARGET,
4
},
{
SPELL_CONFUSE, "Confuse",
SPTYP_ENCHANTMENT,
+ SPFLAG_DIR_OR_TARGET,
3
},
{
SPELL_INVISIBILITY, "Invisibility",
SPTYP_ENCHANTMENT,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_HELPFUL,
6
},
{
SPELL_THROW_FLAME, "Throw Flame",
SPTYP_CONJURATION | SPTYP_FIRE,
+ SPFLAG_DIR_OR_TARGET,
2
},
{
SPELL_THROW_FROST, "Throw Frost",
SPTYP_CONJURATION | SPTYP_ICE,
+ SPFLAG_DIR_OR_TARGET,
2
},
{
SPELL_CONTROLLED_BLINK, "Controlled Blink",
SPTYP_TRANSLOCATION,
- 4
+ SPFLAG_NONE,
+ 8
},
{
SPELL_FREEZING_CLOUD, "Freezing Cloud",
SPTYP_CONJURATION | SPTYP_ICE | SPTYP_AIR,
+ SPFLAG_GRID,
7
},
{
SPELL_MEPHITIC_CLOUD, "Mephitic Cloud",
SPTYP_CONJURATION | SPTYP_POISON | SPTYP_AIR,
+ SPFLAG_DIR_OR_TARGET,
3
},
{
SPELL_RING_OF_FLAMES, "Ring of Flames",
SPTYP_ENCHANTMENT | SPTYP_FIRE,
+ SPFLAG_NONE,
8
},
{
SPELL_RESTORE_STRENGTH, "Restore Strength",
SPTYP_HOLY,
+ SPFLAG_NONE,
2
},
{
SPELL_RESTORE_INTELLIGENCE, "Restore Intelligence",
SPTYP_HOLY,
+ SPFLAG_NONE,
2
},
{
SPELL_RESTORE_DEXTERITY, "Restore Dexterity",
SPTYP_HOLY,
+ SPFLAG_NONE,
2
},
{
SPELL_VENOM_BOLT, "Venom Bolt",
SPTYP_CONJURATION | SPTYP_POISON,
+ SPFLAG_DIR_OR_TARGET,
5
},
{
SPELL_OLGREBS_TOXIC_RADIANCE, "Olgreb's Toxic Radiance",
SPTYP_POISON,
+ SPFLAG_NONE,
4
},
{
SPELL_TELEPORT_OTHER, "Teleport Other",
SPTYP_TRANSLOCATION,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF,
4
},
{
SPELL_LESSER_HEALING, "Lesser Healing",
SPTYP_HOLY,
+ SPFLAG_NONE,
2
},
{
SPELL_GREATER_HEALING, "Greater Healing",
SPTYP_HOLY,
+ SPFLAG_NONE,
6
},
{
SPELL_CURE_POISON_I, "Cure Poison",
SPTYP_HOLY,
+ SPFLAG_NONE,
3
},
{
SPELL_PURIFICATION, "Purification",
SPTYP_HOLY,
+ SPFLAG_NONE,
5
},
{
SPELL_DEATHS_DOOR, "Death's Door",
SPTYP_ENCHANTMENT | SPTYP_NECROMANCY,
+ SPFLAG_NONE,
8
},
{
SPELL_SELECTIVE_AMNESIA, "Selective Amnesia",
SPTYP_ENCHANTMENT,
+ SPFLAG_NONE,
3
},
{
SPELL_MASS_CONFUSION, "Mass Confusion",
SPTYP_ENCHANTMENT,
+ SPFLAG_NONE,
6
},
{
SPELL_SMITING, "Smiting",
SPTYP_HOLY,
+ SPFLAG_NONE,
4
},
{
SPELL_REPEL_UNDEAD, "Repel Undead",
SPTYP_HOLY,
+ SPFLAG_NONE,
3
},
{
SPELL_HOLY_WORD, "Holy Word",
SPTYP_HOLY,
+ SPFLAG_NONE,
7
},
{
SPELL_DETECT_CURSE, "Detect Curse",
SPTYP_DIVINATION,
+ SPFLAG_NONE,
3
},
{
SPELL_SUMMON_SMALL_MAMMAL, "Summon Small Mammals",
SPTYP_SUMMONING,
+ SPFLAG_NONE,
1
},
{
SPELL_ABJURATION_I, "Abjuration",
SPTYP_SUMMONING,
+ SPFLAG_NONE,
3
},
{
SPELL_SUMMON_SCORPIONS, "Summon Scorpions",
SPTYP_SUMMONING | SPTYP_POISON,
+ SPFLAG_NONE,
4
},
{
SPELL_LEVITATION, "Levitation",
SPTYP_ENCHANTMENT | SPTYP_AIR,
+ SPFLAG_NONE,
2
},
{
SPELL_BOLT_OF_DRAINING, "Bolt of Draining",
SPTYP_CONJURATION | SPTYP_NECROMANCY,
+ SPFLAG_DIR_OR_TARGET,
6
},
{
SPELL_LEHUDIBS_CRYSTAL_SPEAR, "Lehudib's Crystal Spear",
SPTYP_CONJURATION | SPTYP_EARTH,
+ SPFLAG_DIR_OR_TARGET,
8
},
{
SPELL_BOLT_OF_INACCURACY, "Bolt of Inaccuracy",
SPTYP_CONJURATION,
+ SPFLAG_DIR_OR_TARGET,
2
},
{
SPELL_POISONOUS_CLOUD, "Poisonous Cloud",
SPTYP_CONJURATION | SPTYP_POISON | SPTYP_AIR,
+ SPFLAG_GRID,
6
}
,
@@ -456,18 +513,21 @@
{
SPELL_FIRE_STORM, "Fire Storm",
SPTYP_CONJURATION | SPTYP_FIRE,
+ SPFLAG_GRID,
9
},
{
SPELL_DETECT_TRAPS, "Detect Traps",
SPTYP_DIVINATION,
+ SPFLAG_NONE,
2
},
{
SPELL_BLINK, "Blink",
SPTYP_TRANSLOCATION,
+ SPFLAG_NONE,
2
},
@@ -477,174 +537,203 @@
{
SPELL_ISKENDERUNS_MYSTIC_BLAST, "Iskenderun's Mystic Blast",
SPTYP_CONJURATION,
+ SPFLAG_DIR_OR_TARGET,
4
},
{
SPELL_SWARM, "Summon Swarm",
SPTYP_SUMMONING,
+ SPFLAG_NONE,
6
},
{
SPELL_SUMMON_HORRIBLE_THINGS, "Summon Horrible Things",
SPTYP_SUMMONING,
+ SPFLAG_UNHOLY,
8
},
{
SPELL_ENSLAVEMENT, "Enslavement",
SPTYP_ENCHANTMENT,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF,
4
},
{
SPELL_MAGIC_MAPPING, "Magic Mapping",
SPTYP_DIVINATION | SPTYP_EARTH,
+ SPFLAG_NONE,
4
},
{
SPELL_HEAL_OTHER, "Heal Other",
SPTYP_HOLY,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_HELPFUL | SPFLAG_NOT_SELF,
3
},
{
SPELL_ANIMATE_DEAD, "Animate Dead",
SPTYP_NECROMANCY,
+ SPFLAG_NONE,
4
},
{
SPELL_PAIN, "Pain",
SPTYP_NECROMANCY,
+ SPFLAG_DIR_OR_TARGET,
1
},
{
SPELL_EXTENSION, "Extension",
SPTYP_ENCHANTMENT,
+ SPFLAG_NONE,
5
},
{
SPELL_CONTROL_UNDEAD, "Control Undead",
SPTYP_ENCHANTMENT | SPTYP_NECROMANCY,
+ SPFLAG_NONE,
6
},
{
SPELL_ANIMATE_SKELETON, "Animate Skeleton",
SPTYP_NECROMANCY,
+ SPFLAG_NONE,
1
},
{
SPELL_VAMPIRIC_DRAINING, "Vampiric Draining",
SPTYP_NECROMANCY,
+ SPFLAG_DIR | SPFLAG_NOT_SELF,
3
},
{
SPELL_SUMMON_WRAITHS, "Summon Wraiths",
SPTYP_NECROMANCY | SPTYP_SUMMONING,
+ SPFLAG_NONE,
7
},
{
SPELL_DETECT_ITEMS, "Detect Items",
SPTYP_DIVINATION,
+ SPFLAG_NONE,
2
},
{
SPELL_BORGNJORS_REVIVIFICATION, "Borgnjor's Revivification",
SPTYP_NECROMANCY,
- 6
+ SPFLAG_NONE,
+ 5
},
{
SPELL_BURN, "Burn", // used by wanderers
SPTYP_FIRE,
+ SPFLAG_DIR | SPFLAG_NOT_SELF,
1
},
{
SPELL_FREEZE, "Freeze",
SPTYP_ICE,
+ SPFLAG_DIR | SPFLAG_NOT_SELF,
1
},
{
SPELL_SUMMON_ELEMENTAL, "Summon Elemental",
SPTYP_SUMMONING,
+ SPFLAG_NONE,
4
},
{
SPELL_OZOCUBUS_REFRIGERATION, "Ozocubu's Refrigeration",
SPTYP_ICE,
+ SPFLAG_NONE,
5
},
{
SPELL_STICKY_FLAME, "Sticky Flame",
SPTYP_CONJURATION | SPTYP_FIRE,
+ SPFLAG_DIR_OR_TARGET,
4
},
{
SPELL_SUMMON_ICE_BEAST, "Summon Ice Beast",
SPTYP_ICE | SPTYP_SUMMONING,
+ SPFLAG_NONE,
5
},
{
SPELL_OZOCUBUS_ARMOUR, "Ozocubu's Armour",
SPTYP_ENCHANTMENT | SPTYP_ICE,
+ SPFLAG_NONE,
3
},
{
SPELL_CALL_IMP, "Call Imp",
SPTYP_SUMMONING,
+ SPFLAG_UNHOLY,
3
},
{
SPELL_REPEL_MISSILES, "Repel Missiles",
SPTYP_ENCHANTMENT | SPTYP_AIR,
+ SPFLAG_NONE,
2
},
{
SPELL_BERSERKER_RAGE, "Berserker Rage",
SPTYP_ENCHANTMENT,
+ SPFLAG_NONE,
3
},
{
SPELL_DISPEL_UNDEAD, "Dispel Undead",
SPTYP_NECROMANCY,
+ SPFLAG_DIR_OR_TARGET,
4
},
{
SPELL_GUARDIAN, "Guardian",
SPTYP_HOLY,
+ SPFLAG_NONE,
7
},
{
SPELL_PESTILENCE, "Pestilence",
SPTYP_HOLY,
+ SPFLAG_NONE,
4
},
{
SPELL_THUNDERBOLT, "Thunderbolt",
SPTYP_HOLY | SPTYP_AIR,
+ SPFLAG_DIR_OR_TARGET,
6 // why is this the only holy spell with a secondary? {dlb}
}
,
@@ -652,150 +741,175 @@
{
SPELL_FLAME_OF_CLEANSING, "Flame of Cleansing",
SPTYP_HOLY,
+ SPFLAG_DIR_OR_TARGET,
8
},
{
SPELL_SHINING_LIGHT, "Shining Light",
SPTYP_HOLY,
+ SPFLAG_NONE,
7
},
{
SPELL_SUMMON_DAEVA, "Summon Daeva",
SPTYP_HOLY,
+ SPFLAG_NONE,
8
},
{
SPELL_ABJURATION_II, "Abjuration",
SPTYP_HOLY,
+ SPFLAG_NONE,
4
},
{
SPELL_TWISTED_RESURRECTION, "Twisted Resurrection",
SPTYP_NECROMANCY,
+ SPFLAG_NONE,
5
},
{
SPELL_REGENERATION, "Regeneration",
SPTYP_ENCHANTMENT | SPTYP_NECROMANCY,
+ SPFLAG_NONE,
3
},
{
SPELL_BONE_SHARDS, "Bone Shards",
SPTYP_NECROMANCY,
+ SPFLAG_NONE,
3
},
{
SPELL_BANISHMENT, "Banishment",
SPTYP_TRANSLOCATION,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_UNHOLY,
5
},
{
SPELL_CIGOTUVIS_DEGENERATION, "Cigotuvi's Degeneration",
SPTYP_TRANSMIGRATION | SPTYP_NECROMANCY,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF,
5
},
{
SPELL_STING, "Sting",
SPTYP_CONJURATION | SPTYP_POISON,
+ SPFLAG_DIR_OR_TARGET,
1
},
{
SPELL_SUBLIMATION_OF_BLOOD, "Sublimation of Blood",
SPTYP_NECROMANCY,
+ SPFLAG_NONE,
2
},
{
SPELL_TUKIMAS_DANCE, "Tukima's Dance",
SPTYP_ENCHANTMENT,
+ SPFLAG_NONE,
3
},
{
SPELL_HELLFIRE, "Hellfire",
SPTYP_CONJURATION | SPTYP_FIRE,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_UNHOLY,
9
},
{
SPELL_SUMMON_DEMON, "Summon Demon",
SPTYP_SUMMONING,
+ SPFLAG_UNHOLY,
5
},
{
SPELL_DEMONIC_HORDE, "Demonic Horde",
SPTYP_SUMMONING,
+ SPFLAG_UNHOLY,
6
},
{
SPELL_SUMMON_GREATER_DEMON, "Summon Greater Demon",
SPTYP_SUMMONING,
+ SPFLAG_UNHOLY,
7
},
{
SPELL_CORPSE_ROT, "Corpse Rot",
SPTYP_NECROMANCY,
+ SPFLAG_NONE,
2
},
{
SPELL_TUKIMAS_VORPAL_BLADE, "Tukima's Vorpal Blade",
SPTYP_ENCHANTMENT,
+ SPFLAG_NONE,
2
},
{
SPELL_FIRE_BRAND, "Fire Brand",
SPTYP_ENCHANTMENT | SPTYP_FIRE,
+ SPFLAG_NONE,
2
},
{
SPELL_FREEZING_AURA, "Freezing Aura",
SPTYP_ENCHANTMENT | SPTYP_ICE,
+ SPFLAG_NONE,
2
},
{
SPELL_LETHAL_INFUSION, "Lethal Infusion",
SPTYP_ENCHANTMENT | SPTYP_NECROMANCY,
+ SPFLAG_NONE,
2
},
{
- SPELL_CRUSH, "Crush", // used by wanderers
+ SPELL_CRUSH, "Crush",
SPTYP_EARTH,
+ SPFLAG_DIR | SPFLAG_NOT_SELF,
1
},
{
SPELL_BOLT_OF_IRON, "Bolt of Iron",
SPTYP_CONJURATION | SPTYP_EARTH,
+ SPFLAG_DIR_OR_TARGET,
6
},
{
SPELL_STONE_ARROW, "Stone Arrow",
SPTYP_CONJURATION | SPTYP_EARTH,
+ SPFLAG_DIR_OR_TARGET,
3
},
{
SPELL_TOMB_OF_DOROKLOHE, "Tomb of Doroklohe",
SPTYP_CONJURATION | SPTYP_EARTH, // conj makes more sense than tmig -- bwr
+ SPFLAG_NONE,
7
}
,
@@ -803,48 +917,56 @@
{
SPELL_STONEMAIL, "Stonemail",
SPTYP_ENCHANTMENT | SPTYP_EARTH,
+ SPFLAG_NONE,
6
},
{
SPELL_SHOCK, "Shock",
SPTYP_CONJURATION | SPTYP_AIR,
+ SPFLAG_DIR_OR_TARGET,
1
},
{
SPELL_SWIFTNESS, "Swiftness",
SPTYP_ENCHANTMENT | SPTYP_AIR,
+ SPFLAG_NONE,
2
},
{
SPELL_FLY, "Fly",
SPTYP_ENCHANTMENT | SPTYP_AIR,
+ SPFLAG_NONE,
4
},
{
SPELL_INSULATION, "Insulation",
SPTYP_ENCHANTMENT | SPTYP_AIR,
+ SPFLAG_NONE,
4
},
{
SPELL_ORB_OF_ELECTROCUTION, "Orb of Electrocution",
SPTYP_CONJURATION | SPTYP_AIR,
+ SPFLAG_DIR_OR_TARGET,
7
},
{
SPELL_DETECT_CREATURES, "Detect Creatures",
SPTYP_DIVINATION,
+ SPFLAG_NONE,
2
},
{
SPELL_CURE_POISON_II, "Cure Poison",
SPTYP_POISON,
+ SPFLAG_NONE,
2
}
,
@@ -852,12 +974,14 @@
{
SPELL_CONTROL_TELEPORT, "Control Teleport",
SPTYP_ENCHANTMENT | SPTYP_TRANSLOCATION,
- 6
+ SPFLAG_NONE,
+ 5
},
{
SPELL_POISON_AMMUNITION, "Poison Ammunition",
SPTYP_ENCHANTMENT | SPTYP_POISON,
+ SPFLAG_NONE,
4 // jmf: SPTYP_TRANSMIGRATION vs SPTYP_ENCHANTMENT?
}
,
@@ -865,150 +989,175 @@
{
SPELL_POISON_WEAPON, "Poison Weapon",
SPTYP_ENCHANTMENT | SPTYP_POISON,
+ SPFLAG_NONE,
4
},
{
SPELL_RESIST_POISON, "Resist Poison",
SPTYP_ENCHANTMENT | SPTYP_POISON,
+ SPFLAG_NONE,
4
},
{
SPELL_PROJECTED_NOISE, "Projected Noise",
SPTYP_ENCHANTMENT,
+ SPFLAG_NONE,
2
},
{
SPELL_ALTER_SELF, "Alter Self",
SPTYP_TRANSMIGRATION,
+ SPFLAG_NONE,
7
},
{
SPELL_DEBUGGING_RAY, "Debugging Ray",
SPTYP_CONJURATION,
+ SPFLAG_DIR_OR_TARGET,
7
},
{
SPELL_RECALL, "Recall",
SPTYP_SUMMONING | SPTYP_TRANSLOCATION,
+ SPFLAG_NONE,
3
},
{
SPELL_PORTAL, "Portal",
SPTYP_TRANSLOCATION,
- 8
+ SPFLAG_NONE,
+ 7
},
{
SPELL_AGONY, "Agony",
SPTYP_NECROMANCY,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF,
5
},
{
SPELL_SPIDER_FORM, "Spider Form",
SPTYP_TRANSMIGRATION | SPTYP_POISON,
+ SPFLAG_NONE,
3
},
{
SPELL_DISRUPT, "Disrupt",
SPTYP_TRANSMIGRATION,
+ SPFLAG_DIR_OR_TARGET,
1
},
{
SPELL_DISINTEGRATE, "Disintegrate",
SPTYP_TRANSMIGRATION,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF,
6
},
{
SPELL_BLADE_HANDS, "Blade Hands",
SPTYP_TRANSMIGRATION,
+ SPFLAG_NONE,
5 // only removes weapon, so I raised this from 4 -- bwr
},
{
SPELL_STATUE_FORM, "Statue Form",
SPTYP_TRANSMIGRATION | SPTYP_EARTH,
+ SPFLAG_NONE,
6
},
{
SPELL_ICE_FORM, "Ice Form",
SPTYP_ICE | SPTYP_TRANSMIGRATION,
+ SPFLAG_NONE,
4 // doesn't allow for equipment, so I lowered this from 5 -- bwr
},
{
SPELL_DRAGON_FORM, "Dragon Form",
SPTYP_FIRE | SPTYP_TRANSMIGRATION,
+ SPFLAG_NONE,
8
},
{
SPELL_NECROMUTATION, "Necromutation",
SPTYP_TRANSMIGRATION | SPTYP_NECROMANCY,
+ SPFLAG_NONE,
8
},
{
SPELL_DEATH_CHANNEL, "Death Channel",
SPTYP_NECROMANCY,
+ SPFLAG_NONE,
9
},
{
SPELL_SYMBOL_OF_TORMENT, "Symbol of Torment",
SPTYP_NECROMANCY,
+ SPFLAG_NONE,
6
},
{
SPELL_DEFLECT_MISSILES, "Deflect Missiles",
SPTYP_ENCHANTMENT | SPTYP_AIR,
+ SPFLAG_NONE,
6
},
{
SPELL_ORB_OF_FRAGMENTATION, "Orb of Fragmentation",
SPTYP_CONJURATION | SPTYP_EARTH,
+ SPFLAG_DIR_OR_TARGET,
7
},
{
SPELL_ICE_BOLT, "Ice Bolt",
SPTYP_CONJURATION | SPTYP_ICE,
+ SPFLAG_DIR_OR_TARGET,
4
},
{
SPELL_ICE_STORM, "Ice Storm",
SPTYP_CONJURATION | SPTYP_ICE,
+ SPFLAG_DIR_OR_TARGET,
9
},
{
- SPELL_ARC, "Arc", // used by wanderers
+ SPELL_ARC, "Arc",
SPTYP_AIR,
+ SPFLAG_DIR | SPFLAG_NOT_SELF,
1
},
{
SPELL_AIRSTRIKE, "Airstrike",
SPTYP_AIR,
+ SPFLAG_TARGET | SPFLAG_NOT_SELF,
4
},
{
SPELL_SHADOW_CREATURES, "Shadow Creatures",
SPTYP_SUMMONING, // jmf: or SPTYP_SUMMONING | SPTYP_CONJURATION
+ SPFLAG_NONE,
5
}
,
@@ -1016,12 +1165,14 @@
{
SPELL_CONFUSING_TOUCH, "Confusing Touch",
SPTYP_ENCHANTMENT,
+ SPFLAG_NONE,
1
},
{
SPELL_SURE_BLADE, "Sure Blade",
SPTYP_ENCHANTMENT,
+ SPFLAG_NONE,
2
},
@@ -1033,246 +1184,280 @@
{
SPELL_FLAME_TONGUE, "Flame Tongue",
SPTYP_CONJURATION | SPTYP_FIRE,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF,
1
},
{
SPELL_PASSWALL, "Passwall",
SPTYP_TRANSMIGRATION | SPTYP_EARTH,
+ SPFLAG_NONE,
3
},
{
SPELL_IGNITE_POISON, "Ignite Poison",
SPTYP_FIRE | SPTYP_TRANSMIGRATION,
+ SPFLAG_NONE,
7
},
{
SPELL_STICKS_TO_SNAKES, "Sticks to Snakes",
SPTYP_TRANSMIGRATION | SPTYP_SUMMONING,
+ SPFLAG_NONE,
2
},
{
SPELL_SUMMON_LARGE_MAMMAL, "Call Canine Familiar",
SPTYP_SUMMONING,
+ SPFLAG_NONE,
3
},
{
SPELL_SUMMON_DRAGON, "Summon Dragon",
SPTYP_FIRE | SPTYP_SUMMONING,
+ SPFLAG_NONE,
9
},
{
SPELL_TAME_BEASTS, "Tame Beasts",
SPTYP_ENCHANTMENT,
+ SPFLAG_NONE,
5
},
{
SPELL_SLEEP, "Ensorcelled Hibernation",
SPTYP_ENCHANTMENT | SPTYP_ICE,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF,
2
},
{
SPELL_MASS_SLEEP, "Metabolic Englaciation",
SPTYP_ENCHANTMENT | SPTYP_ICE,
+ SPFLAG_NONE,
7
},
{
SPELL_DETECT_MAGIC, "Detect Magic",
SPTYP_DIVINATION,
+ SPFLAG_NONE,
1
},
{
SPELL_DETECT_SECRET_DOORS, "Detect Secret Doors",
SPTYP_DIVINATION,
+ SPFLAG_NONE,
1
},
{
SPELL_SEE_INVISIBLE, "See Invisible",
SPTYP_ENCHANTMENT | SPTYP_DIVINATION,
+ SPFLAG_NONE,
4
},
{
SPELL_FORESCRY, "Forescry",
SPTYP_DIVINATION,
+ SPFLAG_NONE,
5
},
{
SPELL_SUMMON_BUTTERFLIES, "Summon Butterflies",
SPTYP_SUMMONING,
+ SPFLAG_NONE,
1
},
{
SPELL_WARP_BRAND, "Warp Weapon",
SPTYP_ENCHANTMENT | SPTYP_TRANSLOCATION,
+ SPFLAG_NONE,
7 // this is high for a reason - Warp brands are very powerful.
},
{
SPELL_SILENCE, "Silence",
SPTYP_ENCHANTMENT | SPTYP_AIR,
- 3
+ SPFLAG_NONE,
+ 5
},
{
SPELL_SHATTER, "Shatter",
SPTYP_TRANSMIGRATION | SPTYP_EARTH,
+ SPFLAG_NONE,
9
},
{
SPELL_DISPERSAL, "Dispersal",
SPTYP_TRANSLOCATION,
+ SPFLAG_NONE,
7
},
{
SPELL_DISCHARGE, "Static Discharge",
SPTYP_CONJURATION | SPTYP_AIR,
+ SPFLAG_NONE,
4
},
{
SPELL_BEND, "Bend",
SPTYP_TRANSLOCATION,
+ SPFLAG_NONE,
1
},
{
SPELL_BACKLIGHT, "Corona",
SPTYP_ENCHANTMENT,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF,
1
},
{
SPELL_INTOXICATE, "Alistair's Intoxication",
SPTYP_TRANSMIGRATION | SPTYP_POISON,
+ SPFLAG_NONE,
4
},
{
SPELL_GLAMOUR, "Glamour",
SPTYP_ENCHANTMENT,
+ SPFLAG_NONE,
5
},
{
SPELL_EVAPORATE, "Evaporate",
SPTYP_FIRE | SPTYP_TRANSMIGRATION,
+ SPFLAG_NONE,
2 // XXX: level 2 or 3, what should it be now? -- bwr
},
{
SPELL_ERINGYAS_SURPRISING_BOUQUET, "Eringya's Surprising Bouquet",
SPTYP_TRANSMIGRATION | SPTYP_EARTH,
+ SPFLAG_NONE,
4
},
{
SPELL_FRAGMENTATION, "Lee's Rapid Deconstruction",
SPTYP_TRANSMIGRATION | SPTYP_EARTH,
+ SPFLAG_NONE,
5
},
{
SPELL_AIR_WALK, "Air Walk",
SPTYP_TRANSMIGRATION | SPTYP_AIR,
+ SPFLAG_NONE,
9
},
{
SPELL_SANDBLAST, "Sandblast",
SPTYP_TRANSMIGRATION | SPTYP_EARTH,
+ SPFLAG_DIR_OR_TARGET | SPFLAG_NOT_SELF,
1
},
{
SPELL_ROTTING, "Rotting",
SPTYP_TRANSMIGRATION | SPTYP_NECROMANCY,
+ SPFLAG_NONE,
5
},
{
- SPELL_SHUGGOTH_SEED, "Shuggoth Seed",
- SPTYP_NECROMANCY | SPTYP_SUMMONING,
- 7
-},
-
-{
SPELL_MAXWELLS_SILVER_HAMMER, "Maxwell's Silver Hammer",
- SPTYP_ENCHANTMENT | SPTYP_EARTH,
+ SPTYP_TRANSMIGRATION | SPTYP_EARTH,
+ SPFLAG_NONE,
2
},
{
SPELL_CONDENSATION_SHIELD, "Condensation Shield",
SPTYP_ICE | SPTYP_TRANSMIGRATION,
+ SPFLAG_NONE,
4
},
{
SPELL_SEMI_CONTROLLED_BLINK, "Semi-Controlled Blink",
SPTYP_TRANSLOCATION,
+ SPFLAG_NONE,
3
},
{
SPELL_STONESKIN, "Stoneskin",
SPTYP_EARTH | SPTYP_TRANSMIGRATION, // was ench -- bwr
+ SPFLAG_NONE,
2
},
{
SPELL_SIMULACRUM, "Simulacrum",
SPTYP_ICE | SPTYP_NECROMANCY,
- 7
+ SPFLAG_NONE,
+ 6
},
{
SPELL_CONJURE_BALL_LIGHTNING, "Conjure Ball Lightning",
SPTYP_AIR | SPTYP_CONJURATION,
+ SPFLAG_NONE,
8
},
{
- SPELL_FAR_STRIKE, "Far Strike",
- SPTYP_TRANSLOCATION,
- 3
+ SPELL_CHAIN_LIGHTNING, "Chain Lightning",
+ SPTYP_AIR | SPTYP_CONJURATION,
+ SPFLAG_NONE,
+ 8
},
{
SPELL_DELAYED_FIREBALL, "Delayed Fireball",
SPTYP_FIRE | SPTYP_CONJURATION,
+ SPFLAG_NONE,
7
},
{
SPELL_FULSOME_DISTILLATION, "Fulsome Distillation",
SPTYP_TRANSMIGRATION | SPTYP_NECROMANCY,
+ SPFLAG_NONE,
1
},
{
SPELL_POISON_ARROW, "Poison Arrow",
SPTYP_CONJURATION | SPTYP_POISON,
+ SPFLAG_DIR_OR_TARGET,
6
},
{
SPELL_STRIKING, "Striking",
0,
+ SPFLAG_DIR_OR_TARGET,
1
},
@@ -1280,6 +1465,7 @@
SPELL_NO_SPELL, "nonexistent spell",
0,
0,
+ 0,
},
diff --git a/crawl-ref/source/spl-util.cc b/crawl-ref/source/spl-util.cc
index 58a9ecb2fe..020e5fa0c2 100644
--- a/crawl-ref/source/spl-util.cc
+++ b/crawl-ref/source/spl-util.cc
@@ -3,6 +3,8 @@
* Summary: data handlers for player-avilable spell list *
* Written by: don brodale <dbrodale@bigfootinteractive.com> *
* *
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Changelog(most recent first): *
*
* <3> 04oct2001 bwr absorbed spells0.cc
@@ -26,7 +28,9 @@
#include "stuff.h"
#include "itemname.h"
#include "macro.h"
+#include "misc.h"
#include "monstuff.h"
+#include "notes.h"
#include "player.h"
#include "spl-book.h"
#include "view.h"
@@ -61,7 +65,7 @@ void init_playerspells(void)
for (x = 0; x < NUM_SPELLS; x++)
plyrspell_list[x] = -1;
- // can only use up to PLYRSPELLDATASIZE _MINUS ONE_, or the
+ // can only use up to PLYRSPELLDATASIZE _MINUS ONE_, or the
// last entry tries to set plyrspell_list[SPELL_NO_SPELL]
// which corrupts the heap.
for (x = 0; x < PLYRSPELLDATASIZE - 1; x++)
@@ -121,6 +125,8 @@ bool add_spell_to_memory( int spell )
you.spell_no++;
+ take_note(Note(NOTE_LEARN_SPELL, spell));
+
return (true);
}
@@ -200,6 +206,11 @@ int spell_levels_required( int which_spell )
return (levels);
}
+unsigned int get_spell_flags( int which_spell )
+{
+ return (seekspell(which_spell)->flags);
+}
+
bool spell_typematch(int which_spell, unsigned int which_discipline)
{
return (seekspell(which_spell)->disciplines & which_discipline);
@@ -456,12 +467,12 @@ int apply_one_neighbouring_square(int (*func) (int, int, int, int), int power)
struct dist bmove;
mpr("Which direction? [ESC to cancel]", MSGCH_PROMPT);
- direction( bmove, DIR_DIR, TARG_ENEMY );
+ direction( bmove, DIR_DIR, TARG_ENEMY, true );
if (!bmove.isValid)
{
- canned_msg(MSG_SPELL_FIZZLES);
- return (0);
+ canned_msg(MSG_OK);
+ return (-1);
}
int rv = func(you.x_pos + bmove.dx, you.y_pos + bmove.dy, power, 1);
@@ -673,23 +684,56 @@ char spell_direction( struct dist &spelld, struct bolt &pbolt,
message_current_target();
- direction( spelld, restrict, mode );
+ direction( spelld, restrict, mode, true );
if (!spelld.isValid)
{
// check for user cancel
- canned_msg(MSG_SPELL_FIZZLES);
+ canned_msg(MSG_OK);
return -1;
}
- pbolt.target_x = spelld.tx;
- pbolt.target_y = spelld.ty;
+ pbolt.set_target(spelld);
pbolt.source_x = you.x_pos;
pbolt.source_y = you.y_pos;
return 1;
} // end spell_direction()
+const char* spelltype_short_name( int which_spelltype ) {
+ switch (which_spelltype)
+ {
+ case SPTYP_CONJURATION:
+ return ("Conj");
+ case SPTYP_ENCHANTMENT:
+ return ("Ench");
+ case SPTYP_FIRE:
+ return ("Fire");
+ case SPTYP_ICE:
+ return ("Ice");
+ case SPTYP_TRANSMIGRATION:
+ return ("Tmgr");
+ case SPTYP_NECROMANCY:
+ return ("Necr");
+ case SPTYP_HOLY:
+ return ("Holy");
+ case SPTYP_SUMMONING:
+ return ("Summ");
+ case SPTYP_DIVINATION:
+ return ("Divn");
+ case SPTYP_TRANSLOCATION:
+ return ("Tloc");
+ case SPTYP_POISON:
+ return ("Pois");
+ case SPTYP_EARTH:
+ return ("Erth");
+ case SPTYP_AIR:
+ return ("Air");
+ default:
+ return "Bug";
+ }
+}
+
const char *spelltype_name(unsigned int which_spelltype)
{
static char bug_string[80];
@@ -776,7 +820,7 @@ static struct playerspell *seekspell(int spell)
static bool cloud_helper( int (*func) (int, int, int, int), int x, int y,
int pow, int ctype )
{
- if (grd[x][y] > DNGN_LAST_SOLID_TILE && env.cgrid[x][y] == EMPTY_CLOUD)
+ if (!grid_is_solid(grd[x][y]) && env.cgrid[x][y] == EMPTY_CLOUD)
{
func(x, y, pow, ctype);
return true;
diff --git a/crawl-ref/source/spl-util.h b/crawl-ref/source/spl-util.h
index 848530dbbf..31a3bc5102 100644
--- a/crawl-ref/source/spl-util.h
+++ b/crawl-ref/source/spl-util.h
@@ -3,6 +3,8 @@
* Summary: data handlers for player spell list
* Written by: don brodale <dbrodale@bigfootinteractive.com>
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Changelog(most recent first):
*
* 24jun2000 jmf simplified structures
@@ -20,7 +22,8 @@ struct playerspell
{
int id;
const char *title;
- unsigned int disciplines; //jmf: a bitfield
+ unsigned int disciplines; // bitfield
+ unsigned int flags; // bitfield
unsigned int level;
};
@@ -46,6 +49,8 @@ int spell_difficulty(int which_spell);
int spell_levels_required(int which_spell);
+unsigned int get_spell_flags( int which_spell );
+
// * called from: chardump - spell - spl-book - spells0
bool spell_typematch(int which_spell, unsigned int which_discipline);
unsigned int spell_type( int which_spell ); //jmf: simplification of above
@@ -54,6 +59,8 @@ int count_bits( unsigned int bits );
// * called from: chardump - command - debug - spl-book - spells0
const char *spell_title(int which_spell);
+const char* spelltype_short_name( int which_spelltype );
+
//int spell_restriction(int which_spell, int which_restriction);
int apply_area_visible(int (*func) (int, int, int, int), int power);
diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc
index 0c7dfe6e34..b1b027fb3a 100644
--- a/crawl-ref/source/stash.cc
+++ b/crawl-ref/source/stash.cc
@@ -2,6 +2,8 @@
* File: stash.cc
* Summary: Classes tracking player stashes
* Written by: Darshan Shaligram
+ *
+ * Modified for Crawl Reference by $Author$ on $Date$
*/
#include "AppHdr.h"
@@ -9,12 +11,14 @@
#include "clua.h"
#include "describe.h"
#include "itemname.h"
+#include "itemprop.h"
#include "files.h"
#include "invent.h"
#include "items.h"
#include "Kills.h"
#include "libutil.h"
#include "menu.h"
+#include "misc.h"
#include "shopping.h"
#include "spl-book.h"
#include "stash.h"
@@ -36,12 +40,6 @@
#define LUA_DUMP_ANNOTATE "ch_stash_dump_annotate_item"
#define LUA_VIEW_ANNOTATE "ch_stash_view_annotate_item"
-std::string short_place_name(level_id id)
-{
- return short_place_name(
- get_packed_place(id.branch, id.depth, LEVEL_DUNGEON));
-}
-
std::string userdef_annotate_item(const char *s, const item_def *item,
bool exclusive)
{
@@ -324,10 +322,10 @@ std::string Stash::stash_item_name(const item_def &item)
return buf;
}
-class StashMenu : public Menu
+class StashMenu : public InvMenu
{
public:
- StashMenu() : Menu(MF_SINGLESELECT), can_travel(false) { }
+ StashMenu() : InvMenu(MF_SINGLESELECT), can_travel(false) { }
public:
bool can_travel;
protected:
@@ -341,7 +339,7 @@ void StashMenu::draw_title()
{
gotoxy(1, 1);
textcolor(title->colour);
- cprintf(title->text.c_str());
+ cprintf( "%s", title->text.c_str());
if (title->quantity)
cprintf(", %d item%s", title->quantity,
title->quantity == 1? "" : "s");
@@ -362,7 +360,7 @@ bool StashMenu::process_key(int key)
return Menu::process_key(key);
}
-static void stash_menu_fixup(MenuEntry *me)
+static MenuEntry *stash_menu_fixup(MenuEntry *me)
{
const item_def *item = static_cast<const item_def *>( me->data );
if (item->base_type == OBJ_GOLD)
@@ -370,19 +368,20 @@ static void stash_menu_fixup(MenuEntry *me)
me->quantity = 0;
me->colour = DARKGREY;
}
+
+ return (me);
}
bool Stash::show_menu(const std::string &prefix, bool can_travel) const
{
StashMenu menu;
- MenuEntry *mtitle = new MenuEntry(" Stash (" + prefix);
+ MenuEntry *mtitle = new MenuEntry("Stash (" + prefix, MEL_TITLE);
menu.can_travel = can_travel;
- mtitle->colour = WHITE;
mtitle->quantity = items.size();
menu.set_title(mtitle);
- populate_item_menu(&menu, items, stash_menu_fixup);
+ menu.load_items( InvMenu::xlat_itemvect(items), stash_menu_fixup);
std::vector<MenuEntry*> sel;
while (true)
{
@@ -412,7 +411,9 @@ std::string Stash::description() const
if (sz > 1)
{
char additionals[50];
- snprintf(additionals, sizeof additionals, " (+%lu)", (unsigned long) (sz - 1));
+ snprintf(additionals, sizeof additionals,
+ " (+%lu)",
+ (unsigned long) (sz - 1));
desc += additionals;
}
return (desc);
@@ -467,8 +468,6 @@ void Stash::write(std::ostream &os,
bool identify)
const
{
- int i;
-
if (!enabled || (items.size() == 0 && verified)) return;
os << "(" << ((int) x - refx) << ", " << ((int) y - refy)
<< (place.length()? ", " + place : "")
@@ -476,7 +475,7 @@ void Stash::write(std::ostream &os,
<< std::endl;
char buf[ITEMNAME_SIZE];
- for (i = 0; i < (int) items.size(); ++i)
+ for (int i = 0; i < (int) items.size(); ++i)
{
item_def item = items[i];
@@ -512,9 +511,9 @@ void Stash::write(std::ostream &os,
if (desc.length())
{
// Walk backwards and prepend indenting spaces to \n characters
- for (i = desc.length() - 1; i >= 0; --i)
- if (desc[i] == '\n')
- desc.insert(i + 1, " ");
+ for (int j = desc.length() - 1; j >= 0; --j)
+ if (desc[j] == '\n')
+ desc.insert(j + 1, " ");
os << " " << desc << std::endl;
}
}
@@ -621,14 +620,7 @@ std::string ShopInfo::shop_item_desc(const shop_item &si) const
desc = munge_description(get_item_description(si.item,
Options.verbose_dump,
true));
-
- // trim leading whitespace
- std::string::size_type notwhite = desc.find_first_not_of(" \t\n");
- desc.erase(0, notwhite);
-
- // trim trailing whitespace
- notwhite = desc.find_last_not_of(" \t\n");
- desc.erase(notwhite + 1);
+ trim_string(desc);
// Walk backwards and prepend indenting spaces to \n characters
for (int i = desc.length() - 1; i >= 0; --i)
@@ -649,9 +641,8 @@ bool ShopInfo::show_menu(const std::string &place,
ShopId id(shoptype);
StashMenu menu;
- MenuEntry *mtitle = new MenuEntry(" " + name + " (" + place);
+ MenuEntry *mtitle = new MenuEntry(name + " (" + place, MEL_TITLE);
menu.can_travel = can_travel;
- mtitle->colour = WHITE;
mtitle->quantity = items.size();
menu.set_title(mtitle);
@@ -701,7 +692,7 @@ std::string ShopInfo::description() const
return (name);
}
-bool ShopInfo::matches_search(const std::string &prefix,
+bool ShopInfo::matches_search(const std::string &prefix,
const base_pattern &search,
stash_search_result &res) const
{
@@ -712,12 +703,12 @@ bool ShopInfo::matches_search(const std::string &prefix,
for (unsigned i = 0; i < items.size(); ++i)
{
- std::string name = shop_item_name(items[i]);
+ std::string sname = shop_item_name(items[i]);
std::string ann = stash_annotate_item(
LUA_SEARCH_ANNOTATE, &items[i].item, true);
bool thismatch = false;
- if (search.matches(prefix + " " + ann + name))
+ if (search.matches(prefix + " " + ann + sname))
thismatch = true;
else
{
@@ -729,7 +720,7 @@ bool ShopInfo::matches_search(const std::string &prefix,
if (thismatch)
{
if (!res.count++)
- res.match = name;
+ res.match = sname;
res.matches++;
}
}
@@ -965,7 +956,9 @@ bool LevelStashes::in_branch(int branchid) const
std::string LevelStashes::level_name() const
{
int curr_subdungeon_level = subdungeon_depth( branch, depth );
- return (branch_level_name(branch, curr_subdungeon_level));
+ return (place_name(
+ get_packed_place(branch, curr_subdungeon_level, LEVEL_DUNGEON),
+ true, true));
}
std::string LevelStashes::short_level_name() const
@@ -1037,11 +1030,11 @@ void LevelStashes::write(std::ostream &os, bool identify) const
{
const Stash &s = stashes.begin()->second;
int refx = s.getX(), refy = s.getY();
- std::string level_name = short_level_name();
+ std::string levname = short_level_name();
for (c_stashes::const_iterator iter = stashes.begin();
iter != stashes.end(); iter++)
{
- iter->second.write(os, refx, refy, level_name, identify);
+ iter->second.write(os, refx, refy, levname, identify);
}
}
os << std::endl;
@@ -1291,7 +1284,8 @@ void StashTracker::search_stashes()
mpr("", MSGCH_PROMPT);
char buf[400];
- bool validline = cancelable_get_line(buf, sizeof buf, 80, &search_history);
+ bool validline =
+ !cancelable_get_line(buf, sizeof buf, 80, &search_history);
mesclr();
if (!validline || (!*buf && !lastsearch.length()))
return;
@@ -1381,7 +1375,7 @@ void StashSearchMenu::draw_title()
{
gotoxy(1, 1);
textcolor(title->colour);
- cprintf(" %d %s%s", title->quantity, title->text.c_str(),
+ cprintf("%d %s%s", title->quantity, title->text.c_str(),
title->quantity > 1? "es" : "");
if (meta_key)
@@ -1395,8 +1389,7 @@ bool StashSearchMenu::process_key(int key)
{
if (key == '?')
{
- if (sel)
- sel->clear();
+ sel.clear();
meta_key = !meta_key;
update_title();
return true;
@@ -1417,8 +1410,7 @@ void StashTracker::display_search_results(
stashmenu.can_travel = travelable;
std::string title = "matching stash";
- MenuEntry *mtitle = new MenuEntry(title);
- mtitle->colour = WHITE;
+ MenuEntry *mtitle = new MenuEntry(title, MEL_TITLE);
// Abuse of the quantity field.
mtitle->quantity = results.size();
stashmenu.set_title(mtitle);
@@ -1509,100 +1501,3 @@ void StashTracker::display_search_results(
StashTracker stashes;
#endif
-
-std::string branch_level_name(unsigned char branch, int sub_depth)
-{
- int ltype = sub_depth == 0xFF? branch : 0;
- if (ltype == LEVEL_PANDEMONIUM)
- return ("Pandemonium");
- else if (ltype == LEVEL_ABYSS)
- return ("The Abyss");
- else if (ltype == LEVEL_LABYRINTH)
- return ("A Labyrinth");
- else
- {
- char buf[200];
- const char *s = NULL;
- *buf = 0;
- // level_type == LEVEL_DUNGEON
- if (branch != BRANCH_VESTIBULE_OF_HELL
- && branch != BRANCH_ECUMENICAL_TEMPLE
- && branch != BRANCH_HALL_OF_BLADES)
- snprintf(buf, sizeof buf, "Level %d", sub_depth);
-
- switch (branch)
- {
- case BRANCH_MAIN_DUNGEON:
- s = " of the Dungeon";
- break;
- case BRANCH_DIS:
- s = " of Dis";
- break;
- case BRANCH_GEHENNA:
- s = " of Gehenna";
- break;
- case BRANCH_VESTIBULE_OF_HELL:
- s = "The Vestibule of Hell";
- break;
- case BRANCH_COCYTUS:
- s = " of Cocytus";
- break;
- case BRANCH_TARTARUS:
- s = " of Tartarus";
- break;
- case BRANCH_INFERNO:
- s = " of the Inferno";
- break;
- case BRANCH_THE_PIT:
- s = " of the Pit";
- break;
- case BRANCH_ORCISH_MINES:
- s = " of the Orcish Mines";
- break;
- case BRANCH_HIVE:
- s = " of the Hive";
- break;
- case BRANCH_LAIR:
- s = " of the Lair";
- break;
- case BRANCH_SLIME_PITS:
- s = " of the Slime Pits";
- break;
- case BRANCH_VAULTS:
- s = " of the Vaults";
- break;
- case BRANCH_CRYPT:
- s = " of the Crypt";
- break;
- case BRANCH_HALL_OF_BLADES:
- s = "The Hall of Blades";
- break;
- case BRANCH_HALL_OF_ZOT:
- s = " of the Realm of Zot";
- break;
- case BRANCH_ECUMENICAL_TEMPLE:
- s = "The Ecumenical Temple";
- break;
- case BRANCH_SNAKE_PIT:
- s = " of the Snake Pit";
- break;
- case BRANCH_ELVEN_HALLS:
- s = " of the Elven Halls";
- break;
- case BRANCH_TOMB:
- s = " of the Tomb";
- break;
- case BRANCH_SWAMP:
- s = " of the Swamp";
- break;
- }
- if (s)
- strncat(buf, s, sizeof(buf) - 1);
- return (buf);
- }
-}
-
-std::string branch_level_name(unsigned short packed_place)
-{
- return branch_level_name(packed_place >> 8, packed_place & 0xFF);
-}
diff --git a/crawl-ref/source/stash.h b/crawl-ref/source/stash.h
index 5e36eb4a61..727fb656e4 100644
--- a/crawl-ref/source/stash.h
+++ b/crawl-ref/source/stash.h
@@ -317,10 +317,6 @@ void describe_stash(int x, int y);
#endif // STASH_TRACKING
-std::string branch_level_name(unsigned char branch, int sub_depth);
-
-std::string branch_level_name(unsigned short packed_place);
-
std::string userdef_annotate_item(const char *s, const item_def *item,
bool exclusive = false);
diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc
index 3a0a281d34..e9b97624ea 100644
--- a/crawl-ref/source/stuff.cc
+++ b/crawl-ref/source/stuff.cc
@@ -14,7 +14,10 @@
*/
#include "AppHdr.h"
+#include "direct.h"
+#include "monplace.h"
#include "stuff.h"
+#include "view.h"
#include <stdlib.h>
#include <stdio.h>
@@ -50,6 +53,7 @@
#include "libunix.h"
#endif
+#include "delay.h"
#include "externs.h"
#include "macro.h"
@@ -57,8 +61,9 @@
#include "monstuff.h"
#include "mon-util.h"
#include "mt19937ar.h"
-#include "player.h"
+#include "notes.h"
#include "output.h"
+#include "player.h"
#include "skills2.h"
#include "view.h"
@@ -133,14 +138,14 @@ void tag_followers( void )
continue;
}
- if (monster_habitat(fmenv->type) != DNGN_FLOOR)
+ if (!monster_habitable_grid(fmenv, DNGN_FLOOR))
continue;
if (fmenv->speed_increment < 50)
continue;
- // only friendly monsters, or those actively seeking the
- // player, will follow up/down stairs.
+ // only friendly monsters, or those actively seeking the
+ // player, will follow up/down stairs.
if (!(mons_friendly(fmenv) ||
(fmenv->behaviour == BEH_SEEK && fmenv->foe == MHITYOU)))
{
@@ -330,6 +335,12 @@ unsigned long random_int( void )
return (genrand_int32());
}
+int random_range(int low, int high)
+{
+ ASSERT(low <= high);
+ return (low + random2(high - low + 1));
+}
+
int random2( int max )
{
if (max <= 1)
@@ -355,6 +366,31 @@ void pop_rng_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 )
+{
+ while (dice.size > threshold)
+ {
+ dice.num *= 2;
+ // If it's an odd number, lose one; this is more than
+ // compensated by the increase in number of dice.
+ dice.size /= 2;
+ }
+}
+
+int bestroll(int max, int rolls)
+{
+ int best = 0;
+ for (int i = 0; i < rolls; i++)
+ {
+ int curr = random2(max);
+ if (curr > best)
+ best = curr;
+ }
+ return (best);
+}
+
// random2avg() returns same mean value as random2() but with a lower variance
// never use with rolls < 2 as that would be silly - use random2() instead {dlb}
int random2avg(int max, int rolls)
@@ -438,10 +474,6 @@ void end(int end_arg)
unixcurses_shutdown();
#endif
-#ifdef MAC
- deinit_mac();
-#endif
-
#ifdef WIN32CONSOLE
deinit_libw32c();
#endif
@@ -474,7 +506,10 @@ void redraw_screen(void)
if (Options.delay_message_clear)
mesclr( true );
+ bool note_status = notes_are_active();
+ activate_notes(false);
new_level();
+ activate_notes(note_status);
viewwindow(1, false);
#endif
@@ -539,6 +574,37 @@ int stepdown_value(int base_value, int stepping, int first_step,
} // end stepdown_value()
+int skill_bump( int skill )
+{
+ return ((you.skills[skill] < 3) ? you.skills[skill] * 2
+ : you.skills[skill] + 3);
+}
+
+// This gives (default div = 20, shift = 3):
+// - shift/div% @ stat_level = 0; (default 3/20 = 15%, or 20% at stat 1)
+// - even (100%) @ stat_level = div - shift; (default 17)
+// - 1/div% per stat_level (default 1/20 = 5%)
+int stat_mult( int stat_level, int value, int div, int shift )
+{
+ return (((stat_level + shift) * value) / ((div > 1) ? div : 1));
+}
+
+// As above but inverted (ie 5x penalty at stat 1)
+int stat_div( int stat_level, int value, int mult, int shift )
+{
+ int div = stat_level + shift;
+
+ if (div < 1)
+ div = 1;
+
+ return ((mult * value) / div);
+}
+
+// Calculates num/den and randomly adds one based on the remainder.
+int div_rand_round( int num, int den )
+{
+ return (num / den + (random2(den) < num % den));
+}
// I got so tired of seeing: ".. && random2(foo) == 0 && .." in the code
// that I broke down and wrote this little -- very little -- function.
@@ -589,10 +655,9 @@ void canned_msg(unsigned char which_message)
switch (which_message)
{
case MSG_SOMETHING_APPEARS:
- strcpy(info, "Something appears ");
- strcat(info, (you.species == SP_NAGA || you.species == SP_CENTAUR)
- ? "before you" : "at your feet");
- strcat(info, "!");
+ snprintf(info, INFO_SIZE, "Something appears %s!",
+ (you.species == SP_NAGA || you.species == SP_CENTAUR)
+ ? "before you" : "at your feet");
mpr(info);
break;
@@ -667,7 +732,44 @@ bool yesno( const char *str, bool safe, int safeanswer, bool clear_after )
}
} // end yesno()
-// More accurate than distance() given the actual movement geonmetry -- bwr
+// like yesno(), but returns 0 for no, 1 for yes, and -1 for quit
+int yesnoquit( const char* str, bool safe, int safeanswer, bool clear_after )
+{
+ unsigned char tmp;
+
+ interrupt_activity( AI_FORCE_INTERRUPT );
+ while (1)
+ {
+ mpr(str, MSGCH_PROMPT);
+
+ tmp = (unsigned char) getch();
+
+ if ( tmp == 27 || tmp == 'q' || tmp == 'Q' )
+ return -1;
+
+ if ((tmp == ' ' || tmp == '\r' || tmp == '\n') && safeanswer)
+ tmp = safeanswer;
+
+ if (Options.easy_confirm == CONFIRM_ALL_EASY
+ || tmp == safeanswer
+ || (Options.easy_confirm == CONFIRM_SAFE_EASY && safe))
+ {
+ tmp = toupper( tmp );
+ }
+
+ if (clear_after)
+ mesclr();
+
+ if (tmp == 'N')
+ return 0;
+ else if (tmp == 'Y')
+ return 1;
+ else
+ mpr("[Y]es or [N]o only, please.");
+ }
+}
+
+// More accurate than distance() given the actual movement geometry -- bwr
int grid_distance( int x, int y, int x2, int y2 )
{
const int dx = abs( x - x2 );
@@ -679,7 +781,7 @@ int grid_distance( int x, int y, int x2, int y2 )
int distance( int x, int y, int x2, int y2 )
{
- //jmf: now accurate, but remember to only compare vs. pre-squared distances.
+ //jmf: now accurate, but remember to only compare vs. pre-squared distances
// thus, next to == (distance(m1.x,m1.y, m2.x,m2.y) <= 2)
const int dx = x - x2;
const int dy = y - y2;
@@ -694,8 +796,6 @@ bool adjacent( int x, int y, int x2, int y2 )
bool silenced(char x, char y)
{
-#ifdef USE_SILENCE_CODE
-
if (you.duration[DUR_SILENCE] > 0
&& distance(x, y, you.x_pos, you.y_pos) <= 36) // (6 * 6)
{
@@ -711,26 +811,308 @@ bool silenced(char x, char y)
// }
return false;
}
-
-#else
- return false;
-#endif
} // end silenced()
bool player_can_hear(char x, char y)
{
-#ifdef USE_SILENCE_CODE
return (!silenced(x, y) && !silenced(you.x_pos, you.y_pos));
-#else
- return true;
-#endif
} // end player_can_hear()
+// Returns true if inside the area the player can move and dig (ie exclusive)
+bool in_bounds( int x, int y )
+{
+ return (x > X_BOUND_1 && x < X_BOUND_2
+ && y > Y_BOUND_1 && y < Y_BOUND_2);
+}
+
+// Returns true if inside the area the player can map (ie inclusive).
+// Note that terrain features should be in_bounds() leaving an outer
+// ring of rock to frame the level.
+bool map_bounds( int x, int y )
+{
+ return (x >= X_BOUND_1 && x <= X_BOUND_2
+ && y >= Y_BOUND_1 && y <= Y_BOUND_2);
+}
+
+// Returns a random location in (x_pos, y_pos)... the grid will be
+// DNGN_FLOOR if clear, and NON_MONSTER if empty. Exclusive tells
+// if we're using in_bounds() or map_bounds() restriction.
+void random_in_bounds( int &x_pos, int &y_pos, int terr, bool empty, bool excl )
+{
+ bool done = false;
+
+ do
+ {
+ x_pos = X_BOUND_1 + random2( X_WIDTH - 2 * excl ) + 1 * excl;
+ y_pos = Y_BOUND_1 + random2( Y_WIDTH - 2 * excl ) + 1 * excl;
+
+ if (terr == DNGN_RANDOM)
+ done = true;
+ else if (terr == grd[x_pos][y_pos])
+ done = true;
+ else if (terr == DNGN_DEEP_WATER && grd[x_pos][y_pos] == DNGN_SHALLOW_WATER)
+ done = true;
+ else if (empty
+ && mgrd[x_pos][y_pos] != NON_MONSTER
+ && (x_pos != you.x_pos || y_pos != you.y_pos))
+ {
+ done = true;
+ }
+ }
+ 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));
} // end random_colour()
+// returns if a colour is one of the special element colours (ie not regular)
+bool is_element_colour( int col )
+{
+ // striping any COLFLAGS (just in case)
+ return ((col & 0x007f) >= EC_FIRE);
+}
+
+int element_colour( int element, bool no_random )
+{
+ // Doing this so that we don't have to do recursion here at all
+ // (these were the only cases which had possible double evaluation):
+ if (element == EC_FLOOR)
+ element = env.floor_colour;
+ else if (element == EC_ROCK)
+ element = env.rock_colour;
+
+ // pass regular colours through for safety.
+ if (!is_element_colour( element ))
+ return (element);
+
+ int ret = BLACK;
+
+ // Setting no_random to true will get the first colour in the cases
+ // below. This is potentially useful for calls to this function
+ // which might want a consistant result.
+ int tmp_rand = (no_random ? 0 : random2(120));
+
+ switch (element & 0x007f) // strip COLFLAGs just in case
+ {
+ case EC_FIRE:
+ ret = (tmp_rand < 40) ? RED :
+ (tmp_rand < 80) ? YELLOW
+ : LIGHTRED;
+ break;
+
+ case EC_ICE:
+ ret = (tmp_rand < 40) ? LIGHTBLUE :
+ (tmp_rand < 80) ? BLUE
+ : WHITE;
+ break;
+
+ case EC_EARTH:
+ ret = (tmp_rand < 60) ? BROWN : LIGHTRED;
+ break;
+
+ case EC_AIR:
+ ret = (tmp_rand < 60) ? LIGHTGREY : WHITE;
+ break;
+
+ case EC_ELECTRICITY:
+ ret = (tmp_rand < 40) ? LIGHTCYAN :
+ (tmp_rand < 80) ? LIGHTBLUE
+ : CYAN;
+ break;
+
+ case EC_POISON:
+ ret = (tmp_rand < 60) ? LIGHTGREEN : GREEN;
+ break;
+
+ case EC_WATER:
+ ret = (tmp_rand < 60) ? BLUE : CYAN;
+ break;
+
+ case EC_MAGIC:
+ ret = (tmp_rand < 30) ? LIGHTMAGENTA :
+ (tmp_rand < 60) ? LIGHTBLUE :
+ (tmp_rand < 90) ? MAGENTA
+ : BLUE;
+ break;
+
+ case EC_MUTAGENIC:
+ case EC_WARP:
+ ret = (tmp_rand < 60) ? LIGHTMAGENTA : MAGENTA;
+ break;
+
+ case EC_ENCHANT:
+ ret = (tmp_rand < 60) ? LIGHTBLUE : BLUE;
+ break;
+
+ case EC_HEAL:
+ ret = (tmp_rand < 60) ? LIGHTBLUE : YELLOW;
+ break;
+
+ case EC_BLOOD:
+ ret = (tmp_rand < 60) ? RED : DARKGREY;
+ break;
+
+ case EC_DEATH: // assassin
+ case EC_NECRO: // necromancer
+ ret = (tmp_rand < 80) ? DARKGREY : MAGENTA;
+ break;
+
+ case EC_UNHOLY: // ie demonology
+ ret = (tmp_rand < 80) ? DARKGREY : RED;
+ break;
+
+ case EC_DARK:
+ ret = DARKGREY;
+ break;
+
+ case EC_HOLY:
+ ret = (tmp_rand < 60) ? YELLOW : WHITE;
+ break;
+
+ case EC_VEHUMET:
+ ret = (tmp_rand < 40) ? LIGHTRED :
+ (tmp_rand < 80) ? LIGHTMAGENTA
+ : LIGHTBLUE;
+ break;
+
+ case EC_CRYSTAL:
+ ret = (tmp_rand < 40) ? LIGHTGREY :
+ (tmp_rand < 80) ? GREEN
+ : LIGHTRED;
+ break;
+
+ case EC_SLIME:
+ ret = (tmp_rand < 40) ? GREEN :
+ (tmp_rand < 80) ? BROWN
+ : LIGHTGREEN;
+ break;
+
+ case EC_SMOKE:
+ ret = (tmp_rand < 30) ? LIGHTGREY :
+ (tmp_rand < 60) ? DARKGREY :
+ (tmp_rand < 90) ? LIGHTBLUE
+ : MAGENTA;
+ break;
+
+ case EC_JEWEL:
+ ret = (tmp_rand < 12) ? WHITE :
+ (tmp_rand < 24) ? YELLOW :
+ (tmp_rand < 36) ? LIGHTMAGENTA :
+ (tmp_rand < 48) ? LIGHTRED :
+ (tmp_rand < 60) ? LIGHTGREEN :
+ (tmp_rand < 72) ? LIGHTBLUE :
+ (tmp_rand < 84) ? MAGENTA :
+ (tmp_rand < 96) ? RED :
+ (tmp_rand < 108) ? GREEN
+ : BLUE;
+ break;
+
+ case EC_ELVEN:
+ ret = (tmp_rand < 40) ? LIGHTGREEN :
+ (tmp_rand < 80) ? GREEN :
+ (tmp_rand < 100) ? LIGHTBLUE
+ : BLUE;
+ break;
+
+ case EC_DWARVEN:
+ ret = (tmp_rand < 40) ? BROWN :
+ (tmp_rand < 80) ? LIGHTRED :
+ (tmp_rand < 100) ? LIGHTGREY
+ : CYAN;
+ break;
+
+ case EC_ORCISH:
+ ret = (tmp_rand < 40) ? DARKGREY :
+ (tmp_rand < 80) ? RED :
+ (tmp_rand < 100) ? BROWN
+ : MAGENTA;
+ break;
+
+ case EC_GILA:
+ ret = (tmp_rand < 30) ? LIGHTMAGENTA :
+ (tmp_rand < 60) ? MAGENTA :
+ (tmp_rand < 90) ? YELLOW :
+ (tmp_rand < 105) ? LIGHTRED
+ : RED;
+ break;
+
+ case EC_STONE:
+ if (player_in_branch( BRANCH_HALL_OF_ZOT ))
+ ret = env.rock_colour;
+ else
+ ret = LIGHTGREY;
+ break;
+
+ case EC_RANDOM:
+ ret = 1 + random2(15); // always random
+ break;
+
+ case EC_FLOOR: // should alredy be handled
+ case EC_ROCK: // should alredy be handled
+ default:
+ break;
+ }
+
+ ASSERT( !is_element_colour( ret ) );
+
+ return ((ret == BLACK) ? GREEN : ret);
+}
+
char index_to_letter(int the_index)
{
return (the_index + ((the_index < 26) ? 'a' : ('A' - 26)));
@@ -771,7 +1153,7 @@ int near_stairs(int px, int py, int max_dist, unsigned char &stair_gfx)
&& grd[x][y] <= DNGN_RETURN_FROM_SWAMP
&& grd[x][y] != DNGN_ENTER_SHOP) // silly
{
- stair_gfx = mapch(grd[x][y]);
+ stair_gfx = get_sightmap_char(grd[x][y]);
return ((x == you.x_pos && y == you.y_pos) ? 2 : 1);
}
}
@@ -779,3 +1161,48 @@ int near_stairs(int px, int py, int max_dist, unsigned char &stair_gfx)
return false;
}
+
+bool is_trap_square(int x, int y)
+{
+ return (grd[x][y] >= DNGN_TRAP_MECHANICAL
+ && grd[x][y] <= DNGN_UNDISCOVERED_TRAP);
+}
+
+// Does the equivalent of KILL_RESET on all monsters in LOS. Should only be
+// applied to new games.
+void zap_los_monsters()
+{
+ losight(env.show, grd, you.x_pos, you.y_pos);
+
+ for (int y = LOS_SY; y <= LOS_EY; ++y)
+ {
+ for (int x = LOS_SX; x <= LOS_EX; ++x)
+ {
+ if (!in_vlos(x, y))
+ continue;
+
+ const int gx = view2gridX(x),
+ gy = view2gridY(y);
+
+ if (!map_bounds(gx, gy))
+ continue;
+
+ if (gx == you.x_pos && gy == you.y_pos)
+ continue;
+
+ int imon = mgrd[gx][gy];
+ if (imon == NON_MONSTER || imon == MHITYOU)
+ continue;
+
+ // If we ever allow starting with a friendly monster,
+ // we'll have to check here.
+ monsters *mon = &menv[imon];
+#ifdef DEBUG_DIAGNOSTICS
+ char mname[ITEMNAME_SIZE];
+ moname(mon->type, true, DESC_PLAIN, mname);
+ mprf(MSGCH_DIAGNOSTICS, "Dismissing %s", mname);
+#endif
+ monster_die(mon, KILL_DISMISSED, 0);
+ }
+ }
+}
diff --git a/crawl-ref/source/stuff.h b/crawl-ref/source/stuff.h
index 72c7d2dcf5..c05231ceb5 100644
--- a/crawl-ref/source/stuff.h
+++ b/crawl-ref/source/stuff.h
@@ -3,6 +3,8 @@
* Summary: Misc stuff.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <3> 11/14/99 cdl added random40
@@ -17,192 +19,82 @@
#include "externs.h"
char *const make_time_string(time_t abs_time, char *const buff, int buff_size, bool terse = false);
-
void set_redraw_status( unsigned long flags );
-
void tag_followers( void );
void untag_followers( void );
void seed_rng(void);
-
void seed_rng(long seed);
-
void push_rng_state();
-
void pop_rng_state();
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: acr
- * *********************************************************************** */
void cf_setseed(void);
-
-
-/* ***********************************************************************
- * called from: xxx
- * *********************************************************************** */
bool coinflip(void);
-
-
-/* ***********************************************************************
- * called from: xxx
- * *********************************************************************** */
+int div_rand_round( int num, int den );
bool one_chance_in(int a_million);
-
-
-/* ***********************************************************************
- * called from: xxx
- * *********************************************************************** */
int random2(int randmax);
-
+int random_range(int low, int high);
unsigned long random_int(void);
-
-/* ***********************************************************************
- * called from: xxx
- * *********************************************************************** */
int random2avg( int max, int rolls );
+int bestroll(int max, int rolls);
int roll_dice( int num, int size );
int roll_dice( const struct dice_def &dice );
+void scale_dice( dice_def &dice, int threshold = 24 );
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: beam - fight - misc
- * *********************************************************************** */
int random2limit(int max, int limit);
-
-
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: bang - beam - monplace - monstuff - spells1 - spells2 -
- * spells4 - view
- * *********************************************************************** */
bool see_grid(unsigned char grx, unsigned char gry);
-
-
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: spells2
- * *********************************************************************** */
int stepdown_value(int base_value, int stepping, int first_step, int last_step, int ceiling_value);
-
-
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: ability - command - effects - food - item_use - items -
- * newgame - ouch - shopping - spell - spl-book - spells1 -
- * spells3
- * *********************************************************************** */
+int stat_mult( int stat_level, int value, int div = 20, int shift = 3 );
+int stat_div( int stat_level, int value, int div = 20, int shift = 3 );
+int skill_bump( int skill );
unsigned char get_ch(void);
-
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: files - newgame - ouch
- * *********************************************************************** */
void end(int end_arg);
-
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: newgame
- * *********************************************************************** */
void modify_all_stats(int STmod, int IQmod, int DXmod);
-
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: ability - acr - command - direct - invent - item_use -
- * religion - shopping - spell - spl-book - spells3
- * *********************************************************************** */
void redraw_screen(void);
-
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: ability - acr - beam - command - decks - debug - effects -
- * it_use3 - item_use - items - misc - ouch - religion -
- * spell - spl-book - spells - spells1 - spells2 - spells3 -
- * spells4
- * *********************************************************************** */
void canned_msg(unsigned char which_message);
-
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
- * called from: ability - acr - command - it_use3 - item_use - items -
- * misc - ouch - religion - spl-book - spells4
- * *********************************************************************** */
-// If safeanswer is nonzero, it should be a lowercase letter.
bool yesno( const char * str, bool safe = true, int safeanswer = 0,
bool clear_after = true );
+int yesnoquit( const char* str, bool safe = true,
+ int safeanswer = 0, bool clear_after = true );
+
+
+bool in_bounds( int x, int y );
+bool map_bounds( int x, int y );
-// last updated 21may2000 {dlb}
-/* ***********************************************************************
- * called from: fight - monstuff - spells4 - view
- * *********************************************************************** */
int grid_distance( int x, int y, int x2, int y2 );
int distance( int x, int y, int x2, int y2);
bool adjacent( int x, int y, int x2, int y2 );
-
-// last updated 21may2000 {dlb}
-/* ***********************************************************************
- * called from: ability - acr - bang - beam - effects - fight - it_use2 -
- * it_use3 - monstuff - mstuff2 - religion - spell - spells -
- * spells3 - spells4 - stuff - view
- * *********************************************************************** */
bool silenced(char x, char y);
-
-// last updated XXmay2000 {dlb}
-/* ***********************************************************************
- * called from: xxx
- * *********************************************************************** */
bool player_can_hear(char x, char y);
-
-// last updated 27may2000 {dlb}
-/* ***********************************************************************
- * called from: dungeon - files - it_use2 - it_use3 - monstuff - mon-util -
- * mstuff2 - newgame - spells - view
- * *********************************************************************** */
unsigned char random_colour(void);
+bool is_element_colour( int col );
+int element_colour( int element, bool no_random = false );
-
-// last updated 08jun2000 {dlb}
-/* ***********************************************************************
- * called from: ability - chardump - command - files - invent - item_use -
- * items - newgame - spl-book - spells0 - spells1
- * *********************************************************************** */
char index_to_letter (int the_index);
-
-// last updated 08jun2000 {dlb}
-/* ***********************************************************************
- * called from: ability - command - food - it_use3 - item_use - items -
- * spell - spl-book - spells1 - spells3
- * *********************************************************************** */
int letter_to_index(int the_letter);
-
-// last updated 16mar2001 {dlb}
-/* ***********************************************************************
- * called from: monplace
- * *********************************************************************** */
int near_stairs(int px, int py, int max_dist, unsigned char &stair_gfx);
-// last updated 16mar2001 {dlb}
-/* ***********************************************************************
- * called from: fight
- * *********************************************************************** */
-// just want to do this in a consistent fashion
inline bool testbits(unsigned int flags, unsigned int test)
{
return ((flags & test) == test);
}
+bool is_trap_square(int x, int y);
+
+void zap_los_monsters();
+
#endif
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index 1aa6752a6b..f671197067 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -17,7 +17,7 @@
than anything else, it is not actually saved as a tag) to TAG_XXX. NUM_TAGS
is equal to the actual number of defined tags.
-2. Tags are created with tag_construct(), which forwards the construction
+2. Tags are created with tag_construct(), which forwards the construction
request appropriately. tag_write() is then used to write the tag to an
output stream.
@@ -25,15 +25,15 @@
forwards the request appropriately, returning the ID of the tag it found,
or zero if no tag was found.
-4. In order to know which tags are used by a particular file type, a client
+4. In order to know which tags are used by a particular file type, a client
calls tag_set_expected( fileType ), which sets up an array of chars.
Within the array, a value of 1 means the tag is expected; -1 means that
the tag is not expected. A client can then set values in this array to
anything other than 1 to indicate a successful tag_read() of that tag.
5. A case should be provided in tag_missing() for any tag which might be
- missing from a tagged save file. For example, if a developer adds
- TAG_YOU_NEW_STUFF to the player save file, he would have to provide a
+ missing from a tagged save file. For example, if a developer adds
+ TAG_YOU_NEW_STUFF to the player save file, he would have to provide a
case in tag_missing() for this tag since it might not be there in
earlier savefiles. The tags defined with the original tag system (and
so not needing cases in tag_missing()) are as follows:
@@ -65,18 +65,6 @@
#include <unistd.h>
#endif
-#ifdef USE_EMX
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#endif
-
-#ifdef OS9
-#include <stat.h>
-#else
-#include <sys/stat.h>
-#endif
-
#include "AppHdr.h"
#include "abl-show.h"
@@ -84,6 +72,7 @@
#include "externs.h"
#include "files.h"
#include "itemname.h"
+#include "itemprop.h"
#include "monstuff.h"
#include "mon-util.h"
#include "randart.h"
@@ -100,9 +89,6 @@ extern FixedArray < unsigned char, MAX_LEVELS, MAX_BRANCHES > altars_present;
extern FixedVector < char, MAX_BRANCHES > stair_level;
extern FixedArray < unsigned char, MAX_LEVELS, MAX_BRANCHES > feature;
-extern unsigned char your_sign; /* these two are defined in view.cc */
-extern unsigned char your_colour;
-
// temp file pairs used for file level cleanup
FixedArray < bool, MAX_LEVELS, MAX_BRANCHES > tmp_file_pairs;
@@ -208,23 +194,31 @@ long unmarshallLong(struct tagHeader &th)
return data;
}
+union float_marshall_kludge
+{
+ // [ds] Does ANSI C guarantee that sizeof(float) == sizeof(long)?
+ float f_num;
+ long l_num;
+};
+
// single precision float -- marshall in network order.
void marshallFloat(struct tagHeader &th, float data)
{
- long intBits = *((long *)(&data));
- marshallLong(th, intBits);
+ float_marshall_kludge k;
+ k.f_num = data;
+ marshallLong(th, k.l_num);
}
// single precision float -- unmarshall in network order.
float unmarshallFloat(struct tagHeader &th)
{
- long intBits = unmarshallLong(th);
-
- return *((float *)(&intBits));
+ float_marshall_kludge k;
+ k.l_num = unmarshallLong(th);
+ return k.f_num;
}
// string -- marshall length & string data
-void marshallString(struct tagHeader &th, char *data, int maxSize)
+void marshallString(struct tagHeader &th, const char *data, int maxSize)
{
// allow for very long strings.
short len = strlen(data);
@@ -250,7 +244,7 @@ void unmarshallString(struct tagHeader &th, char *data, int maxSize)
// read the actual string and null terminate
memcpy(data, &tagBuffer[th.offset], copylen);
- data[copylen] = '\0';
+ data[copylen] = 0;
th.offset += len;
}
@@ -285,7 +279,7 @@ void make_date_string( time_t in_date, char buff[20] )
{
if (in_date <= 0)
{
- buff[0] = '\0';
+ buff[0] = 0;
return;
}
@@ -481,7 +475,7 @@ int tag_read(FILE *fp, char minorVersion)
// For now, none are supported.
// This function will be called AFTER all other tags for
-// the savefile are read, so everything that can be
+// the savefile are read, so everything that can be
// initialized should have been by now.
// minorVersion is available for any child functions that need
@@ -515,6 +509,10 @@ void tag_set_expected(char tags[], int fileType)
if (i >= TAG_YOU && i <=TAG_YOU_DUNGEON)
tags[i] = 1;
break;
+ case TAGTYPE_PLAYER_NAME:
+ if (i == TAG_YOU)
+ tags[i] = 1;
+ break;
case TAGTYPE_LEVEL:
if (i >= TAG_LEVEL && i <= TAG_LEVEL_ATTITUDE)
tags[i] = 1;
@@ -529,12 +527,12 @@ void tag_set_expected(char tags[], int fileType)
}
}
-// NEVER _MODIFY_ THE CONSTRUCT/READ FUNCTIONS, EVER. THAT IS THE WHOLE POINT
+// NEVER _MODIFY_ THE CONSTRUCT/READ FUNCTIONS, EVER. THAT IS THE WHOLE POINT
// OF USING TAGS. Apologies for the screaming.
// Note anyway that the formats are somewhat flexible; you could change map
-// size, the # of slots in player inventory, etc. Constants like GXM,
-// NUM_EQUIP, and NUM_DURATIONS are saved, so the appropriate amount will
+// size, the # of slots in player inventory, etc. Constants like GXM,
+// NUM_EQUIP, and NUM_DURATIONS are saved, so the appropriate amount will
// be restored even if a later version increases these constants.
// --------------------------- player tags (foo.sav) -------------------- //
@@ -555,8 +553,8 @@ static void tag_construct_you(struct tagHeader &th)
marshallByte(th,you.rotting);
marshallByte(th,you.exhausted);
marshallByte(th,you.deaths_door);
- marshallByte(th,your_sign);
- marshallByte(th,your_colour);
+ marshallByte(th,you.symbol);
+ marshallByte(th,you.colour);
marshallByte(th,you.pet_target);
marshallByte(th,you.max_level);
@@ -687,6 +685,10 @@ static void tag_construct_you(struct tagHeader &th)
for (i = 0; i < MAX_NUM_GODS; i++)
marshallByte(th, you.worshipped[i]);
+ // what is the extent of divine generosity?
+ for (i = 0; i < MAX_NUM_GODS; i++)
+ marshallShort(th, you.num_gifts[i]);
+
marshallByte(th, you.gift_timeout);
marshallByte(th, you.normal_vision);
marshallByte(th, you.current_vision);
@@ -738,6 +740,8 @@ static void tag_construct_you_items(struct tagHeader &th)
marshallShort(th,you.inv[i].plus2);
marshallShort(th, you.inv[i].orig_place);
marshallShort(th, you.inv[i].orig_monnum);
+ /*** HP CHANGE ***/
+ marshallString(th, you.inv[i].inscription.c_str(), 80);
}
// item descrip for each type & subtype
@@ -758,7 +762,7 @@ static void tag_construct_you_items(struct tagHeader &th)
marshallByte(th, 50);
// this is really dumb. We copy the id[] array from itemname
- // to the stack, for no good reason that I can see.
+ // to the stack, for no good reason that I can see.
char identy[4][50];
save_id(identy);
@@ -833,8 +837,8 @@ static void tag_read_you(struct tagHeader &th, char minorVersion)
you.rotting = unmarshallByte(th);
you.exhausted = unmarshallByte(th);
you.deaths_door = unmarshallByte(th);
- your_sign = unmarshallByte(th);
- your_colour = unmarshallByte(th);
+ you.symbol = unmarshallByte(th);
+ you.colour = unmarshallByte(th);
you.pet_target = unmarshallByte(th);
you.max_level = unmarshallByte(th);
@@ -956,7 +960,7 @@ static void tag_read_you(struct tagHeader &th, char minorVersion)
// how many durations?
count_c = unmarshallByte(th);
for (j = 0; j < count_c; ++j)
- you.duration[j] = unmarshallByte(th);
+ you.duration[j] = (unsigned char) unmarshallByte(th);
// how many attributes?
count_c = unmarshallByte(th);
@@ -981,6 +985,11 @@ static void tag_read_you(struct tagHeader &th, char minorVersion)
count_c = unmarshallByte(th);
for (i = 0; i < count_c; i++)
you.worshipped[i] = unmarshallByte(th);
+
+ if (minorVersion >= 5)
+ for (i = 0; i < count_c; i++)
+ you.num_gifts[i] = unmarshallShort(th);
+
}
else
{
@@ -1266,6 +1275,7 @@ static void tag_read_you_items(struct tagHeader &th, char minorVersion)
for (i = 0; i < count_c; ++i)
{
you.inv[i].orig_monnum = you.inv[i].orig_place = 0;
+ you.inv[i].inscription.clear();
if (minorVersion < 1)
{
you.inv[i].base_type = (unsigned char) unmarshallByte(th);
@@ -1294,6 +1304,14 @@ static void tag_read_you_items(struct tagHeader &th, char minorVersion)
{
you.inv[i].orig_place = unmarshallShort(th);
you.inv[i].orig_monnum = unmarshallShort(th);
+
+ if (minorVersion >= 6)
+ {
+ /*** HP CHANGE ***/
+ char insstring[80];
+ unmarshallString(th, insstring, 80);
+ you.inv[i].inscription = std::string(insstring);
+ }
}
}
@@ -1485,6 +1503,8 @@ static void tag_construct_level_items(struct tagHeader &th)
marshallShort(th, mitm[i].orig_place);
marshallShort(th, mitm[i].orig_monnum);
+ /*** HP CHANGE ***/
+ marshallString(th, mitm[i].inscription.c_str(), 80);
}
}
@@ -1506,28 +1526,34 @@ static void tag_construct_level_monsters(struct tagHeader &th)
for (i = 0; i < MAX_MONSTERS; i++)
{
- marshallByte(th, menv[i].armour_class);
- marshallByte(th, menv[i].evasion);
- marshallByte(th, menv[i].hit_dice);
- marshallByte(th, menv[i].speed);
- marshallByte(th, menv[i].speed_increment);
- marshallByte(th, menv[i].behaviour);
- marshallByte(th, menv[i].x);
- marshallByte(th, menv[i].y);
- marshallByte(th, menv[i].target_x);
- marshallByte(th, menv[i].target_y);
- marshallByte(th, menv[i].flags);
+ const monsters &m = menv[i];
+
+ marshallByte(th, m.armour_class);
+ marshallByte(th, m.evasion);
+ marshallByte(th, m.hit_dice);
+ marshallByte(th, m.speed);
+ marshallByte(th, m.speed_increment);
+ marshallByte(th, m.behaviour);
+ marshallByte(th, m.x);
+ marshallByte(th, m.y);
+ marshallByte(th, m.target_x);
+ marshallByte(th, m.target_y);
+ marshallByte(th, m.flags);
for (j = 0; j < NUM_MON_ENCHANTS; j++)
- marshallByte(th, menv[i].enchantment[j]);
+ marshallByte(th, m.enchantment[j]);
- marshallShort(th, menv[i].type);
- marshallShort(th, menv[i].hit_points);
- marshallShort(th, menv[i].max_hit_points);
- marshallShort(th, menv[i].number);
+ marshallShort(th, m.type);
+ marshallShort(th, m.hit_points);
+ marshallShort(th, m.max_hit_points);
+ marshallShort(th, m.number);
+ marshallShort(th, m.colour);
for (j = 0; j < NUM_MONSTER_SLOTS; j++)
- marshallShort(th, menv[i].inv[j]);
+ marshallShort(th, m.inv[j]);
+
+ for (j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)
+ marshallShort(th, m.spells[j]);
}
}
@@ -1658,6 +1684,11 @@ static void tag_read_level_items(struct tagHeader &th, char minorVersion)
mitm[i].flags = (unsigned long) unmarshallLong(th);
}
+ // [dshaligram] FIXME, remove this kludge when ARM_CAP is fully
+ // integrated.
+ if (mitm[i].base_type == OBJ_ARMOUR && mitm[i].sub_type == ARM_CAP)
+ mitm[i].sub_type = ARM_HELMET;
+
// pre 4.2 files had monster items stacked at (2,2) -- moved to (0,0)
if (minorVersion < 2 && mitm[i].x == 2 && mitm[i].y == 2)
{
@@ -1673,10 +1704,20 @@ static void tag_read_level_items(struct tagHeader &th, char minorVersion)
mitm[i].slot = unmarshallByte(th);
}
+ mitm[i].inscription.clear();
+
if (minorVersion >= 7)
{
mitm[i].orig_place = unmarshallShort(th);
mitm[i].orig_monnum = unmarshallShort(th);
+
+ if (minorVersion >= 9)
+ {
+ /*** HP CHANGE ***/
+ char insstring[80];
+ unmarshallString(th, insstring, 80);
+ mitm[i].inscription = std::string(insstring);
+ }
}
else
{
@@ -1718,8 +1759,8 @@ static void tag_read_level_monsters(struct tagHeader &th, char minorVersion)
menv[i].target_y = unmarshallByte(th);
menv[i].flags = unmarshallByte(th);
- // VERSION NOTICE: for pre 4.2 files, flags was either 0
- // or 1. Now, we can transfer ENCH_CREATED_FRIENDLY over
+ // VERSION NOTICE: for pre 4.2 files, flags was either 0
+ // or 1. Now, we can transfer ENCH_CREATED_FRIENDLY over
// from the enchantments array to flags.
// Also need to take care of ENCH_FRIEND_ABJ_xx flags
@@ -1755,9 +1796,26 @@ static void tag_read_level_monsters(struct tagHeader &th, char minorVersion)
menv[i].max_hit_points = unmarshallShort(th);
menv[i].number = unmarshallShort(th);
+ if (minorVersion >= 10)
+ menv[i].colour = unmarshallShort(th);
+ else
+ // This will be the wrong colour for many cases, we don't care.
+ menv[i].colour = mons_class_colour( menv[i].type );
+
for (j = 0; j < icount; j++)
menv[i].inv[j] = unmarshallShort(th);
+ if (minorVersion >= 10)
+ {
+ for (j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)
+ menv[i].spells[j] = unmarshallShort(th);
+ }
+ else if (menv[i].type != -1)
+ {
+ const int book = obsolete_mons_spell_template_index( &menv[i] );
+ mons_load_spells( &menv[i], book );
+ }
+
// place monster
if (menv[i].type != -1)
mgrd[menv[i].x][menv[i].y] = i;
@@ -1785,7 +1843,7 @@ void tag_missing_level_attitude()
// a foe first time through handle_monster() if
// there's one around.
- // as for attitude, a couple simple checks
+ // as for attitude, a couple simple checks
// can be used to determine friendly/neutral/
// hostile.
int i;
diff --git a/crawl-ref/source/tags.h b/crawl-ref/source/tags.h
index 7c84709ebf..65a00a208b 100644
--- a/crawl-ref/source/tags.h
+++ b/crawl-ref/source/tags.h
@@ -3,6 +3,8 @@
* Summary: Auxilary functions to make savefile versioning simpler.
* Written by: Gordon Lipford
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> 27 Jan 2001 GDL Created
@@ -37,7 +39,7 @@ void marshallShort(struct tagHeader &th, short data);
void marshallLong(struct tagHeader &th, long data);
void marshallFloat(struct tagHeader &th, float data);
void marshallBoolean(struct tagHeader &th, bool data);
-void marshallString(struct tagHeader &th, char *data, int maxSize = 0);
+void marshallString(struct tagHeader &th, const char *data, int maxSize = 0);
// last updated 22jan2001 {gdl}
/* ***********************************************************************
diff --git a/crawl-ref/source/transfor.cc b/crawl-ref/source/transfor.cc
index 9ee38d548d..697bd4aef7 100644
--- a/crawl-ref/source/transfor.cc
+++ b/crawl-ref/source/transfor.cc
@@ -3,6 +3,8 @@
* Summary: Misc function related to player transformations.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <2> 5/26/99 JDJ transform() and untransform() set you.wield_change so
@@ -26,8 +28,6 @@
#include "skills2.h"
#include "stuff.h"
-extern unsigned char your_sign; // defined in view.cc
-extern unsigned char your_colour; // defined in view.cc
void drop_everything(void);
void extra_hp(int amount_extra);
@@ -89,6 +89,26 @@ static bool check_for_cursed_equipment( FixedVector < char, 8 > &remove_stuff )
return (false);
} // end check_for_cursed_equipment()
+// FIXME: Switch to 4.1 transforms handling.
+size_type transform_size(int)
+{
+ const int transform = you.attribute[ATTR_TRANSFORMATION];
+ switch (transform)
+ {
+ case TRAN_SPIDER:
+ return SIZE_TINY;
+ case TRAN_ICE_BEAST:
+ return SIZE_LARGE;
+ case TRAN_DRAGON:
+ case TRAN_SERPENT_OF_HELL:
+ return SIZE_HUGE;
+ case TRAN_AIR:
+ return SIZE_MEDIUM;
+ default:
+ return SIZE_CHARACTER;
+ }
+}
+
bool transform(int pow, char which_trans)
{
if (you.species == SP_MERFOLK && player_is_swimming()
@@ -163,8 +183,8 @@ bool transform(int pow, char which_trans)
modify_stat( STAT_DEXTERITY, 5, true );
- your_sign = 's';
- your_colour = BROWN;
+ you.symbol = 's';
+ you.colour = BROWN;
return (true);
case TRAN_ICE_BEAST: // also AC +3, cold +3, fire -1, pois +1
@@ -185,8 +205,8 @@ bool transform(int pow, char which_trans)
if (you.duration[DUR_ICY_ARMOUR])
mpr( "Your new body merges with your icy armour." );
- your_sign = 'I';
- your_colour = WHITE;
+ you.symbol = 'I';
+ you.colour = WHITE;
return (true);
case TRAN_BLADE_HANDS:
@@ -237,8 +257,8 @@ bool transform(int pow, char which_trans)
if (you.duration[DUR_STONEMAIL] || you.duration[DUR_STONESKIN])
mpr( "Your new body merges with your stone armour." );
- your_sign = '8';
- your_colour = LIGHTGREY;
+ you.symbol = '8';
+ you.colour = LIGHTGREY;
return (true);
case TRAN_DRAGON: // also AC +10, ev -3, cold -1, fire +2, pois +1, flight
@@ -258,8 +278,8 @@ bool transform(int pow, char which_trans)
modify_stat( STAT_STRENGTH, 10, true );
extra_hp(16); // must occur after attribute set
- your_sign = 'D';
- your_colour = GREEN;
+ you.symbol = 'D';
+ you.colour = GREEN;
return (true);
case TRAN_LICH:
@@ -293,8 +313,8 @@ bool transform(int pow, char which_trans)
you.duration[ DUR_TRANSFORMATION ] = 100;
modify_stat( STAT_STRENGTH, 3, true );
- your_sign = 'L';
- your_colour = LIGHTGREY;
+ you.symbol = 'L';
+ you.colour = LIGHTGREY;
you.is_undead = US_UNDEAD;
you.hunger_state = HS_SATIATED; // no hunger effects while transformed
set_redraw_status( REDRAW_HUNGER );
@@ -316,8 +336,8 @@ bool transform(int pow, char which_trans)
you.duration[ DUR_TRANSFORMATION ] = 150;
modify_stat( STAT_DEXTERITY, 8, true );
- your_sign = '#';
- your_colour = DARKGREY;
+ you.symbol = '#';
+ you.colour = DARKGREY;
return (true);
case TRAN_SERPENT_OF_HELL:
@@ -335,8 +355,8 @@ bool transform(int pow, char which_trans)
modify_stat( STAT_STRENGTH, 13, true );
extra_hp(17); // must occur after attribute set
- your_sign = 'S';
- your_colour = RED;
+ you.symbol = 'S';
+ you.colour = RED;
return (true);
}
@@ -354,8 +374,8 @@ void untransform(void)
you.redraw_armour_class = 1;
you.wield_change = true;
- your_sign = '@';
- your_colour = LIGHTGREY;
+ you.symbol = '@';
+ you.colour = LIGHTGREY;
// must be unset first or else infinite loops might result -- bwr
const int old_form = you.attribute[ ATTR_TRANSFORMATION ];
@@ -401,21 +421,8 @@ void untransform(void)
mpr( "Your transformation has ended.", MSGCH_DURATION );
modify_stat(STAT_STRENGTH, -10, true);
- if (!player_is_levitating()
- && (grd[you.x_pos][you.y_pos] == DNGN_LAVA
- || grd[you.x_pos][you.y_pos] == DNGN_DEEP_WATER
- || grd[you.x_pos][you.y_pos] == DNGN_SHALLOW_WATER))
- {
- if (you.species == SP_MERFOLK
- && grd[you.x_pos][you.y_pos] != DNGN_LAVA)
- {
- mpr("You dive into the water and return to your normal form.");
- merfolk_start_swimming();
- }
-
- if (grd[you.x_pos][you.y_pos] != DNGN_SHALLOW_WATER)
- fall_into_a_pool( true, grd[you.x_pos][you.y_pos] );
- }
+ // re-check terrain now that be may no longer be flying.
+ move_player_to_grid( you.x_pos, you.y_pos, false, true, true );
break;
case TRAN_LICH:
@@ -440,7 +447,7 @@ void untransform(void)
// probably need something better to cover all possibilities. -bwr
if ((you.species == SP_NAGA || you.species == SP_CENTAUR)
&& you.equip[ EQ_BOOTS ] != -1
- && you.inv[ you.equip[EQ_BOOTS] ].plus2 != TBOOT_NAGA_BARDING)
+ && you.inv[ you.equip[EQ_BOOTS] ].sub_type != ARM_NAGA_BARDING)
{
rem_stuff[EQ_BOOTS] = 1;
remove_equipment(rem_stuff);
@@ -451,7 +458,7 @@ void untransform(void)
// XXX: This whole system is a mess as it still relies on special
// cases to handle a large number of things (see wear_armour()) -- bwr
-bool can_equip( char use_which )
+bool can_equip( equipment_type use_which )
{
// if more cases are added to this if must also change in
@@ -519,6 +526,16 @@ bool can_equip( char use_which )
return (true);
} // end can_equip()
+// raw comparison of an item, must use check_armour_shape for full version
+bool transform_can_equip_type( int eq_slot )
+{
+ // FIXME FIXME FIXME
+ return (false);
+
+ // const int form = you.attribute[ATTR_TRANSFORMATION];
+ // return (!must_remove( Trans[form].rem_stuff, eq_slot ));
+}
+
void extra_hp(int amount_extra) // must also set in calc_hp
{
calc_hp();
@@ -549,3 +566,16 @@ void drop_everything(void)
return;
} // end drop_everything()
+
+// Used to mark transformations which override species/mutation intrinsics.
+// If phys_scales is true then we're checking to see if the form keeps
+// the physical (AC/EV) properties from scales... the special intrinsic
+// features (resistances, etc) are lost in those forms however.
+bool transform_changed_physiology( bool phys_scales )
+{
+ return (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE
+ && you.attribute[ATTR_TRANSFORMATION] != TRAN_BLADE_HANDS
+ && (!phys_scales
+ || (you.attribute[ATTR_TRANSFORMATION] != TRAN_LICH
+ && you.attribute[ATTR_TRANSFORMATION] != TRAN_STATUE)));
+}
diff --git a/crawl-ref/source/transfor.h b/crawl-ref/source/transfor.h
index 5efa5a87b2..e292122559 100644
--- a/crawl-ref/source/transfor.h
+++ b/crawl-ref/source/transfor.h
@@ -3,6 +3,8 @@
* Summary: Misc function related to player transformations.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <1> -/--/-- LRH Created
@@ -13,6 +15,7 @@
#define TRANSFOR_H
#include "FixVec.h"
+#include "enum.h"
// last updated 12may2000 {dlb}
@@ -26,8 +29,8 @@ void untransform(void);
/* ***********************************************************************
* called from: item_use
* *********************************************************************** */
-bool can_equip(char use_which);
-
+bool can_equip(equipment_type use_which);
+size_type transform_size(int psize = PSIZE_BODY);
// last updated 12may2000 {dlb}
/* ***********************************************************************
@@ -42,5 +45,6 @@ bool transform(int pow, char which_trans);
* *********************************************************************** */
bool remove_equipment( FixedVector<char, 8>& remove_stuff );
+bool transform_changed_physiology( bool phys_scales = false );
#endif
diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc
index f9c3d2d3d7..f5d418e8be 100644
--- a/crawl-ref/source/travel.cc
+++ b/crawl-ref/source/travel.cc
@@ -3,6 +3,8 @@
* Summary: Travel stuff
* Written by: Darshan Shaligram
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Known issues:
* Hardcoded dungeon features all over the place - this thing is a devil to
* refactor.
@@ -11,15 +13,20 @@
#include "files.h"
#include "FixAry.h"
#include "clua.h"
+#include "delay.h"
+#include "describe.h"
+#include "misc.h"
#include "mon-util.h"
#include "player.h"
#include "stash.h"
#include "stuff.h"
#include "travel.h"
#include "view.h"
-#include <stdarg.h>
-#include <ctype.h>
-#include <stdio.h>
+
+#include <algorithm>
+#include <cstdarg>
+#include <cctype>
+#include <cstdio>
#ifdef DOS
#include <dos.h>
@@ -71,14 +78,6 @@ inline int sgn(int x)
return x < 0? -1 : (x > 0);
}
-/* These are defined in view.cc. BWR says these may become obsolete in next
- * release? */
-extern unsigned char (*mapch) (unsigned char);
-extern unsigned char (*mapch2) (unsigned char);
-extern unsigned char mapchar(unsigned char ldfk);
-extern unsigned char mapchar2(unsigned char ldfk);
-
-
// Array of points on the map, each value being the distance the character
// 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
@@ -91,14 +90,6 @@ signed char curr_traps[GXM][GYM];
static FixedArray< unsigned short, GXM, GYM > mapshadow;
-// Clockwise, around the compass from north (same order as enum RUN_DIR)
-// Copied from acr.cc
-static const struct coord_def Compass[8] =
-{
- { 0, -1 }, { 1, -1 }, { 1, 0 }, { 1, 1 },
- { 0, 1 }, { -1, 1 }, { -1, 0 }, { -1, -1 },
-};
-
#define TRAVERSABLE 1
#define IMPASSABLE 0
#define FORBIDDEN -1
@@ -106,12 +97,17 @@ static const struct coord_def Compass[8] =
// Map of terrain types that are traversable.
static signed char traversable_terrain[256];
-static int trans_negotiate_stairs();
+static command_type trans_negotiate_stairs();
static int find_transtravel_square(const level_pos &pos, bool verbose = true);
static bool loadlev_populate_stair_distances(const level_pos &target);
static void populate_stair_distances(const level_pos &target);
+bool is_player_mapped(int grid_x, int grid_y)
+{
+ return (is_player_mapped( env.map[grid_x - 1][grid_y - 1] ));
+}
+
// Determines whether the player has seen this square, given the user-visible
// character.
//
@@ -119,13 +115,14 @@ static void populate_stair_distances(const level_pos &target);
// a. The square is mapped (the env map char is not zero)
// b. The square was *not* magic-mapped.
//
+// FIXME: There's better ways of doing this with the new view.cc.
bool is_player_mapped(unsigned char envch)
{
// Note that we're relying here on mapch(DNGN_FLOOR) != mapch2(DNGN_FLOOR)
// and that no *other* dungeon feature renders as mapch(DNGN_FLOOR).
// The check for a ~ is to ensure explore stops for items turned up by
// detect items.
- return envch && envch != mapch(DNGN_FLOOR) && envch != '~';
+ return envch && envch != get_magicmap_char(DNGN_FLOOR) && envch != '~';
}
inline bool is_trap(unsigned char grid)
@@ -150,12 +147,12 @@ inline int feature_traverse_cost(unsigned char feature)
}
// Returns true if the dungeon feature supplied is an altar.
-inline bool is_altar(unsigned char grid)
+bool is_altar(unsigned char grid)
{
- return grid >= DNGN_ALTAR_ZIN && grid <= DNGN_ALTAR_ELYVILON;
+ return grid_altar_god(grid) != GOD_NO_GOD;
}
-inline bool is_altar(const coord_def &c)
+bool is_altar(const coord_def &c)
{
return is_altar(grd[c.x][c.y]);
}
@@ -194,13 +191,6 @@ static void init_traps()
traps_inited = true;
}
-static const char *trap_names[] =
-{
- "dart", "arrow", "spear", "axe",
- "teleport", "amnesia", "blade",
- "bolt", "zot", "needle",
-};
-
static const char *trap_name(int x, int y)
{
if (!traps_inited)
@@ -211,7 +201,7 @@ static const char *trap_name(int x, int y)
{
int type = env.trap[ti].type;
if (type >= 0 && type < NUM_TRAPS)
- return (trap_names[type]);
+ return (trap_name(trap_type(type)));
}
return ("");
}
@@ -251,9 +241,9 @@ static bool is_exclude_root(int x, int y)
const char *run_mode_name(int runmode)
{
- return runmode == RUN_TRAVEL? "travel" :
- runmode == RUN_INTERLEVEL? "intertravel" :
- runmode == RUN_EXPLORE? "explore" :
+ return runmode == RMODE_TRAVEL? "travel" :
+ runmode == RMODE_INTERLEVEL? "intertravel" :
+ runmode == RMODE_EXPLORE? "explore" :
runmode > 0? "run" :
"";
}
@@ -387,7 +377,8 @@ static bool is_travel_ok(int x, int y, bool ignore_hostile)
// code paths through the secret door because it looks at the actual grid,
// rather than the env overmap. Hopefully there won't be any more such
// cases.
- if (envc == mapch2(DNGN_SECRET_DOOR)) return false;
+ // FIXME: is_terrain_changed ought to do this with the view.cc changes.
+ if (envc == get_sightmap_char(DNGN_SECRET_DOOR)) return false;
unsigned char mon = mgrd[x][y];
if (mon != NON_MONSTER)
@@ -400,7 +391,7 @@ static bool is_travel_ok(int x, int y, bool ignore_hostile)
// the information we're giving the player for free.
// Navigate around plants and fungi. Yet another tasty hack.
if (player_monster_visible(&menv[mon]) &&
- mons_flag( menv[mon].type, M_NO_EXP_GAIN ))
+ mons_class_flag( menv[mon].type, M_NO_EXP_GAIN ))
{
extern short point_distance[GXM][GYM];
@@ -442,12 +433,12 @@ static bool is_safe(int x, int y)
if (!player_monster_visible(&menv[mon]) ||
mons_is_mimic( menv[mon].type ))
{
- you.running = 0;
+ you.running.stop();
return true;
}
// Stop before wasting energy on plants and fungi.
- if (mons_flag( menv[mon].type, M_NO_EXP_GAIN ))
+ if (mons_class_flag( menv[mon].type, M_NO_EXP_GAIN ))
return false;
// If this is any *other* monster, it'll be visible and
@@ -506,9 +497,14 @@ static void init_terrain_check()
void travel_init_new_level()
{
+ // Clear run details, but preserve the runmode, because we might be in
+ // the middle of interlevel travel.
+ int runmode = you.running;
+ you.running.clear();
+ you.running = runmode;
+
// Zero out last travel coords
- you.run_x = you.run_y = 0;
- you.travel_x = you.travel_y = 0;
+ you.travel_x = you.travel_y = 0;
traps_inited = false;
curr_excludes.clear();
@@ -525,7 +521,6 @@ void initialise_travel()
traversable_terrain[DNGN_FLOOR] =
traversable_terrain[DNGN_ENTER_HELL] =
traversable_terrain[DNGN_OPEN_DOOR] =
- traversable_terrain[DNGN_BRANCH_STAIRS] =
traversable_terrain[DNGN_UNDISCOVERED_TRAP] =
traversable_terrain[DNGN_ENTER_SHOP] =
traversable_terrain[DNGN_ENTER_LABYRINTH] =
@@ -628,6 +623,16 @@ void prevent_travel_to(const std::string &feature)
traversable_terrain[feature_type] = FORBIDDEN;
}
+bool is_branch_stair(int gridx, int gridy)
+{
+ coord_def pos = { gridx, gridy };
+
+ const level_id curr = level_id::get_current_level_id();
+ const level_id next = level_id::get_next_level_id(pos);
+
+ return (next.branch != curr.branch);
+}
+
bool is_stair(unsigned gridc)
{
return (is_travelable_stair(gridc)
@@ -727,18 +732,27 @@ static void userdef_run_startrunning_hook(void)
#endif
}
-/*
- * Stops shift+running and all forms of travel.
- */
-void stop_running(void)
+bool is_resting( void )
{
- userdef_run_stoprunning_hook();
- you.running = 0;
+ return you.running.is_rest();
}
void start_running(void)
{
userdef_run_startrunning_hook();
+
+ if (you.running == RMODE_TRAVEL
+ || you.running == RMODE_EXPLORE
+ || you.running == RMODE_INTERLEVEL)
+ start_delay( DELAY_TRAVEL, 1 );
+}
+
+/*
+ * Stops shift+running and all forms of travel.
+ */
+void stop_running(void)
+{
+ you.running.stop();
}
/*
@@ -750,21 +764,23 @@ void start_running(void)
*
* Don't call travel() if you.running >= 0.
*/
-void travel(int *keyin, char *move_x, char *move_y)
+command_type travel()
{
- *keyin = 128;
+ char holdx, holdy;
+ char *move_x = &holdx;
+ char *move_y = &holdy;
+ holdx = holdy = 0;
+
+ command_type result = CMD_NO_CMD;
// Abort travel/explore if you're confused or a key was pressed.
if (kbhit() || you.conf)
{
stop_running();
- *keyin = 0;
- if (Options.travel_delay == -1)
- redraw_screen();
- return ;
+ return CMD_NO_CMD;
}
- if (Options.explore_stop && you.running == RUN_EXPLORE)
+ if (Options.explore_stop && you.running == RMODE_EXPLORE)
{
// Scan through the shadow map, compare it with the actual map, and if
// there are any squares of the shadow map that have just been
@@ -787,22 +803,22 @@ void travel(int *keyin, char *move_x, char *move_y)
copy(env.map, mapshadow);
}
- if (you.running == RUN_EXPLORE)
+ if (you.running == RMODE_EXPLORE)
{
// Exploring
- you.run_x = 0;
+ you.running.x = 0;
find_travel_pos(you.x_pos, you.y_pos, NULL, NULL);
// No place to go?
- if (!you.run_x)
+ if (!you.running.x)
stop_running();
}
- if (you.running == RUN_INTERLEVEL && !you.run_x)
+ if (you.running == RMODE_INTERLEVEL && !you.running.x)
{
- // Interlevel travel. Since you.run_x is zero, we've either just
+ // Interlevel travel. Since you.running.x is zero, we've either just
// initiated travel, or we've just climbed or descended a staircase,
// and we need to figure out where to travel to next.
- if (!find_transtravel_square(travel_target) || !you.run_x)
+ if (!find_transtravel_square(travel_target) || !you.running.x)
stop_running();
}
@@ -823,15 +839,15 @@ void travel(int *keyin, char *move_x, char *move_y)
// should continue doing so (explore has its own end condition
// upstairs); if we're traveling between levels and we've reached
// our travel target, we're on a staircase and should take it.
- if (you.x_pos == you.run_x && you.y_pos == you.run_y)
+ if (you.x_pos == you.running.x && you.y_pos == you.running.y)
{
- if (runmode == RUN_EXPLORE)
- you.running = RUN_EXPLORE; // Turn explore back on
+ if (runmode == RMODE_EXPLORE)
+ you.running = RMODE_EXPLORE; // Turn explore back on
// For interlevel travel, we'll want to take the stairs unless
// the interlevel travel specified a destination square and
// we've reached that destination square.
- else if (runmode == RUN_INTERLEVEL
+ else if (runmode == RMODE_INTERLEVEL
&& (travel_target.pos.x != you.x_pos
|| travel_target.pos.y != you.y_pos
|| travel_target.id !=
@@ -847,10 +863,10 @@ void travel(int *keyin, char *move_x, char *move_y)
// notify Lua hooks if you.running == 0.
you.running = runmode;
stop_running();
- return;
+ return CMD_NO_CMD;
}
- you.running = RUN_INTERLEVEL;
- *keyin = trans_negotiate_stairs();
+ you.running = RMODE_INTERLEVEL;
+ result = trans_negotiate_stairs();
// If, for some reason, we fail to use the stairs, we
// need to make sure we don't go into an infinite loop
@@ -860,11 +876,11 @@ void travel(int *keyin, char *move_x, char *move_y)
// This is important, else we'll probably stop traveling
// the moment we clear the stairs. That's because the
- // (run_x, run_y) destination will no longer be valid on
- // the new level. Setting run_x to zero forces us to
- // recalculate our travel target next turn (see previous
- // if block).
- you.run_x = you.run_y = 0;
+ // (running.x, running.y) destination will no longer be
+ // valid on the new level. Setting running.x to zero forces
+ // us to recalculate our travel target next turn (see
+ // previous if block).
+ you.running.x = you.running.y = 0;
}
else
{
@@ -884,6 +900,51 @@ void travel(int *keyin, char *move_x, char *move_y)
if (!you.running && Options.travel_delay == -1)
redraw_screen();
+
+ if (!you.running)
+ return CMD_NO_CMD;
+
+ if ( result != CMD_NO_CMD )
+ return result;
+
+ return direction_to_command( *move_x, *move_y );
+}
+
+command_type direction_to_command( char x, char y ) {
+ if ( x == -1 && y == -1 ) return CMD_MOVE_UP_LEFT;
+ if ( x == -1 && y == 0 ) return CMD_MOVE_LEFT;
+ if ( x == -1 && y == 1 ) return CMD_MOVE_DOWN_LEFT;
+ if ( x == 0 && y == -1 ) return CMD_MOVE_UP;
+ if ( x == 0 && y == 0 ) return CMD_NO_CMD;
+ if ( x == 0 && y == 1 ) return CMD_MOVE_DOWN;
+ if ( x == 1 && y == -1 ) return CMD_MOVE_UP_RIGHT;
+ if ( x == 1 && y == 0 ) return CMD_MOVE_RIGHT;
+ if ( x == 1 && y == 1 ) return CMD_MOVE_DOWN_RIGHT;
+
+ ASSERT(0);
+ return CMD_NO_CMD;
+}
+
+static void fill_exclude_radius(const coord_def &c)
+{
+ int radius = 0;
+ while (radius * radius < Options.travel_exclude_radius2)
+ radius++;
+
+ for (int y = c.y - radius; y <= c.y + radius; ++y)
+ {
+ 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])
+ continue;
+
+ if (is_exclude_root(x, y))
+ point_distance[x][y] = PD_EXCLUDED;
+ else if (is_excluded(x, y))
+ point_distance[x][y] = PD_EXCLUDED_RADIUS;
+ }
+ }
}
/*
@@ -896,7 +957,7 @@ void find_travel_pos(int youx, int youy,
{
init_terrain_check();
- int start_x = you.run_x, start_y = you.run_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;
@@ -922,14 +983,14 @@ void find_travel_pos(int youx, int youy,
if (dest_x != -1 && !is_travel_ok(start_x, start_y, false) &&
!is_trap(start_x, start_y))
{
- you.running = 0;
+ you.running = RMODE_NOT_RUNNING;
return ;
}
// Abort run if we're going nowhere.
if (start_x == dest_x && start_y == dest_y)
{
- you.running = 0;
+ you.running = RMODE_NOT_RUNNING;
return ;
}
@@ -1009,13 +1070,13 @@ void find_travel_pos(int youx, int youy,
unsigned char envf = env.map[dx - 1][dy - 1];
- if (floodout && you.running == RUN_EXPLORE
+ if (floodout && you.running == RMODE_EXPLORE
&& !is_player_mapped(envf))
{
- // Setting run_x and run_y here is evil - this function
- // should ideally not modify game state in any way.
- you.run_x = x;
- you.run_y = y;
+ // Setting running.x and running.y here is evil - this
+ // function should ideally not modify game state in any way.
+ you.running.x = x;
+ you.running.y = y;
return;
}
@@ -1115,6 +1176,20 @@ void find_travel_pos(int youx, int youy,
ignore_hostile = true;
}
} // for ( ; points > 0 ...
+
+ 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);
+
+ fill_exclude_radius(exc);
+ }
+ }
}
// Mappings of which branches spring from which other branches, essential to
@@ -1289,7 +1364,7 @@ static struct
{
{ "Dungeon", "the Main Dungeon", 'D' },
{ "Dis", "Dis", 'I' },
- { "Gehenna", "Gehenna", 'W' },
+ { "Gehenna", "Gehenna", 'N' },
{ "Hell", "Hell", 'U' },
{ "Cocytus", "Cocytus", 'X' },
{ "Tartarus", "Tartarus", 'Y' },
@@ -1459,14 +1534,14 @@ static std::vector<unsigned char> get_known_branches()
BRANCH_HALL_OF_ZOT
};
- std::vector<unsigned char> branches;
+ std::vector<unsigned char> result;
for (unsigned i = 0; i < sizeof list_order / sizeof(*list_order); ++i)
{
if (is_known_branch(list_order[i]))
- branches.push_back(list_order[i]);
+ result.push_back(list_order[i]);
}
- return branches;
+ return result;
}
static int prompt_travel_branch()
@@ -1580,7 +1655,7 @@ static int prompt_travel_depth(unsigned char branch)
mesclr();
mpr(buf, MSGCH_PROMPT);
- if (!cancelable_get_line( buf, sizeof buf ))
+ if (cancelable_get_line( buf, sizeof buf ))
return 0;
if (*buf)
@@ -1737,56 +1812,27 @@ void start_translevel_travel(bool prompt_for_destination)
if (travel_target.id.depth > -1)
{
- you.running = RUN_INTERLEVEL;
- you.run_x = you.run_y = 0;
+ you.running = RMODE_INTERLEVEL;
+ you.running.x = you.running.y = 0;
last_stair.depth = -1;
start_running();
}
}
-int stair_direction(int stair)
+command_type stair_direction(int stair)
{
return ((stair < DNGN_STONE_STAIRS_UP_I
|| stair > DNGN_ROCK_STAIRS_UP)
&& (stair < DNGN_RETURN_FROM_ORCISH_MINES
|| stair > DNGN_RETURN_FROM_SWAMP))
- ? '>' : '<';
+ ? CMD_GO_DOWNSTAIRS : CMD_GO_UPSTAIRS;
}
-int trans_negotiate_stairs()
+command_type trans_negotiate_stairs()
{
return stair_direction(grd[you.x_pos][you.y_pos]);
}
-int absdungeon_depth(unsigned char branch, int subdepth)
-{
- int realdepth = subdepth - 1;
-
- if (branch >= BRANCH_ORCISH_MINES && branch <= BRANCH_SWAMP)
- realdepth = subdepth + you.branch_stairs[branch - 10];
-
- if (branch >= BRANCH_DIS && branch <= BRANCH_THE_PIT)
- realdepth = subdepth + 26;
-
- return realdepth;
-}
-
-int subdungeon_depth(unsigned char branch, int depth)
-{
- int curr_subdungeon_level = depth + 1;
-
- // maybe last part better expresssed as <= PIT {dlb}
- if (branch >= BRANCH_DIS && branch <= BRANCH_THE_PIT)
- curr_subdungeon_level = depth - 26;
-
- /* Remember, must add this to the death_string in ouch */
- if (branch >= BRANCH_ORCISH_MINES && branch <= BRANCH_SWAMP)
- curr_subdungeon_level = depth
- - you.branch_stairs[branch - 10];
-
- return curr_subdungeon_level;
-}
-
static int target_distance_from(const coord_def &pos)
{
for (int i = 0, count = curr_stairs.size(); i < count; ++i)
@@ -1910,8 +1956,8 @@ static int find_transtravel_stair( const level_id &cur,
{
si.distance = dist2stair;
+ // Account for the cost of taking the stairs
dist2stair += Options.travel_stair_cost;
- ++dist2stair; // Account for the cost of taking the stairs
// Already too expensive? Short-circuit.
if (local_distance != -1 && dist2stair >= local_distance)
@@ -1935,7 +1981,8 @@ static int find_transtravel_stair( const level_id &cur,
continue;
}
- if (dest.id.depth > -1) { // We have a valid level descriptor.
+ if (dest.id.depth > -1) // We have a valid level descriptor.
+ {
int dist = level_distance(dest.id, target.id);
if (dist != -1 &&
(dist < best_level_distance ||
@@ -2042,8 +2089,8 @@ static int find_transtravel_square(const level_pos &target, bool verbose)
if (best_stair.x != -1 && best_stair.y != -1)
{
- you.run_x = best_stair.x;
- you.run_y = best_stair.y;
+ you.running.x = best_stair.x;
+ you.running.y = best_stair.y;
return 1;
}
else if (best_level_distance != -1 && closest_level != current
@@ -2067,9 +2114,9 @@ void start_travel(int x, int y)
if (x == you.x_pos && y == you.y_pos) return ;
// Start running
- you.running = RUN_TRAVEL;
- you.run_x = x;
- you.run_y = y;
+ you.running = RMODE_TRAVEL;
+ 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;
@@ -2079,7 +2126,7 @@ void start_travel(int x, int y)
find_travel_pos(you.x_pos, you.y_pos, NULL, NULL, NULL);
if (point_distance[x][y] == 0 &&
- (x != you.x_pos || you.run_y != you.y_pos) &&
+ (x != you.x_pos || you.running.y != you.y_pos) &&
is_travel_ok(x, y, false))
{
// We'll need interlevel travel to get here.
@@ -2087,8 +2134,8 @@ void start_travel(int x, int y)
travel_target.pos.x = x;
travel_target.pos.y = y;
- you.running = RUN_INTERLEVEL;
- you.run_x = you.run_y = 0;
+ you.running = RMODE_INTERLEVEL;
+ you.running.x = you.running.y = 0;
last_stair.depth = -1;
// We need the distance of the target from the various stairs around.
@@ -2103,7 +2150,7 @@ void start_travel(int x, int y)
void start_explore()
{
- you.running = RUN_EXPLORE;
+ you.running = RMODE_EXPLORE;
if (Options.explore_stop)
{
// Clone shadow array off map
@@ -2561,7 +2608,11 @@ void LevelInfo::get_stairs(std::vector<coord_def> &st)
unsigned char grid = grd[x + 1][y + 1];
unsigned char envc = (unsigned char) env.map[x][y];
- if (envc && is_travelable_stair(grid))
+ if ((x + 1 == you.x_pos && y + 1 == you.y_pos)
+ || (envc
+ && is_travelable_stair(grid)
+ && (is_terrain_seen(x + 1, y + 1)
+ || !is_branch_stair(x + 1, y + 1))))
{
// Convert to grid coords, because that's what we use
// everywhere else.
@@ -2636,7 +2687,6 @@ void LevelInfo::save(FILE *file) const
}
}
-#define EXCLUDE_LOAD_LIMIT 20
void LevelInfo::load(FILE *file)
{
stairs.clear();
@@ -2919,6 +2969,171 @@ void TravelCache::fixup_levels()
bool can_travel_interlevel()
{
- return !(you.level_type == LEVEL_LABYRINTH || you.level_type == LEVEL_ABYSS
- || you.level_type == LEVEL_PANDEMONIUM);
+ return (player_in_mappable_area() && you.level_type != LEVEL_PANDEMONIUM);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Shift-running and resting.
+
+runrest::runrest()
+ : runmode(0), mp(0), hp(0), x(0), y(0)
+{
+}
+
+// Initialize is only called for resting/shift-running. We should eventually
+// include travel and wrap it all in.
+void runrest::initialise(int dir, int mode)
+{
+ // Note HP and MP for reference.
+ hp = you.hp;
+ mp = you.magic_points;
+
+ if (dir == RDIR_REST)
+ {
+ x = 0;
+ y = 0;
+ runmode = mode;
+ }
+ else
+ {
+ ASSERT( dir >= 0 && dir <= 7 );
+
+ x = Compass[dir].x;
+ y = Compass[dir].y;
+ runmode = mode;
+
+ // Get the compass point to the left/right of intended travel:
+ const int left = (dir - 1 < 0) ? 7 : (dir - 1);
+ const int right = (dir + 1 > 7) ? 0 : (dir + 1);
+
+ // Record the direction and starting tile type for later reference:
+ set_run_check( 0, left );
+ set_run_check( 1, dir );
+ set_run_check( 2, right );
+ }
+
+ if (runmode == RMODE_REST_DURATION)
+ start_delay(DELAY_REST, 1);
+ else
+ start_delay(DELAY_RUN, 1);
+}
+
+runrest::operator int () const
+{
+ return (runmode);
+}
+
+const runrest &runrest::operator = (int newrunmode)
+{
+ runmode = newrunmode;
+ return (*this);
+}
+
+static char base_grid_type( char grid )
+{
+ // Don't stop for undiscovered traps:
+ if (grid == DNGN_UNDISCOVERED_TRAP)
+ return (DNGN_FLOOR);
+
+ // Or secret doors (which currently always look like rock walls):
+ if (grid == DNGN_SECRET_DOOR)
+ return (DNGN_ROCK_WALL);
+
+ return (grid);
+}
+
+void runrest::set_run_check(int index, int dir)
+{
+ run_check[index].dx = Compass[dir].x;
+ run_check[index].dy = Compass[dir].y;
+
+ const int targ_x = you.x_pos + Compass[dir].x;
+ const int targ_y = you.y_pos + Compass[dir].y;
+
+ run_check[index].grid = base_grid_type( grd[ targ_x ][ targ_y ] );
+}
+
+bool runrest::check_stop_running()
+{
+ if (runmode > 0 && runmode != RMODE_START && run_grids_changed())
+ {
+ stop();
+ return (true);
+ }
+ return (false);
+}
+
+// This function creates "equivalence classes" so that undiscovered
+// traps and secret doors aren't running stopping points.
+bool runrest::run_grids_changed() const
+{
+ if (env.cgrid[you.x_pos + x][you.y_pos + y] != EMPTY_CLOUD)
+ return (true);
+
+ if (mgrd[you.x_pos + x][you.y_pos + y] != NON_MONSTER)
+ return (true);
+
+ for (int i = 0; i < 3; i++)
+ {
+ const int targ_x = you.x_pos + run_check[i].dx;
+ const int targ_y = you.y_pos + run_check[i].dy;
+ const int targ_grid = base_grid_type( grd[ targ_x ][ targ_y ] );
+
+ if (run_check[i].grid != targ_grid)
+ return (true);
+ }
+
+ return (false);
+}
+
+void runrest::stop()
+{
+ bool need_redraw =
+ runmode > 0 || (runmode < 0 && Options.travel_delay == -1);
+ userdef_run_stoprunning_hook();
+ runmode = RMODE_NOT_RUNNING;
+
+ // Kill the delay; this is fine because it's not possible to stack
+ // run/rest/travel on top of other delays.
+ stop_delay();
+
+ if (need_redraw)
+ viewwindow(true, false);
+}
+
+bool runrest::is_rest() const
+{
+ return (runmode > 0 && !x && !y);
+}
+
+void runrest::rundown()
+{
+ rest();
+}
+
+void runrest::rest()
+{
+ // stop_running() Lua hooks will never see rest stops.
+ if (runmode > 0)
+ --runmode;
+}
+
+void runrest::clear()
+{
+ runmode = RMODE_NOT_RUNNING;
+ x = y = 0;
+ mp = hp = 0;
+}
+
+void runrest::check_hp()
+{
+ if (is_rest() && you.hp == you.hp_max && you.hp > hp)
+ stop();
+}
+
+void runrest::check_mp()
+{
+ if (is_rest() && you.magic_points == you.max_magic_points
+ && you.magic_points > mp)
+ stop();
}
diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h
index 30327bd46a..8c733b9af2 100644
--- a/crawl-ref/source/travel.h
+++ b/crawl-ref/source/travel.h
@@ -31,27 +31,14 @@ unsigned char is_waypoint(int x, int y);
void update_excludes();
bool is_stair(unsigned gridc);
bool is_travelable_stair(unsigned gridc);
-int stair_direction(int stair_feat);
+command_type stair_direction(int stair_feat);
bool is_player_mapped(unsigned char envch);
+command_type direction_to_command( char x, char y );
+bool is_resting( void );
+bool can_travel_interlevel();
-inline bool is_player_mapped(int grid_x, int grid_y)
-{
- return (is_player_mapped( env.map[grid_x - 1][grid_y - 1] ));
-}
+bool is_player_mapped(int grid_x, int grid_y);
-/* ***********************************************************************
- * Returns the direction to take to move along the shortest path between
- * (you_x, you_y) and (you.run_x, you.run_y) in (*move_x, *move_y).
- * If move_x or move_y is NULL, the function explores the map outwards from
- * (you_x, you_y), populating the coords vector with the coordinates
- * of every dungeon feature it finds, features closest to the character
- * (travel distance-wise) coming first in the vector. A 'feature' is defined
- * as a trap, and any other non-floor, non-water/lava square that the character
- * can step onto.
- *
- * ***********************************************************************
- * called from: acr - view
- * *********************************************************************** */
void find_travel_pos(int you_x, int you_y, char *move_x, char *move_y,
std::vector<coord_def>* coords = NULL);
@@ -72,16 +59,12 @@ void start_translevel_travel(bool prompt_for_destination = true);
void start_travel(int x, int y);
-void travel(int *keyin, char *move_x, char *move_y);
+command_type travel();
int travel_direction(unsigned char branch, int subdungeondepth);
void prevent_travel_to(const std::string &dungeon_feature_name);
-int subdungeon_depth(unsigned char branch, int depth);
-
-int absdungeon_depth(unsigned char branch, int subdepth);
-
// Sort dungeon features as appropriate.
void arrange_features(std::vector<coord_def> &features);
@@ -109,14 +92,6 @@ void arrange_features(std::vector<coord_def> &features);
* *********************************************************************** */
extern short point_distance[GXM][GYM];
-// Possible values of you.running
-enum RUN_MODES
-{
- RUN_TRAVEL = -1, // Classic or Plain Old travel
- RUN_EXPLORE = -2, // Exploring (Ctrl+O)
- RUN_INTERLEVEL = -3 // Interlevel travel (Ctrl+G)
-};
-
enum EXPLORE_STOP
{
ES_NONE = 0,
@@ -129,6 +104,8 @@ enum EXPLORE_STOP
////////////////////////////////////////////////////////////////////////////
// Structs for interlevel travel.
+// Identifies a level. This has no meaning in the Abyss, labyrinths or
+// Pandemonium.
struct level_id
{
unsigned char branch; // The branch in which the level is.
diff --git a/crawl-ref/source/unrand.h b/crawl-ref/source/unrand.h
index ae38b07de8..30bfa5a1be 100644
--- a/crawl-ref/source/unrand.h
+++ b/crawl-ref/source/unrand.h
@@ -3,6 +3,8 @@
* Summary: Definitions for unrandom artifacts.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
* <3> 7 Aug 2001 MV Added many new items
* <2> 5/09/99 JDJ Cekugob no longer has fire and cold
diff --git a/crawl-ref/source/util/levcomp.cc b/crawl-ref/source/util/levcomp.cc
new file mode 100644
index 0000000000..5e0bb4cb64
--- /dev/null
+++ b/crawl-ref/source/util/levcomp.cc
@@ -0,0 +1,18 @@
+#include "AppHdr.h"
+#include "levcomp.h"
+
+std::string lc_desfile;
+map_def lc_map;
+level_range lc_range;
+level_range lc_default_depth;
+
+extern int yylineno;
+
+void reset_map_parser()
+{
+ lc_map.init();
+ lc_range.reset();
+ lc_default_depth.reset();
+
+ yylineno = 1;
+}
diff --git a/crawl-ref/source/util/levcomp.h b/crawl-ref/source/util/levcomp.h
new file mode 100644
index 0000000000..99f0495f90
--- /dev/null
+++ b/crawl-ref/source/util/levcomp.h
@@ -0,0 +1,12 @@
+#include <cstdio>
+#include <string>
+#include <vector>
+#include "mapdef.h"
+#include "maps.h"
+
+extern map_def lc_map;
+extern level_range lc_range;
+extern level_range lc_default_depth;
+extern std::string lc_desfile;
+
+void reset_map_parser();
diff --git a/crawl-ref/source/util/levcomp.lpp b/crawl-ref/source/util/levcomp.lpp
new file mode 100644
index 0000000000..69ad33ee23
--- /dev/null
+++ b/crawl-ref/source/util/levcomp.lpp
@@ -0,0 +1,155 @@
+%{
+
+// levcomp.l:
+// Level compiler lexer for Dungeon Crawl Stone Soup.
+//
+// Based loosely on NetHack's lev_comp.l
+
+#include "AppHdr.h"
+#include "levcomp.tab.h"
+#include <cstring>
+
+static bool alloced = false;
+
+static void clean()
+{
+ if (yylval.text && alloced)
+ free( (void*) yylval.text);
+ yylval.text = NULL;
+ alloced = false;
+}
+
+static void settext()
+{
+ clean();
+ if ((yylval.text = strdup(yytext)))
+ alloced = true;
+}
+
+%}
+
+%s MAPDEF
+%s ARGUMENT
+%s MNAME
+%s KEYWORDS
+
+%option yylineno
+%option never-interactive
+
+NSPACE [^\ \t\r\n]
+
+%%
+
+<MAPDEF>^\s*ENDMAP { BEGIN(INITIAL); }
+
+<MAPDEF>^#.*\r?\n ;
+
+<MAPDEF>[a-zA-Z_&0-9|$+.@^#()\[\]=<>{}%*\-?]* {
+ settext();
+ return MAP_LINE;
+ }
+
+^\s*MAP { BEGIN(MAPDEF); }
+
+^\s*#.* ;
+
+NAME: { BEGIN(ARGUMENT); return NAME; }
+default-depth: return DEFAULT_DEPTH;
+DEPTH: return DEPTH;
+ORIENT: return ORIENT;
+PLACE: { BEGIN(ARGUMENT); return PLACE; }
+CHANCE: return CHANCE;
+FLAGS: return FLAGS;
+TAGS: { BEGIN(KEYWORDS); return TAGS; }
+SYMBOL: { BEGIN(ARGUMENT); return SYMBOL; }
+MONS: { BEGIN(MNAME); return MONS; }
+
+BRANCHDEF: return BRANCH;
+DEFAULT return DEFAULT;
+DESC: return DESC;
+BRANCH: return BRANCH;
+ROOT_DEPTH: return ROOT_DEPTH;
+FLOOR_COLOUR: return FLOOR_COLOUR;
+ROCK_COLOUR: return ROCK_COLOUR;
+
+LEVEL return LEVEL;
+END return END;
+PVAULT: return PVAULT;
+PMINIVAULT: return PMINIVAULT;
+
+ENTRY_MSG: { BEGIN(ARGUMENT); return ENTRY_MSG; }
+EXIT_MSG: { BEGIN(ARGUMENT); return EXIT_MSG; }
+
+MONSTERS return MONSTERS;
+ENDMONSTERS return ENDMONSTERS;
+
+<KEYWORDS>[A-Za-z_0-9\-]+ {
+ settext();
+ return STRING;
+ }
+
+<KEYWORDS>[ \t]+ ;
+<KEYWORDS>[ \t]*\r?\n { BEGIN(INITIAL); }
+
+<MNAME>[^, \t\r\n][^,\r\n]+[^, \t\r\n] {
+ settext();
+ return MONSTER_NAME;
+ }
+
+<MNAME>, return COMMA;
+<MNAME>[ \t]*\r?\n { BEGIN(INITIAL); }
+<MNAME>[ \t] ;
+
+pandemonic return PANDEMONIC;
+no_hmirror return NO_HMIRROR;
+no_vmirror return NO_VMIRROR;
+no_rotate return NO_ROTATE;
+
+encompass return ENCOMPASS;
+north return NORTH;
+south return SOUTH;
+east return EAST;
+west return WEST;
+northeast return NORTHEAST;
+northwest return NORTHWEST;
+southeast return SOUTHEAST;
+southwest return SOUTHWEST;
+
+- return DASH;
+, return COMMA;
+
+[0-9]+ {
+ clean();
+ yylval.i = atoi(yytext);
+ return INTEGER;
+ }
+
+<ARGUMENT>{NSPACE}.*{NSPACE} {
+ BEGIN(INITIAL);
+ settext();
+ return STRING;
+ }
+
+<ARGUMENT>\r?\n { BEGIN(INITIAL); }
+
+[\ \t\r\n]+ ;
+
+\( return OPAREN;
+\) return CPAREN;
+
+\" return QUOTE;
+
+[a-zA-Z_][a-zA-Z_0-9]+ {
+ settext();
+ return IDENTIFIER;
+ }
+
+. return CHARACTER;
+
+%%
+
+int yywrap()
+{
+ clean();
+ return 1;
+}
diff --git a/crawl-ref/source/util/levcomp.ypp b/crawl-ref/source/util/levcomp.ypp
new file mode 100644
index 0000000000..e419bdc878
--- /dev/null
+++ b/crawl-ref/source/util/levcomp.ypp
@@ -0,0 +1,226 @@
+%{
+
+#include "AppHdr.h"
+#include "libutil.h"
+#include "levcomp.h"
+
+int yylex();
+
+extern int yylineno;
+
+void yyerror(const char *e)
+{
+ fprintf(stderr, "%s:%d: %s\n", lc_desfile.c_str(), yylineno, e);
+ // Bail bail bail.
+ exit(1);
+}
+
+%}
+
+%union
+{
+ int i;
+ const char *text;
+}
+
+%token <i> BRANCHDEF BRANCH DESC DEFAULT
+%token <i> DEFAULT_DEPTH SYMBOL TAGS
+%token <i> NAME DEPTH ORIENT PLACE CHANCE FLAGS MONS
+%token <i> ROOT_DEPTH ENTRY_MSG EXIT_MSG
+%token <i> ROCK_COLOUR FLOOR_COLOUR
+%token <i> ENCOMPASS
+%token <i> NORTH EAST SOUTH WEST
+%token <i> NORTHEAST SOUTHEAST SOUTHWEST NORTHWEST
+
+%token <i> LEVEL END PVAULT PMINIVAULT MONSTERS ENDMONSTERS
+
+%token <i> CHARACTER
+
+%token <i> NO_HMIRROR NO_VMIRROR NO_ROTATE
+
+%token <i> PANDEMONIC
+%token <i> DASH COMMA QUOTE OPAREN CPAREN
+%token <i> INTEGER
+
+%type <i> orient_name flagname
+
+%token <text> STRING MAP_LINE MONSTER_NAME
+%token <text> IDENTIFIER
+
+%%
+
+file : definitions { }
+ ;
+
+definitions : /* empty */ {}
+ | definition definitions {}
+ ;
+
+definition : def {}
+ | level {}
+ ;
+
+def : defdepth
+ ;
+
+defdepth : DEFAULT_DEPTH depth_range
+ {
+ lc_default_depth = lc_range;
+ }
+ ;
+
+level : name metalines map_def metalines
+ {
+ add_parsed_map( lc_map );
+ }
+ ;
+
+name : NAME STRING
+ {
+ lc_map.init();
+ lc_map.depth = lc_default_depth;
+ lc_map.name = $2;
+ }
+ ;
+
+metalines : /* no metadata */
+ | metaline metalines
+ ;
+
+metaline : place
+ | depth
+ | chance
+ | orientation
+ | flags
+ | mons
+ | symbol
+ | tags
+ ;
+
+tags : TAGS tagstrings {}
+ ;
+
+tagstrings : /* empty */
+ | STRING tagstrings
+ {
+ lc_map.tags += " ";
+ lc_map.tags += $1;
+ lc_map.tags += " ";
+ }
+ ;
+
+symbol : SYMBOL {}
+ | SYMBOL STRING
+ {
+ lc_map.random_symbols = $2;
+ }
+ ;
+
+mons : MONS {}
+ | MONS mnames {}
+ ;
+
+mnames : mname COMMA mnames
+ | mname
+ ;
+
+mname : MONSTER_NAME
+ {
+ bool recognised = lc_map.mons.add_mons($1);
+ if (!recognised)
+ {
+ char buf[300];
+ snprintf(buf, sizeof buf, "unknown monster '%s'",
+ $1);
+ yyerror(buf);
+ }
+ }
+ ;
+
+place : PLACE STRING
+ {
+ lc_map.place = $2;
+ }
+ ;
+
+depth : DEPTH {}
+ | DEPTH depth_range
+ {
+ lc_map.depth = lc_range;
+ }
+ ;
+
+depth_range : INTEGER DASH INTEGER
+ {
+ lc_range.set($1, $3);
+ }
+
+ | INTEGER
+ {
+ lc_range.set($1);
+ }
+ ;
+
+chance : CHANCE INTEGER
+ {
+ lc_map.chance = $2;
+ }
+ ;
+
+orientation : ORIENT {}
+ | ORIENT orient_name
+ {
+ lc_map.orient = (map_section_type) $2;
+ }
+ ;
+
+orient_name : ENCOMPASS { $$ = MAP_ENCOMPASS; }
+ | NORTH { $$ = MAP_NORTH; }
+ | EAST { $$ = MAP_EAST; }
+ | SOUTH { $$ = MAP_SOUTH; }
+ | WEST { $$ = MAP_WEST; }
+ | NORTHEAST { $$ = MAP_NORTHEAST; }
+ | SOUTHEAST { $$ = MAP_SOUTHEAST; }
+ | SOUTHWEST { $$ = MAP_SOUTHWEST; }
+ | NORTHWEST { $$ = MAP_NORTHWEST; }
+ ;
+
+flags : FLAGS flagnames {}
+ ;
+
+flagnames : /* empty */
+ | flagname flagnames
+ {
+ switch ($1) {
+ case NO_HMIRROR:
+ lc_map.flags &= ~MAPF_MIRROR_HORIZONTAL;
+ break;
+ case NO_VMIRROR:
+ lc_map.flags &= ~MAPF_MIRROR_VERTICAL;
+ break;
+ case NO_ROTATE:
+ lc_map.flags &= ~MAPF_ROTATE;
+ break;
+ }
+ }
+ ;
+
+flagname : NO_HMIRROR { $$ = NO_HMIRROR; }
+ | NO_VMIRROR { $$ = NO_VMIRROR; }
+ | NO_ROTATE { $$ = NO_ROTATE; }
+ ;
+
+map_def : map_lines
+ ;
+
+map_lines : map_line
+ | map_line map_lines
+ ;
+
+map_line : MAP_LINE
+ {
+ lc_map.map.add_line($1);
+ }
+ ;
+
+%%
diff --git a/crawl-ref/source/version.h b/crawl-ref/source/version.h
index 583e965a6c..ce898d6603 100644
--- a/crawl-ref/source/version.h
+++ b/crawl-ref/source/version.h
@@ -3,6 +3,8 @@
* Summary: Contains version information
* Written by: ??
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <2> 10/12/99 BCR Added BUILD_DATE #define
@@ -33,13 +35,13 @@
#ifndef VERSION_H
#define VERSION_H
+#define CRAWL "Dungeon Crawl Stone Soup"
// last updated 07august2001 {mv}
/* ***********************************************************************
* called from: chardump - command - newgame
* *********************************************************************** */
-#define VERSION "4.0.0 beta 26 (crawl-ref)"
-
+#define VERSION "0.2-svn (crawl-ref)"
// last updated 20feb2001 {GDL}
/* ***********************************************************************
@@ -47,5 +49,6 @@
* *********************************************************************** */
#define BUILD_DATE __DATE__
+#define SAVE_MAJOR_VERSION 0
#endif
diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc
index adfb1a62bd..fdbe60d9f3 100644
--- a/crawl-ref/source/view.cc
+++ b/crawl-ref/source/view.cc
@@ -34,10 +34,16 @@
#include "externs.h"
+#include "command.h"
#include "clua.h"
#include "debug.h"
+#include "delay.h"
+#include "direct.h"
+#include "initfile.h"
#include "insult.h"
+#include "itemprop.h"
#include "macro.h"
+#include "misc.h"
#include "monstuff.h"
#include "mon-util.h"
#include "overmap.h"
@@ -48,37 +54,61 @@
#include "stash.h"
#include "travel.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 0x0100
+#define MAP_SEEN_FLAG 0x0200
+#define MAP_CHANGED_FLAG 0x0400
+#define MAP_DETECTED_MONSTER 0x0800
+#define MAP_DETECTED_ITEM 0x1000
+
+#define MAP_CHARACTER_MASK 0x00ff
+
+struct feature_def
+{
+ unsigned short symbol; // symbol used for seen terrain
+ unsigned short magic_symbol; // symbol used for magic-mapped terrain
+ unsigned short colour; // normal in LoS colour
+ unsigned short map_colour; // colour when out of LoS on display
+ unsigned short seen_colour; // map_colour when is_terrain_seen()
+ bool notable; // gets noted when seen
+ bool seen_effect; // requires special handling when seen
+};
+
+struct feature_override
+{
+ dungeon_feature_type feat;
+ feature_def override;
+};
+
+static FixedVector< struct feature_def, NUM_FEATURES > Feature;
+static std::vector<feature_override> Feature_Overrides;
+
#if defined(DOS_TERM)
-typedef char screen_buffer_t;
+// 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
-unsigned char your_sign; // accessed as extern in transfor.cc and acr.cc
-unsigned char your_colour; // accessed as extern in transfor.cc and acr.cc
-
-FixedArray < unsigned int, 20, 19 > show_backup;
+FixedArray < unsigned int, 20, 19 > Show_Backup;
unsigned char show_green;
extern int stealth; // defined in acr.cc
-extern FixedVector<char, 10> Visible_Statue; // defined in acr.cc
// char colour_code_map(unsigned char map_value);
screen_buffer_t colour_code_map( int x, int y, bool item_colour = false,
bool travel_colour = false );
-extern void (*viewwindow) (char, bool);
-unsigned char (*mapch) (unsigned char);
-unsigned char (*mapch2) (unsigned char);
-unsigned char mapchar(unsigned char ldfk);
-unsigned char mapchar2(unsigned char ldfk);
-unsigned char mapchar3(unsigned char ldfk);
-unsigned char mapchar4(unsigned char ldfk);
void cloud_grid(void);
void monster_grid(bool do_updates);
-static int display_glyph(int env_glyph);
-static int item_env_glyph(const item_def &item);
+static int get_item_dngn_code(const item_def &item);
+static void set_show_backup( int ex, int ey );
+
+// Applies EC_ colour substitutions and brands.
+static unsigned fix_colour(unsigned raw_colour);
//---------------------------------------------------------------
//
@@ -105,710 +135,209 @@ int get_number_of_lines(void)
{
#ifdef UNIX
return (get_number_of_lines_from_curses());
-#elif MAC
- return (MAC_NUMBER_OF_LINES);
#else
return (25);
#endif
}
-
-//---------------------------------------------------------------
-//
-// get_ibm_symbol
-//
-// Returns the DOS character code and color for everything drawn
-// with the IBM graphics option.
-//
-//---------------------------------------------------------------
-static void get_ibm_symbol(unsigned int object, unsigned short *ch,
- unsigned short *color)
+int get_number_of_cols(void)
{
- ASSERT(color != NULL);
- ASSERT(ch != NULL);
-
- switch (object)
- {
- case DNGN_UNSEEN:
- *ch = 0;
- break;
-
- case DNGN_ROCK_WALL:
- case DNGN_PERMAROCK_WALL:
- *color = env.rock_colour;
- *ch = 177;
- break; // remember earth elementals
-
- // stone in the realm of Zot is coloured the same as rock
- case DNGN_STONE_WALL:
- *color = (player_in_branch( BRANCH_HALL_OF_ZOT ) ? env.rock_colour
- : LIGHTGREY);
- *ch = 177;
- break;
-
- case DNGN_CLOSED_DOOR:
- *ch = 254;
- break;
-
- case DNGN_METAL_WALL:
- *ch = 177;
- *color = CYAN;
- break;
-
- case DNGN_SECRET_DOOR:
- *ch = 177;
- *color = env.rock_colour;
- break;
-
- case DNGN_GREEN_CRYSTAL_WALL:
- *ch = 177;
- *color = GREEN;
- break;
-
- case DNGN_ORCISH_IDOL:
- *ch = '8';
- *color = DARKGREY;
- break;
-
- case DNGN_WAX_WALL:
- *ch = 177;
- *color = YELLOW;
- break; // wax wall
- /* Anything added here must also be added to the PLAIN_TERMINAL
- viewwindow2 below */
-
- case DNGN_SILVER_STATUE:
- *ch = '8';
- *color = WHITE;
- Visible_Statue[ STATUE_SILVER ] = 1;
- break;
-
- case DNGN_GRANITE_STATUE:
- *ch = '8';
- *color = LIGHTGREY;
- break;
-
- case DNGN_ORANGE_CRYSTAL_STATUE:
- *ch = '8';
- *color = LIGHTRED;
- Visible_Statue[ STATUE_ORANGE_CRYSTAL ] = 1;
- break;
-
- case DNGN_LAVA:
- *ch = 247;
- *color = RED;
- break;
-
- case DNGN_DEEP_WATER:
- *ch = 247; // this wavy thing also used for water elemental
- *color = BLUE;
- break;
-
- case DNGN_SHALLOW_WATER:
- *ch = 247; // this wavy thing also used for water elemental
- *color = CYAN;
- break;
-
- case DNGN_FLOOR:
- *color = env.floor_colour;
- *ch = 249;
- break;
-
- case DNGN_ENTER_HELL:
- *ch = 239;
- *color = RED;
- seen_other_thing(object);
- break;
-
- case DNGN_OPEN_DOOR:
- *ch = 39;
- break;
-
- case DNGN_BRANCH_STAIRS:
- *ch = 240;
- *color = BROWN;
- break;
-
- case DNGN_TRAP_MECHANICAL:
- *color = LIGHTCYAN;
- *ch = 94;
- break;
-
- case DNGN_TRAP_MAGICAL:
- *color = MAGENTA;
- *ch = 94;
- break;
-
- case DNGN_TRAP_III:
- *color = LIGHTGREY;
- *ch = 94;
- break;
-
- case DNGN_UNDISCOVERED_TRAP:
- *ch = 249;
- *color = env.floor_colour;
- break;
-
- case DNGN_ENTER_SHOP:
- *ch = 239;
- *color = YELLOW;
-
- seen_other_thing(object);
- break;
- // if I change anything above here, must also change magic mapping!
-
- case DNGN_ENTER_LABYRINTH:
- *ch = 239;
- *color = LIGHTGREY;
- seen_other_thing(object);
- break;
-
- // not sure why we have "odd" here, but "ladders" are special in
- // that they all lead to the first staircase of the next level
- // (and returning from there will take you somewhere different)
- // ... that's why they're brown... it's a warning -- bwr
- case DNGN_ROCK_STAIRS_DOWN:
- *color = BROWN; // ladder // odd {dlb}
- case DNGN_STONE_STAIRS_DOWN_I:
- case DNGN_STONE_STAIRS_DOWN_II:
- case DNGN_STONE_STAIRS_DOWN_III:
- *ch = '>';
- break;
-
- case DNGN_ROCK_STAIRS_UP:
- *color = BROWN; // ladder // odd {dlb}
- case DNGN_STONE_STAIRS_UP_I:
- case DNGN_STONE_STAIRS_UP_II:
- case DNGN_STONE_STAIRS_UP_III:
- *ch = '<';
- break;
-
- case DNGN_ENTER_DIS:
- *color = CYAN;
- *ch = 239;
- break;
-
- case DNGN_ENTER_GEHENNA:
- *color = RED;
- *ch = 239;
- break;
-
- case DNGN_ENTER_COCYTUS:
- *color = LIGHTCYAN;
- *ch = 239;
- break;
-
- case DNGN_ENTER_TARTARUS:
- *color = DARKGREY;
- *ch = 239;
- break;
-
- case DNGN_ENTER_ABYSS:
- *color = random2(16);
- *ch = 239;
- seen_other_thing(object);
- break;
-
- case DNGN_EXIT_ABYSS:
- *color = random2(16);
- *ch = 239;
- break;
-
- case DNGN_STONE_ARCH:
- *color = LIGHTGREY;
- *ch = 239;
- break;
-
- case DNGN_ENTER_PANDEMONIUM:
- *color = LIGHTBLUE;
- *ch = 239;
- seen_other_thing(object);
- break;
-
- case DNGN_EXIT_PANDEMONIUM:
- *color = LIGHTBLUE;
- *ch = 239;
- break;
-
- case DNGN_TRANSIT_PANDEMONIUM:
- *color = LIGHTGREEN;
- *ch = 239;
- break;
-
- 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 123:
- case 124:
- case 125:
- case 126:
- *color = YELLOW;
- *ch = '>';
- seen_staircase(object);
- break;
-
- case DNGN_ENTER_ZOT:
- *color = MAGENTA;
- *ch = 239;
- seen_staircase(object);
- break;
-
- 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 143:
- case 144:
- case 145:
- case 146:
- *color = YELLOW;
- *ch = '<';
- break;
-
- case DNGN_RETURN_FROM_ZOT:
- *color = MAGENTA;
- *ch = 239;
- break;
-
- case DNGN_ALTAR_ZIN:
- *color = WHITE;
- *ch = 220;
- seen_altar(GOD_ZIN);
- break;
-
- case DNGN_ALTAR_SHINING_ONE:
- *color = YELLOW;
- *ch = 220;
- seen_altar(GOD_SHINING_ONE);
- break;
-
- case DNGN_ALTAR_KIKUBAAQUDGHA:
- *color = DARKGREY;
- *ch = 220;
- seen_altar(GOD_KIKUBAAQUDGHA);
- break;
-
- case DNGN_ALTAR_YREDELEMNUL:
- *color = ((one_chance_in(3)) ? RED : DARKGREY);
- *ch = 220;
- seen_altar(GOD_YREDELEMNUL);
- break;
-
- case DNGN_ALTAR_XOM:
- *color = random_colour();
- *ch = 220;
- seen_altar(GOD_XOM);
- break;
-
- case DNGN_ALTAR_VEHUMET:
- *color = LIGHTBLUE;
- if (one_chance_in(3))
- *color = LIGHTMAGENTA;
- if (one_chance_in(3))
- *color = LIGHTRED;
- *ch = 220;
- seen_altar(GOD_VEHUMET);
- break;
-
- case DNGN_ALTAR_OKAWARU:
- *color = CYAN;
- *ch = 220;
- seen_altar(GOD_OKAWARU);
- break;
-
- case DNGN_ALTAR_MAKHLEB:
- *color = RED;
- if (one_chance_in(3))
- *color = LIGHTRED;
- if (one_chance_in(3))
- *color = YELLOW;
- *ch = 220;
- seen_altar(GOD_MAKHLEB);
- break;
-
- case DNGN_ALTAR_SIF_MUNA:
- *color = BLUE;
- *ch = 220;
- seen_altar(GOD_SIF_MUNA);
- break;
-
- case DNGN_ALTAR_TROG:
- *color = RED;
- *ch = 220;
- seen_altar(GOD_TROG);
- break;
-
- case DNGN_ALTAR_NEMELEX_XOBEH:
- *color = LIGHTMAGENTA;
- *ch = 220;
- seen_altar(GOD_NEMELEX_XOBEH);
- break;
-
- case DNGN_ALTAR_ELYVILON:
- *color = LIGHTGREY;
- *ch = 220;
- seen_altar(GOD_ELYVILON);
- break;
-
- case DNGN_BLUE_FOUNTAIN:
- *color = BLUE;
- *ch = 159;
- break;
-
- case DNGN_SPARKLING_FOUNTAIN:
- *color = LIGHTBLUE;
- *ch = 159;
- break;
-
- case DNGN_DRY_FOUNTAIN_I:
- case DNGN_DRY_FOUNTAIN_II:
- case DNGN_PERMADRY_FOUNTAIN:
- *color = LIGHTGREY;
- *ch = 159;
- break;
-
- case 256:
- *ch = '0';
- break;
-
- case 257:
- *color = CYAN;
- *ch = '~';
- break; /* Invis creature walking through water */
-
- case 258:
- *ch = ')';
- break; // weapon )
-
- case 259:
- *ch = '[';
- break; // armour [
-
- case 260:
- *ch = '/';
- break; // wands, etc.
-
- case 261:
- *ch = '%';
- break; // food
-
- case 262:
- *ch = '+';
- break; // books +
-
- case 263:
- *ch = '?';
- break; // scroll ?
-
- case 264:
- *ch = '=';
- break; // ring = etc
-
- case 265:
- *ch = '!';
- break; // potions !
+#ifdef UNIX
+ return (get_number_of_cols_from_curses());
+#else
+ return (80);
+#endif
+}
- case 266:
- *ch = '(';
- break; // stones
+unsigned get_envmap_char(int x, int y)
+{
+ return static_cast<unsigned char>(
+ env.map[x - 1][y - 1] & MAP_CHARACTER_MASK);
+}
- case 267:
- *ch = '+';
- break; // book +
+void set_envmap_detected_item(int x, int y, bool detected)
+{
+ if (detected)
+ env.map[x - 1][y - 1] |= MAP_DETECTED_ITEM;
+ else
+ env.map[x - 1][y - 1] &= ~MAP_DETECTED_ITEM;
+}
- case 268:
- *ch = '%';
- break; // corpses part 1
+bool is_envmap_detected_item(int x, int y)
+{
+ return (env.map[x - 1][y - 1] & MAP_DETECTED_ITEM);
+}
- case 269:
- *ch = '\\';
- break; // magical staves
+void set_envmap_detected_mons(int x, int y, bool detected)
+{
+ if (detected)
+ env.map[x - 1][y - 1] |= MAP_DETECTED_MONSTER;
+ else
+ env.map[x - 1][y - 1] &= ~MAP_DETECTED_MONSTER;
+}
- case 270:
- *ch = '}';
- break; // gems
+bool is_envmap_detected_mons(int x, int y)
+{
+ return (env.map[x - 1][y - 1] & MAP_DETECTED_MONSTER);
+}
- case 271:
- *ch = '%';
- break; // don't know ?
+void set_envmap_char( int x, int y, unsigned char chr )
+{
+ env.map[x - 1][y - 1] &= (~MAP_CHARACTER_MASK); // clear old first
+ env.map[x - 1][y - 1] |= chr;
+}
- case 272:
- *ch = '$';
- *color = YELLOW;
- break; // $ gold
+bool is_terrain_known( int x, int y )
+{
+ return (env.map[x - 1][y - 1] & (MAP_MAGIC_MAPPED_FLAG | MAP_SEEN_FLAG));
+}
- case 273:
- *ch = '"';
- break; // amulet
+bool is_terrain_seen( int x, int y )
+{
+ return (env.map[x - 1][y - 1] & MAP_SEEN_FLAG);
+}
- default:
- *ch = ((object >= 297) ? mons_char(object - 297) : object);
- break;
- }
-} // end get_ibm_symbol()
+bool is_terrain_changed( int x, int y )
+{
+ return (env.map[x - 1][y - 1] & MAP_CHANGED_FLAG);
+}
-//---------------------------------------------------------------
-//
-// viewwindow2
-//
-// Draws the main window using the extended IBM character set.
-//
-// This function should not interfer with the game condition,
-// unless do_updates is set (ie. stealth checks for visible
-// monsters).
-//
-//---------------------------------------------------------------
-void viewwindow2(char draw_it, bool do_updates)
+// used to mark dug out areas, unset when terrain is seen or mapped again.
+void set_terrain_changed( int x, int y )
{
- const long BUFFER_SIZE = 1550;
-#ifdef DOS_TERM
- // DOS functions like gettext() and puttext() can only
- // work with arrays of characters, not shorts.
- FixedVector < unsigned char, BUFFER_SIZE > buffy; //[800]; //392];
-#else
- FixedVector < unsigned short, BUFFER_SIZE > buffy; //[800]; //392];
-#endif
+ env.map[x - 1][y - 1] |= MAP_CHANGED_FLAG;
+}
- unsigned short ch, color;
+void set_terrain_mapped( int x, int y )
+{
+ env.map[x - 1][y - 1] &= (~MAP_CHANGED_FLAG);
+ env.map[x - 1][y - 1] |= MAP_MAGIC_MAPPED_FLAG;
+}
- losight(env.show, grd, you.x_pos, you.y_pos);
+void set_terrain_seen( int x, int y )
+{
+ env.map[x - 1][y - 1] &= (~MAP_CHANGED_FLAG);
+ env.map[x - 1][y - 1] |= MAP_SEEN_FLAG;
+}
- int count_x, count_y;
+void clear_envmap_grid( int x, int y )
+{
+ env.map[x - 1][y - 1] = 0;
+}
- for (count_x = 0; count_x < 18; count_x++)
+void clear_envmap( void )
+{
+ for (int i = 0; i < GXM; i++)
{
- for (count_y = 0; count_y < 18; count_y++)
+ for (int j = 0; j < GYM; j++)
{
- env.show_col[count_x][count_y] = LIGHTGREY;
- show_backup[count_x][count_y] = 0;
+ env.map[i][j] = 0;
}
}
+}
- item();
- cloud_grid();
- monster_grid(do_updates);
- int bufcount = 0;
-
- if (draw_it == 1)
+#if defined(WIN32CONSOLE) || defined(DOS) || defined(DOS_TERM)
+static unsigned colflag2brand(int colflag)
+{
+ switch (colflag)
{
- _setcursortype(_NOCURSOR);
- for (count_y = you.y_pos - 8; count_y < you.y_pos + 9; count_y++)
- {
- bufcount += 16;
-
- for (count_x = you.x_pos - 8; count_x < you.x_pos + 9; count_x++)
- {
- // may be overriden by the code below
- color = env.show_col[ count_x - you.x_pos + 9 ]
- [ count_y - you.y_pos + 9 ];
-
- unsigned int object = env.show[ count_x - you.x_pos + 9 ]
- [ count_y - you.y_pos + 9 ];
-
- get_ibm_symbol(object, &ch, &color);
-
- if (count_x == you.x_pos && count_y == you.y_pos)
- {
- ch = your_sign;
-
- if (player_is_swimming())
- {
- color = (grd[you.x_pos][you.y_pos] == DNGN_DEEP_WATER)
- ? BLUE : CYAN;
- }
- else
- {
- color = your_colour;
- }
- }
-
- ASSERT(bufcount + 1 < BUFFER_SIZE);
- buffy[bufcount] = ch;
- buffy[bufcount + 1] = color;
-
- bufcount += 2;
- }
-
- bufcount += 16;
- }
-
- if (you.level_type != LEVEL_LABYRINTH && you.level_type != LEVEL_ABYSS)
- {
- bufcount = 0;
-
- for (count_y = 0; count_y < 17; count_y++)
- {
- bufcount += 16;
-
- for (count_x = 0; count_x < 17; count_x++)
- {
- ASSERT(bufcount < BUFFER_SIZE);
+ case COLFLAG_ITEM_HEAP:
+ return (Options.heap_brand);
+ case COLFLAG_FRIENDLY_MONSTER:
+ return (Options.friend_brand);
+ case COLFLAG_WILLSTAB:
+ return (Options.stab_brand);
+ case COLFLAG_MAYSTAB:
+ return (Options.may_stab_brand);
+ default:
+ return (CHATTR_NORMAL);
+ }
+}
+#endif
- int mapx = count_x + you.x_pos - 9;
- int mapy = count_y + you.y_pos - 9;
- if (buffy[bufcount] != 0 && mapx >= 0 && mapx + 1 < GXM
- && mapy >= 0 && mapy + 1 < GYM)
- {
- unsigned short bch = buffy[bufcount];
- if (mgrd[mapx + 1][mapy + 1] != NON_MONSTER) {
- const monsters &m = menv[mgrd[mapx + 1][mapy + 1]];
- if (!mons_is_mimic(m.type)
- && mons_char(m.type) == bch)
- {
- bch |= mons_colour(m.type) << 12;
- }
- }
- env.map[mapx][mapy] = bch;
- }
+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)
+ const int colflags = raw_colour & 0xFF00;
+#endif
- if (Options.clean_map == 1
- && show_backup[count_x + 1][count_y + 1] != 0)
- {
- get_ibm_symbol(show_backup[count_x + 1][count_y + 1],
- &ch, &color);
- if (mapx >= 0 && mapx < GXM
- && mapy >= 0 && mapy < GYM)
- env.map[ count_x + you.x_pos - 9 ]
- [ count_y + you.y_pos - 9 ] = ch;
- }
- bufcount += 2;
- }
- bufcount += 16;
- }
- }
+ // Evaluate any elemental colours to guarantee vanilla colour is returned
+ if (is_element_colour( raw_colour ))
+ raw_colour = element_colour( raw_colour );
- bufcount = 0;
- for (count_y = 0; count_y < 17; count_y++)
- {
- for (count_x = 0; count_x < 33; count_x++)
- {
- if (count_x + you.x_pos - 17 < 3
- || count_y + you.y_pos - 9 < 3
- || count_x + you.x_pos - 14 > 77
- || count_y + you.y_pos - 9 > 67)
- {
- ASSERT(bufcount < BUFFER_SIZE);
- buffy[bufcount] = 0;
- bufcount++;
- buffy[bufcount] = 0;
- bufcount++;
- continue;
- }
+#if defined(WIN32CONSOLE) || defined(DOS) || defined(DOS_TERM)
+ if (colflags)
+ {
+ unsigned brand = colflag2brand(colflags);
+ raw_colour = dos_brand(raw_colour & 0xFF, brand);
+ }
+#endif
- if (count_x >= 8 && count_x <= 24 && count_y >= 0
- && count_y <= 16 && buffy[bufcount] != 0)
- {
- bufcount += 2;
- continue;
- }
+#ifndef USE_COLOUR_OPTS
+ // Strip COLFLAGs for systems that can't do anything meaningful with them.
+ raw_colour &= 0xFF;
+#endif
- ASSERT(bufcount + 1 < BUFFER_SIZE);
+ return (raw_colour);
+}
- buffy[bufcount] = (unsigned char)
- env.map[ count_x + you.x_pos - 17 ]
- [ count_y + you.y_pos - 9 ];
+static void get_symbol( unsigned int object, unsigned short *ch,
+ unsigned short *colour )
+{
+ ASSERT( ch != NULL );
+ ASSERT( colour != NULL );
- buffy[bufcount + 1] = DARKGREY;
- if (Options.colour_map)
- {
- if (env.map[ count_x + you.x_pos - 17 ]
- [ count_y + you.y_pos - 9 ] != 0)
- {
- buffy[bufcount + 1]
- = colour_code_map( count_x + you.x_pos - 17,
- count_y + you.y_pos - 9,
- Options.item_colour );
- }
- }
- bufcount += 2;
- }
- }
+ if (object < NUM_FEATURES)
+ {
+ *ch = Feature[object].symbol;
- if (you.berserker)
- {
- for (count_x = 1; count_x < 1400; count_x += 2)
- {
- if (buffy[count_x] != DARKGREY)
- buffy[count_x] = RED;
- }
- }
+ // Don't clobber with BLACK, because the colour should be already set.
+ if (Feature[object].colour != BLACK)
+ *colour = Feature[object].colour;
- if (show_green != BLACK)
- {
- for (count_x = 1; count_x < 1400; count_x += 2)
- {
- if (buffy[count_x] != DARKGREY)
- buffy[count_x] = show_green;
- }
+ // Note anything we see that's notable
+ if (Feature[object].notable)
+ seen_notable_thing( object );
+ }
+ else
+ {
+ ASSERT( object >= DNGN_START_OF_MONSTERS );
+ *ch = mons_char( object - DNGN_START_OF_MONSTERS );
+ }
- show_green = BLACK;
+ *colour = fix_colour(*colour);
+}
- if (you.special_wield == SPWLD_SHADOW)
- show_green = DARKGREY;
- }
+unsigned char get_sightmap_char( int feature )
+{
+ if (feature < NUM_FEATURES)
+ return (Feature[feature].symbol);
-#ifdef DOS_TERM
- puttext(2, 1, 34, 17, buffy.buffer());
-#endif
+ return (0);
+}
-#ifdef PLAIN_TERM
- gotoxy(2, 1);
- bufcount = 0;
+unsigned char get_magicmap_char( int feature )
+{
+ if (feature < NUM_FEATURES)
+ return (Feature[feature].magic_symbol);
- // following lines are purely optional.
- // if used, players will 'jump' move.
- // Resting will be a LOT faster too.
- if (you.running == 0 || (you.running < 0 && Options.travel_delay > -1))
- {
- for (count_x = 0; count_x < 1120; count_x += 2)
- { // 1056
- ch = buffy[count_x];
- color = buffy[count_x + 1];
-// ASSERT(color < 16);
- ASSERT(ch < 255);
-
- textcolor(color);
- putch(ch);
-
- if (count_x % 66 == 64 && count_x > 0)
- gotoxy(2, wherey() + 1);
- }
- // remember to comment out the line below if you comment out jump move.
- }
- _setcursortype(_NORMALCURSOR);
-#endif
- }
-} // end viewwindow2()
+ return (0);
+}
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];
- return dist > 0 ? BLUE :
- dist == PD_EXCLUDED ? LIGHTMAGENTA :
- dist == PD_EXCLUDED_RADIUS ? RED :
- dist < 0 ? CYAN :
- DARKGREY;
+ short dist = 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 :
+ dist < 0? Options.tc_dangerous :
+ Options.tc_disconnected;
}
#if defined(WIN32CONSOLE) || defined(DOS)
@@ -819,9 +348,7 @@ static unsigned short dos_reverse_brand(unsigned short colour)
// If the console treats the intensity bit on background colours
// correctly, we can do a very simple colour invert.
- // Special casery for shadows. Note this must be matched by the fix
- // to libw32c.cc (the unpatched libw32c.cc does not draw spaces of any
- // colour).
+ // Special casery for shadows.
if (colour == BLACK)
colour = (DARKGREY << 4);
else
@@ -874,8 +401,8 @@ static unsigned short dos_hilite_brand(unsigned short colour,
return (colour);
}
-static unsigned short dos_brand( unsigned short colour,
- unsigned brand = CHATTR_REVERSE )
+unsigned short dos_brand( unsigned short colour,
+ unsigned brand)
{
if ((brand & CHATTR_ATTRMASK) == CHATTR_NORMAL)
return (colour);
@@ -890,199 +417,98 @@ static unsigned short dos_brand( unsigned short 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( int x, int y, bool item_colour,
bool travel_colour )
{
// XXX: Yes, the map array and the grid array are off by one. -- bwr
const int map_value = (unsigned char) env.map[x][y];
- const unsigned short map_flags = env.map[x][y] & ENVF_FLAGS;
+ const unsigned short map_flags = env.map[x][y];
const int grid_value = grd[x + 1][y + 1];
- char tc = travel_colour? get_travel_colour(x, y) : DARKGREY;
+ unsigned tc = travel_colour?
+ get_travel_colour(x, y)
+ : DARKGREY;
- if (map_flags & ENVF_DETECT_ITEM)
+ if (map_flags & MAP_DETECTED_ITEM)
tc = Options.detected_item_colour;
- if (map_flags & ENVF_DETECT_MONS) {
+ if (map_flags & MAP_DETECTED_MONSTER)
+ {
tc = Options.detected_monster_colour;
- return (tc);
+ return fix_colour(tc);
}
- unsigned char ecol = ENVF_COLOR(map_flags);
- if (ecol) {
- unsigned rmc = Options.remembered_monster_colour & 0xFFFF;
- if (rmc == 0xFFFF) // Use real colour
- tc = ecol;
- else if (rmc == 0) // Don't colour
- ;
- else
- tc = rmc;
- }
-
// XXX: [ds] If we've an important colour, override other feature
// colouring. Yes, this is hacky. Story of my life.
if (tc == LIGHTGREEN || tc == LIGHTMAGENTA)
- return tc;
+ return fix_colour(tc);
// XXX: Yeah, this is ugly, but until we have stored layers in the
// map we can't tell if we've seen a square, detected it, or just
// detected the item or monster on top... giving colour here will
// result in detect creature/item detecting features like stairs. -- bwr
- if (map_value != mapch2( grid_value )) {
+ if (map_value != get_sightmap_char(grid_value))
+ {
// If there's an item on this square, change colour to indicate
// that, iff the item's glyph matches map_value. XXX: Potentially
// abusable? -- ds
int item = igrd[x + 1][y + 1];
if (item_colour && item != NON_ITEM
- && map_value == display_glyph(item_env_glyph(mitm[item])))
+ && map_value ==
+ get_sightmap_char(get_item_dngn_code(mitm[item])))
{
- screen_buffer_t ic = mitm[item].colour;
+ unsigned ic = mitm[item].colour;
-#if defined(WIN32CONSOLE) || defined(DOS) || defined(DOS_TERM)
- if (mitm[item].link != NON_ITEM
- && Options.heap_brand != CHATTR_NORMAL)
- {
- ic = dos_brand(ic, Options.heap_brand);
- }
-#elif defined(USE_COLOUR_OPTS)
if (mitm[item].link != NON_ITEM )
- {
ic |= COLFLAG_ITEM_HEAP;
- }
-#endif
+
// If the item colour is the background colour, tweak it to WHITE
// instead to catch the player's eye.
- return ic == tc? WHITE : ic;
+ return fix_colour( ic == tc? WHITE : ic );
}
-
- return tc;
}
- switch (grid_value)
- {
- case DNGN_TRAP_MECHANICAL:
- return (LIGHTCYAN);
-
- case DNGN_TRAP_MAGICAL:
- case DNGN_TRAP_III:
- return (MAGENTA);
-
- case DNGN_ENTER_SHOP:
- return (YELLOW);
-
- case DNGN_ENTER_DIS:
- return (CYAN);
-
- case DNGN_ENTER_HELL:
- case DNGN_ENTER_GEHENNA:
- return (RED);
-
- case DNGN_ENTER_COCYTUS:
- return (LIGHTCYAN);
-
- case DNGN_ENTER_ABYSS:
- return random2(16); // so it can be black - is this right? {dlb}
-
- case DNGN_ENTER_LABYRINTH:
- case DNGN_STONE_ARCH:
- return (LIGHTGREY);
+ int feature_colour = DARKGREY;
+ feature_colour =
+ is_terrain_seen(x + 1, y + 1)? Feature[grid_value].seen_colour
+ : Feature[grid_value].map_colour;
- case DNGN_ENTER_PANDEMONIUM:
- return (LIGHTBLUE);
+ if (feature_colour != DARKGREY)
+ tc = feature_colour;
- case DNGN_EXIT_PANDEMONIUM:
- // Exit pandemonium gates won't show up on the map as light blue
- // unless the character has the "gate to pandemonium" demonspawn
- // mutation. This is so that the player can't quickly use a
- // crystal ball to find their way out. -- bwr
- return (you.mutation[MUT_PANDEMONIUM] ? LIGHTBLUE : LIGHTGREEN);
-
- case DNGN_TRANSIT_PANDEMONIUM:
- return (LIGHTGREEN);
-
- case DNGN_ENTER_ZOT:
- case DNGN_RETURN_FROM_ZOT:
- return (MAGENTA);
-
- case DNGN_STONE_STAIRS_DOWN_I:
- case DNGN_STONE_STAIRS_DOWN_II:
- case DNGN_STONE_STAIRS_DOWN_III:
- case DNGN_ROCK_STAIRS_DOWN:
- return (RED);
-
- case DNGN_STONE_STAIRS_UP_I:
- case DNGN_STONE_STAIRS_UP_II:
- case DNGN_STONE_STAIRS_UP_III:
- case DNGN_ROCK_STAIRS_UP:
- return (GREEN);
-
- 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 123:
- case 124:
- case 125:
- case 126:
- return (LIGHTRED);
-
- 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 143:
- case 144:
- case 145:
- case 146:
- return (LIGHTBLUE);
-
- default:
- break;
- }
-
- return tc;
+ return fix_colour(tc);
}
void clear_map()
{
- for (int y = 0; y < GYM - 1; ++y)
+ for (int y = Y_BOUND_1; y <= Y_BOUND_2; ++y)
{
- for (int x = 0; x < GXM - 1; ++x)
+ for (int x = X_BOUND_1; x <= X_BOUND_2; ++x)
{
- unsigned short envc = env.map[x][y];
- if (!envc)
+ // 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(x, y))
continue;
- bool unmapped = (envc & ENVF_DETECTED) != 0;
- // Discard flags at this point.
- envc = (unsigned char) envc;
-
- const unsigned char &grdc = grd[x + 1][y + 1];
- if (envc == mapch(grdc) || envc == mapch2(grdc))
+ unsigned short envc = env.map[x][y] & MAP_CHARACTER_MASK;
+ if (!envc)
continue;
- int item = igrd[x + 1][y + 1];
+ const int item = igrd[x + 1][y + 1];
if (item != NON_ITEM
- && envc == display_glyph(item_env_glyph(mitm[item])))
+ && envc ==
+ get_sightmap_char(get_item_dngn_code(mitm[item])))
continue;
- env.map[x][y] = unmapped? 0 : mapch2(grdc);
+ set_envmap_char(x, y,
+ is_terrain_seen(x, y)? get_sightmap_char(grd[x][y]) :
+ is_terrain_known(x, y)? get_magicmap_char(grd[x][y]) :
+ 0);
+ set_envmap_detected_mons(x, y, false);
}
}
}
@@ -1104,7 +530,7 @@ void monster_grid(bool do_updates)
{
behaviour_event( monster, ME_ALERT, MHITYOU );
- if (you.turn_is_over == 1
+ if (you.turn_is_over
&& mons_shouts(monster->type) > 0
&& random2(30) >= you.skills[SK_STEALTH])
{
@@ -1194,127 +620,50 @@ void monster_grid(bool do_updates)
}
}
+ const int ex = monster->x - you.x_pos + 9;
+ const int ey = monster->y - you.y_pos + 9;
+
if (!player_monster_visible( monster ))
{
// ripple effect?
if (grd[monster->x][monster->y] == DNGN_SHALLOW_WATER
&& !mons_flies(monster))
{
- show_backup[ monster->x - you.x_pos + 9 ]
- [ monster->y - you.y_pos + 9]
- = env.show[ monster->x - you.x_pos + 9 ]
- [ monster->y - you.y_pos + 9 ];
- env.show[monster->x - you.x_pos + 9]
- [monster->y - you.y_pos + 9] = 257;
+ set_show_backup(ex, ey);
+ env.show[ex][ey] = DNGN_INVIS_EXPOSED;
+ env.show_col[ex][ey] = BLUE;
}
continue;
}
else if (!mons_friendly( monster )
&& !mons_is_mimic( monster->type )
- && !mons_flag( monster->type, M_NO_EXP_GAIN ))
+ && !mons_class_flag( monster->type, M_NO_EXP_GAIN ))
{
- interrupt_activity( AI_SEE_MONSTER );
- if (you.running != 0
-#ifdef CLUA_BINDINGS
- && clua.callbooleanfn(true, "ch_stop_run",
- "M", monster)
-#endif
- )
- {
- // Friendly monsters, mimics, or harmless monsters
- // don't disturb the player's running/resting.
- //
- // Doing it this way causes players in run mode 2
- // to move one square, and in mode 1 to stop. This
- // means that the character will run one square if
- // a monster is in sight... we automatically jump
- // to zero if we're resting. -- bwr
- if (you.run_x == 0 && you.run_y == 0)
- stop_running();
- else if (you.running > 1)
- you.running--;
- else
- stop_running();
- }
+ interrupt_activity( AI_SEE_MONSTER, monster );
+ seen_monster( monster );
}
// mimics are always left on map
if (!mons_is_mimic( monster->type ))
- {
- show_backup[monster->x - you.x_pos + 9]
- [monster->y - you.y_pos + 9]
- = env.show[monster->x - you.x_pos + 9]
- [monster->y - you.y_pos + 9];
- }
+ set_show_backup(ex, ey);
- env.show[monster->x - you.x_pos + 9]
- [monster->y - you.y_pos + 9] = monster->type + 297;
+ env.show[ex][ey] = monster->type + DNGN_START_OF_MONSTERS;
+ env.show_col[ex][ey] = monster->colour;
- env.show_col[monster->x - you.x_pos + 9]
- [monster->y - you.y_pos + 9]
- = ((mcolour[monster->type] == BLACK)
- ? monster->number : mcolour[monster->type]);
-#ifdef USE_COLOUR_OPTS
if (mons_friendly(monster))
{
- env.show_col[monster->x - you.x_pos + 9]
- [monster->y - you.y_pos + 9]
- |= COLFLAG_FRIENDLY_MONSTER;
+ env.show_col[ex][ey] |= COLFLAG_FRIENDLY_MONSTER;
}
else if (Options.stab_brand != CHATTR_NORMAL
- && !mons_is_mimic(monster->type)
- && monster->type != MONS_OKLOB_PLANT
- && mons_is_stabbable(monster))
+ && mons_looks_stabbable(monster))
{
- env.show_col[monster->x - you.x_pos + 9]
- [monster->y - you.y_pos + 9]
- |= COLFLAG_WILLSTAB;
+ env.show_col[ex][ey] |= COLFLAG_WILLSTAB;
}
else if (Options.may_stab_brand != CHATTR_NORMAL
- && !mons_is_mimic(monster->type)
- && monster->type != MONS_OKLOB_PLANT
- && mons_maybe_stabbable(monster))
- {
- env.show_col[monster->x - you.x_pos + 9]
- [monster->y - you.y_pos + 9]
- |= COLFLAG_MAYSTAB;
- }
-
-#elif defined(WIN32CONSOLE) || defined(DOS)
- if (Options.friend_brand != CHATTR_NORMAL
- && mons_friendly(monster))
+ && mons_looks_distracted(monster))
{
- // We munge the colours right here for DOS and Windows, because
- // we know exactly how the colours will be handled, and we don't
- // want to change both DOS and Windows port code to handle
- // friend branding.
- unsigned short &colour =
- env.show_col[monster->x - you.x_pos + 9]
- [monster->y - you.y_pos + 9];
- colour = dos_brand(colour, Options.friend_brand);
+ env.show_col[ex][ey] |= COLFLAG_MAYSTAB;
}
-
- if (Options.stab_brand != CHATTR_NORMAL
- && !mons_is_mimic(monster->type)
- && monster->type != MONS_OKLOB_PLANT
- && mons_is_stabbable(monster))
- {
- unsigned short &colour =
- env.show_col[monster->x - you.x_pos + 9]
- [monster->y - you.y_pos + 9];
- colour = dos_brand(colour, Options.stab_brand);
- }
- else if (Options.may_stab_brand != CHATTR_NORMAL
- && !mons_is_mimic(monster->type)
- && monster->type != MONS_OKLOB_PLANT
- && mons_maybe_stabbable(monster))
- {
- unsigned short &colour =
- env.show_col[monster->x - you.x_pos + 9]
- [monster->y - you.y_pos + 9];
- colour = dos_brand(colour, Options.may_stab_brand);
- }
-#endif
} // end "if (monster->type != -1 && mons_ner)"
} // end "for s"
} // end monster_grid()
@@ -1324,7 +673,7 @@ bool check_awaken(int mons_aw)
{
int mons_perc = 0;
struct monsters *monster = &menv[mons_aw];
- const int mon_holy = mons_holiness( monster->type );
+ const int mon_holy = mons_holiness(monster);
// berserkers aren't really concerned about stealth
if (you.berserker)
@@ -1344,9 +693,9 @@ bool check_awaken(int mons_aw)
+ mons_see_invis(monster) * 5;
// critters that are wandering still have MHITYOU as their foe are
- // still actively on guard for the player, even if they can't see
+ // still actively on guard for the player, even if they can't see
// him. Give them a large bonus (handle_behaviour() will nuke 'foe'
- // after a while, removing this bonus.
+ // after a while, removing this bonus.
if (monster->behaviour == BEH_WANDER && monster->foe == MHITYOU)
mons_perc += 15;
@@ -1380,58 +729,52 @@ bool check_awaken(int mons_aw)
return (random2(stealth) <= mons_perc);
} // end check_awaken()
-static int display_glyph(int env_glyph)
+static void set_show_backup( int ex, int ey )
{
- unsigned short ch, color;
- if (viewwindow == viewwindow2)
- get_ibm_symbol(env_glyph, &ch, &color);
- else
- get_non_ibm_symbol(env_glyph, &ch, &color);
- return ch;
+ // Must avoid double setting it.
+ // We want the base terrain/item, not the cloud or monster that replaced it.
+ if (!Show_Backup[ex][ey])
+ Show_Backup[ex][ey] = env.show[ex][ey];
}
-static int item_env_glyph(const item_def &item)
+static int get_item_dngn_code(const item_def &item)
{
switch (item.base_type)
{
case OBJ_ORBS:
- return 256;
- // need + 6 because show is 0 - 12, not -6 - +6
+ return (DNGN_ITEM_ORB);
case OBJ_WEAPONS:
+ return (DNGN_ITEM_WEAPON);
case OBJ_MISSILES:
- return 258;
+ return (DNGN_ITEM_MISSILE);
case OBJ_ARMOUR:
- return 259;
+ return (DNGN_ITEM_ARMOUR);
case OBJ_WANDS:
- return 260;
+ return (DNGN_ITEM_WAND);
case OBJ_FOOD:
- return 261;
- case OBJ_UNKNOWN_I:
- return 262;
+ return (DNGN_ITEM_FOOD);
case OBJ_SCROLLS:
- return 263;
+ return (DNGN_ITEM_SCROLL);
case OBJ_JEWELLERY:
- return item.sub_type >= AMU_RAGE? 273 : 264;
+ return (jewellery_is_amulet(item)? DNGN_ITEM_AMULET : DNGN_ITEM_RING);
case OBJ_POTIONS:
- return 265;
- case OBJ_UNKNOWN_II:
- return 266;
+ return (DNGN_ITEM_POTION);
case OBJ_BOOKS:
- return 267;
+ return (DNGN_ITEM_BOOK);
case OBJ_STAVES:
- return 269;
+ return (DNGN_ITEM_STAVE);
case OBJ_MISCELLANY:
- return 270;
+ return (DNGN_ITEM_MISCELLANY);
case OBJ_CORPSES:
- return 271;
+ return (DNGN_ITEM_CORPSE);
case OBJ_GOLD:
- return 272;
+ return (DNGN_ITEM_GOLD);
default:
- return '8';
+ return (DNGN_ITEM_ORB); // bad item character
}
}
-void item()
+void item_grid()
{
char count_x, count_y;
@@ -1443,34 +786,22 @@ void item()
{
if (igrd[count_x][count_y] != NON_ITEM)
{
- if (env.show[count_x - you.x_pos + 9]
- [count_y - you.y_pos + 9] != 0)
+ const int ix = count_x - you.x_pos + 9;
+ const int iy = count_y - you.y_pos + 9;
+ if (env.show[ix][iy])
{
const item_def &eitem = mitm[igrd[count_x][count_y]];
- unsigned short &ecol =
- env.show_col[count_x - you.x_pos + 9]
- [count_y - you.y_pos + 9];
+ unsigned short &ecol = env.show_col[ix][iy];
ecol = (grd[count_x][count_y] == DNGN_SHALLOW_WATER)?
CYAN
: eitem.colour;
-#ifdef USE_COLOUR_OPTS
if (eitem.link != NON_ITEM)
{
ecol |= COLFLAG_ITEM_HEAP;
}
-#elif defined(WIN32CONSOLE) || defined(DOS)
- if (eitem.link != NON_ITEM
- && Options.heap_brand != CHATTR_NORMAL)
- {
- // Yes, exact same code as friend-branding.
- ecol = dos_brand(ecol, Options.heap_brand);
- }
-#endif
- env.show[count_x - you.x_pos + 9]
- [count_y - you.y_pos + 9] =
- item_env_glyph( eitem );
+ env.show[ix][iy] = get_item_dngn_code( eitem );
}
}
}
@@ -1484,7 +815,7 @@ void cloud_grid(void)
int mnc = 0;
// btw, this is also the 'default' color {dlb}
- unsigned char which_color = LIGHTGREY;
+ unsigned char which_colour = LIGHTGREY;
for (int s = 0; s < MAX_CLOUDS; s++)
{
@@ -1499,94 +830,105 @@ void cloud_grid(void)
if (see_grid(env.cloud[s].x, env.cloud[s].y))
{
- show_backup[env.cloud[s].x - you.x_pos + 9]
- [env.cloud[s].y - you.y_pos + 9]
- = env.show[env.cloud[s].x - you.x_pos + 9]
- [env.cloud[s].y - you.y_pos + 9];
-
- env.show[env.cloud[s].x - you.x_pos + 9]
- [env.cloud[s].y - you.y_pos + 9] = '#';
-
+ const int ex = env.cloud[s].x - you.x_pos + 9;
+ const int ey = env.cloud[s].y - you.y_pos + 9;
+
switch (env.cloud[s].type)
{
case CLOUD_FIRE:
case CLOUD_FIRE_MON:
if (env.cloud[s].decay <= 20)
- which_color = RED;
+ which_colour = RED;
else if (env.cloud[s].decay <= 40)
- which_color = LIGHTRED;
+ which_colour = LIGHTRED;
else if (one_chance_in(4))
- which_color = RED;
+ which_colour = RED;
else if (one_chance_in(4))
- which_color = LIGHTRED;
+ which_colour = LIGHTRED;
else
- which_color = YELLOW;
+ which_colour = YELLOW;
break;
case CLOUD_STINK:
case CLOUD_STINK_MON:
- which_color = GREEN;
+ which_colour = GREEN;
break;
case CLOUD_COLD:
case CLOUD_COLD_MON:
if (env.cloud[s].decay <= 20)
- which_color = BLUE;
+ which_colour = BLUE;
else if (env.cloud[s].decay <= 40)
- which_color = LIGHTBLUE;
+ which_colour = LIGHTBLUE;
else if (one_chance_in(4))
- which_color = BLUE;
+ which_colour = BLUE;
else if (one_chance_in(4))
- which_color = LIGHTBLUE;
+ which_colour = LIGHTBLUE;
else
- which_color = WHITE;
+ which_colour = WHITE;
break;
case CLOUD_POISON:
case CLOUD_POISON_MON:
- which_color = (one_chance_in(3) ? LIGHTGREEN : GREEN);
+ which_colour = (one_chance_in(3) ? LIGHTGREEN : GREEN);
break;
case CLOUD_BLUE_SMOKE:
case CLOUD_BLUE_SMOKE_MON:
- which_color = LIGHTBLUE;
+ which_colour = LIGHTBLUE;
break;
case CLOUD_PURP_SMOKE:
case CLOUD_PURP_SMOKE_MON:
- which_color = MAGENTA;
+ which_colour = MAGENTA;
break;
case CLOUD_MIASMA:
case CLOUD_MIASMA_MON:
case CLOUD_BLACK_SMOKE:
case CLOUD_BLACK_SMOKE_MON:
- which_color = DARKGREY;
+ which_colour = DARKGREY;
break;
default:
- which_color = LIGHTGREY;
+ which_colour = LIGHTGREY;
break;
}
- env.show_col[env.cloud[s].x - you.x_pos + 9]
- [env.cloud[s].y - you.y_pos + 9] = which_color;
+ set_show_backup(ex, ey);
+ env.show[ex][ey] = DNGN_CLOUD;
+ env.show_col[ex][ey] = which_colour;
}
} // end 'if != CLOUD_NONE'
} // end 'for s' loop
} // end cloud_grid()
-
-void noisy( int loudness, int nois_x, int nois_y )
+// Noisy now has a messenging service for giving messages to the
+// player is appropriate.
+//
+// Returns true if the PC heard the noise.
+bool noisy( int loudness, int nois_x, int nois_y, const char *msg )
{
int p;
struct monsters *monster = 0; // NULL {dlb}
+ bool ret = false;
+ // If the origin is silenced there is no noise.
if (silenced( nois_x, nois_y ))
- return;
+ return (false);
- int dist = loudness * loudness;
+ const int dist = loudness * loudness;
+ // message the player
+ if (distance( you.x_pos, you.y_pos, nois_x, nois_y ) <= dist
+ && player_can_hear( nois_x, nois_y ))
+ {
+ if (msg)
+ mpr( msg, MSGCH_SOUND );
+
+ ret = true;
+ }
+
for (p = 0; p < MAX_MONSTERS; p++)
{
monster = &menv[p];
@@ -1605,21 +947,19 @@ void noisy( int loudness, int nois_x, int nois_y )
behaviour_event( monster, ME_DISTURB, MHITNOT, nois_x, nois_y );
}
}
+
+ return (ret);
} // end noisy()
-/* ========================================================================
- * brand new LOS code
- * ========================================================================
- * The new LOS works via a new (I think) shadow casting algorithm,
- * plus an esthetic tweak for more pleasing corner illumination. More
- * detail can be had by contacting its author, Gordon Lipford. */
+/* The LOS code now uses raycasting -- haranp */
-#define MAX_LIGHT_RADIUS 20
-#define CIRC_MAX 32000
-#define BIG_SHADOW 32000
+#define LONGSIZE (sizeof(unsigned long)*8)
+#define LOS_MAX_RANGE_X 9
+#define LOS_MAX_RANGE_Y 9
+#define LOS_MAX_RANGE 9
// the following two constants represent the 'middle' of the sh array.
-// since the current shown area is 19x19, centering the view at (9,9)
+// since the current shown area is 19x19, centering the view at (9,9)
// means it will be exactly centered.
// This is done to accomodate possible future changes in viewable screen
// area - simply change sh_xo and sh_yo to the new view center.
@@ -1627,340 +967,648 @@ void noisy( int loudness, int nois_x, int nois_y )
const int sh_xo = 9; // X and Y origins for the sh array
const int sh_yo = 9;
-// the Cell class, used in the shadow-casting LOS algorithm
-class Cell
-{
+// Data used for the LOS algorithm
+int los_radius_squared = 8*8 + 1;
-public:
- int up_count;
- int up_max;
- int low_count;
- int low_max;
- bool lit;
- bool lit_delay;
- bool visible; // for blockers only
- void init();
- bool reachedLower();
- bool reachedUpper();
-
- Cell()
- {
- init();
- };
-};
+unsigned long* los_blockrays = NULL;
+unsigned long* dead_rays = NULL;
+std::vector<short> ray_coord_x;
+std::vector<short> ray_coord_y;
+std::vector<short> compressed_ray_x;
+std::vector<short> compressed_ray_y;
+std::vector<int> raylengths;
+std::vector<ray_def> fullrays;
-void Cell::init()
+void setLOSRadius(int newLR)
{
- up_count = 0;
- up_max = 0;
- low_count = 0;
- low_max = 0;
- lit = true;
- visible = true;
- lit_delay = false;
+ los_radius_squared = newLR * newLR + 1*1;
}
-bool Cell::reachedLower()
+bool get_bit_in_long_array( const unsigned long* data, int where )
{
- // integer math: a 'step' has a value of 10
- // see if we're within a half step of the max. VERY important
- // to use 'half step' or else things look really stupid.
- if (low_max != 0 && low_count + 5 >= low_max && low_count - 5 < low_max)
- return true;
+ int wordloc = where / LONGSIZE;
+ int bitloc = where % LONGSIZE;
+ return ((data[wordloc] & (1UL << bitloc)) != 0);
+}
- return false;
+static void set_bit_in_long_array( unsigned long* data, int where ) {
+ int wordloc = where / LONGSIZE;
+ int bitloc = where % LONGSIZE;
+ data[wordloc] |= (1UL << bitloc);
}
-bool Cell::reachedUpper()
+#define EPSILON_VALUE 0.00001
+bool double_is_zero( const double x )
{
- // see if we're within a half step of the max. VERY important
- // to use 'half step' or else things look really stupid.
- if (up_max != 0 && up_count + 5 >= up_max && up_count - 5 < up_max)
- return true;
-
- return false;
+ return (x > -EPSILON_VALUE) && (x < EPSILON_VALUE);
}
-// the cell array
-static FixedVector < Cell, MAX_LIGHT_RADIUS + 1 > cells;
+// note that slope must be nonnegative!
+// returns 0 if the advance was in x, 1 if it was in y, 2 if it was
+// the diagonal
+static int find_next_intercept(double* accx, double* accy, const double slope)
+{
-// the 'circle' array. For any given row, we won't check higher than
-// this given cell.
-static FixedVector < int, MAX_LIGHT_RADIUS + 1 > circle;
+ // handle perpendiculars
+ if ( double_is_zero(slope) )
+ {
+ *accx += 1.0;
+ return 0;
+ }
+ if ( slope > 100.0 )
+ {
+ *accy += 1.0;
+ return 1;
+ }
-// current light radius
-static int LR = 0;
+ const double xtarget = (double)((int)(*accx) + 1);
+ const double ytarget = (double)((int)(*accy) + 1);
+ const double xdistance = xtarget - *accx;
+ const double ydistance = ytarget - *accy;
+ const double distdiff = (xdistance * slope - ydistance);
+
+ // exact corner
+ if ( double_is_zero( distdiff ) ) {
+ // move somewhat away from the corner
+ if ( slope > 1.0 ) {
+ *accx = xtarget + EPSILON_VALUE * 2;
+ *accy = ytarget + EPSILON_VALUE * 2 * slope;
+ }
+ else {
+ *accx = xtarget + EPSILON_VALUE * 2 / slope;
+ *accy = ytarget + EPSILON_VALUE * 2;
+ }
+ return 2;
+ }
+
+ double traveldist;
+ int rc = -1;
+ if ( distdiff > 0.0 ) {
+ traveldist = ydistance / slope;
+ rc = 1;
+ }
+ else {
+ traveldist = xdistance;
+ rc = 0;
+ }
-// View constant
-const int view = 2; // 1=widest LOS .. 5=narrowest
+ traveldist += EPSILON_VALUE * 10.0;
+
+ *accx += traveldist;
+ *accy += traveldist * slope;
+ return rc;
+}
-// initialize LOS code for a given light radius
-extern void setLOSRadius(int newLR)
+void ray_def::advance_and_bounce()
{
- int i, j;
+ // 0 = down-right, 1 = down-left, 2 = up-left, 3 = up-right
+ int bouncequad[4][3] = {
+ { 1, 3, 2 }, { 0, 2, 3 }, { 3, 1, 0 }, { 2, 0, 1 }
+ };
+ int oldx = x(), oldy = y();
+ int rc = advance();
+ int newx = x(), newy = y();
+ ASSERT( grid_is_solid(grd[newx][newy]) );
+ if ( double_is_zero(slope) || slope > 100.0 )
+ quadrant = bouncequad[quadrant][2];
+ else if ( rc != 2 )
+ quadrant = bouncequad[quadrant][rc];
+ else
+ {
+ ASSERT( (oldx != newx) && (oldy != newy) );
+ bool blocked_x = grid_is_solid(grd[oldx][newy]);
+ bool blocked_y = grid_is_solid(grd[newx][oldy]);
+ if ( blocked_x && blocked_y )
+ quadrant = bouncequad[quadrant][rc];
+ else if ( blocked_x )
+ quadrant = bouncequad[quadrant][1];
+ else
+ quadrant = bouncequad[quadrant][0];
+ }
+ advance();
+}
- // sanity check - also allows multiple calls w/out performance loss
- if (LR == newLR)
- return;
+void ray_def::regress()
+{
+ int opp_quadrant[4] = { 2, 3, 0, 1 };
+ quadrant = opp_quadrant[quadrant];
+ advance();
+ quadrant = opp_quadrant[quadrant];
+}
+
+int ray_def::advance()
+{
+ int rc;
+ switch ( quadrant )
+ {
+ case 0:
+ // going down-right
+ rc = find_next_intercept( &accx, &accy, slope );
+ return rc;
+ case 1:
+ // going down-left
+ accx = 100.0 - EPSILON_VALUE/10.0 - accx;
+ rc = find_next_intercept( &accx, &accy, slope );
+ accx = 100.0 - EPSILON_VALUE/10.0 - accx;
+ return rc;
+ case 2:
+ // going up-left
+ accx = 100.0 - EPSILON_VALUE/10.0 - accx;
+ accy = 100.0 - EPSILON_VALUE/10.0 - accy;
+ rc = find_next_intercept( &accx, &accy, slope );
+ accx = 100.0 - EPSILON_VALUE/10.0 - accx;
+ accy = 100.0 - EPSILON_VALUE/10.0 - accy;
+ return rc;
+ case 3:
+ // going up-right
+ accy = 100.0 - EPSILON_VALUE/10.0 - accy;
+ rc = find_next_intercept( &accx, &accy, slope );
+ accy = 100.0 - EPSILON_VALUE/10.0 - accy;
+ return rc;
+ default:
+ return -1;
+ }
+}
- LR = newLR;
- // cells should already be initted. calculate the circle array.
+// Shoot a ray from the given start point (accx, accy) with the given
+// slope, with a maximum distance (in either x or y coordinate) of
+// maxrange. Store the visited cells in xpos[] and ypos[], and
+// return the number of cells visited.
+static int shoot_ray( double accx, double accy, const double slope,
+ int maxrange, int xpos[], int ypos[] )
+{
+ int curx, cury;
+ int cellnum;
+ for ( cellnum = 0; true; ++cellnum )
+ {
+ find_next_intercept( &accx, &accy, slope );
+ curx = (int)(accx);
+ cury = (int)(accy);
+ if ( curx > maxrange || cury > maxrange )
+ break;
- // note that rows 0 and 1 will always go to infinity.
- circle[0] = circle[1] = CIRC_MAX;
+ // work with the new square
+ xpos[cellnum] = curx;
+ ypos[cellnum] = cury;
+ }
+ return cellnum;
+}
- // for the rest, simply calculate max height based on light rad.
- for (i = 2; i <= LR; i++)
+// check if the passed ray has already been created
+static bool is_duplicate_ray( int len, int xpos[], int ypos[] )
+{
+ int cur_offset = 0;
+ for ( unsigned int i = 0; i < raylengths.size(); ++i )
{
- // check top
- if (2 * i * i <= LR * LR)
+ // only compare equal-length rays
+ if ( raylengths[i] != len )
{
- circle[i] = CIRC_MAX;
+ cur_offset += raylengths[i];
continue;
}
- for (j = i - 1; j >= 0; j--)
+ int j;
+ for ( j = 0; j < len; ++j )
{
- // check that Distance (I^2 + J^2) is no more than (R+0.5)^2
- // this rounding allows for *much* better looking circles.
- if (i * i + j * j <= LR * LR + LR)
- {
- circle[i] = j;
+ if ( ray_coord_x[j + cur_offset] != xpos[j] ||
+ ray_coord_y[j + cur_offset] != ypos[j] )
break;
- }
}
+
+ // exact duplicate?
+ if ( j == len )
+ return true;
+
+ // move to beginning of next ray
+ cur_offset += raylengths[i];
}
+ return false;
}
-static int calcUpper(int bX, int bY)
+// is starta...lengtha a subset of startb...lengthb?
+static bool is_subset( int starta, int startb, int lengtha, int lengthb )
{
- // got a blocker at row bX, cell bY. do all values
- // and scale by a factor of 10 for the integer math.
- int upper;
+ int cura = starta, curb = startb;
+ int enda = starta + lengtha, endb = startb + lengthb;
+ while ( cura < enda && curb < endb )
+ {
+ if ( ray_coord_x[curb] > ray_coord_x[cura] )
+ return false;
+ if ( ray_coord_y[curb] > ray_coord_y[cura] )
+ return false;
+ if ( ray_coord_x[cura] == ray_coord_x[curb] &&
+ ray_coord_y[cura] == ray_coord_y[curb] )
+ ++cura;
- upper = (10 * (10 * bX - view)) / (10 * bY + view);
- if (upper < 10) // upper bound for blocker on diagonal
- upper = 10;
+ ++curb;
+ }
+ return ( cura == enda );
+}
- return upper;
+// return a vector which lists all the nonduped cellrays (by index)
+static std::vector<int> find_nonduped_cellrays()
+{
+ // a cellray c in a fullray f is duped if there is a fullray g
+ // such that g contains c and g[:c] is a subset of f[:c]
+ int raynum, cellnum, curidx, testidx, testray, testcell;
+ bool is_duplicate;
+
+ std::vector<int> result;
+ for (curidx=0, raynum=0;
+ raynum < (int)raylengths.size();
+ curidx += raylengths[raynum++])
+ {
+ for (cellnum = 0; cellnum < raylengths[raynum]; ++cellnum)
+ {
+ // is the cellray raynum[cellnum] duplicated?
+ is_duplicate = false;
+ // XXX We should really check everything up to now
+ // completely, and all further rays to see if they're
+ // proper subsets.
+ const int curx = ray_coord_x[curidx + cellnum];
+ const int cury = ray_coord_y[curidx + cellnum];
+ for (testidx = 0, testray = 0; testray < raynum;
+ testidx += raylengths[testray++])
+ {
+ // scan ahead to see if there's an intersect
+ for ( testcell = 0; testcell < raylengths[raynum]; ++testcell )
+ {
+ const int testx = ray_coord_x[testidx + testcell];
+ const int testy = ray_coord_y[testidx + testcell];
+ // we can short-circuit sometimes
+ if ( testx > curx || testy > cury )
+ break;
+ // bingo!
+ if ( testx == curx && testy == cury )
+ {
+ is_duplicate = is_subset(testidx, curidx,
+ testcell, cellnum);
+ break;
+ }
+ }
+ if ( is_duplicate )
+ break; // no point in checking further rays
+ }
+ if ( !is_duplicate )
+ result.push_back(curidx + cellnum);
+ }
+ }
+ return result;
}
-static int calcLower(int bX, int bY)
+// Create and register the ray defined by the arguments.
+// Return true if the ray was actually registered (i.e., not a duplicate.)
+static bool register_ray( double accx, double accy, double slope )
{
- // got a blocker at row bX, cell bY. do all values
- // and scale by a factor of 10 for the integer math.
+ int xpos[LOS_MAX_RANGE * 2 + 1], ypos[LOS_MAX_RANGE * 2 + 1];
+ int raylen = shoot_ray( accx, accy, slope, LOS_MAX_RANGE, xpos, ypos );
- if (bY == 0)
- return BIG_SHADOW;
+ // early out if ray already exists
+ if ( is_duplicate_ray(raylen, xpos, ypos) )
+ return false;
- return (10 * (10 * bX + view)) / (10 * bY - view);
-}
+ // not duplicate, register
+ for ( int i = 0; i < raylen; ++i )
+ {
+ // create the cellrays
+ ray_coord_x.push_back(xpos[i]);
+ ray_coord_y.push_back(ypos[i]);
+ }
-// for easy x,y octant translation
-static int xxcomp[8] = { 1, 0, 0, -1, -1, 0, 0, 1 };
-static int xycomp[8] = { 0, 1, -1, 0, 0, -1, 1, 0 };
-static int yxcomp[8] = { 0, 1, 1, 0, 0, -1, -1, 0 };
-static int yycomp[8] = { 1, 0, 0, 1, -1, 0, 0, -1 };
+ // register the fullray
+ raylengths.push_back(raylen);
+ ray_def ray;
+ ray.accx = accx;
+ ray.accy = accy;
+ ray.slope = slope;
+ ray.quadrant = 0;
+ fullrays.push_back(ray);
-static void los_octant(int o, FixedArray < unsigned int, 19, 19 > &sh,
- FixedArray < unsigned char, 80, 70 > &gr, int x_p,
- int y_p)
+ return true;
+}
+
+static void create_blockrays()
{
- int row, cell, top, south;
- int tx, ty; // translated x, y deltas for this octant
- unsigned char gv; // grid value
- bool row_dark, all_dark;
- bool blocker, vis_corner;
- int up_inc, low_inc;
-
- // leave [0,0] alone, because the old LOS code seems to.
-
- // init cell[0]. this is the only one that needs clearing.
- cells[0].init();
- all_dark = false;
- vis_corner = false;
-
- // loop through each row
- for (row = 1; row <= LR; row++)
+ // determine nonduplicated rays
+ std::vector<int> nondupe_cellrays = find_nonduped_cellrays();
+ const unsigned int num_nondupe_rays = nondupe_cellrays.size();
+ const unsigned int num_nondupe_words =
+ (num_nondupe_rays + LONGSIZE - 1) / LONGSIZE;
+ const unsigned int num_cellrays = ray_coord_x.size();
+ const unsigned int num_words = (num_cellrays + LONGSIZE - 1) / LONGSIZE;
+
+ // first build all the rays: easier to do blocking calculations there
+ unsigned long* full_los_blockrays;
+ full_los_blockrays = new unsigned long[num_words * (LOS_MAX_RANGE_X+1) *
+ (LOS_MAX_RANGE_Y+1)];
+ memset((void*)full_los_blockrays, 0, sizeof(unsigned long) * num_words *
+ (LOS_MAX_RANGE_X+1) * (LOS_MAX_RANGE_Y+1));
+
+ int cur_offset = 0;
+
+ for ( unsigned int ray = 0; ray < raylengths.size(); ++ray )
{
- row_dark = true;
-
- // loop through each cell, up to the max allowed by circle[]
- top = circle[row];
- if (top > row)
- top = row;
-
- for (cell = 0; cell <= top; cell++)
+ for ( int i = 0; i < raylengths[ray]; ++i )
{
- // translate X,Y co'ord + bounds check
- tx = row * xxcomp[o] + cell * xycomp[o];
- ty = row * yxcomp[o] + cell * yycomp[o];
+ // every cell blocks...
+ unsigned long* const inptr = full_los_blockrays +
+ (ray_coord_x[i + cur_offset] * (LOS_MAX_RANGE_Y + 1) +
+ ray_coord_y[i + cur_offset]) * num_words;
- if (x_p + tx < 0 || x_p + tx > 79 || y_p + ty < 0 || y_p + ty > 69)
- continue;
+ // ...all following cellrays
+ for ( int j = i+1; j < raylengths[ray]; ++j )
+ set_bit_in_long_array( inptr, j + cur_offset );
- // check for all_dark - we've finished the octant but
- // have yet to fill in '0' for the rest of the sight grid
- if (all_dark == true)
- {
- sh[sh_xo + tx][sh_yo + ty] = 0;
- continue;
- }
+ }
+ cur_offset += raylengths[ray];
+ }
- // get grid value.. see if it blocks LOS
- gv = gr[x_p + tx][y_p + ty];
- blocker = (gv < MINSEE);
+ // we've built the basic blockray array; now compress it, keeping
+ // only the nonduplicated cellrays.
- // init some other variables
- up_inc = 10;
- low_inc = 10;
- south = cell - 1;
+ // allocate and clear memory
+ los_blockrays = new unsigned long[num_nondupe_words * (LOS_MAX_RANGE_X+1) * (LOS_MAX_RANGE_Y + 1)];
+ memset((void*)los_blockrays, 0, sizeof(unsigned long) * num_nondupe_words *
+ (LOS_MAX_RANGE_X+1) * (LOS_MAX_RANGE_Y+1));
- // STEP 1 - inherit values from immediate West, if possible
- if (cell < row)
- {
- // check for delayed lighting
- if (cells[cell].lit_delay)
- {
- if (!blocker)
- { // blockers don't light up with lit_delay.
- if (cells[south].lit)
- {
- if (cells[south].low_max != 0)
- {
- cells[cell].lit = false;
- // steal lower values
- cells[cell].low_max = cells[south].low_max;
- cells[cell].low_count = cells[south].low_count;
- cells[south].low_count = 0;
- cells[south].low_max = 0;
- low_inc = 0; // avoid double-inc.
- }
- else
- cells[cell].lit = true;
- }
- }
- cells[cell].lit_delay = false;
- }
- }
- else
- {
- // initialize new cell.
- cells[cell].init();
- }
+ // we want to only keep the cellrays from nondupe_cellrays.
+ compressed_ray_x.resize(num_nondupe_rays);
+ compressed_ray_y.resize(num_nondupe_rays);
+ for ( unsigned int i = 0; i < num_nondupe_rays; ++i )
+ {
+ compressed_ray_x[i] = ray_coord_x[nondupe_cellrays[i]];
+ compressed_ray_y[i] = ray_coord_y[nondupe_cellrays[i]];
+ }
+ unsigned long* oldptr = full_los_blockrays;
+ unsigned long* newptr = los_blockrays;
+ for ( int x = 0; x <= LOS_MAX_RANGE_X; ++x )
+ {
+ for ( int y = 0; y <= LOS_MAX_RANGE_Y; ++y )
+ {
+ for ( unsigned int i = 0; i < num_nondupe_rays; ++i )
+ if ( get_bit_in_long_array(oldptr, nondupe_cellrays[i]) )
+ set_bit_in_long_array(newptr, i);
+ oldptr += num_words;
+ newptr += num_nondupe_words;
+ }
+ }
- // STEP 2 - check for blocker
- // a dark blocker in shadow's edge will be visible
- if (blocker)
- {
- if (cells[cell].lit || (cell != 0 && cells[south].lit)
- || vis_corner)
- {
- // hack: make 'corners' visible
- vis_corner = cells[cell].lit;
+ // we can throw away full_los_blockrays now
+ delete [] full_los_blockrays;
- cells[cell].lit = false;
- cells[cell].visible = true;
+ dead_rays = new unsigned long[num_nondupe_words];
+
+#ifdef DEBUG_DIAGNOSTICS
+ mprf( MSGCH_DIAGNOSTICS, "Cellrays: %d Fullrays: %u Compressed: %u",
+ num_cellrays, raylengths.size(), num_nondupe_rays );
+#endif
+}
- int upper = calcUpper(row, cell);
- int lower = calcLower(row, cell);
+static int gcd( int x, int y )
+{
+ int tmp;
+ while ( y != 0 )
+ {
+ x %= y;
+ tmp = x;
+ x = y;
+ y = tmp;
+ }
+ return x;
+}
- if (upper < cells[cell].up_max || cells[cell].up_max == 0)
- {
- // new upper shadow
- cells[cell].up_max = upper;
- cells[cell].up_count = 0;
- up_inc = 0;
- }
+// Cast all rays
+void raycast()
+{
+ static bool done_raycast = false;
+ if ( done_raycast )
+ return;
+
+ // Creating all rays for first quadrant
+ // We have a considerable amount of overkill.
+ done_raycast = true;
+
+ int xangle, yangle;
+
+ // register perpendiculars FIRST, to make them top choice
+ // when selecting beams
+ register_ray( 0.5, 0.5, 1000.0 );
+ register_ray( 0.5, 0.5, 0.0 );
+
+ // For a slope of M = y/x, every x we move on the X axis means
+ // that we move y on the y axis. We want to look at the resolution
+ // of x/y: in that case, every step on the X axis means an increase
+ // of 1 in the Y axis at the intercept point. We can assume gcd(x,y)=1,
+ // so we look at steps of 1/y.
+ for ( xangle = 1; xangle <= LOS_MAX_RANGE; ++xangle ) {
+ for ( yangle = 1; yangle <= LOS_MAX_RANGE; ++yangle ) {
+
+ if ( gcd(xangle, yangle) != 1 )
+ continue;
- if (lower > cells[cell].low_max || cells[cell].low_max == 0)
- {
- // new lower shadow
- cells[cell].low_max = lower;
- cells[cell].low_count = -10;
- low_inc = 0;
- if (lower <= 30) // somewhat arbitrary
- cells[cell].lit_delay = true;
- // set dark_delay if lower > 20?? how to decide?
- }
- }
- else
- {
- cells[cell].visible = false;
- }
- }
- else
- {
- cells[cell].visible = false; // special flags for blockers
+ const double slope = ((double)(yangle)) / xangle;
+ const double rslope = ((double)(xangle)) / yangle;
+ for ( int intercept = 0; intercept <= yangle; ++intercept ) {
+ double xstart = ((double)(intercept)) / yangle;
+ if ( intercept == 0 )
+ xstart += EPSILON_VALUE / 10.0;
+ if ( intercept == yangle )
+ xstart -= EPSILON_VALUE / 10.0;
+ // y should be "about to change"
+ register_ray( xstart, 1.0 - EPSILON_VALUE / 10.0, slope );
+ // also draw the identical ray in octant 2
+ register_ray( 1.0 - EPSILON_VALUE / 10.0, xstart, rslope );
}
+ }
+ }
- // STEP 3 - add increments to upper, lower counts
- cells[cell].up_count += up_inc;
- cells[cell].low_count += low_inc;
+ // Now create the appropriate blockrays array
+ create_blockrays();
+}
- // STEP 4 - check south for dark
- if (south >= 0)
- if (cells[south].reachedUpper() == true)
- {
- if (cells[cell].reachedUpper() == false)
+static void set_ray_quadrant( ray_def& ray, int sx, int sy, int tx, int ty )
+{
+ if ( tx >= sx && ty >= sy )
+ ray.quadrant = 0;
+ else if ( tx < sx && ty >= sy )
+ ray.quadrant = 1;
+ else if ( tx < sx && ty < sy )
+ ray.quadrant = 2;
+ else if ( tx >= sx && ty < sy )
+ ray.quadrant = 3;
+ else
+ mpr("Bad ray quadrant!", MSGCH_DIAGNOSTICS);
+}
+
+
+// Find a nonblocked ray from sx, sy to tx, ty. Return false if no
+// such ray could be found, otherwise return true and fill ray
+// appropriately.
+// If allow_fallback is true, fall back to a center-to-center ray
+// if range is too great or all rays are blocked.
+bool find_ray( int sourcex, int sourcey, int targetx, int targety,
+ bool allow_fallback, ray_def& ray )
+{
+
+ int cellray, inray;
+ const int signx = ((targetx - sourcex >= 0) ? 1 : -1);
+ const int signy = ((targety - sourcey >= 0) ? 1 : -1);
+ const int absx = signx * (targetx - sourcex);
+ const int absy = signy * (targety - sourcey);
+ int cur_offset = 0;
+ for ( unsigned int fullray = 0; fullray < fullrays.size();
+ cur_offset += raylengths[fullray++] ) {
+
+ for ( cellray = 0; cellray < raylengths[fullray]; ++cellray )
+ {
+ if ( ray_coord_x[cellray + cur_offset] == absx &&
+ ray_coord_y[cellray + cur_offset] == absy ) {
+
+ // check if we're blocked so far
+ bool blocked = false;
+ for ( inray = 0; inray < cellray; ++inray ) {
+ if (grid_is_solid(grd[sourcex + signx * ray_coord_x[inray + cur_offset]][sourcey + signy * ray_coord_y[inray + cur_offset]]))
{
- cells[cell].up_max = cells[south].up_max;
- cells[cell].up_count = cells[south].up_count;
- cells[cell].up_count -= cells[south].up_max;
+ blocked = true;
+ break;
}
- cells[cell].lit = false;
- cells[cell].visible = false;
- }
-
- // STEP 5 - nuke lower if south lower
- if (south >= 0)
- {
- if (cells[south].reachedLower())
- {
- cells[cell].low_max = cells[south].low_max;
- cells[cell].low_count = cells[south].low_count;
- cells[cell].low_count -= cells[south].low_max;
- cells[south].low_count = cells[south].low_max = 0;
}
- if (cells[south].low_max != 0
- || (cells[south].lit == false
- && cells[south].low_max == 0))
+ if ( !blocked )
{
- cells[cell].low_count = cells[cell].low_max + 10;
+ // success!
+ ray = fullrays[fullray];
+ if ( sourcex > targetx )
+ ray.accx = 1.0 - ray.accx;
+ if ( sourcey > targety )
+ ray.accy = 1.0 - ray.accy;
+ ray.accx += sourcex;
+ ray.accy += sourcey;
+ set_ray_quadrant(ray, sourcex, sourcey, targetx, targety);
+ return true;
}
}
-
- // STEP 6 - light up if we've reached lower bound
- if (cells[cell].reachedLower() == true)
- cells[cell].lit = true;
-
- // now place appropriate value in sh
- if (cells[cell].lit == true
- || (blocker == true && cells[cell].visible == true))
- {
- sh[sh_xo + tx][sh_yo + ty] = gv;
- }
- else
- sh[sh_xo + tx][sh_yo + ty] = 0;
-
- if (cells[cell].lit == true)
- row_dark = false;
- } // end for - cells
-
- vis_corner = false; // don't carry over to next row. :)
- if (row_dark == true)
- all_dark = true;
- } // end for - rows
+ }
+ }
+ if ( allow_fallback ) {
+ ray.accx = sourcex + 0.5;
+ ray.accy = sourcey + 0.5;
+ if ( targetx == sourcex )
+ ray.slope = 10000.0;
+ else {
+ ray.slope = targety - sourcey;
+ ray.slope /= targetx - sourcex;
+ if ( ray.slope < 0 )
+ ray.slope = -ray.slope;
+ }
+ set_ray_quadrant(ray, sourcex, sourcey, targetx, targety);
+ return true;
+ }
+ return false;
}
+// The rule behind LOS is:
+// Two cells can see each other if there is any line from some point
+// of the first to some point of the second ("generous" LOS.)
+//
+// We use raycasting. The algorithm:
+// PRECOMPUTATION:
+// Create a large bundle of rays and cast them.
+// Mark, for each one, which cells kill it (and where.)
+// Also, for each one, note which cells it passes.
+// ACTUAL LOS:
+// Unite the ray-killers for the given map; this tells you which rays
+// are dead.
+// Look up which cells the surviving rays have, and that's your LOS!
+// OPTIMIZATIONS:
+// WLOG, we can assume that we're in a specific quadrant - say the
+// first quadrant - and just mirror everything after that. We can
+// likely get away with a single octant, but we don't do that. (To
+// do...)
+// Rays are actually split by each cell they pass. So each "ray" only
+// identifies a single cell, and we can do logical ORs. Once a cell
+// kills a cellray, it will kill all remaining cellrays of that ray.
+// Also, rays are checked to see if they are duplicates of each
+// other. If they are, they're eliminated.
+// Some cellrays can also be eliminated. In general, a cellray is
+// unnecessary if there is another cellray with the same coordinates,
+// and whose path (up to those coordinates) is a subset, not necessarily
+// proper, of the original path. We still store the original cellrays
+// fully for beam detection and such.
+// PERFORMANCE:
+// With reasonable values we have around 6000 cellrays, meaning
+// around 600Kb (75 KB) of data. This gets cut down to 700 cellrays
+// after removing duplicates. That means that we need to do
+// around 22*100*4 ~ 9,000 memory reads + writes per LOS call on a
+// 32-bit system. Not too bad.
void losight(FixedArray < unsigned int, 19, 19 > &sh,
FixedArray < unsigned char, 80, 70 > &gr, int x_p, int y_p)
{
- int o;
+ raycast();
+ // go quadrant by quadrant
+ int quadrant_x[4] = { 1, -1, -1, 1 };
+ int quadrant_y[4] = { 1, 1, -1, -1 };
+
+ // clear out sh
+ for ( int i = 0; i < 19; ++i )
+ for ( int j = 0; j < 19; ++j )
+ sh[i][j] = 0;
+
+ const unsigned int num_cellrays = compressed_ray_x.size();
+ const unsigned int num_words = (num_cellrays + LONGSIZE - 1) / LONGSIZE;
+
+ for ( int quadrant = 0; quadrant < 4; ++quadrant ) {
+ const int xmult = quadrant_x[quadrant];
+ const int ymult = quadrant_y[quadrant];
+
+ // clear out the dead rays array
+ memset( (void*)dead_rays, 0, sizeof(unsigned long) * num_words);
+
+ // kill all blocked rays
+ const unsigned long* inptr = los_blockrays;
+ for ( int xdiff = 0; xdiff <= LOS_MAX_RANGE_X; ++xdiff ) {
+ for (int ydiff = 0; ydiff <= LOS_MAX_RANGE_Y;
+ ++ydiff, inptr += num_words ) {
+
+ const int realx = x_p + xdiff * xmult;
+ const int realy = y_p + ydiff * ymult;
+
+ if (realx < 0 || realx > 79 || realy < 0 || realy > 69)
+ continue;
+
+ // if this cell is opaque...
+ if ( grid_is_opaque(gr[realx][realy])) {
+ // then block the appropriate rays
+ for ( unsigned int i = 0; i < num_words; ++i )
+ dead_rays[i] |= inptr[i];
+ }
+ }
+ }
- for (o = 0; o < 8; o++)
- los_octant(o, sh, gr, x_p, y_p);
+ // ray calculation done, now work out which cells in this
+ // quadrant are visible
+ unsigned int rayidx = 0;
+ for ( unsigned int wordloc = 0; wordloc < num_words; ++wordloc ) {
+ const unsigned long curword = dead_rays[wordloc];
+ // Note: the last word may be incomplete
+ for ( unsigned int bitloc = 0; bitloc < LONGSIZE; ++bitloc) {
+ // make the cells seen by this ray at this point visible
+ if ( ((curword >> bitloc) & 1UL) == 0 ) {
+ // this ray is alive!
+ const int realx = xmult * compressed_ray_x[rayidx];
+ const int realy = ymult * compressed_ray_y[rayidx];
+ // update shadow map
+ if (x_p + realx >= 0 && x_p + realx < 80 &&
+ y_p + realy >= 0 && y_p + realy < 70 &&
+ realx * realx + realy * realy <= los_radius_squared )
+ sh[sh_xo+realx][sh_yo+realy]=gr[x_p+realx][y_p+realy];
+ }
+ ++rayidx;
+ if ( rayidx == num_cellrays )
+ break;
+ }
+ }
+ }
}
@@ -2206,11 +1854,34 @@ static int find_feature( const std::vector<coord_def>& features,
return 0;
}
+#ifdef USE_CURSES
+// NOTE: This affects libunix.cc draw state; use this just before setting
+// textcolour and drawing a character and call set_altcharset(false)
+// after you're done drawing.
+//
+static int cset_adjust(int raw)
+{
+ if (Options.char_set != CSET_ASCII)
+ {
+ // switch to alternate char set for 8-bit characters:
+ set_altcharset( raw > 127 );
+
+ // shift the DEC line drawing set:
+ if (Options.char_set == CSET_DEC
+ && raw >= 0xE0)
+ {
+ raw &= 0x7F;
+ }
+ }
+ return (raw);
+}
+#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( FixedVector<int, 2> &spec_place )
+void show_map( FixedVector<int, 2> &spec_place, bool travel_mode )
{
int i, j;
@@ -2226,7 +1897,8 @@ void show_map( FixedVector<int, 2> &spec_place )
// Vector to track all features we can travel to, in order of distance.
std::vector<coord_def> features;
- if (!spec_place[0]) {
+ if (travel_mode)
+ {
travel_cache.update();
find_travel_pos(you.x_pos, you.y_pos, NULL, NULL, &features);
@@ -2336,16 +2008,21 @@ void show_map( FixedVector<int, 2> &spec_place )
colour = colour_code_map(start_x + i, start_y + j,
Options.item_colour,
- !spec_place[0] && Options.travel_colour);
+ travel_mode && Options.travel_colour);
buffer2[bufcount2 + 1] = colour;
-
- if (start_x + i + 1 == you.x_pos && start_y + j + 1 == you.y_pos)
- buffer2[bufcount2 + 1] = WHITE;
-
buffer2[bufcount2] =
(unsigned char) env.map[start_x + i][start_y + j];
+ if (start_x + i + 1 == you.x_pos && start_y + j + 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
+ // 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.
@@ -2355,8 +2032,8 @@ void show_map( FixedVector<int, 2> &spec_place )
screen_buffer_t &bc = buffer2[bufcount2];
int gridx = start_x + i + 1, gridy = start_y + j + 1;
unsigned char ch = is_waypoint(gridx, gridy);
- if (ch && (bc == mapch2(DNGN_FLOOR) ||
- bc == mapch(DNGN_FLOOR)))
+ if (ch && (bc == get_sightmap_char(DNGN_FLOOR) ||
+ bc == get_magicmap_char(DNGN_FLOOR)))
bc = ch;
}
@@ -2373,12 +2050,20 @@ void show_map( FixedVector<int, 2> &spec_place )
if (i == 0 && j > 0)
gotoxy( 1, j + 1 );
+ int ch = buffer2[bufcount2 - 2];
+#ifdef USE_CURSES
+ ch = cset_adjust( ch );
+#endif
textcolor( buffer2[bufcount2 - 1] );
- putch( buffer2[bufcount2 - 2] );
+ putch(ch);
#endif
}
}
+#ifdef USE_CURSES
+ set_altcharset(false);
+#endif
+
#ifdef DOS_TERM
puttext(1, 1, 80, 25, buffer2);
#endif
@@ -2389,7 +2074,7 @@ void show_map( FixedVector<int, 2> &spec_place )
gettything:
getty = getchm(KC_LEVELMAP);
- if (spec_place[0] == 0 && getty != 0 && getty != '+' && getty != '-'
+ if (travel_mode && getty != 0 && getty != '+' && getty != '-'
&& getty != 'h' && getty != 'j' && getty != 'k' && getty != 'l'
&& getty != 'y' && getty != 'u' && getty != 'b' && getty != 'n'
&& getty != 'H' && getty != 'J' && getty != 'K' && getty != 'L'
@@ -2406,12 +2091,13 @@ void show_map( FixedVector<int, 2> &spec_place )
&& getty != CONTROL('F')
&& getty != CONTROL('W')
&& getty != CONTROL('C')
+ && getty != '?'
&& getty != 'X' && getty != 'F' && getty != 'I' && getty != 'W')
{
goto putty;
}
- if (spec_place[0] == 1 && getty != 0 && getty != '+' && getty != '-'
+ if (!travel_mode && getty != 0 && getty != '+' && getty != '-'
&& getty != 'h' && getty != 'j' && getty != 'k' && getty != 'l'
&& getty != 'y' && getty != 'u' && getty != 'b' && getty != 'n'
&& getty != 'H' && getty != 'J' && getty != 'K' && getty != 'L'
@@ -2425,9 +2111,13 @@ void show_map( FixedVector<int, 2> &spec_place )
}
if (getty == 0)
+ {
getty = getchm(KC_LEVELMAP);
+ // [dshaligram] DOS madness.
+ getty = dos_direction_unmunge(getty);
+ }
-#ifdef WIN32CONSOLE
+#if defined(WIN32CONSOLE) || defined(DOS)
// Translate shifted numpad to shifted vi keys. Yes,
// this is horribly hacky.
{
@@ -2441,6 +2131,10 @@ void show_map( FixedVector<int, 2> &spec_place )
switch (getty)
{
+ case '?':
+ show_levelmap_help();
+ break;
+
case CONTROL('C'):
clear_map();
break;
@@ -2591,7 +2285,7 @@ void show_map( FixedVector<int, 2> &spec_place )
search_feat = getty;
search_found = 0;
}
- if (!spec_place[0])
+ if (travel_mode)
search_found = find_feature(features, getty, curs_x, curs_y,
start_x, start_y,
search_found, &move_x, &move_y);
@@ -2608,7 +2302,7 @@ void show_map( FixedVector<int, 2> &spec_place )
case ';':
{
int x = start_x + curs_x, y = start_y + curs_y;
- if (!spec_place[0] && x == you.x_pos && y == you.y_pos)
+ if (travel_mode && x == you.x_pos && y == you.y_pos)
{
if (you.travel_x > 0 && you.travel_y > 0) {
move_x = you.travel_x - x;
@@ -2701,1404 +2395,1177 @@ void magic_mapping(int map_radius, int proportion)
{
int i, j, k, l, empty_count;
- if (map_radius > 50)
+ if (map_radius > 50 && map_radius != 1000)
map_radius = 50;
+ else if (map_radius < 5)
+ map_radius = 5;
+
+ // now gradually weaker with distance:
+ const int pfar = (map_radius * 7) / 10;
+ const int very_far = (map_radius * 9) / 10;
for (i = you.x_pos - map_radius; i < you.x_pos + map_radius; i++)
{
for (j = you.y_pos - map_radius; j < you.y_pos + map_radius; j++)
{
- if (random2(100) > proportion)
+ if (proportion < 100 && random2(100) >= proportion)
continue; // note that proportion can be over 100
- if (i < 5 || j < 5 || i > (GXM - 5) || j > (GYM - 5))
+ if (!map_bounds(i, j))
continue;
- //if (env.map[i][j] == mapch2(grd[i + 1][j + 1]))
- // continue;
- if (env.map[i][j])
+ const int dist = grid_distance( you.x_pos, you.y_pos, i, j );
+
+ if (dist > pfar && one_chance_in(3))
+ continue;
+
+ if (dist > very_far && coinflip())
+ continue;
+
+ if (is_terrain_changed(i, j))
+ clear_envmap_grid(i, j);
+
+ if (is_terrain_known(i, j))
continue;
empty_count = 8;
- if (grd[i][j] < DNGN_LAVA && grd[i][j] != DNGN_CLOSED_DOOR)
+ if (grid_is_solid(grd[i][j]) && grd[i][j] != DNGN_CLOSED_DOOR)
{
- for (k = 0; k < 3; k++)
+ for (k = -1; k <= 1; k++)
{
- for (l = 0; l < 3; l++)
+ for (l = -1; l <= 1; l++)
{
- if (k == 1 && l == 1)
+ if (k == 0 && l == 0)
continue;
- if (grd[i + k][j + l] <= 60
- && grd[i + k][j + l] != DNGN_CLOSED_DOOR)
+ if (!map_bounds( i + k, j + l ))
{
- empty_count--;
+ --empty_count;
+ continue;
}
+
+ if (grid_is_solid( grd[i + k][j + l] )
+ && grd[i + k][j + l] != DNGN_CLOSED_DOOR)
+ empty_count--;
}
}
}
if (empty_count > 0)
- env.map[i][j] = mapch(grd[i + 1][j + 1]);
+ {
+ if (!get_envmap_char(i, j))
+ set_envmap_char(i, j, get_magicmap_char(grd[i][j]));
+
+ // 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)
+ set_terrain_seen( i, j );
+ else
+ set_terrain_mapped( i, j );
+ }
}
}
} // end magic_mapping()
-
-/* mapchars 3 & 4 are for non-ibm char sets */
-unsigned char mapchar(unsigned char ldfk)
+// realize that this is simply a repackaged version of
+// stuff::see_grid() -- make certain they correlate {dlb}:
+bool mons_near(struct monsters *monster, unsigned int foe)
{
- unsigned char showed = 0;
+ // early out -- no foe!
+ if (foe == MHITNOT)
+ return (false);
- switch (ldfk)
+ if (foe == MHITYOU)
{
- case DNGN_UNSEEN:
- showed = 0;
- break;
+ if (monster->x > you.x_pos - 9 && monster->x < you.x_pos + 9
+ && monster->y > you.y_pos - 9 && monster->y < you.y_pos + 9)
+ {
+ if (env.show[monster->x - you.x_pos + 9][monster->y - you.y_pos + 9])
+ return (true);
+ }
+ return (false);
+ }
- case DNGN_SECRET_DOOR:
- case DNGN_ROCK_WALL:
- case DNGN_PERMAROCK_WALL:
- case DNGN_STONE_WALL:
- case DNGN_METAL_WALL:
- case DNGN_GREEN_CRYSTAL_WALL:
- case DNGN_WAX_WALL:
- showed = 176;
- break;
+ // must be a monster
+ struct monsters *myFoe = &menv[foe];
+ if (myFoe->type >= 0)
+ {
+ if (monster->x > myFoe->x - 9 && monster->x < myFoe->x + 9
+ && monster->y > myFoe->y - 9 && monster->y < myFoe->y + 9)
+ {
+ return (true);
+ }
+ }
- case DNGN_CLOSED_DOOR:
- showed = 206;
- break;
+ return (false);
+} // end mons_near()
- case 20: // orcish idol
- case 24: // ???
- case 25: // ???
- case DNGN_SILVER_STATUE:
- case DNGN_GRANITE_STATUE:
- case DNGN_ORANGE_CRYSTAL_STATUE:
- showed = '8';
- break;
+// answers the question: "Is a grid within character's line of sight?"
+bool see_grid( int grx, int gry )
+{
+ // rare case: can player see self? (of course!)
+ if (grx == you.x_pos && gry == you.y_pos)
+ return (true);
- case DNGN_LAVA_X:
- case DNGN_WATER_X:
- case DNGN_LAVA:
- case DNGN_DEEP_WATER:
- case DNGN_SHALLOW_WATER:
- showed = 247;
- break;
+ // check env.show array
+ if (grid_distance( grx, gry, you.x_pos, you.y_pos ) < 9)
+ {
+ const int ex = grx - you.x_pos + 9;
+ const int ey = gry - you.y_pos + 9;
- case DNGN_FLOOR:
- case DNGN_UNDISCOVERED_TRAP:
- showed = 250;
- break;
+ if (env.show[ex][ey])
+ return (true);
+ }
- //case 68: showed = '>'; break; // < (60)
+ return (false);
+} // end see_grid()
- case DNGN_OPEN_DOOR:
- showed = 39;
- break;
+static const unsigned char table[ NUM_CSET ][ NUM_DCHAR_TYPES ] =
+{
+ // CSET_ASCII
+ {
+ '#', '*', '.', ',', '\'', '+', '^', '>', '<', // wall, stairs up
+ '_', '\\', '}', '{', '8', '~', '~', // altar, item detect
+ '0', ')', '[', '/', '%', '?', '=', '!', '(', // orb, missile
+ ':', '|', '}', '%', '$', '"', '#', // book, cloud
+ },
- //case 72: showed = '<'; break;
+ // 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
+ '+', '\\', '}', '%', '$', '"', '#', // book, cloud
+ },
- case DNGN_TRAP_MECHANICAL:
- case DNGN_TRAP_MAGICAL:
- case DNGN_TRAP_III:
- showed = '^';
- break;
+ // 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
+ '+', '\\', '}', '%', '$', '"', '#', // book, cloud
+ },
+};
- case DNGN_STONE_STAIRS_DOWN_I:
- case DNGN_STONE_STAIRS_DOWN_II:
- case DNGN_STONE_STAIRS_DOWN_III:
- case DNGN_ROCK_STAIRS_DOWN:
- 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 123:
- case 124:
- case 125:
- case 126:
- showed = '>';
- break;
+static unsigned char cset_override[NUM_CSET][NUM_DCHAR_TYPES];
- case DNGN_STONE_STAIRS_UP_I:
- case DNGN_STONE_STAIRS_UP_II:
- case DNGN_STONE_STAIRS_UP_III:
- case DNGN_ROCK_STAIRS_UP:
- 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 143:
- case 144:
- case 145:
- case 146:
- showed = '<';
- break;
+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"
+ };
+ 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);
+}
- case DNGN_ENTER_HELL:
- case DNGN_ENTER_LABYRINTH:
- 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_STONE_ARCH:
- case DNGN_ENTER_PANDEMONIUM:
- case DNGN_EXIT_PANDEMONIUM:
- case DNGN_TRANSIT_PANDEMONIUM:
- case DNGN_ENTER_ZOT:
- case DNGN_RETURN_FROM_ZOT:
- showed = 239;
- break;
+void clear_cset_overrides()
+{
+ memset(cset_override, 0, sizeof cset_override);
+}
- 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:
- showed = 220;
- break;
+static unsigned short read_symbol(std::string s)
+{
+ if (s.empty())
+ return (0);
+ if (s.length() == 1)
+ return s[0];
- case DNGN_BLUE_FOUNTAIN:
- case DNGN_DRY_FOUNTAIN_I:
- case DNGN_SPARKLING_FOUNTAIN:
- case DNGN_DRY_FOUNTAIN_II:
- case DNGN_DRY_FOUNTAIN_III:
- case DNGN_DRY_FOUNTAIN_IV:
- case DNGN_DRY_FOUNTAIN_V:
- case DNGN_DRY_FOUNTAIN_VI:
- case DNGN_DRY_FOUNTAIN_VII:
- case DNGN_DRY_FOUNTAIN_VIII:
- case DNGN_PERMADRY_FOUNTAIN:
- showed = 159;
- break;
+ if (s[0] == '\\')
+ s = s.substr(1);
+
+ int feat = atoi(s.c_str());
+ if (feat < 0)
+ feat = 0;
+ return static_cast<unsigned short>(feat);
+}
- default:
- showed = 0;
- break;
+void add_cset_override(char_set_type set, dungeon_char_type dc,
+ unsigned char symbol)
+{
+ cset_override[set][dc] = symbol;
+}
+
+void add_cset_override(char_set_type set, const std::string &overrides)
+{
+ std::vector<std::string> overs = split_string(",", overrides);
+ for (int i = 0, size = overs.size(); i < size; ++i)
+ {
+ std::vector<std::string> mapping = split_string(":", overs[i]);
+ if (mapping.size() != 2)
+ continue;
+
+ dungeon_char_type dc = dchar_by_name(mapping[0]);
+ if (dc == NUM_DCHAR_TYPES)
+ continue;
+
+ unsigned char symbol =
+ static_cast<unsigned char>(read_symbol(mapping[1]));
+
+ if (set == NUM_CSET)
+ for (int c = 0; c < NUM_CSET; ++c)
+ add_cset_override(char_set_type(c), dc, symbol);
+ else
+ add_cset_override(set, dc, symbol);
}
+}
- return showed;
+void init_char_table( char_set_type set )
+{
+ for (int i = 0; i < NUM_DCHAR_TYPES; i++)
+ {
+ if (cset_override[set][i])
+ Options.char_table[i] = cset_override[set][i];
+ else
+ Options.char_table[i] = table[set][i];
+ }
}
+void clear_feature_overrides()
+{
+ Feature_Overrides.clear();
+}
-unsigned char mapchar2(unsigned char ldfk)
+void add_feature_override(const std::string &text)
{
- unsigned char showed = 0;
+ std::string::size_type epos = text.rfind("}");
+ if (epos == std::string::npos)
+ return;
+
+ std::string::size_type spos = text.rfind("{", epos);
+ if (spos == std::string::npos)
+ return;
+
+ std::string fname = text.substr(0, spos);
+ std::string props = text.substr(spos + 1, epos - spos - 1);
+ std::vector<std::string> iprops = split_string(",", props, true, true);
+
+ if (iprops.size() < 1 || iprops.size() > 5)
+ return;
+
+ if (iprops.size() < 5)
+ iprops.resize(5);
+
+ trim_string(fname);
+ std::vector<dungeon_feature_type> feats = features_by_desc(fname);
+ if (feats.empty())
+ return;
- switch (ldfk)
+ for (int i = 0, size = feats.size(); i < size; ++i)
{
- case DNGN_UNSEEN:
- showed = 0;
- break;
+ feature_override fov;
+ fov.feat = feats[i];
+
+ fov.override.symbol = read_symbol(iprops[0]);
+ fov.override.magic_symbol = read_symbol(iprops[1]);
+ fov.override.colour = str_to_colour(iprops[2], BLACK);
+ fov.override.map_colour = str_to_colour(iprops[3], BLACK);
+ fov.override.seen_colour = str_to_colour(iprops[4], BLACK);
- case DNGN_SECRET_DOOR:
- case DNGN_ROCK_WALL:
- case DNGN_PERMAROCK_WALL:
- case DNGN_STONE_WALL:
- case DNGN_METAL_WALL:
- case DNGN_GREEN_CRYSTAL_WALL:
- case DNGN_WAX_WALL:
- showed = 177;
- break;
+ Feature_Overrides.push_back(fov);
+ }
+}
- case DNGN_CLOSED_DOOR:
- showed = 254;
- break;
+void apply_feature_overrides()
+{
+ for (int i = 0, size = Feature_Overrides.size(); i < size; ++i)
+ {
+ const feature_override &fov = Feature_Overrides[i];
+ const feature_def &ofeat = fov.override;
+ feature_def &feat = Feature[fov.feat];
+
+ if (ofeat.symbol)
+ feat.symbol = ofeat.symbol;
+ if (ofeat.magic_symbol)
+ feat.magic_symbol = ofeat.magic_symbol;
+ if (ofeat.colour)
+ feat.colour = ofeat.colour;
+ if (ofeat.map_colour)
+ feat.map_colour = ofeat.map_colour;
+ if (ofeat.seen_colour)
+ feat.seen_colour = ofeat.seen_colour;
+ }
+}
- //case DNGN_LAVA_X: showed = 247; break; // deprecated? {dlb}
- //case DNGN_WATER_X: showed = 247; break; // deprecated? {dlb}
+void init_feature_table( void )
+{
+ for (int i = 0; i < NUM_FEATURES; i++)
+ {
+ Feature[i].symbol = 0;
+ Feature[i].colour = BLACK; // means must be set some other way
+ Feature[i].notable = false;
+ Feature[i].seen_effect = false;
+ Feature[i].magic_symbol = 0; // made equal to symbol if untouched
+ Feature[i].map_colour = DARKGREY;
+ Feature[i].seen_colour = BLACK; // marks no special seen map handling
+
+ switch (i)
+ {
+ case DNGN_UNSEEN:
+ default:
+ break;
- case 20: // orcish idol
- case 24: // ???
- case 25: // ???
- case DNGN_SILVER_STATUE:
- case DNGN_GRANITE_STATUE:
- case DNGN_ORANGE_CRYSTAL_STATUE:
- showed = '8';
- break;
+ case DNGN_ROCK_WALL:
+ case DNGN_PERMAROCK_WALL:
+ Feature[i].symbol = Options.char_table[ DCHAR_WALL ];
+ Feature[i].colour = EC_ROCK;
+ Feature[i].magic_symbol = Options.char_table[ DCHAR_WALL_MAGIC ];
+ break;
- case DNGN_LAVA:
- case DNGN_DEEP_WATER:
- case DNGN_SHALLOW_WATER:
- showed = 247;
- break;
+ case DNGN_STONE_WALL:
+ Feature[i].symbol = Options.char_table[ DCHAR_WALL ];
+ Feature[i].colour = EC_STONE;
+ Feature[i].magic_symbol = Options.char_table[ DCHAR_WALL_MAGIC ];
+ break;
- case DNGN_FLOOR:
- case DNGN_UNDISCOVERED_TRAP:
- showed = 249;
- break;
+ case DNGN_OPEN_DOOR:
+ Feature[i].symbol = Options.char_table[ DCHAR_DOOR_OPEN ];
+ Feature[i].colour = LIGHTGREY;
+ break;
- case 68:
- showed = '>';
- break; // <
+ case DNGN_CLOSED_DOOR:
+ Feature[i].symbol = Options.char_table[ DCHAR_DOOR_CLOSED ];
+ Feature[i].colour = LIGHTGREY;
+ break;
- case DNGN_OPEN_DOOR:
- showed = 39;
- break;
+ case DNGN_METAL_WALL:
+ Feature[i].symbol = Options.char_table[ DCHAR_WALL ];
+ Feature[i].colour = CYAN;
+ Feature[i].magic_symbol = Options.char_table[ DCHAR_WALL_MAGIC ];
+ break;
- case 72:
- showed = '<';
- break; // <
+ case DNGN_SECRET_DOOR:
+ // Note: get_secret_door_appearance means this probably isn't used
+ Feature[i].symbol = Options.char_table[ DCHAR_WALL ];
+ Feature[i].colour = EC_ROCK;
+ Feature[i].magic_symbol = Options.char_table[ DCHAR_WALL_MAGIC ];
+ break;
- case DNGN_TRAP_MECHANICAL:
- case DNGN_TRAP_MAGICAL:
- case DNGN_TRAP_III:
- showed = '^';
- break;
+ case DNGN_GREEN_CRYSTAL_WALL:
+ Feature[i].symbol = Options.char_table[ DCHAR_WALL ];
+ Feature[i].colour = GREEN;
+ Feature[i].magic_symbol = Options.char_table[ DCHAR_WALL_MAGIC ];
+ break;
- case DNGN_STONE_STAIRS_DOWN_I:
- case DNGN_STONE_STAIRS_DOWN_II:
- case DNGN_STONE_STAIRS_DOWN_III:
- case DNGN_ROCK_STAIRS_DOWN:
- 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 123:
- case 124:
- case 125:
- case 126:
- showed = '>';
- break;
+ case DNGN_ORCISH_IDOL:
+ Feature[i].symbol = Options.char_table[ DCHAR_STATUE ];
+ Feature[i].colour = DARKGREY;
+ break;
- case DNGN_STONE_STAIRS_UP_I:
- case DNGN_STONE_STAIRS_UP_II:
- case DNGN_STONE_STAIRS_UP_III:
- case DNGN_ROCK_STAIRS_UP:
- 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 143:
- case 144:
- case 145:
- case 146:
- showed = '<';
- break;
+ case DNGN_WAX_WALL:
+ Feature[i].symbol = Options.char_table[ DCHAR_WALL ];
+ Feature[i].colour = YELLOW;
+ Feature[i].magic_symbol = Options.char_table[ DCHAR_WALL_MAGIC ];
+ break; // wax wall
- case DNGN_ENTER_HELL:
- case DNGN_ENTER_LABYRINTH:
- 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_STONE_ARCH:
- case DNGN_ENTER_PANDEMONIUM:
- case DNGN_EXIT_PANDEMONIUM:
- case DNGN_TRANSIT_PANDEMONIUM:
- case DNGN_ENTER_ZOT:
- case DNGN_RETURN_FROM_ZOT:
- showed = 239;
- break;
+ case DNGN_SILVER_STATUE:
+ Feature[i].symbol = Options.char_table[ DCHAR_STATUE ];
+ Feature[i].colour = WHITE;
+ Feature[i].seen_effect = true;
+ break;
- 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:
- showed = 220;
- break;
+ case DNGN_GRANITE_STATUE:
+ Feature[i].symbol = Options.char_table[ DCHAR_STATUE ];
+ Feature[i].colour = LIGHTGREY;
+ break;
- case DNGN_BLUE_FOUNTAIN:
- case DNGN_DRY_FOUNTAIN_I:
- case DNGN_SPARKLING_FOUNTAIN:
- case DNGN_DRY_FOUNTAIN_II:
- case DNGN_DRY_FOUNTAIN_III:
- case DNGN_DRY_FOUNTAIN_IV:
- case DNGN_DRY_FOUNTAIN_V:
- case DNGN_DRY_FOUNTAIN_VI:
- case DNGN_DRY_FOUNTAIN_VII:
- case DNGN_DRY_FOUNTAIN_VIII:
- case DNGN_PERMADRY_FOUNTAIN:
- showed = 159;
- break;
- default:
- showed = 0;
- break;
- }
+ case DNGN_ORANGE_CRYSTAL_STATUE:
+ Feature[i].symbol = Options.char_table[ DCHAR_STATUE ];
+ Feature[i].colour = LIGHTRED;
+ Feature[i].seen_effect = true;
+ break;
- return showed;
-}
+ case DNGN_LAVA:
+ Feature[i].symbol = Options.char_table[ DCHAR_WAVY ];
+ Feature[i].colour = RED;
+ break;
+ case DNGN_DEEP_WATER:
+ Feature[i].symbol = Options.char_table[ DCHAR_WAVY ];
+ Feature[i].colour = BLUE;
+ break;
-// realize that this is simply a repackaged version of
-// stuff::see_grid() -- make certain they correlate {dlb}:
-bool mons_near(struct monsters *monster, unsigned int foe)
-{
- // early out -- no foe!
- if (foe == MHITNOT)
- return (false);
+ case DNGN_SHALLOW_WATER:
+ Feature[i].symbol = Options.char_table[ DCHAR_WAVY ];
+ Feature[i].colour = CYAN;
+ break;
- if (foe == MHITYOU)
- {
- if (monster->x > you.x_pos - 9 && monster->x < you.x_pos + 9
- && monster->y > you.y_pos - 9 && monster->y < you.y_pos + 9)
- {
- if (env.show[monster->x - you.x_pos + 9][monster->y - you.y_pos + 9])
- return (true);
- }
- return (false);
- }
+ case DNGN_FLOOR:
+ Feature[i].symbol = Options.char_table[ DCHAR_FLOOR ];
+ Feature[i].colour = EC_FLOOR;
+ Feature[i].magic_symbol = Options.char_table[ DCHAR_FLOOR_MAGIC ];
+ break;
- // must be a monster
- struct monsters *myFoe = &menv[foe];
- if (myFoe->type >= 0)
- {
- if (monster->x > myFoe->x - 9 && monster->x < myFoe->x + 9
- && monster->y > myFoe->y - 9 && monster->y < myFoe->y + 9)
- {
- return (true);
- }
- }
+ case DNGN_EXIT_HELL:
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].colour = LIGHTRED;
+ Feature[i].notable = false;
+ Feature[i].map_colour = LIGHTGREY;
+ Feature[i].seen_colour = LIGHTRED;
+ break;
- return (false);
-} // end mons_near()
+ case DNGN_ENTER_HELL:
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].colour = RED;
+ Feature[i].notable = true;
+ Feature[i].map_colour = LIGHTGREY;
+ Feature[i].seen_colour = RED;
+ break;
+ case DNGN_TRAP_MECHANICAL:
+ Feature[i].colour = LIGHTCYAN;
+ Feature[i].symbol = Options.char_table[ DCHAR_TRAP ];
+ Feature[i].map_colour = LIGHTCYAN;
+ break;
-//---------------------------------------------------------------
-//
-// get_non_ibm_symbol
-//
-// Returns the character code and color for everything drawn
-// without the IBM graphics option.
-//
-//---------------------------------------------------------------
-void get_non_ibm_symbol(unsigned int object, unsigned short *ch,
- unsigned short *color)
-{
- ASSERT(color != NULL);
- ASSERT(ch != NULL);
+ case DNGN_TRAP_MAGICAL:
+ Feature[i].colour = MAGENTA;
+ Feature[i].symbol = Options.char_table[ DCHAR_TRAP ];
+ Feature[i].map_colour = MAGENTA;
+ break;
- switch (object)
- {
+ case DNGN_TRAP_III:
+ Feature[i].colour = LIGHTGREY;
+ Feature[i].symbol = Options.char_table[ DCHAR_TRAP ];
+ Feature[i].map_colour = LIGHTGREY;
+ break;
- case DNGN_UNSEEN:
- *ch = 0;
- break;
+ case DNGN_UNDISCOVERED_TRAP:
+ Feature[i].symbol = Options.char_table[ DCHAR_FLOOR ];
+ Feature[i].colour = EC_FLOOR;
+ Feature[i].magic_symbol = Options.char_table[ DCHAR_FLOOR_MAGIC ];
+ break;
- case DNGN_ROCK_WALL:
- case DNGN_PERMAROCK_WALL:
- *color = env.rock_colour;
- *ch = '#';
- break;
+ case DNGN_ENTER_SHOP:
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].colour = YELLOW;
+ Feature[i].notable = true;
+ Feature[i].map_colour = LIGHTGREY;
+ Feature[i].seen_colour = YELLOW;
+ break;
- case DNGN_STONE_WALL:
- if (player_in_branch( BRANCH_HALL_OF_ZOT ))
- *color = env.rock_colour;
- else
- *color = LIGHTGREY;
- *ch = '#';
- break;
+ case DNGN_ENTER_LABYRINTH:
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].colour = CYAN;
+ Feature[i].notable = true;
+ Feature[i].map_colour = LIGHTGREY;
+ Feature[i].seen_colour = CYAN;
+ break;
- case DNGN_CLOSED_DOOR:
- *ch = '+';
- break;
+ case DNGN_ROCK_STAIRS_DOWN:
+ case DNGN_STONE_STAIRS_DOWN_I:
+ case DNGN_STONE_STAIRS_DOWN_II:
+ case DNGN_STONE_STAIRS_DOWN_III:
+ Feature[i].symbol = Options.char_table[ DCHAR_STAIRS_DOWN ];
+ Feature[i].colour = ((i == DNGN_ROCK_STAIRS_DOWN) ? BROWN
+ : LIGHTGREY);
+ Feature[i].map_colour = RED;
+ break;
- case DNGN_METAL_WALL:
- *ch = '#';
- *color = CYAN;
- break;
+ case DNGN_ROCK_STAIRS_UP:
+ case DNGN_STONE_STAIRS_UP_I:
+ case DNGN_STONE_STAIRS_UP_II:
+ case DNGN_STONE_STAIRS_UP_III:
+ Feature[i].symbol = Options.char_table[ DCHAR_STAIRS_UP ];
+ Feature[i].colour = ((i == DNGN_ROCK_STAIRS_UP) ? BROWN
+ : LIGHTGREY);
+ Feature[i].map_colour = GREEN;
+ break;
- case DNGN_SECRET_DOOR:
- *ch = '#';
- *color = env.rock_colour;
- break;
+ case DNGN_ENTER_DIS:
+ Feature[i].colour = CYAN;
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = LIGHTGREY;
+ Feature[i].seen_colour = CYAN;
+ break;
- case DNGN_GREEN_CRYSTAL_WALL:
- *ch = '#';
- *color = GREEN;
- break;
+ case DNGN_ENTER_GEHENNA:
+ Feature[i].colour = RED;
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = LIGHTGREY;
+ Feature[i].seen_colour = RED;
+ break;
- case DNGN_ORCISH_IDOL:
- *ch = '8';
- *color = DARKGREY;
- break;
+ case DNGN_ENTER_COCYTUS:
+ Feature[i].colour = LIGHTCYAN;
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = LIGHTGREY;
+ Feature[i].seen_colour = LIGHTCYAN;
+ break;
- case DNGN_WAX_WALL:
- *ch = '#';
- *color = YELLOW;
- break;
+ case DNGN_ENTER_TARTARUS:
+ Feature[i].colour = DARKGREY;
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = LIGHTGREY;
+ Feature[i].seen_colour = DARKGREY;
+ break;
- case DNGN_SILVER_STATUE:
- *ch = '8';
- *color = WHITE;
- Visible_Statue[ STATUE_SILVER ] = 1;
- break;
+ case DNGN_ENTER_ABYSS:
+ Feature[i].colour = EC_RANDOM;
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = LIGHTGREY;
+ Feature[i].seen_colour = EC_RANDOM;
+ break;
- case DNGN_GRANITE_STATUE:
- *ch = '8';
- *color = LIGHTGREY;
- break;
+ case DNGN_EXIT_ABYSS:
+ Feature[i].colour = EC_RANDOM;
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].map_colour = EC_RANDOM;
+ break;
- case DNGN_ORANGE_CRYSTAL_STATUE:
- *ch = '8';
- *color = LIGHTRED;
- Visible_Statue[ STATUE_ORANGE_CRYSTAL ] = 1;
- break;
+ case DNGN_STONE_ARCH:
+ Feature[i].colour = LIGHTGREY;
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].map_colour = LIGHTGREY;
+ break;
- case DNGN_LAVA:
- *ch = '{';
- *color = RED;
- break;
+ case DNGN_ENTER_PANDEMONIUM:
+ Feature[i].colour = LIGHTBLUE;
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = LIGHTGREY;
+ Feature[i].seen_colour = LIGHTBLUE;
+ break;
- case DNGN_DEEP_WATER:
- *ch = '{';
- // this wavy thing also used for water elemental
- // note that some monsters which use IBM graphics aren't set
- // for this function - too tricky for now.
- *color = BLUE;
- break;
+ case DNGN_EXIT_PANDEMONIUM:
+ // Note: has special handling for colouring with mutation
+ Feature[i].colour = LIGHTBLUE;
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].map_colour = LIGHTGREY;
+ Feature[i].seen_colour = LIGHTBLUE;
+ break;
- case DNGN_SHALLOW_WATER:
- *color = CYAN;
- *ch = '{';
- break;
+ case DNGN_TRANSIT_PANDEMONIUM:
+ Feature[i].colour = LIGHTGREEN;
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].map_colour = LIGHTGREY;
+ Feature[i].seen_colour = LIGHTGREEN;
+ break;
- case DNGN_FLOOR:
- *color = env.floor_colour;
- *ch = '.';
- break;
+ 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_RESERVED_1:
+ case DNGN_ENTER_RESERVED_2:
+ case DNGN_ENTER_RESERVED_3:
+ case DNGN_ENTER_RESERVED_4:
+ Feature[i].colour = YELLOW;
+ Feature[i].symbol = Options.char_table[ DCHAR_STAIRS_DOWN ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = RED;
+ Feature[i].seen_colour = LIGHTRED;
+ break;
- case DNGN_ENTER_HELL:
- *color = RED;
- *ch = '\\';
- seen_other_thing(DNGN_ENTER_HELL);
- break;
+ case DNGN_ENTER_ZOT:
+ Feature[i].colour = MAGENTA;
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = LIGHTGREY;
+ Feature[i].seen_colour = MAGENTA;
+ break;
- case DNGN_OPEN_DOOR:
- *ch = '\'';
- break;
+ 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_RESERVED_1:
+ case DNGN_RETURN_RESERVED_2:
+ case DNGN_RETURN_RESERVED_3:
+ case DNGN_RETURN_RESERVED_4:
+ Feature[i].colour = YELLOW;
+ Feature[i].symbol = Options.char_table[ DCHAR_STAIRS_UP ];
+ Feature[i].map_colour = BLUE;
+ Feature[i].seen_colour = LIGHTBLUE;
+ break;
- case DNGN_BRANCH_STAIRS:
- *color = BROWN;
- *ch = '>';
- break;
+ case DNGN_RETURN_FROM_ZOT:
+ Feature[i].colour = MAGENTA;
+ Feature[i].symbol = Options.char_table[ DCHAR_ARCH ];
+ Feature[i].map_colour = LIGHTGREY;
+ Feature[i].seen_colour = MAGENTA;
+ break;
- case DNGN_TRAP_MECHANICAL:
- *color = 11;
- *ch = '^';
- break;
+ case DNGN_ALTAR_ZIN:
+ Feature[i].colour = WHITE;
+ Feature[i].symbol = Options.char_table[ DCHAR_ALTAR ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = DARKGREY;
+ Feature[i].seen_colour = WHITE;
+ break;
- case DNGN_TRAP_MAGICAL:
- *color = MAGENTA;
- *ch = '^';
- break;
+ case DNGN_ALTAR_SHINING_ONE:
+ Feature[i].colour = YELLOW;
+ Feature[i].symbol = Options.char_table[ DCHAR_ALTAR ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = DARKGREY;
+ Feature[i].seen_colour = YELLOW;
+ break;
- case DNGN_TRAP_III:
- *color = LIGHTGREY;
- *ch = '^';
- break;
+ case DNGN_ALTAR_KIKUBAAQUDGHA:
+ Feature[i].colour = DARKGREY;
+ Feature[i].symbol = Options.char_table[ DCHAR_ALTAR ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = DARKGREY;
+ Feature[i].seen_colour = DARKGREY;
+ break;
- case DNGN_UNDISCOVERED_TRAP:
- *color = env.floor_colour;
- *ch = '.';
- break;
+ case DNGN_ALTAR_YREDELEMNUL:
+ Feature[i].colour = EC_UNHOLY;
+ Feature[i].symbol = Options.char_table[ DCHAR_ALTAR ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = DARKGREY;
+ Feature[i].seen_colour = EC_UNHOLY;
+ break;
- case DNGN_ENTER_SHOP:
- *color = YELLOW;
- *ch = '\\';
- seen_other_thing(DNGN_ENTER_SHOP);
- break;
-// if I change anything above here, must also change magic mapping!
+ case DNGN_ALTAR_XOM:
+ Feature[i].colour = EC_RANDOM;
+ Feature[i].symbol = Options.char_table[ DCHAR_ALTAR ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = DARKGREY;
+ Feature[i].seen_colour = EC_RANDOM;
+ break;
- case DNGN_ENTER_LABYRINTH:
- *color = LIGHTGREY;
- *ch = '\\';
- seen_other_thing(DNGN_ENTER_LABYRINTH);
- break;
+ case DNGN_ALTAR_VEHUMET:
+ Feature[i].colour = EC_VEHUMET;
+ Feature[i].symbol = Options.char_table[ DCHAR_ALTAR ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = DARKGREY;
+ Feature[i].seen_colour = EC_VEHUMET;
+ break;
- case DNGN_ROCK_STAIRS_DOWN:
- *color = BROWN; // ladder
- case DNGN_STONE_STAIRS_DOWN_I:
- case DNGN_STONE_STAIRS_DOWN_II:
- case DNGN_STONE_STAIRS_DOWN_III:
- *ch = '>';
- break;
+ case DNGN_ALTAR_OKAWARU:
+ Feature[i].colour = CYAN;
+ Feature[i].symbol = Options.char_table[ DCHAR_ALTAR ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = DARKGREY;
+ Feature[i].seen_colour = CYAN;
+ break;
- case DNGN_ROCK_STAIRS_UP:
- *color = BROWN; // ladder
- case DNGN_STONE_STAIRS_UP_I:
- case DNGN_STONE_STAIRS_UP_II:
- case DNGN_STONE_STAIRS_UP_III:
- *ch = '<';
- break;
+ case DNGN_ALTAR_MAKHLEB:
+ Feature[i].colour = EC_FIRE;
+ Feature[i].symbol = Options.char_table[ DCHAR_ALTAR ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = DARKGREY;
+ Feature[i].seen_colour = EC_FIRE;
+ break;
- case DNGN_ENTER_DIS:
- *color = CYAN;
- *ch = '\\';
- break;
+ case DNGN_ALTAR_SIF_MUNA:
+ Feature[i].colour = BLUE;
+ Feature[i].symbol = Options.char_table[ DCHAR_ALTAR ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = DARKGREY;
+ Feature[i].seen_colour = BLUE;
+ break;
- case DNGN_ENTER_GEHENNA:
- *color = RED;
- *ch = '\\';
- break;
+ case DNGN_ALTAR_TROG:
+ Feature[i].colour = RED;
+ Feature[i].symbol = Options.char_table[ DCHAR_ALTAR ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = DARKGREY;
+ Feature[i].seen_colour = RED;
+ break;
- case DNGN_ENTER_COCYTUS:
- *color = LIGHTCYAN;
- *ch = '\\';
- break;
+ case DNGN_ALTAR_NEMELEX_XOBEH:
+ Feature[i].colour = LIGHTMAGENTA;
+ Feature[i].symbol = Options.char_table[ DCHAR_ALTAR ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = DARKGREY;
+ Feature[i].seen_colour = LIGHTMAGENTA;
+ break;
- case DNGN_ENTER_TARTARUS:
- *color = DARKGREY;
- *ch = '\\';
- break;
+ case DNGN_ALTAR_ELYVILON:
+ Feature[i].colour = LIGHTGREY;
+ Feature[i].symbol = Options.char_table[ DCHAR_ALTAR ];
+ Feature[i].notable = true;
+ Feature[i].map_colour = DARKGREY;
+ Feature[i].seen_colour = LIGHTGREY;
+ break;
- case DNGN_ENTER_ABYSS:
- *color = random2(16);
- *ch = '\\';
- seen_other_thing(DNGN_ENTER_ABYSS);
- break;
+ case DNGN_BLUE_FOUNTAIN:
+ Feature[i].colour = BLUE;
+ Feature[i].symbol = Options.char_table[ DCHAR_FOUNTAIN ];
+ break;
- case DNGN_EXIT_ABYSS:
- *color = random2(16);
- *ch = '\\';
- break;
+ case DNGN_SPARKLING_FOUNTAIN:
+ Feature[i].colour = LIGHTBLUE;
+ Feature[i].symbol = Options.char_table[ DCHAR_FOUNTAIN ];
+ break;
- case DNGN_STONE_ARCH:
- *color = LIGHTGREY;
- *ch = '\\';
- break;
+ case DNGN_DRY_FOUNTAIN_I:
+ case DNGN_DRY_FOUNTAIN_II:
+ case DNGN_PERMADRY_FOUNTAIN:
+ Feature[i].colour = LIGHTGREY;
+ Feature[i].symbol = Options.char_table[ DCHAR_FOUNTAIN ];
+ break;
- case DNGN_ENTER_PANDEMONIUM:
- *color = LIGHTBLUE;
- *ch = '\\';
- seen_other_thing(DNGN_ENTER_PANDEMONIUM);
- break;
+ case DNGN_INVIS_EXPOSED:
+ Feature[i].symbol = Options.char_table[ DCHAR_INVIS_EXPOSED ];
+ break;
- case DNGN_EXIT_PANDEMONIUM:
- *color = LIGHTBLUE;
- *ch = '\\';
- break;
+ case DNGN_ITEM_DETECTED:
+ Feature[i].magic_symbol = Options.char_table[ DCHAR_ITEM_DETECTED ];
+ break;
- case DNGN_TRANSIT_PANDEMONIUM:
- *color = LIGHTGREEN;
- *ch = '\\';
- break; // gate to other part of pandemonium
-
- 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 123:
- case 124:
- case 125:
- case 126:
- *color = YELLOW;
- *ch = '>';
- seen_staircase(object);
- break;
+ case DNGN_ITEM_ORB:
+ Feature[i].symbol = Options.char_table[ DCHAR_ITEM_ORB ];
+ break;
- case DNGN_ENTER_ZOT:
- *color = MAGENTA;
- *ch = '\\';
- seen_staircase(object);
- break;
+ case DNGN_ITEM_WEAPON:
+ Feature[i].symbol = Options.char_table[ DCHAR_ITEM_WEAPON ];
+ break;
- 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 143:
- case 144:
- case 145:
- case 146:
- *color = YELLOW;
- *ch = '<';
- break;
+ case DNGN_ITEM_ARMOUR:
+ Feature[i].symbol = Options.char_table[ DCHAR_ITEM_ARMOUR ];
+ break;
- case DNGN_RETURN_FROM_ZOT:
- *color = MAGENTA;
- *ch = '\\';
- break;
+ case DNGN_ITEM_WAND:
+ Feature[i].symbol = Options.char_table[ DCHAR_ITEM_WAND ];
+ break;
- case DNGN_ALTAR_ZIN:
- *color = WHITE;
- *ch = '_';
- seen_altar(GOD_ZIN);
- break;
+ case DNGN_ITEM_FOOD:
+ Feature[i].symbol = Options.char_table[ DCHAR_ITEM_FOOD ];
+ break;
- case DNGN_ALTAR_SHINING_ONE:
- *color = YELLOW;
- *ch = '_';
- seen_altar(GOD_SHINING_ONE);
- break;
+ case DNGN_ITEM_SCROLL:
+ Feature[i].symbol = Options.char_table[ DCHAR_ITEM_SCROLL ];
+ break;
- case DNGN_ALTAR_KIKUBAAQUDGHA:
- *color = DARKGREY;
- *ch = '_';
- seen_altar(GOD_KIKUBAAQUDGHA);
- break;
+ case DNGN_ITEM_RING:
+ Feature[i].symbol = Options.char_table[ DCHAR_ITEM_RING ];
+ break;
- case DNGN_ALTAR_YREDELEMNUL:
- *color = DARKGREY;
- if (one_chance_in(3))
- *color = RED;
- *ch = '_';
- seen_altar(GOD_YREDELEMNUL);
- break;
+ case DNGN_ITEM_POTION:
+ Feature[i].symbol = Options.char_table[ DCHAR_ITEM_POTION ];
+ break;
- case DNGN_ALTAR_XOM:
- *color = random_colour();
- *ch = '_';
- seen_altar(GOD_XOM);
- break;
+ case DNGN_ITEM_MISSILE:
+ Feature[i].symbol = Options.char_table[ DCHAR_ITEM_MISSILE ];
+ break;
- case DNGN_ALTAR_VEHUMET:
- *color = LIGHTBLUE;
- if (one_chance_in(3))
- *color = LIGHTMAGENTA;
- if (one_chance_in(3))
- *color = LIGHTRED;
- *ch = '_';
- seen_altar(GOD_VEHUMET);
- break;
+ case DNGN_ITEM_BOOK:
+ Feature[i].symbol = Options.char_table[ DCHAR_ITEM_BOOK ];
+ break;
- case DNGN_ALTAR_OKAWARU:
- *color = CYAN;
- *ch = '_';
- seen_altar(GOD_OKAWARU);
- break;
+ case DNGN_ITEM_STAVE:
+ Feature[i].symbol = Options.char_table[ DCHAR_ITEM_STAVE ];
+ break;
- case DNGN_ALTAR_MAKHLEB:
- *color = RED;
- if (one_chance_in(3))
- *color = LIGHTRED;
- if (one_chance_in(3))
- *color = YELLOW;
- *ch = '_';
- seen_altar(GOD_MAKHLEB);
- break;
+ case DNGN_ITEM_MISCELLANY:
+ Feature[i].symbol = Options.char_table[ DCHAR_ITEM_MISCELLANY ];
+ break;
- case DNGN_ALTAR_SIF_MUNA:
- *color = BLUE;
- *ch = '_';
- seen_altar(GOD_SIF_MUNA);
- break;
+ case DNGN_ITEM_CORPSE:
+ Feature[i].symbol = Options.char_table[ DCHAR_ITEM_CORPSE ];
+ break;
- case DNGN_ALTAR_TROG:
- *color = RED;
- *ch = '_';
- seen_altar(GOD_TROG);
- break;
+ case DNGN_ITEM_GOLD:
+ Feature[i].symbol = Options.char_table[ DCHAR_ITEM_GOLD ];
+ break;
- case DNGN_ALTAR_NEMELEX_XOBEH:
- *color = LIGHTMAGENTA;
- *ch = '_';
- seen_altar(GOD_NEMELEX_XOBEH);
- break;
+ case DNGN_ITEM_AMULET:
+ Feature[i].symbol = Options.char_table[ DCHAR_ITEM_AMULET ];
+ break;
- case DNGN_ALTAR_ELYVILON:
- *color = LIGHTGREY;
- *ch = '_';
- seen_altar(GOD_ELYVILON);
- break;
+ case DNGN_CLOUD:
+ Feature[i].symbol = Options.char_table[ DCHAR_CLOUD ];
+ break;
+ }
+ }
- case DNGN_BLUE_FOUNTAIN:
- *color = BLUE;
- *ch = '}';
- break;
+ apply_feature_overrides();
- case DNGN_SPARKLING_FOUNTAIN:
- *color = LIGHTBLUE;
- *ch = '}';
- break;
+ for (int i = 0; i < NUM_FEATURES; ++i)
+ {
+ if (!Feature[i].magic_symbol)
+ Feature[i].magic_symbol = Feature[i].symbol;
- case DNGN_DRY_FOUNTAIN_I:
- case DNGN_DRY_FOUNTAIN_II:
- case DNGN_PERMADRY_FOUNTAIN:
- *color = LIGHTGREY;
- *ch = '}';
- break;
+ if (Feature[i].seen_colour == BLACK)
+ Feature[i].seen_colour = Feature[i].map_colour;
+ }
+}
- case 256:
- *ch = '0';
- break;
+static int get_screen_glyph( int x, int y )
+{
+ const int ex = x - you.x_pos + 9;
+ const int ey = y - you.y_pos + 9;
- case 257:
- *color = CYAN;
- *ch = '~';
- break; /* Invis creature walking through water */
+ int object = env.show[ex][ey];
+ unsigned short colour = env.show_col[ex][ey];
+ unsigned short ch;
- case 258:
- *ch = ')';
- break; // weapon )
+ if (!object)
+ return get_envmap_char(x, y);
- case 259:
- *ch = '[';
- break; // armour [
+ if (object == DNGN_SECRET_DOOR)
+ object = grid_secret_door_appearance( x, y );
- case 260:
- *ch = '/';
- break; // wands, etc.
+ get_symbol( object, &ch, &colour );
+ return (ch);
+}
- case 261:
- *ch = '%';
- break; // food
+// 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
+// snipped.
+std::string screenshot( bool fullscreen )
+{
+ UNUSED( fullscreen );
- case 262:
- *ch = '+';
- break; // books +
+ const int X_SIZE = VIEW_WIDTH;
+ const int Y_SIZE = VIEW_HEIGHT;
- case 263:
- *ch = '?';
- break; // scroll ?
+ // [ds] Screenshots need to be straight ASCII. We will now proceed to force
+ // the char and feature tables back to ASCII.
+ FixedVector<unsigned char, NUM_DCHAR_TYPES> char_table_bk;
+ char_table_bk = Options.char_table;
- case 264:
- *ch = '=';
- break; // ring = etc
+ init_char_table(CSET_ASCII);
+ init_feature_table();
+
+ int firstnonspace = -1;
+ int firstpopline = -1;
+ int lastpopline = -1;
- case 265:
- *ch = '!';
- break; // potions !
+ char lines[Y_SIZE][X_SIZE + 1];
+ for (int count_y = 0; count_y < Y_SIZE; count_y++)
+ {
+ int lastnonspace = -1;
+
+ for (int count_x = 0; count_x < X_SIZE; count_x++)
+ {
+ // in grid coords
+ const int gx = count_x + you.x_pos - 16;
+ const int gy = count_y + you.y_pos - 8;
+
+ int ch = (!map_bounds(gx, gy))
+ ? 0
+ : (count_x < 8 || count_x > 24)
+ ? get_envmap_char(gx, gy)
+ : (gx == you.x_pos && gy == you.y_pos)
+ ? you.symbol
+ : get_screen_glyph(gx, gy);
+
+ if (ch && !isprint(ch))
+ {
+ // [ds] Evil hack time again. Peek at grid, use that character.
+ int object = grd[gx][gy];
+ unsigned short glych, glycol;
- case 266:
- *ch = '(';
- break; // stones
+ if (object == DNGN_SECRET_DOOR)
+ object = grid_secret_door_appearance( gx, gy );
- case 267:
- *ch = ':';
- break; // book +
+ get_symbol( object, &glych, &glycol );
+ ch = glych;
+ }
+
+ // More mangling to accommodate C strings.
+ if (!ch)
+ ch = ' ';
- case 268:
- *ch = '%';
- break; // corpses part 1
+ if (ch != ' ')
+ {
+ lastnonspace = count_x;
+ lastpopline = count_y;
- case 269:
- *ch = '|';
- break; // magical staves
+ if (firstnonspace == -1 || firstnonspace > count_x)
+ firstnonspace = count_x;
- case 270:
- *ch = '}';
- break; // gems
+ if (firstpopline == -1)
+ firstpopline = count_y;
+ }
- case 271:
- *ch = '%';
- break; // don't know ?
+ lines[count_y][count_x] = ch;
+ }
- case 272:
- *ch = '$';
- *color = YELLOW;
- break; // $ gold
+ lines[count_y][lastnonspace + 1] = 0;
+ }
- case 273:
- *ch = '"';
- break; // amulet
+ // Restore char and feature tables
+ Options.char_table = char_table_bk;
+ init_feature_table();
- default:
- int mnr = object;
- *ch = ((mnr >= 297) ? mons_char(mnr - 297) : object); // yeah
- break;
+ std::string ss;
+ if (firstpopline != -1 && lastpopline != -1)
+ {
+ if (firstnonspace == -1)
+ firstnonspace = 0;
+
+ for (int i = firstpopline; i <= lastpopline; ++i)
+ {
+ char *curr = lines[i];
+
+ while (*curr && curr - lines[i] < firstnonspace)
+ curr++;
+
+ ss += curr;
+ ss += EOL;
+ }
}
-}
+ return (ss);
+}
-/*
- This is the viewwindow function for computers without IBM graphic displays.
- It is activated by a command line argument, which sets a function pointer.
- */
-void viewwindow3(char draw_it, bool do_updates)
+static int viewmap_flash_colour()
{
- int bufcount = 0;
- FixedVector < unsigned short, 1500 > buffy; //[800]; //392];
+ if (you.special_wield == SPWLD_SHADOW)
+ return (DARKGREY);
+ else if (you.berserker)
+ return (RED);
+
+ return (BLACK);
+}
- unsigned short ch, color;
+//---------------------------------------------------------------
+//
+// viewwindow -- now unified and rolled into a single pass
+//
+// Draws the main window using the character set returned
+// by get_symbol().
+//
+// This function should not interfere with the game condition,
+// unless do_updates is set (ie. stealth checks for visible
+// monsters).
+//
+//---------------------------------------------------------------
+void viewwindow(bool draw_it, bool do_updates)
+{
+ const int X_SIZE = VIEW_WIDTH;
+ const int Y_SIZE = VIEW_HEIGHT;
+ const int BUFFER_SIZE = 1550;
+ FixedVector < screen_buffer_t, BUFFER_SIZE > buffy;
int count_x, count_y;
- losight(env.show, grd, you.x_pos, you.y_pos);
+ losight( env.show, grd, you.x_pos, you.y_pos ); // must be done first
+
+ for (count_x = 0; count_x < NUM_STATUE_TYPES; count_x++)
+ you.visible_statue[count_x] = 0;
for (count_x = 0; count_x < 18; count_x++)
{
for (count_y = 0; count_y < 18; count_y++)
{
env.show_col[count_x][count_y] = LIGHTGREY;
- show_backup[count_x][count_y] = 0;
+ Show_Backup[count_x][count_y] = 0;
}
}
- item();
+ item_grid(); // must be done before cloud and monster
cloud_grid();
- monster_grid(do_updates);
- bufcount = 0;
+ monster_grid( do_updates );
- if (draw_it == 1)
+ if (draw_it)
{
_setcursortype(_NOCURSOR);
- for (count_y = (you.y_pos - 8); (count_y < you.y_pos + 9); count_y++)
- {
- bufcount += 16;
- for (count_x = (you.x_pos - 8); (count_x < you.x_pos + 9); count_x++)
+ const bool map = player_in_mappable_area();
+ int bufcount = 0;
+
+ int flash_colour = you.flash_colour;
+ if (flash_colour == BLACK)
+ flash_colour = viewmap_flash_colour();
+
+ for (count_y = 0; count_y < Y_SIZE; count_y++)
+ {
+ for (count_x = 0; count_x < X_SIZE; count_x++)
{
- color = env.show_col[count_x - you.x_pos + 9]
- [count_y - you.y_pos + 9];
+ // in grid coords
+ const int gx = count_x + you.x_pos - 16;
+ const int gy = count_y + you.y_pos - 8;
- if (count_x == you.x_pos && count_y == you.y_pos)
+ // order is important here
+ if (!map_bounds( gx, gy ))
{
- ch = your_sign;
+ // off the map
+ buffy[bufcount] = 0;
+ buffy[bufcount + 1] = DARKGREY;
+ }
+ else if (count_x < 8 || count_x > 24)
+ {
+ // outside the env.show area
+ buffy[bufcount] = get_envmap_char( gx, gy );
+ buffy[bufcount + 1] = DARKGREY;
+
+ if (Options.colour_map)
+ buffy[bufcount + 1] =
+ colour_code_map(gx - 1, gy - 1,
+ Options.item_colour);
+ }
+ else if (gx == you.x_pos && gy == you.y_pos)
+ {
+ // player overrides everything in cell
+ buffy[bufcount] = you.symbol;
+ buffy[bufcount + 1] = you.colour;
if (player_is_swimming())
{
- color = (grd[you.x_pos][you.y_pos] == DNGN_DEEP_WATER)
- ? BLUE : CYAN;
- }
- else
- {
- color = your_colour;
+ if (grd[gx][gy] == DNGN_DEEP_WATER)
+ buffy[bufcount + 1] = BLUE;
+ else
+ buffy[bufcount + 1] = CYAN;
}
}
else
{
- unsigned int object = env.show[count_x - you.x_pos + 9]
- [count_y - you.y_pos + 9];
+ // Note: env.show is set for grids in LoS
+ // get env coords
+ const int ex = gx - you.x_pos + 9;
+ const int ey = gy - you.y_pos + 9;
- get_non_ibm_symbol(object, &ch, &color);
- }
+ int object = env.show[ex][ey];
+ unsigned short colour = env.show_col[ex][ey];
+ unsigned short ch;
- buffy[bufcount] = ch; //showed;
- buffy[bufcount + 1] = color;
- bufcount += 2;
- }
+ if (object == DNGN_SECRET_DOOR)
+ object = grid_secret_door_appearance( gx, gy );
- bufcount += 16;
- }
+ get_symbol( object, &ch, &colour );
- bufcount = 0;
+ buffy[bufcount] = ch;
+ buffy[bufcount + 1] = colour;
- if (you.level_type != LEVEL_LABYRINTH
- && you.level_type != LEVEL_ABYSS)
- {
- for (count_y = 0; count_y < 17; count_y++)
- {
- bufcount += 16;
- for (count_x = 0; count_x < 17; count_x++)
- {
- int enx = count_x + you.x_pos - 9,
- eny = count_y + you.y_pos - 9;
- if (buffy[bufcount] != 0 && enx >= 0 && eny >= 0
- && enx + 1 < GXM && eny + 1 < GYM)
+ if (map)
{
- unsigned short bch = buffy[bufcount];
- if (mgrd[enx + 1][eny + 1] != NON_MONSTER) {
- const monsters &m = menv[ mgrd[enx + 1][eny + 1] ];
- if (!mons_is_mimic(m.type)
- && mons_char(m.type) == bch)
- {
- bch |= mons_colour(m.type) << 12;
- }
+ // This section is very tricky because it
+ // duplicates the old code (which was horrid).
+
+ // if the grid is in LoS env.show was set and
+ // we set the buffer already, so...
+ if (buffy[bufcount] != 0)
+ {
+ // ... map that we've seen this
+ set_envmap_char( gx, gy, buffy[bufcount] );
+ set_terrain_seen( gx, gy );
+ set_envmap_detected_mons(gx, gy, false);
+ set_envmap_detected_item(gx, gy, false);
}
- env.map[enx][eny] = bch;
- }
-
- if (Options.clean_map == 1
- && show_backup[count_x + 1][count_y + 1] != 0
- && enx >= 0
- && eny >= 0)
- {
- get_non_ibm_symbol( show_backup[count_x + 1]
- [count_y + 1],
- &ch, &color );
- env.map[enx][eny] = ch;
- }
- bufcount += 2;
- }
- bufcount += 16;
- }
- }
- bufcount = 0;
+ // Check if we're looking to clean_map...
+ // but don't touch the buffer to clean it,
+ // instead we modify the env.map itself so
+ // that the map stays clean as it moves out
+ // of the env.show radius.
+ //
+ // Note: show_backup is 0 on every square which
+ // is inside the env.show radius and doesn't
+ // have a monster or cloud on it, and is equal
+ // to the grid before monsters and clouds were
+ // added otherwise.
+ if (Options.clean_map
+ && Show_Backup[ex][ey]
+ && is_terrain_seen( gx, gy ))
+ {
+ get_symbol( Show_Backup[ex][ey], &ch, &colour );
+ set_envmap_char( gx, gy, ch );
+ }
- for (count_y = 0; count_y < 17; count_y++)
- {
- for (count_x = 0; count_x < 33; count_x++)
- {
- if (count_x + you.x_pos - 17 < 3
- || count_y + you.y_pos - 9 < 3
- || count_x + you.x_pos - 14 > (GXM - 3)
- || count_y + you.y_pos - 9 > (GYM - 3))
- {
- buffy[bufcount] = 0;
- bufcount++;
- buffy[bufcount] = 0;
- bufcount++;
- continue;
+ // Now we get to filling in both the unseen
+ // grids in the env.show radius area as
+ // well doing the clean_map. The clean_map
+ // is done by having the env.map set to the
+ // backup character above, and down here we
+ // procede to override that character if it's
+ // out of LoS! If it wasn't, buffy would have
+ // already been set (but we'd still have
+ // clobbered env.map... which is important
+ // to do for when we move away from the area!)
+ if (buffy[bufcount] == 0)
+ {
+ // show map
+ buffy[bufcount] = get_envmap_char( gx, gy );
+ buffy[bufcount + 1] = DARKGREY;
+
+ if (Options.colour_map)
+ buffy[bufcount + 1] =
+ colour_code_map(gx - 1, gy - 1,
+ Options.item_colour);
+ }
+ }
}
-
- if (count_x >= 8 && count_x <= 24 && count_y >= 0
- && count_y <= 16 && buffy[bufcount] != 0)
+
+ // alter colour if flashing the characters vision
+ if (flash_colour != BLACK
+ && buffy[bufcount + 1] != DARKGREY)
{
- bufcount += 2;
- continue;
- }
-
- buffy[bufcount] = (unsigned char)
- env.map[count_x + you.x_pos - 17]
- [count_y + you.y_pos - 9];
-
- buffy[bufcount + 1] = DARKGREY;
-
- if (Options.colour_map)
- {
- if (env.map[count_x + you.x_pos - 17]
- [count_y + you.y_pos - 9] != 0)
- {
- buffy[bufcount + 1]
- = colour_code_map( count_x + you.x_pos - 17,
- count_y + you.y_pos - 9,
- Options.item_colour );
- }
+ buffy[bufcount + 1] = flash_colour;
}
bufcount += 2;
}
}
- if (you.berserker)
- {
- for (count_x = 1; count_x < 1400; count_x += 2)
- {
- if (buffy[count_x] != DARKGREY)
- buffy[count_x] = RED;
- }
- }
-
- if (show_green != BLACK)
- {
- for (count_x = 1; count_x < 1400; count_x += 2)
- {
- if (buffy[count_x] != DARKGREY)
- buffy[count_x] = show_green;
- }
-
- show_green = ((you.special_wield == SPWLD_SHADOW) ? DARKGREY
- : BLACK);
- }
+ // Leaving it this way because short flashes can occur in long ones,
+ // and this simply works without requiring a stack.
+ you.flash_colour = BLACK;
#ifdef DOS_TERM
- puttext(2, 1, 34, 17, buffy.buffer());
+ puttext( 2, 1, X_SIZE + 1, Y_SIZE, buffy.buffer() );
#endif
#ifdef PLAIN_TERM
- gotoxy(2, 1);
- bufcount = 0;
-
- // this line is purely optional
- if (you.running == 0 || (you.running < 0 && Options.travel_delay > -1))
+ // avoiding unneeded draws when running
+ if (!you.running || (you.running < 0 && Options.travel_delay > -1))
{
- for (count_x = 0; count_x < 1120; count_x += 2) // 1056
- {
- textcolor(buffy[count_x + 1]);
- putch(buffy[count_x]);
+ gotoxy( 2, 1 );
- if (count_x % 66 == 64 && count_x > 0)
-#ifdef DOS_TERM
- cprintf(EOL " ");
+ bufcount = 0;
+ for (count_y = 0; count_y < Y_SIZE; count_y++)
+ {
+ for (count_x = 0; count_x < X_SIZE; count_x++)
+ {
+#ifdef USE_CURSES
+ buffy[bufcount] = cset_adjust( buffy[bufcount] );
#endif
+ textcolor( buffy[bufcount + 1] );
+ putch( buffy[bufcount] );
+ bufcount += 2;
+ }
-#ifdef PLAIN_TERM
- gotoxy(2, wherey() + 1);
-#endif
+ gotoxy( 2, count_y + 2 );
}
}
-#endif
- _setcursortype(_NORMALCURSOR);
- } // end of (if brek...)
-} // end viewwindow3()
-
-
-unsigned char mapchar3(unsigned char ldfk)
-{
- unsigned char showed = 0;
-
- switch (ldfk)
- {
- case DNGN_UNSEEN:
- showed = 0;
- break;
-
- case DNGN_SECRET_DOOR:
- case DNGN_ROCK_WALL:
- case DNGN_PERMAROCK_WALL:
- case DNGN_STONE_WALL:
- case DNGN_METAL_WALL:
- case DNGN_GREEN_CRYSTAL_WALL:
- case DNGN_WAX_WALL:
- showed = '*';
- break;
- case DNGN_CLOSED_DOOR:
- showed = '+';
- break;
-
- case 20: // orcish idol
- case 24: // ???
- case 25: // ???
- case DNGN_SILVER_STATUE:
- case DNGN_GRANITE_STATUE:
- case DNGN_ORANGE_CRYSTAL_STATUE:
- showed = '8';
- break;
-
- case DNGN_LAVA_X:
- case DNGN_WATER_X:
- case DNGN_LAVA:
- case DNGN_DEEP_WATER:
- case DNGN_SHALLOW_WATER:
- showed = '{';
- break;
-
- case DNGN_FLOOR:
- case DNGN_UNDISCOVERED_TRAP:
- showed = ',';
- break;
-
- //case 68: showed = '>'; break; // < (60)
-
- case DNGN_OPEN_DOOR:
- showed = 39;
- break; // open door
-
- //case 72: showed = '<'; break;
-
- case DNGN_TRAP_MECHANICAL:
- case DNGN_TRAP_MAGICAL:
- case DNGN_TRAP_III:
- showed = '^';
- break;
-
- case DNGN_STONE_STAIRS_DOWN_I:
- case DNGN_STONE_STAIRS_DOWN_II:
- case DNGN_STONE_STAIRS_DOWN_III:
- case DNGN_ROCK_STAIRS_DOWN:
- 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 123:
- case 124:
- case 125:
- case 126:
- showed = '>';
- break;
-
- case DNGN_STONE_STAIRS_UP_I:
- case DNGN_STONE_STAIRS_UP_II:
- case DNGN_STONE_STAIRS_UP_III:
- case DNGN_ROCK_STAIRS_UP:
- 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 143:
- case 144:
- case 145:
- case 146:
- showed = '<';
- break;
-
- case DNGN_ENTER_HELL:
- case DNGN_ENTER_LABYRINTH:
- 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_STONE_ARCH:
- case DNGN_ENTER_PANDEMONIUM:
- case DNGN_EXIT_PANDEMONIUM:
- case DNGN_TRANSIT_PANDEMONIUM:
- case DNGN_ENTER_ZOT:
- case DNGN_RETURN_FROM_ZOT:
- showed = '\\';
- break;
-
- 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:
- showed = '_';
- break;
-
- case DNGN_BLUE_FOUNTAIN:
- case DNGN_DRY_FOUNTAIN_I:
- case DNGN_SPARKLING_FOUNTAIN:
- case DNGN_DRY_FOUNTAIN_II:
- case DNGN_DRY_FOUNTAIN_III:
- case DNGN_DRY_FOUNTAIN_IV:
- case DNGN_DRY_FOUNTAIN_V:
- case DNGN_DRY_FOUNTAIN_VI:
- case DNGN_DRY_FOUNTAIN_VII:
- case DNGN_DRY_FOUNTAIN_VIII:
- case DNGN_PERMADRY_FOUNTAIN:
- showed = '}';
- break;
-
- default:
- showed = 0;
- break;
- }
-
- return showed;
-}
-
-
-unsigned char mapchar4(unsigned char ldfk)
-{
- unsigned char showed = 0;
-
- switch (ldfk)
- {
- case DNGN_UNSEEN:
- showed = 0;
- break;
-
- case DNGN_CLOSED_DOOR:
- showed = '+';
- break;
-
- case DNGN_SECRET_DOOR:
- case DNGN_ROCK_WALL:
- case DNGN_PERMAROCK_WALL:
- case DNGN_STONE_WALL:
- case DNGN_METAL_WALL:
- case DNGN_GREEN_CRYSTAL_WALL:
- case DNGN_WAX_WALL:
- showed = '#';
- break;
-
- case 20: // orcish idol
- case 24: // ???
- case 25: // ???
- case DNGN_SILVER_STATUE:
- case DNGN_GRANITE_STATUE:
- case DNGN_ORANGE_CRYSTAL_STATUE:
- showed = '8';
- break;
-
- case DNGN_LAVA_X:
- case DNGN_WATER_X:
- case DNGN_LAVA:
- case DNGN_DEEP_WATER:
- case DNGN_SHALLOW_WATER:
- showed = '{';
- break;
-
- case DNGN_FLOOR:
- case DNGN_UNDISCOVERED_TRAP:
- showed = '.';
- break;
-
- case 68:
- showed = '>'; // <
- break;
-
- case DNGN_OPEN_DOOR:
- showed = 39;
- break;
-
- case 72:
- showed = '<';
- break;
-
- case DNGN_TRAP_MECHANICAL:
- case DNGN_TRAP_MAGICAL:
- case DNGN_TRAP_III:
- showed = '^';
- break;
-
- case DNGN_STONE_STAIRS_DOWN_I:
- case DNGN_STONE_STAIRS_DOWN_II:
- case DNGN_STONE_STAIRS_DOWN_III:
- case DNGN_ROCK_STAIRS_DOWN:
- 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 123:
- case 124:
- case 125:
- case 126:
- showed = '>';
- break;
-
- case DNGN_STONE_STAIRS_UP_I:
- case DNGN_STONE_STAIRS_UP_II:
- case DNGN_STONE_STAIRS_UP_III:
- case DNGN_ROCK_STAIRS_UP:
- 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 143:
- case 144:
- case 145:
- case 146:
- showed = '<';
- break;
-
- case DNGN_ENTER_HELL:
- case DNGN_ENTER_LABYRINTH:
- 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_STONE_ARCH:
- case DNGN_ENTER_PANDEMONIUM:
- case DNGN_EXIT_PANDEMONIUM:
- case DNGN_TRANSIT_PANDEMONIUM:
- case DNGN_ENTER_ZOT:
- case DNGN_RETURN_FROM_ZOT:
- showed = '\\';
- break;
-
- 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:
- showed = '_';
- break;
-
- case DNGN_BLUE_FOUNTAIN:
- case DNGN_DRY_FOUNTAIN_I:
- case DNGN_SPARKLING_FOUNTAIN:
- case DNGN_DRY_FOUNTAIN_II:
- case DNGN_DRY_FOUNTAIN_III:
- case DNGN_DRY_FOUNTAIN_IV:
- case DNGN_DRY_FOUNTAIN_V:
- case DNGN_DRY_FOUNTAIN_VI:
- case DNGN_DRY_FOUNTAIN_VII:
- case DNGN_DRY_FOUNTAIN_VIII:
- case DNGN_PERMADRY_FOUNTAIN:
- showed = '}';
- break;
+#ifdef USE_CURSES
+ set_altcharset( false );
+#endif
- default:
- showed = 0;
- break;
+#endif
+ _setcursortype(_NORMALCURSOR);
}
-
- return showed;
-}
+} // end viewwindow()
diff --git a/crawl-ref/source/view.h b/crawl-ref/source/view.h
index b36ff18551..26d17ada8c 100644
--- a/crawl-ref/source/view.h
+++ b/crawl-ref/source/view.h
@@ -3,6 +3,8 @@
* Summary: Misc function used to render the dungeon.
* Written by: Linley Henzell
*
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
* Change History (most recent first):
*
* <2> 9/29/99 BCR Added the BORDER_COLOR define
@@ -16,10 +18,13 @@
#include "externs.h"
-
#define BORDER_COLOR BROWN
+void init_char_table(char_set_type set);
+void init_feature_table( void );
+
int get_number_of_lines(void);
+int get_number_of_cols(void);
/* ***********************************************************************
* called from: dump_screenshot - chardump
@@ -69,14 +74,14 @@ void magic_mapping(int map_radius, int proportion);
* called from: acr - effects - it_use2 - it_use3 - item_use - spell -
* spells - spells3 - spells4
* *********************************************************************** */
-void noisy( int loudness, int nois_x, int nois_y );
+bool noisy( int loudness, int nois_x, int nois_y, const char *msg = NULL );
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: acr - spells3
* *********************************************************************** */
-void show_map( FixedVector<int, 2>& spec_place );
+void show_map( FixedVector<int, 2>& spec_place, bool travel_mode );
// last updated 12may2000 {dlb}
@@ -108,4 +113,36 @@ void clear_map();
bool is_feature(int feature, int x, int y);
+void set_envmap_char( int x, int y, unsigned char chr );
+void set_envmap_detected_item(int x, int y, bool detected = true);
+void set_envmap_detected_mons(int x, int y, bool detected = true);
+bool is_envmap_detected_item(int x, int y);
+bool is_envmap_detected_mons(int x, int y);
+void set_terrain_mapped( int x, int y );
+void set_terrain_seen( int x, int y );
+bool is_terrain_known( int x, int y );
+bool is_terrain_seen( int x, int 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);
+
+bool see_grid( int grx, int gry );
+
+std::string screenshot(bool fullscreen = false);
+
+unsigned char get_sightmap_char(int feature);
+unsigned char get_magicmap_char(int feature);
+
+void viewwindow(bool draw_it, bool do_updates);
+
+bool find_ray( int sourcex, int sourcey, int targetx, int targety,
+ bool allow_fallback, ray_def& ray );
+
+#if defined(WIN32CONSOLE) || defined(DOS)
+unsigned short dos_brand( unsigned short colour,
+ unsigned brand = CHATTR_REVERSE);
+#endif
+
#endif
diff --git a/crawl-ref/source/wpn-misc.cc b/crawl-ref/source/wpn-misc.cc
deleted file mode 100644
index c6d38f98e6..0000000000
--- a/crawl-ref/source/wpn-misc.cc
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- *********************************************************************
- * File: wpn-misc.cc *
- * Summary: temporary home for weapon f(x) until struct'ed *
- * Written by: don brodale <dbrodale@bigfootinteractive.com> *
- * *
- * Changelog(most recent first): *
- * *
- * <00> 12jun2000 dlb created after little thought *
- *********************************************************************
- */
-
-#include "AppHdr.h"
-#include "wpn-misc.h"
-
-#include "externs.h"
-
-// all of this will be replaced by a struct and data handlers {dlb}:
-
-/*
- **************************************************
- * *
- * BEGIN PUBLIC FUNCTIONS *
- * *
- **************************************************
-*/
-
-char damage_type(unsigned char wclass, unsigned char wtype)
-{
- char type_damage = DVORP_CRUSHING; // this is the default, btw {dlb}
-
- if (wclass == OBJ_WEAPONS)
- {
- switch (wtype)
- {
- case WPN_DAGGER:
- case WPN_DEMON_BLADE:
- case WPN_DOUBLE_SWORD:
- case WPN_GREAT_SWORD:
- case WPN_KATANA:
- case WPN_KNIFE:
- case WPN_LONG_SWORD:
- case WPN_QUICK_BLADE:
- case WPN_SABRE:
- case WPN_FALCHION:
- case WPN_SCIMITAR:
- case WPN_SCYTHE:
- case WPN_SHORT_SWORD:
- case WPN_TRIPLE_SWORD:
- type_damage = DVORP_SLICING;
- break;
-
- case WPN_DEMON_TRIDENT:
- case WPN_EVENINGSTAR:
- case WPN_GIANT_SPIKED_CLUB:
- case WPN_MORNINGSTAR:
- case WPN_SPEAR:
- case WPN_SPIKED_FLAIL:
- case WPN_TRIDENT:
- type_damage = DVORP_PIERCING;
- break;
-
- case WPN_WAR_AXE:
- case WPN_BATTLEAXE:
- case WPN_BROAD_AXE:
- case WPN_EXECUTIONERS_AXE:
- case WPN_GLAIVE:
- case WPN_HALBERD:
- case WPN_HAND_AXE:
- type_damage = DVORP_CHOPPING;
- break;
- }
- }
-
- return (type_damage);
-} // end damage_type()
-
-bool can_cut_meat(unsigned char wclass, unsigned char wtype)
-{
- int type = damage_type( wclass, wtype );
-
- if (type == DVORP_CHOPPING || type == DVORP_SLICING)
- return (true);
-
- return (false);
-}
-
-int hands_reqd_for_weapon(unsigned char wclass, unsigned char wtype)
-{
- int reqd_hands = HANDS_ONE_HANDED;
-
- switch (wclass)
- {
- case OBJ_WEAPONS:
- switch (wtype)
- {
- case WPN_HALBERD:
- case WPN_SCYTHE:
- case WPN_GLAIVE:
- case WPN_QUARTERSTAFF:
- case WPN_BATTLEAXE:
- case WPN_EXECUTIONERS_AXE:
- case WPN_GREAT_SWORD:
- case WPN_TRIPLE_SWORD:
- case WPN_GREAT_MACE:
- case WPN_GREAT_FLAIL:
- case WPN_GIANT_CLUB:
- case WPN_GIANT_SPIKED_CLUB:
- reqd_hands = HANDS_TWO_HANDED;
- break;
-
- case WPN_SPEAR:
- case WPN_TRIDENT:
- case WPN_DEMON_TRIDENT:
- case WPN_WAR_AXE:
- case WPN_BROAD_AXE:
- case WPN_KATANA:
- case WPN_DOUBLE_SWORD:
- reqd_hands = HANDS_ONE_OR_TWO_HANDED;
- break;
- }
- break;
-
- case OBJ_STAVES:
- reqd_hands = HANDS_TWO_HANDED;
- break;
- }
-
- return (reqd_hands);
-} // end hands_reqd_for_weapon()
-
-bool is_demonic(unsigned char weapon_subtype)
-{
- switch (weapon_subtype)
- {
- case WPN_DEMON_BLADE:
- case WPN_DEMON_WHIP:
- case WPN_DEMON_TRIDENT:
- return true;
-
- default:
- return false;
- }
-} // end is_demonic()
-
-bool launches_things( unsigned char weapon_subtype )
-{
- switch (weapon_subtype)
- {
- case WPN_SLING:
- case WPN_BOW:
- case WPN_CROSSBOW:
- case WPN_HAND_CROSSBOW:
- case WPN_BLOWGUN:
- return (true);
-
- default:
- return (false);
- }
-} // end launches_things()
-
-unsigned char launched_by(unsigned char weapon_subtype)
-{
- switch (weapon_subtype)
- {
- case WPN_BLOWGUN:
- return MI_NEEDLE;
- case WPN_SLING:
- return MI_STONE;
- case WPN_BOW:
- return MI_ARROW;
- case WPN_CROSSBOW:
- return MI_BOLT;
- case WPN_HAND_CROSSBOW:
- return MI_DART;
- default:
- return MI_EGGPLANT; // lame debugging code :P {dlb}
- }
-} // end launched_by()
-
-// this function returns the skill that the weapon would use in melee
-char weapon_skill(unsigned char wclass, unsigned char wtype)
-{
- char skill2use = SK_FIGHTING;
-
- if (wclass == OBJ_STAVES
- && (wtype < STAFF_SMITING || wtype >= STAFF_AIR))
- {
- skill2use = SK_STAVES;
- }
- else if (wclass != OBJ_WEAPONS)
- skill2use = SK_FIGHTING;
- else
- {
- switch (wtype)
- {
- case WPN_CLUB:
- case WPN_MACE:
- case WPN_HAMMER:
- case WPN_ANCUS:
- case WPN_WHIP:
- case WPN_FLAIL:
- case WPN_MORNINGSTAR:
- case WPN_GIANT_CLUB:
- case WPN_GIANT_SPIKED_CLUB:
- case WPN_EVENINGSTAR:
- case WPN_DEMON_WHIP:
- case WPN_SPIKED_FLAIL:
- case WPN_GREAT_FLAIL:
- case WPN_GREAT_MACE:
- case WPN_BOW:
- case WPN_BLOWGUN:
- case WPN_CROSSBOW:
- case WPN_HAND_CROSSBOW:
- skill2use = SK_MACES_FLAILS;
- break;
-
- case WPN_KNIFE:
- case WPN_DAGGER:
- case WPN_SHORT_SWORD:
- case WPN_QUICK_BLADE:
- case WPN_SABRE:
- skill2use = SK_SHORT_BLADES;
- break;
-
- case WPN_FALCHION:
- case WPN_LONG_SWORD:
- case WPN_SCIMITAR:
- case WPN_KATANA:
- case WPN_DOUBLE_SWORD:
- case WPN_DEMON_BLADE:
- case WPN_GREAT_SWORD:
- case WPN_TRIPLE_SWORD:
- skill2use = SK_LONG_SWORDS;
- break;
-
- case WPN_HAND_AXE:
- case WPN_WAR_AXE:
- case WPN_BROAD_AXE:
- case WPN_BATTLEAXE:
- case WPN_EXECUTIONERS_AXE:
- skill2use = SK_AXES;
- break;
-
- case WPN_SPEAR:
- case WPN_HALBERD:
- case WPN_GLAIVE:
- case WPN_SCYTHE:
- case WPN_TRIDENT:
- case WPN_DEMON_TRIDENT:
- skill2use = SK_POLEARMS;
- break;
-
- case WPN_QUARTERSTAFF:
- skill2use = SK_STAVES;
- break;
- }
- }
-
- return (skill2use);
-} // end weapon_skill()
-/*
- **************************************************
- * *
- * END PUBLIC FUNCTIONS *
- * *
- **************************************************
-*/
diff --git a/crawl-ref/source/wpn-misc.h b/crawl-ref/source/wpn-misc.h
deleted file mode 100644
index e1d45c8d4a..0000000000
--- a/crawl-ref/source/wpn-misc.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- *********************************************************************
- * File: wpn-misc.h *
- * Summary: temporary home for weapon f(x) until struct'ed *
- * Written by: don brodale <dbrodale@bigfootinteractive.com> *
- * *
- * Changelog(most recent first): *
- * *
- * <00> 12jun2000 dlb created after little thought *
- *********************************************************************
-*/
-
-
-#ifndef WPNMISC_H
-#define WPNMISC_H
-
-#include "externs.h"
-
-
-/* ***********************************************************************
- * called from: food.h
- * *********************************************************************** */
-bool can_cut_meat(unsigned char wclass, unsigned char wtype);
-
-/* ***********************************************************************
- * called from: acr - fight - food - item_use - itemname - spells2
- * *********************************************************************** */
-char damage_type(unsigned char wclass, unsigned char wtype);
-
-
-// last updated: 10jun2000 {dlb}
-/* ***********************************************************************
- * called from: describe - fight - item_use
- * *********************************************************************** */
-int hands_reqd_for_weapon(unsigned char wclass, unsigned char wtype);
-
-
-// last updated: 10jun2000 {dlb}
-/* ***********************************************************************
- * called from: dungeon - fight - item_use - randart
- * *********************************************************************** */
-bool is_demonic(unsigned char weapon_subtype);
-
-
-// last updated: 10jun2000 {dlb}
-/* ***********************************************************************
- * called from: dungeon - item_use - mstuff2
- * *********************************************************************** */
-unsigned char launched_by(unsigned char weapon_subtype);
-
-
-// last updated: 10jun2000 {dlb}
-/* ***********************************************************************
- * called from: describe - dungeon - fight - item_use - mstuff2 - randart -
- * spells2 - spells3
- * *********************************************************************** */
-bool launches_things( unsigned char weapon_subtype );
-
-
-// last updated: 10jun2000 {dlb}
-/* ***********************************************************************
- * called from: describe - fight - files - it_use3 - newgame - spells1
- * *********************************************************************** */
-char weapon_skill(unsigned char wclass, unsigned char wtype);
-
-
-#endif