mirror of
https://github.com/swarm-game/swarm.git
synced 2024-10-27 01:49:15 +03:00
validate subworld names of explicitly located robots (#1875)
## Demo ``` scripts/test/run-tests.sh --test-options '--pattern "1875-robot-subworld-location"' ``` and ``` scripts/play.sh -i data/scenarios/Testing/144-subworlds/subworld-shared-structures.yaml --autoplay ```
This commit is contained in:
parent
eb20ea9b07
commit
834f549759
@ -1,7 +1,7 @@
|
||||
version: 1
|
||||
name: Subworld shared structures
|
||||
description: |
|
||||
Traverse floors of the tower
|
||||
Traverse the floors of the tower, then grab the flower in the middle
|
||||
attrs:
|
||||
- name: portal_in
|
||||
fg: "#ff9a00"
|
||||
@ -9,6 +9,12 @@ attrs:
|
||||
- name: portal_out
|
||||
fg: "#00a2ff"
|
||||
bg: "#0065ff"
|
||||
objectives:
|
||||
- goal:
|
||||
- |
|
||||
Visit all of the floors
|
||||
condition: |
|
||||
as base {has "flower"}
|
||||
entities:
|
||||
- name: telepad entrance
|
||||
display:
|
||||
@ -27,7 +33,9 @@ entities:
|
||||
robots:
|
||||
- name: base
|
||||
dir: east
|
||||
loc: [0, 0]
|
||||
loc:
|
||||
subworld: root
|
||||
loc: [0, 0]
|
||||
devices:
|
||||
- ADT calculator
|
||||
- branch predictor
|
||||
@ -41,6 +49,20 @@ robots:
|
||||
- logger
|
||||
- strange loop
|
||||
- treads
|
||||
solution: |
|
||||
def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end;
|
||||
|
||||
doN 4 (
|
||||
doN 4 move;
|
||||
turn right;
|
||||
doN 4 move;
|
||||
);
|
||||
|
||||
doN 2 move;
|
||||
turn right;
|
||||
doN 2 move;
|
||||
|
||||
grab;
|
||||
known: [flower]
|
||||
structures:
|
||||
- name: minibox
|
||||
@ -87,17 +109,18 @@ subworlds:
|
||||
waypoint:
|
||||
name: portal_in
|
||||
placements:
|
||||
- src: flowers
|
||||
offset: [1, 1]
|
||||
- src: minibox
|
||||
offset: [0, 0]
|
||||
orient:
|
||||
up: west
|
||||
- src: flowers
|
||||
offset: [1, 1]
|
||||
portals:
|
||||
- entrance: portal_in
|
||||
exitInfo:
|
||||
exit: portal_out
|
||||
subworldName: floor2
|
||||
reorient: back
|
||||
upperleft: [0, 0]
|
||||
map: |
|
||||
.....
|
||||
@ -119,17 +142,18 @@ subworlds:
|
||||
waypoint:
|
||||
name: portal_in
|
||||
placements:
|
||||
- src: flowers
|
||||
offset: [1, 0]
|
||||
- src: minibox
|
||||
offset: [0, 0]
|
||||
orient:
|
||||
up: south
|
||||
- src: flowers
|
||||
offset: [1, 0]
|
||||
portals:
|
||||
- entrance: portal_in
|
||||
exitInfo:
|
||||
exit: portal_out
|
||||
subworldName: floor3
|
||||
reorient: back
|
||||
upperleft: [0, 0]
|
||||
map: |
|
||||
.....
|
||||
@ -151,17 +175,18 @@ subworlds:
|
||||
waypoint:
|
||||
name: portal_in
|
||||
placements:
|
||||
- src: flowers
|
||||
offset: [1, -2]
|
||||
- src: minibox
|
||||
offset: [0, 0]
|
||||
orient:
|
||||
up: east
|
||||
- src: flowers
|
||||
offset: [1, -2]
|
||||
portals:
|
||||
- entrance: portal_in
|
||||
exitInfo:
|
||||
exit: portal_out
|
||||
subworldName: root
|
||||
reorient: back
|
||||
upperleft: [0, 0]
|
||||
map: |
|
||||
.....
|
||||
@ -171,20 +196,21 @@ subworlds:
|
||||
.....
|
||||
world:
|
||||
name: root
|
||||
default: [blank]
|
||||
palette:
|
||||
'.': [grass]
|
||||
'B': [grass, null, base]
|
||||
upperleft: [0, 0]
|
||||
placements:
|
||||
- src: flowers
|
||||
offset: [0, -2]
|
||||
- src: minibox
|
||||
offset: [0, 0]
|
||||
- src: flowers
|
||||
offset: [0, -2]
|
||||
portals:
|
||||
- entrance: portal_in
|
||||
exitInfo:
|
||||
exit: portal_out
|
||||
subworldName: floor1
|
||||
reorient: back
|
||||
map: |
|
||||
.....
|
||||
.....
|
||||
|
@ -0,0 +1,16 @@
|
||||
version: 1
|
||||
name: Robot location in nonexistent named subworld
|
||||
description: |
|
||||
Robot specifies an explicit "planar" location, which uses
|
||||
the "default" subworld name. However, since the root subworld
|
||||
has been given a name, we object that the subworld specified by
|
||||
the robot doesn't exist.
|
||||
robots:
|
||||
- name: base
|
||||
loc: [0, 0]
|
||||
world:
|
||||
name: mySubworld
|
||||
palette:
|
||||
'.': [grass]
|
||||
map: |-
|
||||
.
|
@ -69,7 +69,7 @@ import Control.Carrier.Throw.Either (runThrow)
|
||||
import Control.Effect.Lift (Lift, sendIO)
|
||||
import Control.Effect.Throw
|
||||
import Control.Lens hiding (from, (.=), (<.>))
|
||||
import Control.Monad (filterM, unless, (<=<))
|
||||
import Control.Monad (filterM, forM_, unless, (<=<))
|
||||
import Data.Aeson
|
||||
import Data.List.NonEmpty (NonEmpty ((:|)))
|
||||
import Data.List.NonEmpty qualified as NE
|
||||
@ -89,7 +89,7 @@ import Swarm.Game.Land
|
||||
import Swarm.Game.Location
|
||||
import Swarm.Game.Recipe
|
||||
import Swarm.Game.ResourceLoading (getDataFileNameSafe)
|
||||
import Swarm.Game.Robot (TRobot)
|
||||
import Swarm.Game.Robot (TRobot, trobotLocation, trobotName)
|
||||
import Swarm.Game.Scenario.Objective
|
||||
import Swarm.Game.Scenario.Objective.Validation
|
||||
import Swarm.Game.Scenario.RobotLookup
|
||||
@ -112,7 +112,7 @@ import Swarm.Language.Pipeline (ProcessedTerm)
|
||||
import Swarm.Language.Pretty (prettyText)
|
||||
import Swarm.Language.Syntax (Syntax)
|
||||
import Swarm.Language.Text.Markdown (Document)
|
||||
import Swarm.Util (binTuples, failT)
|
||||
import Swarm.Util (binTuples, commaList, failT, quote)
|
||||
import Swarm.Util.Effect (ignoreWarnings, throwToMaybe, withThrow)
|
||||
import Swarm.Util.Lens (makeLensesNoSigs)
|
||||
import Swarm.Util.Yaml
|
||||
@ -352,6 +352,18 @@ instance FromJSONE ScenarioInputs Scenario where
|
||||
, T.intercalate ", " $ map renderWorldName dupedNames
|
||||
]
|
||||
|
||||
-- Validate robot locations
|
||||
forM_ rs $ \r -> forM_ (r ^. trobotLocation) $ \rLoc ->
|
||||
unless ((rLoc ^. subworld) `M.member` worldsByName)
|
||||
. failT
|
||||
$ [ "Robot"
|
||||
, quote $ r ^. trobotName
|
||||
, "specifies location in nonexistent subworld"
|
||||
, renderQuotedWorldName (rLoc ^. subworld) <> "."
|
||||
, "Valid subworlds are:"
|
||||
, commaList $ map renderQuotedWorldName $ M.keys worldsByName
|
||||
]
|
||||
|
||||
let mergedWaypoints =
|
||||
M.fromList $
|
||||
map (worldName &&& runIdentity . waypoints . navigation) $
|
||||
|
@ -16,6 +16,7 @@ import Data.Yaml (FromJSON, ToJSON, Value (Object), parseJSON, withText, (.:))
|
||||
import GHC.Generics (Generic)
|
||||
import Linear (V2 (..))
|
||||
import Swarm.Game.Location
|
||||
import Swarm.Util (quote)
|
||||
|
||||
-- * Referring to subworlds
|
||||
|
||||
@ -30,6 +31,11 @@ renderWorldName = \case
|
||||
SubworldName s -> s
|
||||
DefaultRootSubworld -> "<default>"
|
||||
|
||||
renderQuotedWorldName :: SubworldName -> Text
|
||||
renderQuotedWorldName = \case
|
||||
SubworldName s -> quote s
|
||||
DefaultRootSubworld -> "<default>"
|
||||
|
||||
-- * Universal location
|
||||
|
||||
-- | The swarm universe consists of locations
|
||||
|
@ -353,6 +353,7 @@ testScenarioSolutions rs ui =
|
||||
, testSolution Default "Testing/144-subworlds/basic-subworld"
|
||||
, testSolution Default "Testing/144-subworlds/subworld-mapped-robots"
|
||||
, testSolution Default "Testing/144-subworlds/subworld-located-robots"
|
||||
, testSolution Default "Testing/144-subworlds/subworld-shared-structures"
|
||||
, testSolution Default "Testing/1355-combustion"
|
||||
, testSolution Default "Testing/1379-single-world-portal-reorientation"
|
||||
, testSolution Default "Testing/1322-wait-with-instant"
|
||||
|
Loading…
Reference in New Issue
Block a user