diff --git a/include/decl.h b/include/decl.h index 6b7142e57..1caf4c5bc 100644 --- a/include/decl.h +++ b/include/decl.h @@ -949,6 +949,7 @@ struct instance_globals { int mhitu_dieroll; /* mklev.c */ + genericptr_t luathemes[MAXDUNGEON]; xchar vault_x; xchar vault_y; boolean made_branch; /* used only during level creation */ diff --git a/include/dungeon.h b/include/dungeon.h index eba96d8bd..b0e3c1b93 100644 --- a/include/dungeon.h +++ b/include/dungeon.h @@ -67,7 +67,6 @@ typedef struct dungeon { /* basic dungeon identifier */ xchar dunlev_ureached; /* how deep you have been in this dungeon */ int ledger_start, /* the starting depth in "real" terms */ depth_start; /* the starting depth in "logical" terms */ - lua_State *themelua; /* themerms compiled lua */ } dungeon; /* diff --git a/include/extern.h b/include/extern.h index a5730affc..6d177cb8c 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1325,6 +1325,7 @@ E void NDECL(sort_rooms); E void FDECL(add_room, (int, int, int, int, BOOLEAN_P, SCHAR_P, BOOLEAN_P)); E void FDECL(add_subroom, (struct mkroom *, int, int, int, int, BOOLEAN_P, SCHAR_P, BOOLEAN_P)); +E void FDECL(free_luathemes, (BOOLEAN_P)); E void NDECL(makecorridors); E void FDECL(add_door, (int, int, struct mkroom *)); E void NDECL(clear_level_structures); diff --git a/include/patchlevel.h b/include/patchlevel.h index b02d2d613..24b92cf36 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -14,7 +14,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 19 +#define EDITLEVEL 20 #define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2020" #define COPYRIGHT_BANNER_B \ diff --git a/src/decl.c b/src/decl.c index a6de86e35..0f078496b 100644 --- a/src/decl.c +++ b/src/decl.c @@ -413,7 +413,7 @@ const struct instance_globals g_init = { DUMMY, /* warnsyms */ /* dungeon.c */ - UNDEFINED_VALUE, /* n_dgns */ + 0, /* n_dgns */ NULL, /* branches */ NULL, /* mapseenchn */ @@ -478,6 +478,7 @@ const struct instance_globals g_init = { UNDEFINED_VALUE, /* mhitu_dieroll */ /* mklev.c */ + UNDEFINED_VALUES, /* luathemes[] */ UNDEFINED_VALUE, /* vault_x */ UNDEFINED_VALUE, /* vault_y */ UNDEFINED_VALUE, /* made_branch */ diff --git a/src/do.c b/src/do.c index 530f09a61..8feb069a5 100644 --- a/src/do.c +++ b/src/do.c @@ -1420,6 +1420,8 @@ boolean at_stairs, falling, portal; update_mlstmv(); /* current monsters are becoming inactive */ if (nhfp->structlevel) bufon(nhfp->fd); /* use buffered output */ + } else { + free_luathemes(TRUE); } save_mode = nhfp->mode; nhfp->mode = cant_go_back ? FREEING : (WRITING | FREEING); diff --git a/src/dungeon.c b/src/dungeon.c index e5c2be68b..f376e5237 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -144,23 +144,24 @@ boolean perform_write, free_data; bwrite(nhfp->fd, (genericptr_t) &g.n_dgns, sizeof g.n_dgns); bwrite(nhfp->fd, (genericptr_t) g.dungeons, sizeof(dungeon) * (unsigned) g.n_dgns); - bwrite(nhfp->fd, (genericptr_t) &g.dungeon_topology, sizeof g.dungeon_topology); + bwrite(nhfp->fd, (genericptr_t) &g.dungeon_topology, + sizeof g.dungeon_topology); bwrite(nhfp->fd, (genericptr_t) g.tune, sizeof tune); } for (count = 0, curr = g.branches; curr; curr = curr->next) count++; if (nhfp->structlevel) - bwrite(nhfp->fd, (genericptr_t) &count, sizeof(count)); + bwrite(nhfp->fd, (genericptr_t) &count, sizeof count); for (curr = g.branches; curr; curr = curr->next) { if (nhfp->structlevel) - bwrite(nhfp->fd, (genericptr_t) curr, sizeof(branch)); + bwrite(nhfp->fd, (genericptr_t) curr, sizeof *curr); } count = maxledgerno(); if (nhfp->structlevel) { bwrite(nhfp->fd, (genericptr_t) &count, sizeof count); bwrite(nhfp->fd, (genericptr_t) g.level_info, - (unsigned) count * sizeof(struct linfo)); + (unsigned) count * sizeof (struct linfo)); bwrite(nhfp->fd, (genericptr_t) &g.inv_pos, sizeof g.inv_pos); } for (count = 0, curr_ms = g.mapseenchn; curr_ms; @@ -168,7 +169,7 @@ boolean perform_write, free_data; count++; if (nhfp->structlevel) - bwrite(nhfp->fd, (genericptr_t) &count, sizeof(count)); + bwrite(nhfp->fd, (genericptr_t) &count, sizeof count); for (curr_ms = g.mapseenchn; curr_ms; curr_ms = curr_ms->next) { save_mapseen(nhfp, curr_ms); @@ -203,23 +204,22 @@ NHFILE *nhfp; mapseen *curr_ms, *last_ms; if (nhfp->structlevel) { - mread(nhfp->fd, (genericptr_t) &g.n_dgns, sizeof(g.n_dgns)); - mread(nhfp->fd, (genericptr_t) g.dungeons, sizeof(dungeon) * (unsigned) g.n_dgns); - mread(nhfp->fd, (genericptr_t) &g.dungeon_topology, sizeof g.dungeon_topology); + mread(nhfp->fd, (genericptr_t) &g.n_dgns, sizeof g.n_dgns); + mread(nhfp->fd, (genericptr_t) g.dungeons, + sizeof (dungeon) * (unsigned) g.n_dgns); + mread(nhfp->fd, (genericptr_t) &g.dungeon_topology, + sizeof g.dungeon_topology); mread(nhfp->fd, (genericptr_t) g.tune, sizeof tune); } last = g.branches = (branch *) 0; - for (i = 0; i < g.n_dgns; i++) - g.dungeons[i].themelua = (lua_State *) 0; - if (nhfp->structlevel) - mread(nhfp->fd, (genericptr_t) &count, sizeof(count)); + mread(nhfp->fd, (genericptr_t) &count, sizeof count); for (i = 0; i < count; i++) { - curr = (branch *) alloc(sizeof(branch)); + curr = (branch *) alloc(sizeof *curr); if (nhfp->structlevel) - mread(nhfp->fd, (genericptr_t) curr, sizeof(branch)); + mread(nhfp->fd, (genericptr_t) curr, sizeof *curr); curr->next = (branch *) 0; if (last) last->next = curr; @@ -229,18 +229,18 @@ NHFILE *nhfp; } if (nhfp->structlevel) - mread(nhfp->fd, (genericptr_t) &count, sizeof(count)); + mread(nhfp->fd, (genericptr_t) &count, sizeof count); if (count >= MAXLINFO) panic("level information count larger (%d) than allocated size", count); if (nhfp->structlevel) mread(nhfp->fd, (genericptr_t) g.level_info, - (unsigned) count * sizeof(struct linfo)); + (unsigned) count * sizeof (struct linfo)); if (nhfp->structlevel) { mread(nhfp->fd, (genericptr_t) &g.inv_pos, sizeof g.inv_pos); - mread(nhfp->fd, (genericptr_t) &count, sizeof(count)); + mread(nhfp->fd, (genericptr_t) &count, sizeof count); } last_ms = (mapseen *) 0; @@ -1030,7 +1030,6 @@ init_dungeons() Strcpy(g.dungeons[i].dname, dgn_name); /* FIXME: dname length */ Strcpy(g.dungeons[i].proto, dgn_protoname); /* FIXME: proto length */ Strcpy(g.dungeons[i].themerms, dgn_themerms); /* FIXME: length */ - g.dungeons[i].themelua = (lua_State *) 0; g.dungeons[i].boneid = *dgn_bonetag ? *dgn_bonetag : 0; free((genericptr) dgn_fill); /* free((genericptr) dgn_protoname); -- stored in pd.tmpdungeon[] */ diff --git a/src/mklev.c b/src/mklev.c index 71f6f4bef..007262ea0 100644 --- a/src/mklev.c +++ b/src/mklev.c @@ -239,30 +239,46 @@ boolean special; g.nsubroom++; } +void +free_luathemes(keependgame) +boolean keependgame; /* False: exiting, True: discarding main dungeon */ +{ + int i; + + for (i = 0; i < g.n_dgns; ++i) { + if (keependgame && i == astral_level.dnum) + continue; + if (g.luathemes[i]) { + lua_close((lua_State *) g.luathemes[i]); + g.luathemes[i] = (lua_State *) 0; + } + } +} + static void makerooms() { boolean tried_vault = FALSE; int themeroom_tries = 0; - boolean dothemes = (g.dungeons[u.uz.dnum].themelua != NULL); - char *fname = g.dungeons[u.uz.dnum].themerms; + char *fname; + lua_State *themes = (lua_State *) g.luathemes[u.uz.dnum]; - if (*fname && !g.dungeons[u.uz.dnum].themelua) { - g.dungeons[u.uz.dnum].themelua = nhl_init(); - if (g.dungeons[u.uz.dnum].themelua) { - if (!nhl_loadlua(g.dungeons[u.uz.dnum].themelua, fname)) { + if (!themes && *(fname = g.dungeons[u.uz.dnum].themerms)) { + if ((themes = nhl_init()) != 0) { + if (!nhl_loadlua(themes, fname)) { /* loading lua failed, don't use themed rooms */ - g.dungeons[u.uz.dnum].themerms[0] = '\0'; - lua_close(g.dungeons[u.uz.dnum].themelua); - g.dungeons[u.uz.dnum].themelua = NULL; - dothemes = FALSE; + lua_close(themes); + themes = (lua_State *) 0; } else { - dothemes = TRUE; + /* success; save state for this dungeon branch */ + g.luathemes[u.uz.dnum] = (genericptr_t) themes; } } + if (!themes) /* don't try again when making next level */ + *fname = '\0'; /* g.dungeons[u.uz.dnum].themerms */ } - if (dothemes) { + if (themes) { create_des_coder(); } @@ -277,12 +293,11 @@ makerooms() g.rooms[g.nroom].hx = -1; } } else { - if (dothemes) { + if (themes) { g.in_mk_themerooms = TRUE; g.themeroom_failed = FALSE; - lua_getglobal(g.dungeons[u.uz.dnum].themelua, - "themerooms_generate"); - lua_call(g.dungeons[u.uz.dnum].themelua, 0, 0); + lua_getglobal(themes, "themerooms_generate"); + lua_call(themes, 0, 0); g.in_mk_themerooms = FALSE; if (g.themeroom_failed && ((themeroom_tries++ > 10) @@ -294,7 +309,7 @@ makerooms() } } } - if (dothemes) { + if (themes) { wallification(1, 0, COLNO - 1, ROWNO - 1); free(g.coder); g.coder = NULL; diff --git a/src/save.c b/src/save.c index c2d710f4c..b3fe86656 100644 --- a/src/save.c +++ b/src/save.c @@ -1070,17 +1070,12 @@ free_dungeons() { #ifdef FREE_ALL_MEMORY NHFILE tnhfp; - int i; zero_nhfile(&tnhfp); /* also sets fd to -1 */ tnhfp.mode = FREEING; savelevchn(&tnhfp); save_dungeon(&tnhfp, FALSE, TRUE); - for (i = 0; i < g.n_dgns; i++) - if (g.dungeons[i].themelua) { - lua_close(g.dungeons[i].themelua); - g.dungeons[i].themelua = (lua_State *) 0; - } + free_luathemes(TRUE); #endif return; }