summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/AppHdr.h6
-rw-r--r--crawl-ref/source/acr.cc4
-rw-r--r--crawl-ref/source/dat/descript.txt (renamed from crawl-ref/source/dat/descriptions.txt)0
-rw-r--r--crawl-ref/source/dat/splev.des5
-rw-r--r--crawl-ref/source/dat/vaults.des4
-rw-r--r--crawl-ref/source/database.cc246
-rw-r--r--crawl-ref/source/database.h31
-rw-r--r--crawl-ref/source/files.cc28
-rw-r--r--crawl-ref/source/files.h19
-rw-r--r--crawl-ref/source/ghost.cc1
-rw-r--r--crawl-ref/source/makefile.unix5
-rw-r--r--crawl-ref/source/mon-data.h5
12 files changed, 247 insertions, 107 deletions
diff --git a/crawl-ref/source/AppHdr.h b/crawl-ref/source/AppHdr.h
index 42c371f581..097cfb35a4 100644
--- a/crawl-ref/source/AppHdr.h
+++ b/crawl-ref/source/AppHdr.h
@@ -72,6 +72,8 @@
#define UNIX
#define USE_8_COLOUR_TERM_MAP
#define COL_TO_REPLACE_DARKGREY BLUE
+
+ #define DB_NDBM
#endif
// =========================================================================
@@ -399,6 +401,10 @@
# error Must define USE_FILE_LOCKING for DGL_SIMPLE_MESSAGING
#endif
+#ifndef DB_NDBM
+#define DB_DBH
+#endif
+
// Uncomment these if you can't find these functions on your system
// #define NEED_USLEEP
// #define NEED_SNPRINTF
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index d7bcd81287..0442ede796 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -228,7 +228,6 @@ int main( int argc, char *argv[] )
// override some options for tutorial
init_tutorial_options();
- databaseSystemInit();
if (game_start || Options.always_greet)
{
mprf( "Welcome, %s the %s %s.",
@@ -2878,6 +2877,9 @@ static bool initialise(void)
// Read special levels and vaults.
read_maps();
+
+ // Initialise internal databases.
+ databaseSystemInit();
cio_init();
diff --git a/crawl-ref/source/dat/descriptions.txt b/crawl-ref/source/dat/descript.txt
index 6bc96bb43e..6bc96bb43e 100644
--- a/crawl-ref/source/dat/descriptions.txt
+++ b/crawl-ref/source/dat/descript.txt
diff --git a/crawl-ref/source/dat/splev.des b/crawl-ref/source/dat/splev.des
index a1741de17e..5ff45b2593 100644
--- a/crawl-ref/source/dat/splev.des
+++ b/crawl-ref/source/dat/splev.des
@@ -2936,9 +2936,9 @@ MAP
.wIwwwwwwwwwwwwwwwwwwwwwwwww.
.ww2ccccccccccccccccccccccww.
.ww.c.......3.3.3......w2cww.
-.wwxx........3.3.......wwcww.
+.wwxx........3.3.......cccww.
.122........3.I.3......4Ocww.
-.wwxx........3.3.......wwcww.
+.wwxx........3.3.......cccww.
.ww.c.......3.3.3......w2cww.
.ww2ccccccccccccccccccccccww.
.wIwwwwwwwwwwwwwwwwwwwwwwwww.
@@ -2946,7 +2946,6 @@ MAP
.............................
ENDMAP
-
##############################################################################
# Just like home
#
diff --git a/crawl-ref/source/dat/vaults.des b/crawl-ref/source/dat/vaults.des
index d13d31d445..48f0123dce 100644
--- a/crawl-ref/source/dat/vaults.des
+++ b/crawl-ref/source/dat/vaults.des
@@ -3881,7 +3881,7 @@ FLAGS: no_rotate
ORIENT: float
ITEM: stone
MONS: rat, goblin, kobold, ooze
-SHUFFLE: {[(
+SHUFFLE: {[(
MAP
xxxxxxxxxxx@xxxxxxxxxxxxxxxxxx
x.........l.l................x
@@ -3903,7 +3903,7 @@ x.....lllll..4....lllllll....x
x.....llllll....lllllll......x
x.....lllllllllllll..........x
x.........lllllll............x
-x............................x
+x>..........................>x
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ENDMAP
diff --git a/crawl-ref/source/database.cc b/crawl-ref/source/database.cc
index 71927f6b8e..d8d954e912 100644
--- a/crawl-ref/source/database.cc
+++ b/crawl-ref/source/database.cc
@@ -14,48 +14,71 @@
#include <unistd.h>
#include <stdlib.h>
#endif
-#include <stdlib.h>
+#include <cstdlib>
+#include <fstream>
#include "database.h"
#include "files.h"
+#include "libutil.h"
+#include "stuff.h"
// Convenience functions for (read-only) access to generic
// berkeley DB databases.
-#define nil 0
+db_list openDBList;
+DBM *descriptionDB;
-static bool databaseIsInitted = false;
-dbList_t *openDBList;
-DBM *descriptionDB;
+#define DESC_BASE_NAME "descript"
+#define DESC_TXT (DESC_BASE_NAME ".txt")
+#define DESC_DB (DESC_BASE_NAME ".db")
-struct dbList_s {
- DBM *dbPtr;
- dbList_s *next;
-} dbList_s;
+static void generate_description_db();
+time_t file_modtime(const std::string &file)
+{
+ struct stat filestat;
+ if (stat(file.c_str(), &filestat))
+ return (0);
-void databaseSystemInit() {
- if (!databaseIsInitted) {
- databaseIsInitted = true;
- openDBList = nil;
- std::string descriptionPath = datafile_path("descriptions.db");
- descriptionPath.erase(descriptionPath.length() - 3, descriptionPath.length());
- descriptionDB = openDB(descriptionPath.c_str());
- }
+ return (filestat.st_mtime);
+}
+
+// Returns true if file a is newer than file b.
+bool is_newer(const std::string &a, const std::string &b)
+{
+ return (file_modtime(a) > file_modtime(b));
+}
+
+void check_newer(const std::string &target,
+ const std::string &dependency,
+ void (*action)())
+{
+ if (is_newer(dependency, target))
+ action();
}
-void databaseSystemShutdown() {
- if (!databaseIsInitted) {
- // All done.
- return;
+void databaseSystemInit()
+{
+ if (!descriptionDB)
+ {
+ std::string descriptionPath = get_savedir_path(DESC_DB);
+ check_newer(descriptionPath,
+ datafile_path(DESC_TXT),
+ generate_description_db);
+ descriptionPath.erase(descriptionPath.length() - 3);
+ if (!(descriptionDB = openDB(descriptionPath.c_str())))
+ end(1, true, "Failed to open DB: %s", descriptionPath.c_str());
}
- dbList_t *current = openDBList;
- dbList_t *prev = nil;
- while (current) {
- dbm_close(current->dbPtr);
- prev = current;
- current = current->next;
- free(prev);
+}
+
+void databaseSystemShutdown()
+{
+ for (db_list::iterator i = openDBList.begin();
+ i != openDBList.end(); ++i)
+ {
+ dbm_close(*i);
}
+ openDBList.clear();
+ descriptionDB = NULL;
}
// This is here, and is external, just for future expansion -- if we
@@ -64,76 +87,141 @@ void databaseSystemShutdown() {
// morally wrong to have the database module manage the memory here.
// But hey, life is hard and you can write your own berkeley DB
// calls if you like.
-DBM *openDB(const char *dbFilename) {
- if (!databaseIsInitted) {
- return nil;
- }
+DBM *openDB(const char *dbFilename)
+{
DBM *dbToReturn = dbm_open(dbFilename, O_RDONLY, 0660);
- if (dbToReturn) {
- if (openDBList) {
- dbList_t *endOfDBList = openDBList;
- while (openDBList->next) {
- endOfDBList = openDBList->next;
- }
- endOfDBList->next = (dbList_t *)malloc(sizeof(dbList_t));
- endOfDBList = endOfDBList->next;
- endOfDBList->next = nil;
- endOfDBList->dbPtr = dbToReturn;
-
- } else {
- openDBList = (dbList_t *)malloc(sizeof(dbList_t));
- openDBList->next = nil;
- openDBList->dbPtr = dbToReturn;
- }
- } else {
- dbToReturn = nil;
- }
+ if (dbToReturn)
+ openDBList.push_front(dbToReturn);
+
return dbToReturn;
}
-datum database_fetch(DBM *database, const char *key) {
+datum database_fetch(DBM *database, const std::string &key)
+{
datum result;
- result.dptr = nil;
+ result.dptr = NULL;
result.dsize = 0;
- if (!databaseIsInitted) {
- return result;
- }
datum dbKey;
- dbKey.dptr = (void *)key;
- dbKey.dsize = strlen(key);
+ dbKey.dptr = (DPTR_COERCE) key.c_str();
+ dbKey.dsize = key.length();
result = dbm_fetch(database, dbKey);
return result;
}
-char *private_strlwr(char *string) {
- int i;
- for (i = 0; string[i]; i++) {
- string[i] = tolower(string[i]);
- }
- return string;
-}
+std::string getLongDescription(const char *key)
+{
+ if (!descriptionDB)
+ return ("");
-std::string getLongDescription(const char *key) {
- if (!databaseIsInitted) {
- return nil;
- }
// We have to canonicalize the key (in case the user typed it
// in and got the case wrong.
- int len = strlen(key);
- char *lowercaseKey = (char *)malloc(len+1);
- (void) strncpy(lowercaseKey, key, len+1);
- lowercaseKey = private_strlwr(lowercaseKey);
+ std::string canonical_key = key;
+ lowercase(canonical_key);
// Query the DB.
- datum result = database_fetch(descriptionDB, (const char *)lowercaseKey);
+ datum result = database_fetch(descriptionDB, canonical_key);
// Cons up a (C++) string to return. The caller must release it.
- std::string stringToReturn((const char *)result.dptr, result.dsize);
- // free the result...
- free(lowercaseKey);
-
- return stringToReturn;
+ return std::string((const char *)result.dptr, result.dsize);
+}
+
+static void store_descriptions(const std::string &in, const std::string &out);
+static void generate_description_db()
+{
+ std::string db_path = get_savedir_path(DESC_BASE_NAME);
+ std::string txt_path = datafile_path(DESC_TXT);
+
+ file_lock lock(get_savedir_path(DESC_BASE_NAME ".lk"), "wb");
+ store_descriptions(txt_path, db_path);
+ DO_CHMOD_PRIVATE(get_savedir_path(DESC_DB).c_str());
+}
+
+static void trim_right(std::string &s)
+{
+ s.erase(s.find_last_not_of(" \r\t\n") + 1);
+}
+
+static void trim_leading_newlines(std::string &s)
+{
+ s.erase(0, s.find_first_not_of("\n"));
+}
+
+static void add_entry(DBM *db, const std::string &k, std::string &v)
+{
+ trim_leading_newlines(v);
+ datum key, value;
+ key.dptr = (char *) k.c_str();
+ key.dsize = k.length();
+
+ value.dptr = (char *) v.c_str();
+ value.dsize = v.length();
+
+ if (dbm_store(db, key, value, DBM_REPLACE))
+ end(1, true, "Error storing %s", k.c_str());
+}
+
+static void parse_descriptions(std::ifstream &inf, DBM *db)
+{
+ char buf[1000];
+
+ std::string key;
+ std::string value;
+
+ bool in_entry = false;
+ while (!inf.eof())
+ {
+ inf.getline(buf, sizeof buf);
+
+ if (*buf == '#')
+ continue;
+
+ if (!strncmp(buf, "%%%%", 4))
+ {
+ if (!key.empty())
+ add_entry(db, key, value);
+ key.clear();
+ value.clear();
+ in_entry = true;
+ continue;
+ }
+
+ if (!in_entry)
+ continue;
+
+ if (key.empty())
+ {
+ key = buf;
+ trim_string(key);
+ lowercase(key);
+ }
+ else
+ {
+ std::string line = buf;
+ trim_right(line);
+ value += line + "\n";
+ }
+ }
+
+ if (!key.empty())
+ add_entry(db, key, value);
+}
+
+static void store_descriptions(const std::string &in, const std::string &out)
+{
+ std::ifstream inf(in.c_str());
+ if (!inf)
+ end(1, true, "Unable to open input file: %s", in.c_str());
+
+ if (DBM *db = dbm_open(out.c_str(), O_RDWR | O_CREAT, 0660))
+ {
+ parse_descriptions(inf, db);
+ dbm_close(db);
+ }
+ else
+ end(1, true, "Unable to open DB: %s", out.c_str());
+
+ inf.close();
}
diff --git a/crawl-ref/source/database.h b/crawl-ref/source/database.h
index 71b8474033..364a87c7b6 100644
--- a/crawl-ref/source/database.h
+++ b/crawl-ref/source/database.h
@@ -10,29 +10,34 @@
#ifndef DATABASE_H
#define DATABASE_H
-#undef DEBUG // hack
-#define NDEBUG
+#include "AppHdr.h"
#include "externs.h"
+#include <list>
-#ifdef __cplusplus
extern "C" {
-#endif
+#ifdef DB_NDBM
-#include <ndbm.h>
+# include <ndbm.h>
+# define DPTR_COERCE void *
+
+#else
+
+# define DB_DBM_HSEARCH 1
+# include <db.h>
+# define DPTR_COERCE char *
-// For convenience during shutdown.
-typedef struct dbList_s dbList_t;
-#ifdef __cplusplus
-}
#endif
-extern dbList_t *openDBList;
+}
+
+typedef std::list<DBM *> db_list;
+
+extern db_list openDBList;
void databaseSystemInit();
void databaseSystemShutdown();
DBM *openDB(const char *dbFilename);
-datum *database_fetch(DBM *database, char *key);
-
+datum database_fetch(DBM *database, const std::string &key);
-std::string getLongDescription(const char *key);
+std::string getLongDescription(const std::string &key);
#endif
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index d8753231ef..72379982ad 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -80,12 +80,6 @@
#include "travel.h"
#include "tutorial.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, level_area_type lt,
branch_type where_were_you);
@@ -1646,3 +1640,25 @@ void lk_close(FILE *handle, const char *mode, const std::string &file)
chmod(file.c_str(), SHARED_FILES_CHMOD_PUBLIC);
#endif
}
+
+/////////////////////////////////////////////////////////////////////////////
+// file_lock
+//
+// Locks a named file (usually an empty lock file), creating it if necessary.
+
+file_lock::file_lock(const std::string &s, const char *_mode, bool die_on_fail)
+ : handle(NULL), mode(_mode), filename(s)
+{
+#ifdef USE_FILE_LOCKING
+ if (!(handle = lk_open(mode, filename)) && die_on_fail)
+ end(1, true, "Unable to open lock file \"%s\"", filename.c_str());
+#endif
+}
+
+file_lock::~file_lock()
+{
+#ifdef USE_FILE_LOCKING
+ if (handle)
+ lk_close(handle, mode, filename);
+#endif
+}
diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h
index 814c25b1eb..ccf73c3a62 100644
--- a/crawl-ref/source/files.h
+++ b/crawl-ref/source/files.h
@@ -40,6 +40,7 @@ std::string get_savedir_filename(const std::string &pre,
const std::string &suf,
const std::string &ext,
bool suppress_uid = false);
+std::string get_savedir_path(const std::string &shortpath);
std::string get_prefs_filename();
@@ -100,4 +101,22 @@ bool lock_file_handle( FILE *handle, int type );
bool unlock_file_handle( FILE *handle );
#endif // USE_FILE_LOCKING
+#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
+
+class file_lock
+{
+public:
+ file_lock(const std::string &filename, const char *mode,
+ bool die_on_fail = true);
+ ~file_lock();
+private:
+ FILE *handle;
+ const char *mode;
+ std::string filename;
+};
+
#endif
diff --git a/crawl-ref/source/ghost.cc b/crawl-ref/source/ghost.cc
index d09f1484ac..bda3da6972 100644
--- a/crawl-ref/source/ghost.cc
+++ b/crawl-ref/source/ghost.cc
@@ -85,6 +85,7 @@ static int search_order_misc[] = {
SPELL_BANISHMENT,
SPELL_PARALYSE,
SPELL_CONFUSE,
+ SPELL_MEPHITIC_CLOUD,
SPELL_SLOW,
SPELL_POLYMORPH_OTHER,
SPELL_TELEPORT_OTHER,
diff --git a/crawl-ref/source/makefile.unix b/crawl-ref/source/makefile.unix
index 709421c090..013022bb81 100644
--- a/crawl-ref/source/makefile.unix
+++ b/crawl-ref/source/makefile.unix
@@ -48,7 +48,10 @@ endif
LUALIB = lua
LUALIBA = l$(LUALIB).a
-LIB = -lncurses -L$(LUASRC) -l$(LUALIB)
+LIBDBM = $(shell [ "`ls /usr/lib/libdbm.* 2>/dev/null`" != "" ] \
+ && echo 'dbm' || echo 'db')
+
+LIB = -lncurses -L$(LUASRC) -l$(LUALIB) -l$(LIBDBM)
INCLUDES := $(INCLUDES) -Iutil -I. -I$(LUASRC)
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index 71bcba6ba9..f5b7a4b12c 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -2849,7 +2849,8 @@
{
MONS_DEEP_ELF_SORCERER, 'e', RED, "deep elf sorcerer",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS | M_SPEAKS,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS | M_SPEAKS
+ | M_EVIL,
MR_NO_FLAGS,
450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -6,
{ {AT_HIT, AF_PLAIN, 12}, {AT_NONE, AF_PLAIN, 0}, {AT_NONE, AF_PLAIN, 0}, {AT_NONE, AF_PLAIN, 0} },
@@ -4425,4 +4426,4 @@
MONUSE_STARTING_EQUIPMENT, SIZE_MEDIUM
},
-#endif \ No newline at end of file
+#endif