diff --git a/data/scenarios/Testing/00-ORDER.txt b/data/scenarios/Testing/00-ORDER.txt index f5c7c5d622..177e10b450 100644 --- a/data/scenarios/Testing/00-ORDER.txt +++ b/data/scenarios/Testing/00-ORDER.txt @@ -40,7 +40,7 @@ 1320-world-DSL 1356-portals 144-subworlds -1341-command-count +1341-command-count.yaml 1355-combustion.yaml 1379-single-world-portal-reorientation.yaml 1399-backup-command.yaml diff --git a/data/scenarios/Testing/1341-command-count.yaml b/data/scenarios/Testing/1341-command-count.yaml index 4e8fd668a1..2647586c98 100644 --- a/data/scenarios/Testing/1341-command-count.yaml +++ b/data/scenarios/Testing/1341-command-count.yaml @@ -14,8 +14,11 @@ solution: | wait 10; x <- harvest; if (x == "flower") { - turn back; - } {move; + turn right; + move; + grab; + } { + return ""; }; robots: - name: base @@ -28,15 +31,16 @@ robots: - comparator - hourglass - branch predictor -known: [flower] +known: [flower, tree] world: default: [blank] palette: '.': [grass] 'f': [grass, flower] + 'T': [grass, tree] 'B': [grass, null, base] upperleft: [-1, 1] map: | ....... .B.fff. - ....... + ...T... diff --git a/src/Swarm/Game/Robot.hs b/src/Swarm/Game/Robot.hs index 968c279c7a..fa8f20bdd2 100644 --- a/src/Swarm/Game/Robot.hs +++ b/src/Swarm/Game/Robot.hs @@ -62,6 +62,8 @@ module Swarm.Game.Robot ( activityCounts, tickStepBudget, tangibleCommandCount, + anyCommandCount, + lifetimeStepCount, -- ** Creation & instantiation mkRobot, @@ -172,6 +174,8 @@ data RobotPhase data ActivityCounts = ActivityCounts { _tickStepBudget :: Int , _tangibleCommandCount :: Int + , _anyCommandCount :: Int + , _lifetimeStepCount :: Int } deriving (Eq, Show, Generic, FromJSON, ToJSON) @@ -218,9 +222,17 @@ makeLensesNoSigs ''ActivityCounts -- can tell when the counter increments. tickStepBudget :: Lens' ActivityCounts Int --- | Total number of commands executed over robot's lifetime +-- | Total number of tangible commands executed over robot's lifetime tangibleCommandCount :: Lens' ActivityCounts Int +-- | Total number of commands executed over robot's lifetime +anyCommandCount :: Lens' ActivityCounts Int + +-- | Total number of CESK steps executed over robot's lifetime. +-- This could be thought of as "CPU cycles" consumed, and is labeled +-- as "cycles" in the F2 dialog in the UI. +lifetimeStepCount :: Lens' ActivityCounts Int + -- | With a robot template, we may or may not have a location. With a -- concrete robot we must have a location. type family RobotLocation (phase :: RobotPhase) :: Data.Kind.Type where @@ -508,6 +520,8 @@ mkRobot rid pid name descr loc dir disp m devs inv sys heavy ts = ActivityCounts { _tickStepBudget = 0 , _tangibleCommandCount = 0 + , _anyCommandCount = 0 + , _lifetimeStepCount = 0 } , _runningAtomic = False } diff --git a/src/Swarm/Game/Step.hs b/src/Swarm/Game/Step.hs index 308d0814bf..f094b4cc1b 100644 --- a/src/Swarm/Game/Step.hs +++ b/src/Swarm/Game/Step.hs @@ -523,7 +523,10 @@ stepRobot :: (Has (State GameState) sig m, Has (Lift IO) sig m) => Robot -> m Ro stepRobot r = do (r', cesk') <- runState (r & activityCounts . tickStepBudget -~ 1) (stepCESK (r ^. machine)) -- sendIO $ appendFile "out.txt" (prettyString cesk' ++ "\n") - return $ r' & machine .~ cesk' + return $ + r' + & machine .~ cesk' + & activityCounts . lifetimeStepCount +~ 1 -- | replace some entity in the world with another entity updateWorld :: @@ -1003,6 +1006,8 @@ execConst c vs s k = do when (isTangible c) $ activityCounts . tangibleCommandCount %= (+ 1) + activityCounts . anyCommandCount %= (+ 1) + -- Now proceed to actually carry out the operation. case c of Noop -> return $ Out VUnit s k diff --git a/src/Swarm/TUI/View.hs b/src/Swarm/TUI/View.hs index afb771f0c2..6d9ce002f0 100644 --- a/src/Swarm/TUI/View.hs +++ b/src/Swarm/TUI/View.hs @@ -628,6 +628,8 @@ robotsListWidget s = hCenter table , "Inventory" , "Status" , "Actions" + , "Commands" + , "Cycles" , "Log" ] headers = withAttr robotAttr . txt <$> applyWhen cheat ("ID" :) headings @@ -642,6 +644,8 @@ robotsListWidget s = hCenter table , padRight (Pad 1) (str $ show rInvCount) , statusWidget , str $ show $ robot ^. activityCounts . tangibleCommandCount + , str $ show $ robot ^. activityCounts . anyCommandCount + , str $ show $ robot ^. activityCounts . lifetimeStepCount , txt rLog ] idWidget = str $ show $ robot ^. robotID diff --git a/test/integration/Main.hs b/test/integration/Main.hs index c4e6342020..a21bde30a7 100644 --- a/test/integration/Main.hs +++ b/test/integration/Main.hs @@ -32,7 +32,7 @@ import Swarm.Game.CESK (emptyStore, getTickNumber, initMachine) import Swarm.Game.Entity (EntityMap, lookupByName) import Swarm.Game.Failure (SystemFailure) import Swarm.Game.Log (ErrorLevel (..), LogEntry, LogSource (..), leSource, leText) -import Swarm.Game.Robot (defReqs, equippedDevices, machine, robotContext, robotLog, systemRobot, waitingUntil) +import Swarm.Game.Robot (activityCounts, anyCommandCount, defReqs, equippedDevices, lifetimeStepCount, machine, robotContext, robotLog, systemRobot, tangibleCommandCount, waitingUntil) import Swarm.Game.Scenario (Scenario) import Swarm.Game.State ( GameState, @@ -70,7 +70,7 @@ import Swarm.Util.Yaml (decodeFileEitherE) import System.FilePath.Posix (splitDirectories) import System.Timeout (timeout) import Test.Tasty (TestTree, defaultMain, testGroup) -import Test.Tasty.HUnit (Assertion, assertBool, assertFailure, testCase) +import Test.Tasty.HUnit (Assertion, assertBool, assertEqual, assertFailure, testCase) import Witch (into) isUnparseableTest :: (FilePath, String) -> Bool @@ -339,6 +339,13 @@ testScenarioSolutions rs ui = maybe False (view systemRobot) r2 assertBool "The third built robot should be a normal robot like base." $ maybe False (not . view systemRobot) r3 + , testSolution' Default "Testing/1341-command-count" CheckForBadErrors $ \g -> case g ^. robotMap . at 0 of + Nothing -> assertFailure "No base bot!" + Just base -> do + let counters = base ^. activityCounts + assertEqual "Incorrect tangible command count." 7 $ view tangibleCommandCount counters + assertEqual "Incorrect command count." 10 $ view anyCommandCount counters + assertEqual "Incorrect step count." 64 $ view lifetimeStepCount counters ] where -- expectFailIf :: Bool -> String -> TestTree -> TestTree