From f83dede8e57bec1947687ff74ec98caebd3660a2 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Mon, 6 Jan 2020 11:48:16 +0200 Subject: [PATCH] Fixes for degenerate RNG Assume a degenerate RNG that always returns the same number. With these fixes, the game starts and is almost playable. There are still some places that will go into infinite loop, eg. the mines level generation. --- src/mklev.c | 8 +++++--- src/mkmaze.c | 3 +++ src/role.c | 12 +++++++++++- src/u_init.c | 3 +++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/mklev.c b/src/mklev.c index 64faea76b..41e2ae95d 100644 --- a/src/mklev.c +++ b/src/mklev.c @@ -812,6 +812,7 @@ makelevel() /* for each room: put things inside */ for (croom = g.rooms; croom->hx > 0; croom++) { + int trycnt = 0; if (croom->rtype != OROOM) continue; @@ -833,7 +834,7 @@ makelevel() x = 8 - (level_difficulty() / 6); if (x <= 1) x = 2; - while (!rn2(x)) + while (!rn2(x) && (++trycnt < 1000)) mktrap(0, 0, croom, (coord *) 0); if (!rn2(3)) (void) mkgold(0L, somex(croom), somey(croom)); @@ -1121,6 +1122,7 @@ coord *mp; if (g.nroom == 0) { mazexy(mp); /* already verifies location */ } else { + int cnt = 0; /* not perfect - there may be only one stairway */ if (g.nroom > 2) { int tryct = 0; @@ -1135,9 +1137,9 @@ coord *mp; do { if (!somexy(croom, mp)) impossible("Can't place branch!"); - } while (occupied(mp->x, mp->y) + } while ((occupied(mp->x, mp->y) || (levl[mp->x][mp->y].typ != CORR - && levl[mp->x][mp->y].typ != ROOM)); + && levl[mp->x][mp->y].typ != ROOM)) && (++cnt < 1000)); } return croom; } diff --git a/src/mkmaze.c b/src/mkmaze.c index 7863214de..b287189a9 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -1035,6 +1035,7 @@ const char *s; mazexy(&mm); mkstairs(mm.x, mm.y, 0, (struct mkroom *) 0); /* down */ } else { /* choose "vibrating square" location */ + int trycnt = 0; #define x_maze_min 2 #define y_maze_min 2 /* @@ -1064,6 +1065,8 @@ const char *s; y = rn1(y_range, y_maze_min + INVPOS_Y_MARGIN + 1); /* we don't want it to be too near the stairs, nor to be on a spot that's already in use (wall|trap) */ + if (++trycnt > 1000) + break; } while (x == xupstair || y == yupstair /*(direct line)*/ || abs(x - xupstair) == abs(y - yupstair) || distmin(x, y, xupstair, yupstair) <= INVPOS_DISTANCE diff --git a/src/role.c b/src/role.c index bda974187..1a1a88986 100644 --- a/src/role.c +++ b/src/role.c @@ -2028,9 +2028,19 @@ role_init() /* Fix up the god names */ if (flags.pantheon == -1) { /* new game */ + int trycnt = 0; flags.pantheon = flags.initrole; /* use own gods */ - while (!roles[flags.pantheon].lgod) /* unless they're missing */ + /* unless they're missing */ + while (!roles[flags.pantheon].lgod && ++trycnt < 100) flags.pantheon = randrole(FALSE); + if (!roles[flags.pantheon].lgod) { + int i; + for (i = 0; i < SIZE(roles) - 1; i++) + if (roles[i].lgod) { + flags.pantheon = i; + break; + } + } } if (!g.urole.lgod) { g.urole.lgod = roles[flags.pantheon].lgod; diff --git a/src/u_init.c b/src/u_init.c index 707117dca..0ae46c13a 100644 --- a/src/u_init.c +++ b/src/u_init.c @@ -979,6 +979,7 @@ register struct trobj *trop; if (otyp != UNDEF_TYP) { obj = mksobj(otyp, TRUE, FALSE); } else { /* UNDEF_TYP */ + int trycnt = 0; /* * For random objects, do not create certain overly powerful * items: wand of wishing, ring of levitation, or the @@ -1019,6 +1020,8 @@ register struct trobj *trop; dealloc_obj(obj); obj = mkobj(trop->trclass, FALSE); otyp = obj->otyp; + if (++trycnt > 1000) + break; } /* Don't start with +0 or negative rings */