From 83a1ffcf92c210187c54a550bddee002333a34f1 Mon Sep 17 00:00:00 2001 From: flend Date: Thu, 21 Dec 2023 17:55:04 +0000 Subject: [PATCH] Redo the level if stairs cannot be placed (#635) --- src/brogue/Architect.c | 34 ++++++++++++++++++++++++---------- src/brogue/Rogue.h | 3 ++- src/brogue/RogueMain.c | 15 +++++++++++++-- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/brogue/Architect.c b/src/brogue/Architect.c index e94d8fd8..bbcf1875 100644 --- a/src/brogue/Architect.c +++ b/src/brogue/Architect.c @@ -3669,15 +3669,10 @@ static void prepareForStairs(short x, short y, char grid[DCOLS][DROWS]) { } } -// Places the player, monsters, items and stairs. -void initializeLevel() { - short i, j, dir; - short **mapToStairs, **mapToPit; +boolean placeStairs(pos *upStairsLoc) { char grid[DCOLS][DROWS]; short n = rogue.depthLevel - 1; - // Place the stairs. - for (int i=0; i < DCOLS; i++) { for (int j=0; j < DROWS; j++) { grid[i][j] = validStairLoc(i, j); @@ -3694,9 +3689,12 @@ void initializeLevel() { if (getQualifyingGridLocNear(&downLoc, levels[n].downStairsLoc, grid, false)) { prepareForStairs(downLoc.x, downLoc.y, grid); } else { - getQualifyingLocNear(&downLoc, levels[n].downStairsLoc, false, 0, - (T_OBSTRUCTS_PASSABILITY | T_OBSTRUCTS_ITEMS | T_AUTO_DESCENT | T_IS_DEEP_WATER | T_LAVA_INSTA_DEATH | T_IS_DF_TRAP), - (HAS_MONSTER | HAS_ITEM | HAS_STAIRS | IS_IN_MACHINE), true, false); + boolean hasQualifyingLoc = getQualifyingLocNear(&downLoc, levels[n].downStairsLoc, false, 0, + (T_OBSTRUCTS_PASSABILITY | T_OBSTRUCTS_ITEMS | T_AUTO_DESCENT | T_IS_DEEP_WATER | T_LAVA_INSTA_DEATH | T_IS_DF_TRAP), + (HAS_MONSTER | HAS_ITEM | HAS_STAIRS | IS_IN_MACHINE), true, false); + if (!hasQualifyingLoc) { + return false; + } } if (rogue.depthLevel == gameConst->deepestLevel) { @@ -3716,9 +3714,13 @@ void initializeLevel() { if (getQualifyingGridLocNear(&upLoc, levels[n].upStairsLoc, grid, false)) { prepareForStairs(upLoc.x, upLoc.y, grid); } else { // Hopefully this never happens. - getQualifyingLocNear(&upLoc, levels[n].upStairsLoc, false, 0, + boolean hasQualifyingLoc; + hasQualifyingLoc = getQualifyingLocNear(&upLoc, levels[n].upStairsLoc, false, 0, (T_OBSTRUCTS_PASSABILITY | T_OBSTRUCTS_ITEMS | T_AUTO_DESCENT | T_IS_DEEP_WATER | T_LAVA_INSTA_DEATH | T_IS_DF_TRAP), (HAS_MONSTER | HAS_ITEM | HAS_STAIRS | IS_IN_MACHINE), true, false); + if (!hasQualifyingLoc) { + return false; + } } levels[n].upStairsLoc = upLoc; @@ -3736,6 +3738,18 @@ void initializeLevel() { rogue.upLoc = upLoc; pmapAt(upLoc)->flags |= HAS_STAIRS; + *upStairsLoc = upLoc; + return true; +} + +// Places the player, monsters, items and stairs. +void initializeLevel(pos upStairsLoc) { + short i, j, dir; + short **mapToStairs, **mapToPit; + char grid[DCOLS][DROWS]; + + pos upLoc = upStairsLoc; + if (!levels[rogue.depthLevel-1].visited) { // Run a field of view check from up stairs so that monsters do not spawn within sight of it. diff --git a/src/brogue/Rogue.h b/src/brogue/Rogue.h index 132bd522..f8ad3521 100644 --- a/src/brogue/Rogue.h +++ b/src/brogue/Rogue.h @@ -2983,7 +2983,8 @@ extern "C" { void nextBrogueEvent(rogueEvent *returnEvent, boolean textInput, boolean colorsDance, boolean realInputEvenInPlayback); void executeMouseClick(rogueEvent *theEvent); void executeKeystroke(signed long keystroke, boolean controlKey, boolean shiftKey); - void initializeLevel(void); + boolean placeStairs(pos *upStairsLoc); + void initializeLevel(pos upStairsLoc); void startLevel (short oldLevelNumber, short stairDirection); void updateMinersLightRadius(void); void freeCreature(creature *monst); diff --git a/src/brogue/RogueMain.c b/src/brogue/RogueMain.c index b3fb9fda..d9332957 100644 --- a/src/brogue/RogueMain.c +++ b/src/brogue/RogueMain.c @@ -684,8 +684,19 @@ void startLevel(short oldLevelNumber, short stairDirection) { levels[rogue.depthLevel-1].items = NULL; - digDungeon(); - initializeLevel(); + pos upStairLocation; + int failsafe; + for (failsafe = 50; failsafe; failsafe--) { + digDungeon(); + if (placeStairs(&upStairLocation)) { + break; + } + } + if (!failsafe) { + printf("\nFailed to place stairs for level %d! Please report this error\n", rogue.depthLevel); + exit(1); + } + initializeLevel(upStairLocation); setUpWaypoints(); shuffleTerrainColors(100, false);