From c015525958e4ee6507e428647a19b607f983180f Mon Sep 17 00:00:00 2001 From: Karl Ostmo Date: Mon, 23 Oct 2023 11:15:38 -0700 Subject: [PATCH] instant entity change detection --- data/scenarios/Testing/00-ORDER.txt | 4 +- .../Testing/1322-wait-with-instant.yaml | 73 +++++++++++++++ .../Testing/1598-detect-entity-change.yaml | 89 +++++++++++++++++++ .../_1598-detect-entity-change/setup.sw | 17 ++++ src/Swarm/Game/State.hs | 11 ++- test/integration/Main.hs | 2 + 6 files changed, 191 insertions(+), 5 deletions(-) create mode 100644 data/scenarios/Testing/1322-wait-with-instant.yaml create mode 100644 data/scenarios/Testing/1598-detect-entity-change.yaml create mode 100644 data/scenarios/Testing/_1598-detect-entity-change/setup.sw diff --git a/data/scenarios/Testing/00-ORDER.txt b/data/scenarios/Testing/00-ORDER.txt index 91789eed9d..5ee7df4b7b 100644 --- a/data/scenarios/Testing/00-ORDER.txt +++ b/data/scenarios/Testing/00-ORDER.txt @@ -45,7 +45,9 @@ Achievements 1341-command-count.yaml 1355-combustion.yaml 1379-single-world-portal-reorientation.yaml +1322-wait-with-instant.yaml +1598-detect-entity-change.yaml 1399-backup-command.yaml 1430-built-robot-ownership.yaml 1536-custom-unwalkable-entities.yaml -1535-ping +1535-ping \ No newline at end of file diff --git a/data/scenarios/Testing/1322-wait-with-instant.yaml b/data/scenarios/Testing/1322-wait-with-instant.yaml new file mode 100644 index 0000000000..2d8fa39e2a --- /dev/null +++ b/data/scenarios/Testing/1322-wait-with-instant.yaml @@ -0,0 +1,73 @@ +version: 1 +name: Using wait with instant +author: Karl Ostmo +description: | + Observe timing of (instant $ wait 1) + interspersed with other commands +creative: false +seed: 0 +objectives: + - goal: + - | + Hare must win by three cells + condition: | + h <- robotnamed "hare"; + hareloc <- as h {whereami}; + + t <- robotnamed "tortoise"; + tortoiseloc <- as t {whereami}; + + let xDiff = fst hareloc - fst tortoiseloc in + + return $ fst hareloc == 0 && xDiff == 3; +solution: | + noop; +robots: + - name: base + dir: [1, 0] + display: + invisible: true + devices: + - hourglass + - logger + - name: tortoise + system: true + display: + invisible: false + attr: green + dir: [1, 0] + program: | + move; move; + move; move; + move; move; + - name: hare + system: true + display: + invisible: false + attr: snow + dir: [1, 0] + program: | + instant ( + move; move; + wait 1; + move; move; + wait 1; + move; move; + ); +world: + dsl: | + {blank} + upperleft: [-6, 2] + offset: false + palette: + '.': [grass, erase] + 'd': [dirt, erase] + 'B': [grass, erase, base] + 'T': [grass, erase, tortoise] + 'H': [grass, erase, hare] + map: | + B.....d. + T.....d. + H.....d. + ......d. + diff --git a/data/scenarios/Testing/1598-detect-entity-change.yaml b/data/scenarios/Testing/1598-detect-entity-change.yaml new file mode 100644 index 0000000000..ba7569baa4 --- /dev/null +++ b/data/scenarios/Testing/1598-detect-entity-change.yaml @@ -0,0 +1,89 @@ +version: 1 +name: Entity change detection +author: Karl Ostmo +description: | + Ensure that a change to an entity can be observed + by a system robot within a single tick. +creative: true +seed: 0 +objectives: + - goal: + - | + Turn the light green + condition: | + as base {has "flower"}; + prerequisite: + not: blue_light + - id: blue_light + teaser: No blue light + optional: true + goal: + - | + Turn the light blue + condition: | + r <- robotnamed "lockbot"; + as r {ishere "dial (B)"}; +robots: + - name: base + dir: [1, 0] + display: + invisible: true + devices: + - hourglass + - fast grabber + - logger + - treads + inventory: + - [1, "dial (R)"] + - [1, "dial (G)"] + - [1, "dial (B)"] + - name: lockbot + system: true + display: + invisible: true + dir: [1, 0] + program: | + run "scenarios/Testing/_1598-detect-entity-change/setup.sw" + inventory: + - [1, flower] +solution: | + wait 8; + move; + move; + swap "dial (G)"; + //wait 0; + swap "dial (B)"; +entities: + - name: "dial (R)" + display: + char: '•' + attr: red + description: + - A red dial + properties: [known, portable] + - name: "dial (G)" + display: + char: '•' + attr: green + description: + - A green dial + properties: [known, portable] + - name: "dial (B)" + display: + char: '•' + attr: blue + description: + - A blue dial + properties: [known, portable] +world: + dsl: | + {blank} + upperleft: [-1, -1] + offset: false + palette: + '.': [grass, erase] + 'B': [grass, erase, base] + 'c': [grass, dial (R), lockbot] + map: | + B.c + diff --git a/data/scenarios/Testing/_1598-detect-entity-change/setup.sw b/data/scenarios/Testing/_1598-detect-entity-change/setup.sw new file mode 100644 index 0000000000..21b1aa3f63 --- /dev/null +++ b/data/scenarios/Testing/_1598-detect-entity-change/setup.sw @@ -0,0 +1,17 @@ +def doUntilCorrect = + herenow <- ishere "dial (G)"; + if herenow { + give base "flower"; + } { + watch down; + wait 1000; + doUntilCorrect; + } + end; + +def go = + instant $ + doUntilCorrect; + end; + +go; diff --git a/src/Swarm/Game/State.hs b/src/Swarm/Game/State.hs index 7e8775ceaf..06ee376325 100644 --- a/src/Swarm/Game/State.hs +++ b/src/Swarm/Game/State.hs @@ -1020,12 +1020,14 @@ activateRobot rid = internalActiveRobots %= IS.insert rid wakeUpRobotsDoneSleeping :: (Has (State GameState) sig m) => m () wakeUpRobotsDoneSleeping = do time <- use $ temporal . ticks - mrids <- internalWaitingRobots . at time <<.= Nothing + waitingMap <- use waitingRobots + let (beforeMap, maybeAt, _) = M.splitLookup time waitingMap + mrids = NE.nonEmpty $ concat $ fromMaybe [] maybeAt : M.elems beforeMap case mrids of Nothing -> return () Just rids -> do robots <- use robotMap - let aliveRids = filter (`IM.member` robots) rids + let aliveRids = filter (`IM.member` robots) $ NE.toList rids internalActiveRobots %= IS.union (IS.fromList aliveRids) forM_ aliveRids $ \rid -> @@ -1033,7 +1035,7 @@ wakeUpRobotsDoneSleeping = do -- These robots' wake times may have been moved "forward" -- by 'wakeWatchingRobots'. - clearWatchingRobots rids + clearWatchingRobots $ NE.toList rids -- | Clear the "watch" state of all of the -- awakened robots @@ -1086,7 +1088,8 @@ wakeWatchingRobots loc = do -- Step 4: Re-add the watching bots to be awakened at the next tick: wakeableBotIds = map fst wakeTimes - newWakeTime = addTicks 1 currentTick + -- newWakeTime = addTicks 1 currentTick + newWakeTime = currentTick newInsertions = M.singleton newWakeTime wakeableBotIds forM_ wakeableBotIds $ \rid -> diff --git a/test/integration/Main.hs b/test/integration/Main.hs index 416cf0294a..20e1f5b0e2 100644 --- a/test/integration/Main.hs +++ b/test/integration/Main.hs @@ -334,6 +334,8 @@ testScenarioSolutions rs ui = , testSolution Default "Testing/144-subworlds/subworld-located-robots" , testSolution Default "Testing/1355-combustion" , testSolution Default "Testing/1379-single-world-portal-reorientation" + , testSolution Default "Testing/1322-wait-with-instant" + , testSolution Default "Testing/1598-detect-entity-change" , testSolution Default "Testing/1399-backup-command" , testSolution Default "Testing/1536-custom-unwalkable-entities" , testGroup