From c7fda03b994c39a7e463050220f185714b7af701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C5=A0ebek?= <44544735+xsebek@users.noreply.github.com> Date: Tue, 11 Feb 2025 00:14:33 +0100 Subject: [PATCH] Remove say command one message limit (#2316) * remove the `say` command limitation that only keeps one last said message in hearing robot logs * add test case from #1593 * add correct behavior check to scenario objective and integration test * closes #1592 * closes #1593 * see the original merge request #565 for context Co-authored-by: Karl Ostmo Co-authored-by: Brent Yorgey --- data/scenarios/Testing/00-ORDER.txt | 1 + .../1592-shared-template-robot-say-logs.yaml | 61 +++++++++++++++++++ data/schema/entity.json | 2 +- src/swarm-engine/Swarm/Game/Step/Const.hs | 30 ++------- test/integration/Main.hs | 15 +++-- 5 files changed, 80 insertions(+), 29 deletions(-) create mode 100644 data/scenarios/Testing/1592-shared-template-robot-say-logs.yaml diff --git a/data/scenarios/Testing/00-ORDER.txt b/data/scenarios/Testing/00-ORDER.txt index 8e5cd929e..ff8109ae8 100644 --- a/data/scenarios/Testing/00-ORDER.txt +++ b/data/scenarios/Testing/00-ORDER.txt @@ -57,6 +57,7 @@ Achievements 1721-walkability-whitelist-path-cache.yaml 1535-ping 1575-structure-recognizer +1592-shared-template-robot-say-logs.yaml 1631-tags.yaml 1634-message-colors.yaml 1681-pushable-entity.yaml diff --git a/data/scenarios/Testing/1592-shared-template-robot-say-logs.yaml b/data/scenarios/Testing/1592-shared-template-robot-say-logs.yaml new file mode 100644 index 000000000..dc6184b1c --- /dev/null +++ b/data/scenarios/Testing/1592-shared-template-robot-say-logs.yaml @@ -0,0 +1,61 @@ +version: 1 +name: Logs from same-template robots +creative: false +description: | + Logs from different robots generated from the same template. + + The objective checks that base hears one message each tick, + afterwards the integration test checks that all messages + are present in the base log. +objectives: + - goal: + - Please `grab` the `token`{=entity} if you hear what you expected. + condition: | + as base { has "token" } +solution: | + s <- listen; + if (s == "Hello from (2, -2)!") { + s <- listen; + if (s == "Hello from (3, -2)!") { + s <- listen; + if (s == "Hello from (4, -2)!") { + grab; say "OK!" + } {say $ "3: Not what I expected: " ++ s} + } {say $ "2: Not what I expected: " ++ s} + } {say $ "1: Not what I expected: " ++ s} +robots: + - name: base + devices: + - logger + - hearing aid + - comparator + - branch predictor + - string + - grabber + - name: saybot + system: true + display: + invisible: false + attr: blue + program: | + loc <- whereami; + wait $ fst loc; + say ("Hello from " ++ format loc ++ "!"); +entities: + - name: token + display: + char: 'W' + properties: + - known + - pickable + description: + - Signals a success. +world: + palette: + '.': [grass] + 'B': [grass, token, base] + 's': [grass, null, saybot] + map: | + B...s + ...ss + ..sss diff --git a/data/schema/entity.json b/data/schema/entity.json index 2f7a791b8..c513b3455 100644 --- a/data/schema/entity.json +++ b/data/schema/entity.json @@ -122,7 +122,7 @@ "type": "string", "examples": [ "unwalkable", - "portable", + "pickable", "infinite", "known", "growable" diff --git a/src/swarm-engine/Swarm/Game/Step/Const.hs b/src/swarm-engine/Swarm/Game/Step/Const.hs index d59af1c6f..a93e45520 100644 --- a/src/swarm-engine/Swarm/Game/Step/Const.hs +++ b/src/swarm-engine/Swarm/Game/Step/Const.hs @@ -749,34 +749,16 @@ execConst runChildProg c vs s k = do [VText msg] -> do isPrivileged <- isPrivilegedBot loc <- use robotLocation - -- current robot will be inserted into the robot set, so it needs the log m <- traceLog Said Info msg emitMessage m - let measureToLog robLoc = \case - RobotLog _ _ logLoc -> cosmoMeasure manhattan robLoc logLoc - SystemLog -> Measurable 0 - addLatestClosest rl = \case - Seq.Empty -> Seq.singleton m - es Seq.:|> e - | e `isEarlierThan` m -> es |> e |> m - | e `isFartherThan` m -> es |> m - | otherwise -> es |> e - where - isEarlierThan = (<) `on` (^. leTime) - isFartherThan = (>) `on` (measureToLog rl . view leSource) let addToRobotLog :: (Has (State GameState) sgn m) => Robot -> m () - addToRobotLog r = do - maybeRidLoc <- evalState r $ do - hasLog <- hasCapability $ CExecute Log - hasListen <- hasCapability $ CExecute Listen - loc' <- use robotLocation - rid <- use robotID - return $ do - guard $ hasLog && hasListen - Just (rid, loc') - forM_ maybeRidLoc $ \(rid, loc') -> - robotInfo . robotMap . at rid . _Just . robotLog %= addLatestClosest loc' + addToRobotLog r = evalState r $ do + hasLog <- hasCapability $ CExecute Log + hasListen <- hasCapability $ CExecute Listen + rid <- use robotID + when (hasLog && hasListen) $ + robotInfo . robotMap . at rid . _Just . robotLog %= (|> m) robotsAround <- zoomRobots $ if isPrivileged diff --git a/test/integration/Main.hs b/test/integration/Main.hs index 2a8a82252..571b2bc53 100644 --- a/test/integration/Main.hs +++ b/test/integration/Main.hs @@ -32,7 +32,7 @@ import Swarm.Failure (SystemFailure) import Swarm.Game.Achievement.Definitions (GameplayAchievement (..)) import Swarm.Game.CESK (initMachine) import Swarm.Game.Entity (lookupByName) -import Swarm.Game.Robot (equippedDevices, systemRobot) +import Swarm.Game.Robot (equippedDevices, robotName, systemRobot) import Swarm.Game.Robot.Activity (commandsHistogram, lifetimeStepCount, tangibleCommandCount) import Swarm.Game.Robot.Concrete (activityCounts, machine, robotLog, waitingUntil) import Swarm.Game.Scenario (Scenario, ScenarioInputs (..), gsiScenarioInputs) @@ -508,6 +508,13 @@ testScenarioSolutions rs ui key = && any ("- tank treads" `T.isInfixOf`) msgs , testSolution Default "Testing/2253-halt-waiting" , testSolution Default "Testing/2270-instant-defs" + , testSolution' Default "Testing/1592-shared-template-robot-say-logs" CheckForBadErrors $ \g -> do + let baseLogs = g ^.. baseRobot . robotLog . to logToText . traverse + -- printAllLogs g + assertEqual + "There should be 6 logs from all of the robots saying things at once!" + (length baseLogs) + 6 -- the final OK said by base happens after win, and is for debugging ] where -- expectFailIf :: Bool -> String -> TestTree -> TestTree @@ -555,9 +562,9 @@ noBadErrors g = printAllLogs :: GameState -> IO () printAllLogs g = - mapM_ - (\r -> forM_ (r ^. robotLog) (putStrLn . T.unpack . view leText)) - (g ^. robotInfo . robotMap) + forM_ (g ^. robotInfo . robotMap) $ \r -> do + putStrLn $ "-- ROBOT: " ++ T.unpack (r ^. robotName) + forM_ (r ^. robotLog) (putStrLn . T.unpack . view leText) -- | Test that editor files are up-to-date. testEditorFiles :: TestTree