From 3ef9f556aa44a709c1e59e306c63f76e1973bb5f Mon Sep 17 00:00:00 2001 From: BoatsandJoes Date: Sun, 26 Oct 2025 16:57:38 -0500 Subject: [PATCH 1/5] Fix arrow keys inventory scrolling not working in some screens (#756) --- changes/fix-inventory-scrolling.md | 1 + src/brogue/IO.c | 33 +++++++++++++----------------- 2 files changed, 15 insertions(+), 19 deletions(-) create mode 100644 changes/fix-inventory-scrolling.md diff --git a/changes/fix-inventory-scrolling.md b/changes/fix-inventory-scrolling.md new file mode 100644 index 00000000..fc620c6f --- /dev/null +++ b/changes/fix-inventory-scrolling.md @@ -0,0 +1 @@ +Allow scrolling through inventory with arrow keys and 8/2 even when other actions are disabled. Applies to enchant/ID menu, replays, and the death screen. diff --git a/src/brogue/IO.c b/src/brogue/IO.c index 97953b8f..2a13b449 100644 --- a/src/brogue/IO.c +++ b/src/brogue/IO.c @@ -5099,27 +5099,22 @@ unsigned long printCarriedItemDetails(item *theItem, buttons[b].hotkey[0] = RELABEL_KEY; b++; } - - // Add invisible previous and next buttons, so up and down arrows can page through items. - // Previous - buttons[b].flags = B_ENABLED; // clear everything else - buttons[b].hotkey[0] = UP_KEY; - buttons[b].hotkey[1] = NUMPAD_8; - buttons[b].hotkey[2] = UP_ARROW; - b++; - // Next - buttons[b].flags = B_ENABLED; // clear everything else - buttons[b].hotkey[0] = DOWN_KEY; - buttons[b].hotkey[1] = NUMPAD_2; - buttons[b].hotkey[2] = DOWN_ARROW; - b++; } - b = printTextBox(textBuf, x, y, width, &white, &interfaceBoxColor, buttons, b); + // Add invisible previous and next buttons, so up and down arrows can page through items. + // Previous + buttons[b].flags = B_ENABLED; // clear everything else + buttons[b].hotkey[0] = UP_KEY; + buttons[b].hotkey[1] = NUMPAD_8; + buttons[b].hotkey[2] = UP_ARROW; + b++; + // Next + buttons[b].flags = B_ENABLED; // clear everything else + buttons[b].hotkey[0] = DOWN_KEY; + buttons[b].hotkey[1] = NUMPAD_2; + buttons[b].hotkey[2] = DOWN_ARROW; + b++; - if (!includeButtons) { - waitForKeystrokeOrMouseClick(); - return -1; - } + b = printTextBox(textBuf, x, y, width, &white, &interfaceBoxColor, buttons, b); if (b >= 0) { return buttons[b].hotkey[0]; From ae94b2796c1d0f1c290e51a960888fea88c2720a Mon Sep 17 00:00:00 2001 From: zeb33n <91947631+zeb33n@users.noreply.github.com> Date: Thu, 6 Nov 2025 16:29:44 +0000 Subject: [PATCH 2/5] Add log messages for using a staff or wand (#755) --- changes/wand-staff-messages.md | 1 + src/brogue/Items.c | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 changes/wand-staff-messages.md diff --git a/changes/wand-staff-messages.md b/changes/wand-staff-messages.md new file mode 100644 index 00000000..9f4eb6b3 --- /dev/null +++ b/changes/wand-staff-messages.md @@ -0,0 +1 @@ +Added messages to the game log for zapping wands and staffs. diff --git a/src/brogue/Items.c b/src/brogue/Items.c index 937f083f..67822465 100644 --- a/src/brogue/Items.c +++ b/src/brogue/Items.c @@ -6543,7 +6543,7 @@ static void recordApplyItemCommand(item *theItem) { } static boolean useStaffOrWand(item *theItem) { - char buf[COLS], buf2[COLS]; + char buf[COLS], buf2[COLS], buf3[COLS]; short maxDistance; boolean autoID, confirmedTarget; bolt theBolt; @@ -6583,6 +6583,7 @@ static boolean useStaffOrWand(item *theItem) { confirmedTarget = false; } + if (confirmedTarget) { recordApplyItemCommand(theItem); @@ -6592,13 +6593,22 @@ static boolean useStaffOrWand(item *theItem) { rogue.featRecord[FEAT_PURE_WARRIOR] = false; if (theItem->charges > 0) { + + creature *monst = monsterAtLoc(zapTarget); + if (monst) { + monsterName(buf3, monst, true); + sprintf(buf, "you zap your %s at %s.", buf2, buf3); + } else { + sprintf(buf, "you zap your %s.", buf2); + } + message(buf, 0); + autoID = zap(originLoc, zapTarget, &theBolt, !boltKnown, // hide bolt details false); if (autoID) { if (!tableForItemCategory(theItem->category)[theItem->kind].identified) { - itemName(theItem, buf2, false, false, NULL); sprintf(buf, "(Your %s must be ", buf2); identifyItemKind(theItem); itemName(theItem, buf2, false, true, NULL); @@ -6608,7 +6618,6 @@ static boolean useStaffOrWand(item *theItem) { } } } else { - itemName(theItem, buf2, false, false, NULL); if (theItem->category == STAFF) { sprintf(buf, "Your %s fizzles; it must be out of charges for now.", buf2); } else { From 0de5f42199d27093a03f78ad70ed06326f942f09 Mon Sep 17 00:00:00 2001 From: ZayadNimrod <32575659+ZayadNimrod@users.noreply.github.com> Date: Sun, 16 Nov 2025 14:26:38 +0000 Subject: [PATCH 3/5] Coalesce Wizard and Easy mode into a single field This will be useful when we check that a save was made in the same mode as the one the game is in. --- src/brogue/Combat.c | 2 +- src/brogue/IO.c | 8 ++++---- src/brogue/MainMenu.c | 13 +++++-------- src/brogue/Monsters.c | 2 +- src/brogue/Movement.c | 2 +- src/brogue/Recordings.c | 8 ++++---- src/brogue/Rogue.h | 36 +++++++++++++++++++++--------------- src/brogue/RogueMain.c | 22 ++++++++++------------ src/platform/main.c | 4 ++-- src/platform/web-platform.c | 4 ++-- 10 files changed, 51 insertions(+), 50 deletions(-) diff --git a/src/brogue/Combat.c b/src/brogue/Combat.c index 6e34ee03..cf9ef831 100644 --- a/src/brogue/Combat.c +++ b/src/brogue/Combat.c @@ -1558,7 +1558,7 @@ boolean inflictDamage(creature *attacker, creature *defender, } if (defender == &player - && rogue.easyMode + && rogue.mode == GAME_MODE_EASY && damage > 0) { damage = max(1, damage/5); } diff --git a/src/brogue/IO.c b/src/brogue/IO.c index 2a13b449..2ca5292b 100644 --- a/src/brogue/IO.c +++ b/src/brogue/IO.c @@ -28,7 +28,7 @@ #include "GlobalsBase.h" #include "Globals.h" -#define D_DISABLE_BACKGROUND_COLORS (rogue.wizard && 0) +#define D_DISABLE_BACKGROUND_COLORS (WIZARD_MODE && 0) // Populates path[][] with a list of coordinates starting at origin and traversing down the map. Returns the number of steps in the path. short getPlayerPathOnMap(pos path[1000], short **map, pos origin) { @@ -275,7 +275,7 @@ static short actionMenu(short x, boolean playingBack) { buttons[buttonCount].hotkey[0] = RETHROW_KEY; buttonCount++; - if (!rogue.easyMode) { + if (!rogue.mode == GAME_MODE_EASY) { if (KEYBOARD_LABELS) { sprintf(buttons[buttonCount].text, " %s&: %sEasy mode ", yellowColorEscape, whiteColorEscape); } else { @@ -4396,9 +4396,9 @@ void printSeed() { char buf[COLS]; char mode[14] = ""; - if (rogue.easyMode) { + if (rogue.mode = GAME_MODE_EASY) { strcpy(mode,"easy mode; "); - } else if (rogue.wizard) { + } else if (WIZARD_MODE) { strcpy(mode,"wizard mode; "); } if (rogue.hideSeed) { diff --git a/src/brogue/MainMenu.c b/src/brogue/MainMenu.c index 64d1be34..7c12bd86 100644 --- a/src/brogue/MainMenu.c +++ b/src/brogue/MainMenu.c @@ -48,9 +48,9 @@ static void drawMenuFlames(signed short flames[COLS][(ROWS + MENU_FLAME_ROW_PADD versionStringLength = strLenWithoutEscapes(gameConst->versionString); - if (rogue.wizard) { + if (WIZARD_MODE) { strcpy(gameModeString, "Wizard Mode"); - } else if (rogue.easyMode) { + } else if (rogue.mode == GAME_MODE_EASY) { strcpy(gameModeString, "Easy Mode"); } gameModeStringLength = strLenWithoutEscapes(gameModeString); @@ -456,14 +456,11 @@ static void chooseGameMode() { gameMode = printTextBox(textBuf, 10, 5, 66, &white, &black, buttons, 3); restoreDisplayBuffer(&rbuf); if (gameMode == 0) { - rogue.wizard = true; - rogue.easyMode = false; + rogue.mode = GAME_MODE_WIZARD; } else if (gameMode == 1) { - rogue.wizard = false; - rogue.easyMode = true; + rogue.mode = GAME_MODE_EASY; } else if (gameMode == 2) { - rogue.wizard = false; - rogue.easyMode = false; + rogue.mode = GAME_MODE_NORMAL; } rogue.nextGame = NG_NOTHING; diff --git a/src/brogue/Monsters.c b/src/brogue/Monsters.c index c0caadba..ad65bfc1 100644 --- a/src/brogue/Monsters.c +++ b/src/brogue/Monsters.c @@ -408,7 +408,7 @@ void initializeGender(creature *monst) { /// @brief Sets the character used to represent the player in the game, based on the game mode void setPlayerDisplayChar() { - if (rogue.easyMode) { + if (rogue.mode == GAME_MODE_EASY) { player.info.displayChar = G_DEMON; } else { player.info.displayChar = G_PLAYER; diff --git a/src/brogue/Movement.c b/src/brogue/Movement.c index 71f0d624..44a23b6e 100644 --- a/src/brogue/Movement.c +++ b/src/brogue/Movement.c @@ -2071,7 +2071,7 @@ boolean startFighting(enum directions dir, boolean tillDeath) { return false; } int expectedDamage = monst->info.damage.upperBound * monsterDamageAdjustmentAmount(monst) / FP_FACTOR; - if (rogue.easyMode) { + if (rogue.mode == GAME_MODE_EASY) { expectedDamage /= 5; } rogue.blockCombatText = true; diff --git a/src/brogue/Recordings.c b/src/brogue/Recordings.c index 7dcf3627..6a3539f3 100644 --- a/src/brogue/Recordings.c +++ b/src/brogue/Recordings.c @@ -188,7 +188,7 @@ static void writeHeaderInfo(char *path) { for (i = 0; rogue.versionString[i] != '\0'; i++) { c[i] = rogue.versionString[i]; } - c[15] = rogue.wizard; + c[15] = rogue.mode; i = 16; numberToString(rogue.seed, 8, &c[i]); i += 8; @@ -527,7 +527,7 @@ void initRecording() { rogue.gameExitStatusCode = EXIT_STATUS_FAILURE_RECORDING_WRONG_VERSION; } - if (wizardMode != rogue.wizard) { + if (wizardMode != WIZARD_MODE) { // wizard game cannot be played in normal mode and vice versa rogue.playbackMode = false; rogue.playbackFastForward = false; @@ -1182,9 +1182,9 @@ static void getDefaultFilePath(char *defaultPath, boolean gameOver) { } else { sprintf(defaultPath, "%s #%s Escaped the dungeons", gameConst->versionString, seed); } - if (rogue.wizard) { + if (rogue.mode == GAME_MODE_WIZARD) { strcat(defaultPath, " (wizard)"); - } else if (rogue.easyMode) { + } else if (rogue.mode == GAME_MODE_EASY) { strcat(defaultPath, " (easy)"); } } diff --git a/src/brogue/Rogue.h b/src/brogue/Rogue.h index 442c1a9d..fb69db13 100644 --- a/src/brogue/Rogue.h +++ b/src/brogue/Rogue.h @@ -46,23 +46,25 @@ // Macro to compare BROGUE_MAJOR.BROGUE_MINOR.patchVersion to a.b.c #define BROGUE_VERSION_ATLEAST(a,b,c) (BROGUE_MAJOR != (a) ? BROGUE_MAJOR > (a) : BROGUE_MINOR != (b) ? BROGUE_MINOR > (b) : rogue.patchVersion >= (c)) -#define DEBUG if (rogue.wizard) -#define MONSTERS_ENABLED (!rogue.wizard || 1) // Quest room monsters can be generated regardless. -#define ITEMS_ENABLED (!rogue.wizard || 1) +#define WIZARD_MODE (rogue.mode == GAME_MODE_WIZARD) -#define D_BULLET_TIME (rogue.wizard && 0) -#define D_WORMHOLING (rogue.wizard && 1) -#define D_IMMORTAL (rogue.wizard && 1) +#define DEBUG if (WIZARD_MODE) +#define MONSTERS_ENABLED (!WIZARD_MODE || 1) // Quest room monsters can be generated regardless. +#define ITEMS_ENABLED (!WIZARD_MODE || 1) -#define D_SAFETY_VISION (rogue.wizard && 0) -#define D_SCENT_VISION (rogue.wizard && 0) -#define D_OMNISCENCE (rogue.wizard && 0) +#define D_BULLET_TIME (WIZARD_MODE && 0) +#define D_WORMHOLING (WIZARD_MODE && 1) +#define D_IMMORTAL (WIZARD_MODE && 1) -#define D_INSPECT_LEVELGEN (rogue.wizard && 0) -#define D_INSPECT_MACHINES (rogue.wizard && 0) +#define D_SAFETY_VISION (WIZARD_MODE && 0) +#define D_SCENT_VISION (WIZARD_MODE && 0) +#define D_OMNISCENCE (WIZARD_MODE && 0) -#define D_MESSAGE_ITEM_GENERATION (rogue.wizard && 0) -#define D_MESSAGE_MACHINE_GENERATION (rogue.wizard && 0) +#define D_INSPECT_LEVELGEN (WIZARD_MODE && 0) +#define D_INSPECT_MACHINES (WIZARD_MODE && 0) + +#define D_MESSAGE_ITEM_GENERATION (WIZARD_MODE && 0) +#define D_MESSAGE_MACHINE_GENERATION (WIZARD_MODE && 0) // If enabled, runs a benchmark for the performance of repeatedly updating the screen at the start of the game. // #define SCREEN_UPDATE_BENCHMARK @@ -2424,10 +2426,15 @@ typedef struct gameConstants { const int mainMenuTitleWidth; // width of the title screen in characters } gameConstants; +enum gameMode { + GAME_MODE_NORMAL, + GAME_MODE_WIZARD, + GAME_MODE_EASY +}; // these are basically global variables pertaining to the game state and player's unique variables: typedef struct playerCharacter { - boolean wizard; // in wizard mode + enum gameMode mode; // in wizard/easy mode short depthLevel; // which dungeon level are we on short deepestLevel; @@ -2446,7 +2453,6 @@ typedef struct playerCharacter { boolean updatedAllySafetyMapThisTurn; // so it's updated no more than once per turn boolean updatedMapToSafeTerrainThisTurn;// so it's updated no more than once per turn boolean updatedMapToShoreThisTurn; // so it's updated no more than once per turn - boolean easyMode; // enables easy mode boolean inWater; // helps with the blue water filter effect boolean heardCombatThisTurn; // so you get only one "you hear combat in the distance" per turn boolean creaturesWillFlashThisTurn; // there are creatures out there that need to flash before the turn ends diff --git a/src/brogue/RogueMain.c b/src/brogue/RogueMain.c index 6373b658..7d108f87 100644 --- a/src/brogue/RogueMain.c +++ b/src/brogue/RogueMain.c @@ -190,7 +190,7 @@ void initializeGameVariant() { void initializeRogue(uint64_t seed) { short i, j, k; item *theItem; - boolean playingback, playbackFF, playbackPaused, wizard, easy, displayStealthRangeMode; + boolean playingback, playbackFF, playbackPaused, mode, easy, displayStealthRangeMode; boolean trueColorMode; boolean hideSeed; short oldRNG; @@ -199,9 +199,8 @@ void initializeRogue(uint64_t seed) { playingback = rogue.playbackMode; // the only animals that need to go on the ark playbackPaused = rogue.playbackPaused; playbackFF = rogue.playbackFastForward; - wizard = rogue.wizard; + mode = rogue.mode; hideSeed = rogue.hideSeed; - easy = rogue.easyMode; displayStealthRangeMode = rogue.displayStealthRangeMode; trueColorMode = rogue.trueColorMode; @@ -215,9 +214,8 @@ void initializeRogue(uint64_t seed) { rogue.playbackMode = playingback; rogue.playbackPaused = playbackPaused; rogue.playbackFastForward = playbackFF; - rogue.wizard = wizard; + rogue.mode = mode; rogue.hideSeed = hideSeed; - rogue.easyMode = easy; rogue.displayStealthRangeMode = displayStealthRangeMode; rogue.trueColorMode = trueColorMode; @@ -1150,7 +1148,7 @@ void gameOver(char *killedBy, boolean useCustomPhrasing) { rogue.gold += 500 * numGems; theEntry.score = rogue.gold; - if (rogue.easyMode) { + if (rogue.mode == GAME_MODE_EASY) { theEntry.score /= 10; } strcpy(highScoreText, buf); @@ -1208,7 +1206,7 @@ void gameOver(char *killedBy, boolean useCustomPhrasing) { notifyEvent(GAMEOVER_RECORDING, 0, 0, "recording ended", "none"); } - if (!rogue.playbackMode && !rogue.easyMode && !rogue.wizard) { + if (!rogue.playbackMode && rogue.mode != GAME_MODE_EASY && rogue.mode != GAME_MODE_WIZARD) { saveRunHistory(rogue.quit ? "Quit" : "Died", rogue.quit ? "-" : killedBy, (int) theEntry.score, numGems); } @@ -1336,11 +1334,11 @@ void victory(boolean superVictory) { theEntry.score = totalValue; - if (rogue.easyMode) { + if (rogue.mode == GAME_MODE_EASY) { theEntry.score /= 10; } - if (!rogue.wizard && !rogue.playbackMode) { + if (!rogue.mode == GAME_MODE_WIZARD && !rogue.playbackMode) { qualified = saveHighScore(theEntry); } else { qualified = false; @@ -1374,7 +1372,7 @@ void victory(boolean superVictory) { notifyEvent(GAMEOVER_RECORDING, 0, 0, "recording ended", "none"); } - if (!rogue.playbackMode && !rogue.easyMode && !rogue.wizard) { + if (!rogue.playbackMode && rogue.mode != GAME_MODE_EASY && rogue.mode != GAME_MODE_NORMAL) { saveRunHistory(victoryVerb, "-", (int) theEntry.score, gemCount); } @@ -1383,7 +1381,7 @@ void victory(boolean superVictory) { } void enableEasyMode() { - if (rogue.easyMode) { + if (rogue.mode == GAME_MODE_EASY) { message("Alas, all hope of salvation is lost. You shed scalding tears at your plight.", 0); return; } @@ -1391,7 +1389,7 @@ void enableEasyMode() { if (confirm("Succumb to demonic temptation (i.e. enable Easy Mode)?", false)) { recordKeystroke(EASY_MODE_KEY, false, true); message("An ancient and terrible evil burrows into your willing flesh!", REQUIRE_ACKNOWLEDGMENT); - rogue.easyMode = true; + rogue.mode == GAME_MODE_EASY; setPlayerDisplayChar(); refreshDungeonCell(player.loc); refreshSideBar(-1, -1, false); diff --git a/src/platform/main.c b/src/platform/main.c index 81961516..b50a40e7 100644 --- a/src/platform/main.c +++ b/src/platform/main.c @@ -103,7 +103,7 @@ int main(int argc, char *argv[]) rogue.nextGame = NG_NOTHING; rogue.nextGamePath[0] = '\0'; rogue.nextGameSeed = 0; - rogue.wizard = false; + rogue.mode = GAME_MODE_NORMAL; rogue.displayStealthRangeMode = false; rogue.trueColorMode = false; @@ -309,7 +309,7 @@ int main(int argc, char *argv[]) } if (strcmp(argv[i], "--wizard") == 0 || strcmp(argv[i], "-W") == 0) { - rogue.wizard = true; + rogue.mode = GAME_MODE_WIZARD; continue; } diff --git a/src/platform/web-platform.c b/src/platform/web-platform.c index 2b1ce331..a7445926 100644 --- a/src/platform/web-platform.c +++ b/src/platform/web-platform.c @@ -35,7 +35,7 @@ enum StatusTypes DEEPEST_LEVEL_STATUS, GOLD_STATUS, SEED_STATUS, - EASY_MODE_STATUS, + MODE_STATUS, STATUS_TYPES_NUMBER }; @@ -185,7 +185,7 @@ static void sendStatusUpdate() { statusValues[DEEPEST_LEVEL_STATUS] = rogue.deepestLevel; statusValues[GOLD_STATUS] = rogue.gold; statusValues[SEED_STATUS] = rogue.seed; - statusValues[EASY_MODE_STATUS] = rogue.easyMode; + statusValues[MODE_STATUS] = rogue.mode; memset(statusOutputBuffer, 0, OUTPUT_SIZE); From 042f648dd9c20e46d41495b7462ece2432a2e3fe Mon Sep 17 00:00:00 2001 From: ZayadNimrod <32575659+ZayadNimrod@users.noreply.github.com> Date: Sun, 16 Nov 2025 14:26:38 +0000 Subject: [PATCH 4/5] Check the easy mode flag matches when loading a game. --- src/brogue/Recordings.c | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/src/brogue/Recordings.c b/src/brogue/Recordings.c index 6a3539f3..8e82b827 100644 --- a/src/brogue/Recordings.c +++ b/src/brogue/Recordings.c @@ -468,7 +468,7 @@ void initRecording() { } short i; - boolean wizardMode; + enum gameMode mode; unsigned short recPatch; char buf[1000], *versionString = rogue.versionString; FILE *recordFile; @@ -502,7 +502,7 @@ void initRecording() { for (i=0; i<15; i++) { versionString[i] = recallChar(); } - wizardMode = recallChar(); + rogue.mode = recallChar(); if (getPatchVersion(versionString, &recPatch) && recPatch <= gameConst->patchVersion) { // Major and Minor match ours, Patch is less than or equal to ours: we are compatible. @@ -527,34 +527,6 @@ void initRecording() { rogue.gameExitStatusCode = EXIT_STATUS_FAILURE_RECORDING_WRONG_VERSION; } - if (wizardMode != WIZARD_MODE) { - // wizard game cannot be played in normal mode and vice versa - rogue.playbackMode = false; - rogue.playbackFastForward = false; - if (wizardMode) { - if (!nonInteractivePlayback) { - sprintf(buf, "This game was played in wizard mode. You must start Brogue in wizard mode to replay it."); - dialogAlert(buf); - } else { - printf("This game was played in wizard mode. You must start Brogue in wizard mode to replay it."); - } - } else { - if (!nonInteractivePlayback) { - sprintf(buf, "To play this regular recording, please restart Brogue without the wizard mode option."); - dialogAlert(buf); - } else { - printf("To play this regular recording, please restart Brogue without the wizard mode option."); - } - } - - rogue.playbackMode = true; - rogue.playbackPaused = true; - rogue.playbackFastForward = false; - rogue.playbackOOS = false; - rogue.gameHasEnded = true; - rogue.gameExitStatusCode = EXIT_STATUS_FAILURE_RECORDING_WRONG_VERSION; - } - rogue.seed = recallNumber(8); // master random seed rogue.howManyTurns = recallNumber(4); // how many turns are in this recording maxLevelChanges = recallNumber(4); // how many times the player changes depths From 3fb2833823a17436c65e931e04800bf0c82a072a Mon Sep 17 00:00:00 2001 From: ZayadNimrod <32575659+ZayadNimrod@users.noreply.github.com> Date: Mon, 1 Dec 2025 22:26:10 +0000 Subject: [PATCH 5/5] Document the change made to the game loading. --- changes/game-mode-mismatch.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changes/game-mode-mismatch.md diff --git a/changes/game-mode-mismatch.md b/changes/game-mode-mismatch.md new file mode 100644 index 00000000..4fa70299 --- /dev/null +++ b/changes/game-mode-mismatch.md @@ -0,0 +1 @@ +Loading a savegame will now place the game into the same mode the savegame was made in (i.e normal, wizard, easy). \ No newline at end of file