swarm 0.3.0.0 → 0.3.0.1
raw patch · 8 files changed
+75/−26 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +8/−0
- data/scenarios/Tutorials/backstory.yaml +2/−0
- data/scenarios/Tutorials/bind2.yaml +2/−0
- data/scenarios/Tutorials/require.yaml +1/−0
- src/Swarm/TUI/Controller.hs +28/−4
- src/Swarm/TUI/Model/Menu.hs +5/−1
- swarm.cabal +1/−1
- test/integration/Main.hs +28/−20
CHANGELOG.md view
@@ -1,5 +1,13 @@ # Revision history for swarm +## **0.3.0.1** - 2023-02-01++A few critical bug fixes and improvements:++* Make sure the base always has a `logger` installed in every tutorial level, by @byorgey in [#1067](https://github.com/swarm-game/swarm/pull/1067) and @xsebek in [#1073](https://github.com/swarm-game/swarm/pull/1073)+* Allow dialog boxes to scroll by @byorgey in [#1071](https://github.com/swarm-game/swarm/pull/1071)+* Fix bug that sometimes caused scenarios to be skipped or repeated by @byorgey in [#1065](https://github.com/swarm-game/swarm/pull/1065)+ ## **0.3.0.0** - 2023-01-30 This is the first release of 2023! It contains:
data/scenarios/Tutorials/backstory.yaml view
@@ -62,6 +62,8 @@ loc: [0,0] inventory: - [1, READY]+ devices:+ - logger - name: listener system: true display:
data/scenarios/Tutorials/bind2.yaml view
@@ -77,10 +77,12 @@ attr: robot devices: - 3D printer+ - logger inventory: - [1, solar panel] - [1, treads] - [1, grabber]+ - [1, compass] - name: floorspot system: true - name: pedestal
data/scenarios/Tutorials/require.yaml view
@@ -56,6 +56,7 @@ - [10, boat] - [10, grabber] - [10, scanner]+ - [10, compass] known: [water] world: default: [blank]
src/Swarm/TUI/Controller.hs view
@@ -189,6 +189,10 @@ _ -> error "No tutorials exist!" -- | If we are in a New Game menu, advance the menu to the next item in order.+--+-- NOTE: be careful to maintain the invariant that the currently selected+-- menu item is always the same as the currently played scenario! `quitGame`+-- is the only place this function should be called. advanceMenu :: Menu -> Menu advanceMenu = _NewGameMenu . ix 0 %~ BL.listMoveDown @@ -401,7 +405,7 @@ Just (Button QuitButton, _) -> quitGame Just (Button KeepPlayingButton, _) -> toggleModal KeepPlayingModal Just (Button StartOverButton, StartOver currentSeed siPair) -> restartGame currentSeed siPair- Just (Button NextButton, Next siPair) -> saveScenarioInfoOnQuit >> startGame siPair Nothing+ Just (Button NextButton, Next siPair) -> quitGame >> startGame siPair Nothing _ -> return () ev -> do Brick.zoom (uiState . uiModal . _Just . modalDialog) (handleDialogEvent ev)@@ -419,7 +423,7 @@ uiState . uiGoal . listWidget .= newList GoalSummary -> handleInfoPanelEvent modalScroll (VtyEvent ev) _ -> handleInfoPanelEvent modalScroll (VtyEvent ev)- _ -> return ()+ _ -> handleInfoPanelEvent modalScroll (VtyEvent ev) where refreshList lw = nestEventM' lw $ handleListEventWithSeparators ev isHeader @@ -470,13 +474,28 @@ -- -- * writes out the updated REPL history to a @.swarm_history@ file -- * saves current scenario status (InProgress/Completed)+-- * advances the menu to the next scenario IF the current one was won -- * returns to the previous menu quitGame :: EventM Name AppState () quitGame = do+ -- Write out REPL history. history <- use $ uiState . uiREPL . replHistory let hist = mapMaybe getREPLEntry $ getLatestREPLHistoryItems maxBound history liftIO $ (`T.appendFile` T.unlines hist) =<< getSwarmHistoryPath True++ -- Save scenario status info. saveScenarioInfoOnQuit++ -- Automatically advance the menu to the next scenario iff the+ -- player has won the current one.+ wc <- use $ gameState . winCondition+ case wc of+ WinConditions (Won _) _ -> uiState . uiMenu %= advanceMenu+ _ -> return ()++ -- Either quit the entire app (if the scenario was chosen directly+ -- from the command line) or return to the menu (if the scenario was+ -- chosen from the menu). menu <- use $ uiState . uiMenu case menu of NoMenu -> halt@@ -759,14 +778,19 @@ gameState . winCondition .= WinConditions (Unwinnable True) x openModal LoseModal - uiState . uiMenu %= advanceMenu return True WinConditions (Won False) x -> do -- This clears the "flag" that the Win dialog needs to pop up gameState . winCondition .= WinConditions (Won True) x openModal WinModal - uiState . uiMenu %= advanceMenu+ -- We do NOT advance the New Game menu to the next item here (we+ -- used to!), because we do not know if the user is going to+ -- select 'keep playing' or 'next challenge'. We maintain the+ -- invariant that the current menu item is always the same as+ -- the scenario currently being played. If the user either (1)+ -- quits to the menu or (2) selects 'next challenge' we will+ -- advance the menu at that point. return True WinConditions _ oc -> do let newGoalTracking = GoalTracking announcementsList $ constructGoalMap isCheating oc
src/Swarm/TUI/Model/Menu.hs view
@@ -74,7 +74,11 @@ data Menu = NoMenu -- We started playing directly from command line, no menu to show | MainMenu (BL.List Name MainMenuEntry)- | NewGameMenu (NonEmpty (BL.List Name ScenarioItem)) -- stack of scenario item lists+ | -- Stack of scenario item lists. INVARIANT: the currently selected+ -- menu item is ALWAYS the same as the scenario currently being played.+ -- See https://github.com/swarm-game/swarm/issues/1064 and+ -- https://github.com/swarm-game/swarm/pull/1065.+ NewGameMenu (NonEmpty (BL.List Name ScenarioItem)) | AchievementsMenu (BL.List Name CategorizedAchievement) | MessagesMenu | AboutMenu
swarm.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: swarm-version: 0.3.0.0+version: 0.3.0.1 synopsis: 2D resource gathering game with programmable robots description: Swarm is a 2D programming and resource gathering
test/integration/Main.hs view
@@ -24,8 +24,8 @@ import Swarm.DocGen (EditorType (..)) import Swarm.DocGen qualified as DocGen import Swarm.Game.CESK (emptyStore, initMachine)-import Swarm.Game.Entity (EntityMap, loadEntities)-import Swarm.Game.Robot (LogEntry, defReqs, leText, machine, robotContext, robotLog, waitingUntil)+import Swarm.Game.Entity (EntityMap, loadEntities, lookupByName)+import Swarm.Game.Robot (LogEntry, defReqs, equippedDevices, leText, machine, robotContext, robotLog, waitingUntil) import Swarm.Game.Scenario (Scenario) import Swarm.Game.State ( GameState,@@ -155,28 +155,28 @@ "Test scenario solutions" [ testGroup "Tutorial"- [ testSolution Default "Tutorials/backstory"- , testSolution (Sec 3) "Tutorials/move"- , testSolution Default "Tutorials/craft"- , testSolution Default "Tutorials/grab"- , testSolution Default "Tutorials/place"- , testSolution Default "Tutorials/types"- , testSolution Default "Tutorials/type-errors"- , testSolution Default "Tutorials/equip"- , testSolution Default "Tutorials/build"- , testSolution Default "Tutorials/bind2"- , testSolution' Default "Tutorials/crash" CheckForBadErrors $ \g -> do+ [ testTutorialSolution Default "Tutorials/backstory"+ , testTutorialSolution (Sec 3) "Tutorials/move"+ , testTutorialSolution Default "Tutorials/craft"+ , testTutorialSolution Default "Tutorials/grab"+ , testTutorialSolution Default "Tutorials/place"+ , testTutorialSolution Default "Tutorials/types"+ , testTutorialSolution Default "Tutorials/type-errors"+ , testTutorialSolution Default "Tutorials/equip"+ , testTutorialSolution Default "Tutorials/build"+ , testTutorialSolution Default "Tutorials/bind2"+ , testTutorialSolution' Default "Tutorials/crash" CheckForBadErrors $ \g -> do let rs = toList $ g ^. robotMap let hints = any (T.isInfixOf "you will win" . view leText) . toList . view robotLog let win = isJust $ find hints rs assertBool "Could not find a robot with winning instructions!" win- , testSolution Default "Tutorials/scan"- , testSolution Default "Tutorials/def"- , testSolution Default "Tutorials/lambda"- , testSolution Default "Tutorials/require"- , testSolution (Sec 3) "Tutorials/requireinv"- , testSolution Default "Tutorials/conditionals"- , testSolution (Sec 5) "Tutorials/farming"+ , testTutorialSolution Default "Tutorials/scan"+ , testTutorialSolution Default "Tutorials/def"+ , testTutorialSolution Default "Tutorials/lambda"+ , testTutorialSolution Default "Tutorials/require"+ , testTutorialSolution (Sec 3) "Tutorials/requireinv"+ , testTutorialSolution Default "Tutorials/conditionals"+ , testTutorialSolution (Sec 5) "Tutorials/farming" ] , testGroup "Challenges"@@ -289,6 +289,14 @@ -- printAllLogs when (shouldCheckBadErrors == CheckForBadErrors) $ noBadErrors g verify g++ tutorialHasLog :: GameState -> Assertion+ tutorialHasLog gs =+ let baseDevs = gs ^?! baseRobot . equippedDevices+ in assertBool "Base should have a logger installed!" (not . null $ lookupByName "logger" baseDevs)++ testTutorialSolution t f = testSolution' t f CheckForBadErrors tutorialHasLog+ testTutorialSolution' t f s v = testSolution' t f s $ \g -> tutorialHasLog g >> v g playUntilWin :: StateT GameState IO () playUntilWin = do