diff --git a/src/Swarm/TUI/Controller.hs b/src/Swarm/TUI/Controller.hs index a4541aad2..8d891e9aa 100644 --- a/src/Swarm/TUI/Controller.hs +++ b/src/Swarm/TUI/Controller.hs @@ -140,15 +140,22 @@ handleNewGameMenuEvent scenarioStack@(curMenu :| rest) s = \case let gs = s ^. gameState gs' <- liftIO $ playScenario (gs ^. entityMap) scene Nothing Nothing gs + let nextMenu + -- Go back to the scenario list + | null rest = NewGameMenu scenarioStack + -- Advance to the next tutorial or challenge + | otherwise = NewGameMenu (BL.listMoveDown curMenu :| rest) + continue $ s & uiState . uiMenu .~ NoMenu + & uiState . uiPrevMenu .~ nextMenu & gameState .~ gs' Just (SICollection _ c) -> continue $ s & uiState . uiMenu .~ NewGameMenu (NE.cons (mkScenarioList (s ^. uiState . uiCheatMode) c) scenarioStack) Key V.KEsc -> exitNewGameMenu s scenarioStack CharKey 'q' -> exitNewGameMenu s scenarioStack - ControlKey 'q' -> exitNewGameMenu s scenarioStack + ControlKey 'q' -> halt s VtyEvent ev -> do menu' <- handleListEvent ev curMenu continue $ s & uiState . uiMenu .~ NewGameMenu (menu' :| rest) @@ -243,14 +250,14 @@ handleModalEvent s = \case continue s' -- | Quit a game. Currently all it does is write out the updated REPL --- history to a @.swarm_history@ file, and return to the main menu. +-- history to a @.swarm_history@ file, and return to the previous menu. quitGame :: AppState -> EventM Name (Next AppState) quitGame s = do let hist = mapMaybe getREPLEntry $ getLatestREPLHistoryItems maxBound history liftIO $ (`T.appendFile` T.unlines hist) =<< getSwarmHistoryPath True let s' = s & uiState . uiReplHistory %~ restartREPLHistory - & uiState . uiMenu .~ MainMenu (mainMenu NewGame) + & uiState . uiMenu .~ (s ^. uiState . uiPrevMenu) continue s' where history = s ^. uiState . uiReplHistory diff --git a/src/Swarm/TUI/Model.hs b/src/Swarm/TUI/Model.hs index 604c26b37..faaffd80a 100644 --- a/src/Swarm/TUI/Model.hs +++ b/src/Swarm/TUI/Model.hs @@ -57,6 +57,7 @@ module Swarm.TUI.Model ( -- ** UI Model UIState, uiMenu, + uiPrevMenu, uiCheatMode, uiFocusRing, uiReplForm, @@ -359,6 +360,7 @@ makePrisms ''InventoryListEntry -- see the lenses below. data UIState = UIState { _uiMenu :: Menu + , _uiPrevMenu :: Menu , _uiCheatMode :: Bool , _uiFocusRing :: FocusRing Name , _uiReplForm :: Form Text AppEvent Name @@ -407,6 +409,9 @@ let exclude = ['_lgTicksPerSecond] -- | The current menu state. uiMenu :: Lens' UIState Menu +-- | The previous menu state, to go back after playing a game +uiPrevMenu :: Lens' UIState Menu + -- | Cheat mode, i.e. are we allowed to turn creative mode on and off? uiCheatMode :: Lens' UIState Bool @@ -579,6 +584,7 @@ initUIState showMainMenu cheatMode = liftIO $ do return $ UIState { _uiMenu = if showMainMenu then MainMenu (mainMenu NewGame) else NoMenu + , _uiPrevMenu = NoMenu , _uiCheatMode = cheatMode , _uiFocusRing = initFocusRing , _uiReplForm = initReplForm diff --git a/src/Swarm/TUI/View.hs b/src/Swarm/TUI/View.hs index 2bc578a1f..b2e5fefb8 100644 --- a/src/Swarm/TUI/View.hs +++ b/src/Swarm/TUI/View.hs @@ -288,7 +288,15 @@ generateModal s mt = Modal mt (dialog (Just title) buttons (maxModalWindowWidth (title, widget, buttons, requiredWidth) = case mt of HelpModal -> (" Help ", helpWidget, Nothing, maxModalWindowWidth) - WinModal -> ("", txt "Congratulations!", Nothing, maxModalWindowWidth) + WinModal -> + let winMsg = "Congratulations!" + continueMsg = "Keep playing" + stopMsg = "Pick the next game" + in ( "" + , padBottom (Pad 1) $ hCenter $ txt winMsg + , Just (0, [(stopMsg, Confirm), (continueMsg, Cancel)]) + , length continueMsg + length stopMsg + 32 + ) DescriptionModal e -> (descriptionTitle e, descriptionWidget s e, Nothing, 100) QuitModal -> let quitMsg = "Are you sure you want to quit this game and return to the menu?"