From a733004912be8428f77ddb1a25a7de1160181509 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Fri, 9 Sep 2022 12:58:45 +0300 Subject: [PATCH] Remove the per dungeon level door limit Number of doors in a room-and-corridor style level was fixed at 120; now the doors-array is dynamically allocated when needed. Breaks saves and bones. --- doc/fixes3-7-0.txt | 1 + include/decl.h | 3 +- include/global.h | 2 +- include/mkroom.h | 2 +- include/patchlevel.h | 2 +- src/decl.c | 3 +- src/mklev.c | 123 ++++++++++++++++++++++++------------------- src/restore.c | 6 ++- src/save.c | 3 +- src/sp_lev.c | 2 +- 10 files changed, 85 insertions(+), 62 deletions(-) diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 593105247..8a2dc1638 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -2107,4 +2107,5 @@ for Planes of Water and Air, save the air bubbles and clouds with the level switch to a flags arg on newcham() in place of the pair of boolean args replace some old 'time_t' hackery in system.h and hacklib.c with something less obtrusive in unixconf.h +remove the per dungeon level door limit diff --git a/include/decl.h b/include/decl.h index e5bd58910..9989a93dc 100644 --- a/include/decl.h +++ b/include/decl.h @@ -817,7 +817,8 @@ struct instance_globals { char toplines[TBUFSZ]; coord bhitpos; /* place where throw or zap hits or stops */ boolean in_steed_dismounting; - coord doors[DOORMAX]; + int doors_alloc; /* doors-array allocated size */ + coord *doors; /* array of door locations */ struct menucoloring *menu_colorings; schar lastseentyp[COLNO][ROWNO]; /* last seen/touched dungeon typ */ struct spell spl_book[MAXSPELL + 1]; diff --git a/include/global.h b/include/global.h index 12d6211e0..d274b8667 100644 --- a/include/global.h +++ b/include/global.h @@ -400,7 +400,7 @@ extern struct nomakedefs_s nomakedefs; #define MAXNROFROOMS 40 /* max number of rooms per level */ #define MAX_SUBROOMS 24 /* max # of subrooms in a given room */ -#define DOORMAX 120 /* max number of doors per level */ +#define DOORINC 120 /* number of doors per level, increment */ #define BUFSZ 256 /* for getlin buffers */ #define QBUFSZ 128 /* for building question text */ diff --git a/include/mkroom.h b/include/mkroom.h index c555abcc5..bac5a76e7 100644 --- a/include/mkroom.h +++ b/include/mkroom.h @@ -16,7 +16,7 @@ struct mkroom { schar needfill; /* sp_lev: does the room need filling? */ boolean needjoining; /* sp_lev: should the room connect to others? */ schar doorct; /* door count */ - schar fdoor; /* index for the first door of the room */ + int fdoor; /* index for the first door of the room */ schar nsubrooms; /* number of subrooms */ boolean irregular; /* true if room is non-rectangular */ schar roomnoidx; diff --git a/include/patchlevel.h b/include/patchlevel.h index 37a4a8e01..bbc96bdad 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -17,7 +17,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 62 +#define EDITLEVEL 63 /* * Development status possibilities. diff --git a/src/decl.c b/src/decl.c index c51901885..e2384a0da 100644 --- a/src/decl.c +++ b/src/decl.c @@ -286,7 +286,8 @@ const struct instance_globals g_init = { UNDEFINED_VALUES, /* toplines */ { 0, 0 }, /* bhitpos */ FALSE, /* in_steed_dismounting */ - { { 0, 0 } }, /* doors */ + 0, /* doors_alloc */ + NULL, /* doors */ UNDEFINED_PTR, /* menu_colorings */ { { 0 } }, /* lastseentyp */ { DUMMY }, /* spl_book */ diff --git a/src/mklev.c b/src/mklev.c index 174a2992d..3a9d4d617 100644 --- a/src/mklev.c +++ b/src/mklev.c @@ -30,6 +30,7 @@ static void make_niches(void); static int QSORTCALLBACK mkroom_cmp(const genericptr, const genericptr); static void dosdoor(coordxy, coordxy, struct mkroom *, int); static void join(int, int, boolean); +static void alloc_doors(void); static void do_room_or_subroom(struct mkroom *, coordxy, coordxy, coordxy, coordxy, boolean, schar, boolean, boolean); @@ -343,7 +344,7 @@ join(register int a, register int b, boolean nxcor) /* find positions cc and tt for doors in croom and troom and direction for a corridor between them */ - if (troom->hx < 0 || croom->hx < 0 || g.doorindex >= DOORMAX) + if (troom->hx < 0 || croom->hx < 0) return; if (troom->lx > croom->hx) { dx = 1; @@ -442,6 +443,22 @@ makecorridors(void) } } +/* (re)allocate space for g.doors array */ +static void +alloc_doors(void) +{ + if (!g.doors || g.doorindex >= g.doors_alloc) { + int c = g.doors_alloc + DOORINC; + coord *doortmp = (coord *) alloc(c * sizeof(coord)); + if (g.doors) { + (void) memcpy(doortmp, g.doors, g.doors_alloc * sizeof(coord)); + free(g.doors); + } + g.doors = doortmp; + g.doors_alloc = c; + } +} + void add_door(coordxy x, coordxy y, register struct mkroom *aroom) { @@ -449,6 +466,8 @@ add_door(coordxy x, coordxy y, register struct mkroom *aroom) register int tmp; int i; + alloc_doors(); + if (aroom->doorct) { for (i = 0; i < aroom->doorct; i++) { tmp = aroom->fdoor + i; @@ -589,58 +608,56 @@ makeniche(int trap_type) coordxy dy, xx, yy; struct trap *ttmp; - if (g.doorindex < DOORMAX) { - while (vct--) { - aroom = &g.rooms[rn2(g.nroom)]; - if (aroom->rtype != OROOM) - continue; /* not an ordinary room */ - if (aroom->doorct == 1 && rn2(5)) - continue; - if (!place_niche(aroom, &dy, &xx, &yy)) - continue; + while (vct--) { + aroom = &g.rooms[rn2(g.nroom)]; + if (aroom->rtype != OROOM) + continue; /* not an ordinary room */ + if (aroom->doorct == 1 && rn2(5)) + continue; + if (!place_niche(aroom, &dy, &xx, &yy)) + continue; - rm = &levl[xx][yy + dy]; - if (trap_type || !rn2(4)) { - rm->typ = SCORR; - if (trap_type) { - if (is_hole(trap_type) && !Can_fall_thru(&u.uz)) - trap_type = ROCKTRAP; - ttmp = maketrap(xx, yy + dy, trap_type); - if (ttmp) { - if (trap_type != ROCKTRAP) - ttmp->once = 1; - if (trap_engravings[trap_type]) { - make_engr_at(xx, yy - dy, - trap_engravings[trap_type], 0L, - DUST); - wipe_engr_at(xx, yy - dy, 5, - FALSE); /* age it a little */ - } + rm = &levl[xx][yy + dy]; + if (trap_type || !rn2(4)) { + rm->typ = SCORR; + if (trap_type) { + if (is_hole(trap_type) && !Can_fall_thru(&u.uz)) + trap_type = ROCKTRAP; + ttmp = maketrap(xx, yy + dy, trap_type); + if (ttmp) { + if (trap_type != ROCKTRAP) + ttmp->once = 1; + if (trap_engravings[trap_type]) { + make_engr_at(xx, yy - dy, + trap_engravings[trap_type], 0L, + DUST); + wipe_engr_at(xx, yy - dy, 5, + FALSE); /* age it a little */ } } - dosdoor(xx, yy, aroom, SDOOR); - } else { - rm->typ = CORR; - if (rn2(7)) - dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR); - else { - /* inaccessible niches occasionally have iron bars */ - if (!rn2(5) && IS_WALL(levl[xx][yy].typ)) { - (void) set_levltyp(xx, yy, IRONBARS); - if (rn2(3)) - (void) mkcorpstat(CORPSE, (struct monst *) 0, - mkclass(S_HUMAN, 0), xx, - yy + dy, TRUE); - } - if (!g.level.flags.noteleport) - (void) mksobj_at(SCR_TELEPORTATION, xx, yy + dy, TRUE, - FALSE); - if (!rn2(3)) - (void) mkobj_at(RANDOM_CLASS, xx, yy + dy, TRUE); - } } - return; + dosdoor(xx, yy, aroom, SDOOR); + } else { + rm->typ = CORR; + if (rn2(7)) + dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR); + else { + /* inaccessible niches occasionally have iron bars */ + if (!rn2(5) && IS_WALL(levl[xx][yy].typ)) { + (void) set_levltyp(xx, yy, IRONBARS); + if (rn2(3)) + (void) mkcorpstat(CORPSE, (struct monst *) 0, + mkclass(S_HUMAN, 0), xx, + yy + dy, TRUE); + } + if (!g.level.flags.noteleport) + (void) mksobj_at(SCR_TELEPORTATION, xx, yy + dy, TRUE, + FALSE); + if (!rn2(3)) + (void) mkobj_at(RANDOM_CLASS, xx, yy + dy, TRUE); + } } + return; } } @@ -728,6 +745,9 @@ clear_level_structures(void) g.nsubroom = 0; g.subrooms[0].hx = -1; g.doorindex = 0; + g.doors_alloc = 0; + free(g.doors); + g.doors = (coord *) 0; init_rect(); init_vault(); stairway_free_all(); @@ -1334,17 +1354,12 @@ okdoor(coordxy x, coordxy y) || (isok(x + 1, y) && !IS_ROCK(levl[x + 1][y].typ)) || (isok(x, y - 1) && !IS_ROCK(levl[x][y - 1].typ)) || (isok(x, y + 1) && !IS_ROCK(levl[x][y + 1].typ))) - && g.doorindex < DOORMAX && !near_door); + && !near_door); } void dodoor(coordxy x, coordxy y, struct mkroom *aroom) { - if (g.doorindex >= DOORMAX) { - impossible("DOORMAX exceeded?"); - return; - } - dosdoor(x, y, aroom, rn2(8) ? DOOR : SDOOR); } diff --git a/src/restore.c b/src/restore.c index 0ffe4e2f3..1d1ed6ccc 100644 --- a/src/restore.c +++ b/src/restore.c @@ -1068,7 +1068,11 @@ getlev(NHFILE* nhfp, int pid, xint8 lev) mread(nhfp->fd, (genericptr_t)&g.updest, sizeof(dest_area)); mread(nhfp->fd, (genericptr_t)&g.dndest, sizeof(dest_area)); mread(nhfp->fd, (genericptr_t)&g.level.flags, sizeof(g.level.flags)); - mread(nhfp->fd, (genericptr_t)g.doors, sizeof(g.doors)); + if (g.doors) + free(g.doors); + mread(nhfp->fd, (genericptr_t) &g.doors_alloc, sizeof (g.doors_alloc)); + g.doors = (coord *) alloc(g.doors_alloc * sizeof (coord)); + mread(nhfp->fd, (genericptr_t) g.doors, g.doors_alloc * sizeof (coord)); } rest_rooms(nhfp); /* No joke :-) */ if (g.nroom) diff --git a/src/save.c b/src/save.c index 2824f7f7c..4d3784386 100644 --- a/src/save.c +++ b/src/save.c @@ -539,7 +539,8 @@ savelev_core(NHFILE *nhfp, xint8 lev) bwrite(nhfp->fd, (genericptr_t) &g.updest, sizeof (dest_area)); bwrite(nhfp->fd, (genericptr_t) &g.dndest, sizeof (dest_area)); bwrite(nhfp->fd, (genericptr_t) &g.level.flags, sizeof g.level.flags); - bwrite(nhfp->fd, (genericptr_t) g.doors, sizeof g.doors); + bwrite(nhfp->fd, (genericptr_t) &g.doors_alloc, sizeof g.doors_alloc); + bwrite(nhfp->fd, (genericptr_t) g.doors, g.doors_alloc * sizeof (coord)); } save_rooms(nhfp); /* no dynamic memory to reclaim */ diff --git a/src/sp_lev.c b/src/sp_lev.c index 2e079b746..a546bc6e0 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -1071,7 +1071,7 @@ shared_with_room(int x, int y, struct mkroom *droom) static void maybe_add_door(int x, int y, struct mkroom* droom) { - if (droom->hx >= 0 && g.doorindex < DOORMAX + if (droom->hx >= 0 && ((!droom->irregular && inside_room(droom, x, y)) || (int) levl[x][y].roomno == (droom - g.rooms) + ROOMOFFSET || shared_with_room(x, y, droom))) {