--- /dev/null
+
+-- This file contains lua code used by NetHack core.
+-- Is it loaded once, at game start, and kept in memory until game exit.
+
+
+-- This is an example of generating an external file during gameplay,
+-- which is updated periodically.
+-- Intended for public servers using dgamelaunch as their login manager.
+local prev_dgl_extrainfo = 0;
+function mk_dgl_extrainfo()
+ if ((prev_dgl_extrainfo == 0) or (prev_dgl_extrainfo + 50 < u.moves)) then
+ local filename = nh.dump_fmtstr("/tmp/nethack.%n.%d.log");
+ local extrai, err = io.open(filename, "w");
+ if extrai then
+ local sortval = 0;
+ local dname = nh.dnum_name(u.dnum);
+ local dstr = "";
+ local astr = " ";
+ if u.uhave_amulet == 1 then
+ sortval = sortval + 1024;
+ astr = "A";
+ end
+ if dname == "Fort Ludios" then
+ dstr = "Knx";
+ sortval = sortval + 245;
+ elseif dname == "The Quest" then
+ dstr = "Q" .. u.dlevel;
+ sortval = sortval + 250 + u.dlevel;
+ elseif dname == "The Elemental Planes" then
+ dstr = "End";
+ sortval = sortval + 256;
+ elseif dname == "Vlad's Tower" then
+ dstr = "T" .. u.dlevel;
+ sortval = sortval + 235 + u.depth;
+ elseif dname == "Sokoban" then
+ dstr = "S" .. u.dlevel;
+ sortval = sortval + 225 + u.depth;
+ elseif dname == "The Gnomish Mines" then
+ dstr = "M" .. u.dlevel;
+ sortval = sortval + 215 + u.dlevel;
+ else
+ dstr = "D" .. u.depth;
+ sortval = sortval + u.depth;
+ end
+ local str = sortval .. "|" .. astr .. " " .. dstr;
+
+ extrai:write(str);
+ extrai:close();
+ else
+ -- failed to open the file.
+ nh.pline("Failed to open dgl extrainfo file: " .. err);
+ end
+ prev_dgl_extrainfo = u.moves;
+ end
+end
+
+
+-- Callback functions
+nhcore = {
+ -- start_new_game called once, when starting a new game
+ -- after "Welcome to NetHack" message has been given.
+ -- start_new_game = function() nh.pline("NEW GAME!"); end,
+
+ -- restore_old_game called once, when restoring a saved game
+ -- after "Welcome back to NetHack" message has been given.
+ -- restore_old_game = function() nh.pline("RESTORED OLD GAME!"); end,
+
+ -- moveloop_turn is called once per turn.
+ -- moveloop_turn = mk_dgl_extrainfo,
+
+ -- game_exit is called when the game exits (quit, saved, ...)
+ -- game_exit = function() end,
+};
+
and accessed on the target platform
replace quest.txt and associated conversion to quest.dat via makedefs with
Lua quest texts loaded at runtime
+callback lua functions from core at certain game actions
some altars are displayed in different colors (for tty and curses at least)
add 'quick_farsight' option to provide some control over random clairvoyance
where pausing to be able to browse temporarily visible aspects of the
local str = nh.an("unicorn");
+=== dnum_name
+
+Returns the full dungeon name (as defined in dungeon.lua) for the dungeon
+number given as parameter.
+
+Example:
+
+ local dungeon_name = nh.dnum_name(u.dnum);
+
+=== dump_fmtstr
+
+Returns a string replacing special format chars with game data.
+Only available if NetHack was compiled with DUMPLOG.
+
+|===
+| %% | literal '%'
+| %t | game start, timestamp
+| %T | current time, timestamp
+| %d | game start, YYYYMMDDhhmmss
+| %D | current time, YYYYMMDDhhmmss
+| %v | game version, eg. '3.7.0-0'
+| %u | UID
+| %n | player name
+| %N | first character of player name
+|===
+
+Example:
+
+ local filename = nh.dump_fmtstr("/tmp/nethack.%n.%d.log");
=== getlin
int lusername_size;
#endif
+ /* nhlua.c */
+ genericptr_t luacore; /* lua_State * */
+
/* o_init.c */
short disco[NUM_OBJECTS];
/* ### nhlua.c ### */
#if !defined(CROSSCOMPILE) || defined(CROSSCOMPILE_TARGET)
+extern void l_nhcore_init(void);
+extern void l_nhcore_done(void);
+extern void l_nhcore_call(int);
extern lua_State * nhl_init(void);
extern void nhl_done(lua_State *);
extern boolean nhl_loadlua(lua_State *, const char *);
#define SUPPRESS_HISTORY 4
#define URGENT_MESSAGE 8
+/* Lua callback functions */
+enum nhcore_calls {
+ NHCORE_START_NEW_GAME = 0,
+ NHCORE_RESTORE_OLD_GAME,
+ NHCORE_MOVELOOP_TURN,
+ NHCORE_GAME_EXIT,
+
+ NUM_NHCORE_CALLS
+};
+
/* Macros for messages referring to hands, eyes, feet, etc... */
enum bodypart_types {
ARM = 0,
/* once-per-turn things go here */
/********************************/
+ l_nhcore_call(NHCORE_MOVELOOP_TURN);
+
if (Glib)
glibr();
nh_timeout();
* any artifacts */
u_init();
+ l_nhcore_init();
+
#ifndef NO_SIGNAL
(void) signal(SIGINT, (SIG_RET_TYPE) done1);
#endif
: "%s %s, the%s %s %s, welcome back to NetHack!",
Hello((struct monst *) 0), g.plname, buf, g.urace.adj,
(currentgend && g.urole.name.f) ? g.urole.name.f : g.urole.name.m);
+
+ l_nhcore_call(new_game ? NHCORE_START_NEW_GAME : NHCORE_RESTORE_OLD_GAME);
}
#ifdef POSITIONBAR
MAX_LAN_USERNAME, /* lusername_size */
#endif /* MAX_LAN_USERNAME */
+ /* nhlua.c */
+ UNDEFINED_VALUE, /* luacore */
+
/* o_init.c */
DUMMY, /* disco */
nh_terminate(int status)
{
g.program_state.in_moveloop = 0; /* won't be returning to normal play */
+
+ l_nhcore_call(NHCORE_GAME_EXIT);
#ifdef MAC
getreturn("to exit");
#endif
if (!g.program_state.panicking) {
freedynamicdata();
dlb_cleanup();
+ l_nhcore_done();
}
#ifdef VMS
/* */
/* lua_CFunction prototypes */
+#ifdef DUMPLOG
+static int nhl_dump_fmtstr(lua_State *);
+#endif /* DUMPLOG */
+static int nhl_dnum_name(lua_State *);
static int nhl_test(lua_State *);
static int nhl_getmap(lua_State *);
static void nhl_add_table_entry_bool(lua_State *, const char *, boolean);
static int nhl_set_package_path(lua_State *, const char *);
static int traceback_handler(lua_State *);
+static const char *nhcore_call_names[NUM_NHCORE_CALLS] = {
+ "start_new_game",
+ "restore_old_game",
+ "moveloop_turn",
+ "game_exit",
+};
+static boolean nhcore_call_available[NUM_NHCORE_CALLS];
+
+void
+l_nhcore_init(void)
+{
+ if ((g.luacore = nhl_init()) != 0) {
+ if (!nhl_loadlua(g.luacore, "nhcore.lua")) {
+ g.luacore = (lua_State *) 0;
+ } else {
+ int i;
+
+ for (i = 0; i < NUM_NHCORE_CALLS; i++)
+ nhcore_call_available[i] = TRUE;
+ }
+ }
+}
+
+void
+l_nhcore_done(void)
+{
+ if (g.luacore) {
+ nhl_done(g.luacore);
+ g.luacore = 0;
+ }
+}
+
+void
+l_nhcore_call(int callidx)
+{
+ int ltyp;
+
+ if (callidx < 0 || callidx >= NUM_NHCORE_CALLS
+ || !g.luacore || !nhcore_call_available[callidx])
+ return;
+
+ lua_getglobal(g.luacore, "nhcore");
+ if (!lua_istable(g.luacore, -1)) {
+ /*impossible("nhcore is not a lua table");*/
+ nhl_done(g.luacore);
+ g.luacore = 0;
+ return;
+ }
+
+ lua_getfield(g.luacore, -1, nhcore_call_names[callidx]);
+ ltyp = lua_type(g.luacore, -1);
+ if (ltyp == LUA_TFUNCTION) {
+ lua_remove(g.luacore, -2); /* nhcore_call_names[callidx] */
+ lua_remove(g.luacore, -2); /* nhcore */
+ lua_call(g.luacore, 0, 1);
+ } else {
+ /*impossible("nhcore.%s is not a lua function",
+ nhcore_call_names[callidx]);*/
+ nhcore_call_available[callidx] = FALSE;
+ }
+}
+
void
nhl_error(lua_State *L, const char *msg)
{
return ret;
}
+#ifdef DUMPLOG
+/* local fname = dump_fmtstr("/tmp/nethack.%n.%d.log"); */
+static int
+nhl_dump_fmtstr(lua_State *L)
+{
+ int argc = lua_gettop(L);
+ char buf[512];
+
+ if (argc == 1)
+ lua_pushstring(L, dump_fmtstr(luaL_checkstring(L, 1), buf, TRUE));
+ else
+ nhl_error(L, "Expected a string parameter");
+ return 1;
+}
+#endif /* DUMPLOG */
+
+/* local dungeon_name = dnum_name(u.dnum); */
+static int
+nhl_dnum_name(lua_State *L)
+{
+ int argc = lua_gettop(L);
+
+ if (argc == 1) {
+ int dnum = luaL_checkinteger(L, 1);
+
+ if (dnum >= 0 && dnum < g.n_dgns)
+ lua_pushstring(L, g.dungeons[dnum].dname);
+ else
+ lua_pushstring(L, "");
+ } else
+ nhl_error(L, "Expected an integer parameter");
+ return 1;
+}
+
/*
test( { x = 123, y = 456 } );
*/
{"parse_config", nhl_parse_config},
{"get_config", nhl_get_config},
{"get_config_errors", l_get_config_errors},
+#ifdef DUMPLOG
+ {"dump_fmtstr", nhl_dump_fmtstr},
+#endif /* DUMPLOG */
+ {"dnum_name", nhl_dnum_name},
{NULL, NULL}
};
} else if (!strcmp(tkey, "role")) {
lua_pushstring(L, g.urole.name.m);
return 1;
+ } else if (!strcmp(tkey, "moves")) {
+ lua_pushinteger(L, g.moves);
+ return 1;
+ } else if (!strcmp(tkey, "uhave_amulet")) {
+ lua_pushinteger(L, u.uhave.amulet);
+ return 1;
+ } else if (!strcmp(tkey, "depth")) {
+ lua_pushinteger(L, depth(&u.uz));
+ return 1;
}
nhl_error(L, "Unknown u table index");
SPEC_LEVS = asmodeus.lua baalz.lua bigrm-*.lua castle.lua fakewiz?.lua \
juiblex.lua knox.lua medusa-?.lua minend-?.lua minefill.lua \
minetn-?.lua oracle.lua orcus.lua sanctum.lua soko?-?.lua \
- tower?.lua valley.lua wizard?.lua nhlib.lua themerms.lua \
+ tower?.lua valley.lua wizard?.lua nhcore.lua nhlib.lua themerms.lua \
astral.lua air.lua earth.lua fire.lua water.lua
QUEST_LEVS = ???-goal.lua ???-fil?.lua ???-loca.lua ???-strt.lua
"$(NH_DAT_DIR)/Mon-goal.lua",
"$(NH_DAT_DIR)/Mon-loca.lua",
"$(NH_DAT_DIR)/Mon-strt.lua",
+ "$(NH_DAT_DIR)/nhcore.lua",
"$(NH_DAT_DIR)/nhlib.lua",
"$(NH_DAT_DIR)/oracle.lua",
"$(NH_DAT_DIR)/orcus.lua",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "cd \"${NH_DAT_DIR}\"\n\"${NH_UTIL_DIR}\"/dlb cf nhdat help hh cmdhelp keyhelp history opthelp wizhelp dungeon.lua tribute asmodeus.lua baalz.lua bigrm-*.lua castle.lua fakewiz?.lua juiblex.lua knox.lua medusa-?.lua minend-?.lua minefill.lua minetn-?.lua oracle.lua orcus.lua sanctum.lua soko?-?.lua tower?.lua valley.lua wizard?.lua nhlib.lua themerms.lua astral.lua air.lua earth.lua fire.lua water.lua ???-goal.lua ???-fil?.lua ???-loca.lua ???-strt.lua bogusmon data engrave epitaph oracles options quest.lua rumors\n";
+ shellScript = "cd \"${NH_DAT_DIR}\"\n\"${NH_UTIL_DIR}\"/dlb cf nhdat help hh cmdhelp keyhelp history opthelp wizhelp dungeon.lua tribute asmodeus.lua baalz.lua bigrm-*.lua castle.lua fakewiz?.lua juiblex.lua knox.lua medusa-?.lua minend-?.lua minefill.lua minetn-?.lua oracle.lua orcus.lua sanctum.lua soko?-?.lua tower?.lua valley.lua wizard?.lua nhcore.lua nhlib.lua themerms.lua astral.lua air.lua earth.lua fire.lua water.lua ???-goal.lua ???-fil?.lua ???-loca.lua ???-strt.lua bogusmon data engrave epitaph oracles options quest.lua rumors\n";
};
3192867021A39F6A00325BEB /* Install */ = {
isa = PBXShellScriptBuildPhase;