des.feature({ type = "throne", coord = {4, 6}, looted = true });
des.feature({ type = "tree", coord = {4, 6}, looted = true, swarm = false });
+=== finalize_level
+
+Only used for testing purposes. See also <<_reset_level>>.
+
+Example:
+
+ des.finalize_level();
+
=== gold
Create a pile of gold.
=== reset_level
-Only used for testing purposes.
+Only used for testing purposes. See also <<_finalize_level>>.
Example:
extern void makecorridors(void);
extern void add_door(int, int, struct mkroom *);
extern void clear_level_structures(void);
+extern void level_finalize_topology(void);
extern void mklev(void);
#ifdef SPECIALIZATION
extern void topologize(struct mkroom *, boolean));
int);
extern void selection_do_gradient(struct selectionvar *, long, long, long,
long, long, long, long, long);
+extern int lspo_reset_level(lua_State *);
+extern int lspo_finalize_level(lua_State *);
extern void update_croom(void);
extern const char *get_trapname_bytype(int);
extern void l_register_des(lua_State *);
* behaviour of various NetHack functions and probably warrant
* a structure of their own elsewhere some day.
*/
+ boolean lua_testing; /* doing lua tests */
boolean debug_fuzzer; /* fuzz testing */
boolean in_lua; /* executing a lua script */
boolean defer_plname; /* X11 hack: askname() might not set g.plname */
wiz_load_splua(void)
{
if (wizard) {
- boolean was_in_W_tower = In_W_tower(u.ux, u.uy, &u.uz);
char buf[BUFSZ];
- int ridx;
buf[0] = '\0';
getlin("Load which des lua file?", buf);
return 0;
if (!strchr(buf, '.'))
strcat(buf, ".lua");
- makemap_prepost(TRUE, was_in_W_tower);
-
- /* TODO: need to split some of this out of mklev(), makelevel(),
- makemaz() */
- g.in_mklev = TRUE;
- oinit(); /* assign level dependent obj probabilities */
- clear_level_structures();
+ lspo_reset_level(NULL);
(void) load_special(buf);
+ lspo_finalize_level(NULL);
- bound_digging();
- mineralize(-1, -1, -1, -1, FALSE);
- g.in_mklev = FALSE;
- if (g.level.flags.has_morgue)
- g.level.flags.graveyard = 1;
- if (!g.level.flags.is_maze_lev) {
- struct mkroom *croom;
- for (croom = &g.rooms[0]; croom != &g.rooms[g.nroom]; croom++)
-#ifdef SPECIALIZATION
- topologize(croom, FALSE);
-#else
- topologize(croom);
-#endif
- }
- set_wall_state();
- /* for many room types, rooms[].rtype is zeroed once the room has been
- entered; rooms[].orig_rtype always retains original rtype value */
- for (ridx = 0; ridx < SIZE(g.rooms); ridx++)
- g.rooms[ridx].orig_rtype = g.rooms[ridx].rtype;
-
- makemap_prepost(FALSE, was_in_W_tower);
} else
pline("Unavailable command 'wiz_load_splua'.");
return 0;
}
void
-mklev(void)
+level_finalize_topology(void)
{
struct mkroom *croom;
int ridx;
- reseed_random(rn2);
- reseed_random(rn2_on_display_rng);
-
- init_mapseen(&u.uz);
- if (getbones())
- return;
-
- g.in_mklev = TRUE;
- makelevel();
bound_digging();
mineralize(-1, -1, -1, -1, FALSE);
g.in_mklev = FALSE;
entered; g.rooms[].orig_rtype always retains original rtype value */
for (ridx = 0; ridx < SIZE(g.rooms); ridx++)
g.rooms[ridx].orig_rtype = g.rooms[ridx].rtype;
+}
+
+void
+mklev(void)
+{
+ reseed_random(rn2);
+ reseed_random(rn2_on_display_rng);
+
+ init_mapseen(&u.uz);
+ if (getbones())
+ return;
+
+ g.in_mklev = TRUE;
+ makelevel();
+
+ level_finalize_topology();
reseed_random(rn2);
reseed_random(rn2_on_display_rng);
} nhl_consts[] = {
{ "COLNO", COLNO },
{ "ROWNO", ROWNO },
+#ifdef DLB
+ { "DLB", 1},
+#else
+ { "DLB", 0},
+#endif /* DLB */
{ NULL, 0 },
};
saveobjchn(nhfp, &fobj);
saveobjchn(nhfp, &g.level.buriedobjlist);
saveobjchn(nhfp, &g.billobjs);
- if (release_data(nhfp)) {
- int x,y;
- /* TODO: maybe use clear_level_structures() */
- for (y = 0; y < ROWNO; y++)
- for (x = 0; x < COLNO; x++) {
- g.level.monsters[x][y] = 0;
- g.level.objects[x][y] = 0;
- levl[x][y].seenv = 0;
- levl[x][y].glyph = GLYPH_UNEXPLORED;
- }
- fmon = 0;
- g.ftrap = 0;
- fobj = 0;
- g.level.buriedobjlist = 0;
- g.billobjs = 0;
- stairway_free_all();
- (void) memset(g.rooms, 0, sizeof(g.rooms));
- g.nroom = g.nsubroom = 0;
- g.rooms[0].hx = g.subrooms[0].hx = -1;
- /* level.bonesinfo = 0; -- handled by savecemetery() */
- }
save_engravings(nhfp);
savedamage(nhfp); /* pending shop wall and/or floor repair */
save_regions(nhfp);
bflush(nhfp->fd);
}
g.program_state.saving--;
+ if (release_data(nhfp)) {
+ clear_level_structures();
+ g.ftrap = 0;
+ g.billobjs = 0;
+ (void) memset(g.rooms, 0, sizeof(g.rooms));
+ }
return;
}
int lspo_region(lua_State *);
int lspo_replace_terrain(lua_State *);
int lspo_reset_level(lua_State *);
+int lspo_finalize_level(lua_State *);
int lspo_room(lua_State *);
int lspo_stair(lua_State *);
int lspo_teleport_region(lua_State *);
} else {
impossible(prize_warning, "sokoban end");
}
- } else {
+ } else if (!iflags.lua_testing) {
char lbuf[QBUFSZ];
(void) describe_level(lbuf); /* always has a trailing space */
{
boolean wtower = In_W_tower(u.ux, u.uy, &u.uz);
- create_des_coder();
+ iflags.lua_testing = TRUE;
+ if (L)
+ create_des_coder();
makemap_prepost(TRUE, wtower);
+ g.in_mklev = TRUE;
+ oinit(); /* assign level dependent obj probabilities */
clear_level_structures();
return 0;
}
+/* finalize_level is only needed for testing purposes */
+int
+lspo_finalize_level(lua_State *L UNUSED)
+{
+ boolean wtower = In_W_tower(u.ux, u.uy, &u.uz);
+ int i;
+
+ if (L)
+ create_des_coder();
+
+ link_doors_rooms();
+ remove_boundary_syms();
+
+ /* TODO: ensure_way_out() needs rewrite */
+ if (L && g.coder->check_inaccessibles)
+ ensure_way_out();
+
+ /* FIXME: Ideally, we want this call to only cover areas of the map
+ * which were not inserted directly by the special level file (see
+ * the insect legs on Baalzebub's level, for instance). Since that
+ * is currently not possible, we overload the corrmaze flag for this
+ * purpose.
+ */
+ if (!g.level.flags.corrmaze)
+ wallification(1, 0, COLNO - 1, ROWNO - 1);
+
+ if (L)
+ flip_level_rnd(g.coder->allow_flips, FALSE);
+
+ count_features();
+
+ if (L && g.coder->solidify)
+ solidify_map();
+
+ /* This must be done before sokoban_detect(),
+ * otherwise branch stairs won't be premapped. */
+ fixup_special();
+
+ if (L && g.coder->premapped)
+ sokoban_detect();
+
+ level_finalize_topology();
+
+ for (i = 0; i < g.nroom; ++i) {
+ fill_special_room(&g.rooms[i]);
+ }
+
+ makemap_prepost(FALSE, wtower);
+ iflags.lua_testing = FALSE;
+ return 0;
+}
+
/* map({ x = 10, y = 10, map = [[...]] }); */
/* map({ coord = {10, 10}, map = [[...]] }); */
/* map({ halign = "center", valign = "center", map = [[...]] }); */
{ "non_passwall", lspo_non_passwall },
{ "teleport_region", lspo_teleport_region },
{ "reset_level", lspo_reset_level },
+ { "finalize_level", lspo_finalize_level },
/* TODO: { "branch", lspo_branch }, */
/* TODO: { "portal", lspo_portal }, */
{ NULL, NULL }
-- Test all of the special levels
+function saferequire(file)
+ if (not pcall(require, file)) then
+ nh.pline("Cannot load level file '" .. file .. "'.");
+ if (nhc.DLB == 1) then
+ nh.pline("Maybe due to compile-time option DLB.")
+ end
+ return false;
+ end
+ return true;
+end;
+
local special_levels = {
"air",
"asmodeus",
"astral",
"baalz",
-"bigrm-10",
"bigrm-1",
"bigrm-2",
"bigrm-3",
"bigrm-7",
"bigrm-8",
"bigrm-9",
+"bigrm-10",
+"bigrm-11",
"castle",
"earth",
"fakewiz1",
for _,lev in ipairs(special_levels) do
des.reset_level();
- require(lev)
+ if (not saferequire(lev)) then
+ error("Cannot load a required file.");
+ end
+ des.finalize_level();
end