Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

subworld-aware teleportation and location query commands #2195

Merged
merged 3 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions data/scenarios/Testing/144-subworlds/00-ORDER.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ subworld-shared-structures.yaml
subworld-mapped-robots.yaml
subworld-located-robots.yaml
spatial-consistency-enforcement.yaml
teleport-and-query.yaml
66 changes: 66 additions & 0 deletions data/scenarios/Testing/144-subworlds/teleport-and-query.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
version: 1
name: Subworld teleportation
description: |
Surface and underground with portals.
objectives:
- goal:
- |
System robot must teleport the base to another subworld.
The goal condition utilizes location query command.
condition: |
as base {
myloc <- locateme;
return $ fst myloc == "underground";
}
solution: |
noop
robots:
- name: base
dir: east
devices:
- ADT calculator
- branch predictor
- comparator
- compass
- dictionary
- GPS receiver
- grabber
- lambda
- lodestone
- logger
- strange loop
- treads
- name: judge
dir: east
system: true
display:
char: 'J'
invisible: true
program: |
wait 10;
warp base ("underground", (0, 0));
known: [flower, boulder]
subworlds:
- name: underground
default: [blank]
palette:
'.': [dirt]
'f': [dirt, flower]
'b': [dirt, boulder]
upperleft: [-1, 1]
map: |
b..b..b..b
....f.....
b..b..b..b
world:
name: root
default: [blank]
palette:
'.': [grass]
'B': [grass, null, base]
't': [ice, null, judge]
upperleft: [-1, 1]
map: |
..........
...Bt.....
..........
2 changes: 2 additions & 0 deletions editors/emacs/swarm-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
"time"
"scout"
"whereami"
"locateme"
"waypoint"
"structure"
"floorplan"
Expand Down Expand Up @@ -122,6 +123,7 @@
"instant"
"installkeyhandler"
"teleport"
"warp"
"as"
"robotnamed"
"robotnumbered"
Expand Down
2 changes: 1 addition & 1 deletion editors/vim/swarm.vim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
syn keyword Keyword def tydef rec end let in require
syn keyword Builtins self parent base if inl inr case fst snd force undefined fail not format chars split charat tochar key
syn keyword Command noop wait selfdestruct move backup volume path push stride turn grab harvest sow ignite place ping give equip unequip make has equipped count drill use build salvage reprogram say listen log view appear create halt time scout whereami waypoint structure floorplan hastag tagmembers detect resonate density sniff chirp watch surveil heading blocked scan upload ishere isempty meet meetall whoami setname random run return try swap atomic instant installkeyhandler teleport as robotnamed robotnumbered knows
syn keyword Command noop wait selfdestruct move backup volume path push stride turn grab harvest sow ignite place ping give equip unequip make has equipped count drill use build salvage reprogram say listen log view appear create halt time scout whereami locateme waypoint structure floorplan hastag tagmembers detect resonate density sniff chirp watch surveil heading blocked scan upload ishere isempty meet meetall whoami setname random run return try swap atomic instant installkeyhandler teleport warp as robotnamed robotnumbered knows
syn keyword Direction east north west south down forward left back right
syn match Type "\<[A-Z][a-zA-Z_]*\>"
syn match Operators "[-=!<>|&+*/^$:]"
Expand Down
2 changes: 1 addition & 1 deletion editors/vscode/syntaxes/swarm.tmLanguage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ repository:
keyword:
name: keyword.other
match: >-
\b(self|parent|base|if|inl|inr|case|fst|snd|force|undefined|fail|not|format|chars|split|charat|tochar|key|noop|wait|selfdestruct|move|backup|volume|path|push|stride|turn|grab|harvest|sow|ignite|place|ping|give|equip|unequip|make|has|equipped|count|drill|use|build|salvage|reprogram|say|listen|log|view|appear|create|halt|time|scout|whereami|waypoint|structure|floorplan|hastag|tagmembers|detect|resonate|density|sniff|chirp|watch|surveil|heading|blocked|scan|upload|ishere|isempty|meet|meetall|whoami|setname|random|run|return|try|swap|atomic|instant|installkeyhandler|teleport|as|robotnamed|robotnumbered|knows)\b
\b(self|parent|base|if|inl|inr|case|fst|snd|force|undefined|fail|not|format|chars|split|charat|tochar|key|noop|wait|selfdestruct|move|backup|volume|path|push|stride|turn|grab|harvest|sow|ignite|place|ping|give|equip|unequip|make|has|equipped|count|drill|use|build|salvage|reprogram|say|listen|log|view|appear|create|halt|time|scout|whereami|locateme|waypoint|structure|floorplan|hastag|tagmembers|detect|resonate|density|sniff|chirp|watch|surveil|heading|blocked|scan|upload|ishere|isempty|meet|meetall|whoami|setname|random|run|return|try|swap|atomic|instant|installkeyhandler|teleport|warp|as|robotnamed|robotnumbered|knows)\b
require:
name: keyword.control.require
match: \b(require)\b
Expand Down
67 changes: 39 additions & 28 deletions src/swarm-engine/Swarm/Game/Step/Const.hs
Original file line number Diff line number Diff line change
Expand Up @@ -272,34 +272,12 @@ execConst runChildProg c vs s k = do
_ -> badConst
Teleport -> case vs of
[VRobot rid, VPair (VInt x) (VInt y)] -> do
-- Make sure the other robot exists and is close
target <- getRobotWithinTouch rid
-- either change current robot or one in robot map
let oldLoc = target ^. robotLocation
nextLoc = fmap (const $ Location (fromIntegral x) (fromIntegral y)) oldLoc

onTarget rid $ do
checkMoveAhead nextLoc $ \case
PathBlockedBy _ -> Destroy
PathLiquid _ -> Destroy
updateRobotLocation oldLoc nextLoc

-- Privileged robots can teleport without causing any
-- improbable effects. Unprivileged robots must be using an
-- infinite improbability drive, which can cause a random entity
-- to spawn near the target location.
omni <- isPrivilegedBot
unless omni $ do
let area = map (<$ nextLoc) $ getLocsInArea (nextLoc ^. planar) 5
emptyLocs <- filterM (fmap isNothing . entityAt) area
randomLoc <- weightedChoice (const 1) emptyLocs
es <- uses (landscape . terrainAndEntities . entityMap) allEntities
randomEntity <- weightedChoice (const 1) es
case (randomLoc, randomEntity) of
(Just loc, Just e) -> updateEntityAt loc (const (Just e))
_ -> return ()

return $ mkReturn ()
doTeleport rid (Location (fromIntegral x) (fromIntegral y) <$)
_ -> badConst
Warp -> case vs of
[VRobot rid, VPair (VText swName) (VPair (VInt x) (VInt y))] -> do
doTeleport rid . const . Cosmic (SubworldName swName) $
Location (fromIntegral x) (fromIntegral y)
_ -> badConst
Grab -> mkReturn <$> doGrab Grab' PerformRemoval
Harvest -> mkReturn <$> doGrab Harvest' PerformRemoval
Expand Down Expand Up @@ -557,6 +535,9 @@ execConst runChildProg c vs s k = do
Whereami -> do
loc <- use robotLocation
return $ mkReturn $ loc ^. planar
LocateMe -> do
loc <- use robotLocation
return $ mkReturn (loc ^. subworld, loc ^. planar)
Waypoint -> case vs of
[VText name, VInt idx] -> do
lm <- use $ landscape . worldNavigation
Expand Down Expand Up @@ -1255,6 +1236,36 @@ execConst runChildProg c vs s k = do
let msg = "The operator '$' should only be a syntactic sugar and removed in elaboration:\n"
in throwError . Fatal $ msg <> badConstMsg
where
doTeleport rid locUpdateFunc = do
-- Make sure the other robot exists and is close
target <- getRobotWithinTouch rid
-- either change current robot or one in robot map
let oldLoc = target ^. robotLocation
nextLoc = locUpdateFunc oldLoc

onTarget rid $ do
checkMoveAhead nextLoc $ \case
PathBlockedBy _ -> Destroy
PathLiquid _ -> Destroy
updateRobotLocation oldLoc nextLoc

-- Privileged robots can teleport without causing any
-- improbable effects. Unprivileged robots must be using an
-- infinite improbability drive, which can cause a random entity
-- to spawn near the target location.
omni <- isPrivilegedBot
unless omni $ do
let area = map (<$ nextLoc) $ getLocsInArea (nextLoc ^. planar) 5
emptyLocs <- filterM (fmap isNothing . entityAt) area
randomLoc <- weightedChoice (const 1) emptyLocs
es <- uses (landscape . terrainAndEntities . entityMap) allEntities
randomEntity <- weightedChoice (const 1) es
case (randomLoc, randomEntity) of
(Just loc, Just e) -> updateEntityAt loc (const (Just e))
_ -> return ()

return $ mkReturn ()

doDrill d = do
ins <- use equippedDevices

Expand Down
4 changes: 4 additions & 0 deletions src/swarm-engine/Swarm/Game/Value.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import Swarm.Game.Entity
import Swarm.Game.Location
import Swarm.Game.Robot
import Swarm.Game.Scenario.Topography.Area (AreaDimensions (..))
import Swarm.Game.Universe
import Swarm.Language.Syntax.Direction
import Swarm.Language.Value

Expand Down Expand Up @@ -52,6 +53,9 @@ instance Valuable Bool where
instance Valuable Text where
asValue = VText

instance Valuable SubworldName where
asValue = asValue . renderWorldName

instance Valuable () where
asValue = const VUnit

Expand Down
10 changes: 10 additions & 0 deletions src/swarm-lang/Swarm/Language/Syntax/Constants.hs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ data Const
Scout
| -- | Get the current x, y coordinates
Whereami
| -- | Get the current subworld and x, y coordinates
LocateMe
| -- | Get the x, y coordinates of a named waypoint, by index
Waypoint
| -- | Get the x, y coordinates of southwest corner of a constructed structure, by index
Expand Down Expand Up @@ -304,6 +306,8 @@ data Const

-- | Teleport a robot to the given position.
Teleport
| -- | Relocate a robot to the given cosmic position.
Warp
| -- | Run a command as if you were another robot.
As
| -- | Find an actor by name.
Expand Down Expand Up @@ -678,6 +682,11 @@ constInfo c = case c of
shortDoc
(Set.singleton $ Query $ Sensing RobotSensing)
"Get the current x and y coordinates."
LocateMe ->
command 0 Intangible $
shortDoc
(Set.singleton $ Query $ Sensing RobotSensing)
"Get the current subworld and x, y coordinates."
Waypoint ->
command 2 Intangible . doc (Set.singleton $ Query APriori) "Get the x, y coordinates of a named waypoint, by index" $
[ "Return only the waypoints in the same subworld as the calling robot."
Expand Down Expand Up @@ -852,6 +861,7 @@ constInfo c = case c of
, "The second argument is a function to handle keyboard inputs."
]
Teleport -> command 2 short $ shortDoc (Set.singleton $ Mutation $ RobotChange PositionChange) "Teleport a robot to the given location."
Warp -> command 2 short $ shortDoc (Set.singleton $ Mutation $ RobotChange PositionChange) "Relocate a robot to the given cosmic location."
As -> command 2 Intangible $ shortDoc (Set.singleton $ Mutation $ RobotChange BehaviorChange) "Hypothetically run a command as if you were another robot."
RobotNamed -> command 1 Intangible $ shortDoc (Set.singleton $ Query $ Sensing RobotSensing) "Find an actor by name."
RobotNumbered -> command 1 Intangible $ shortDoc (Set.singleton $ Query $ Sensing RobotSensing) "Find an actor by number."
Expand Down
2 changes: 2 additions & 0 deletions src/swarm-lang/Swarm/Language/Typecheck.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,7 @@ inferConst c = run . runReader @TVCtx Ctx.empty . quantify $ case c of
Time -> [tyQ| Cmd Int |]
Scout -> [tyQ| Dir -> Cmd Bool |]
Whereami -> [tyQ| Cmd (Int * Int) |]
LocateMe -> [tyQ| Cmd (Text * (Int * Int)) |]
Waypoint -> [tyQ| Text -> Int -> Cmd (Int * (Int * Int)) |]
Structure -> [tyQ| Text -> Int -> Cmd (Unit + (Int * (Int * Int))) |]
Floorplan -> [tyQ| Text -> Cmd (Int * Int) |]
Expand Down Expand Up @@ -1102,6 +1103,7 @@ inferConst c = run . runReader @TVCtx Ctx.empty . quantify $ case c of
Key -> [tyQ| Text -> Key |]
InstallKeyHandler -> [tyQ| Text -> (Key -> Cmd Unit) -> Cmd Unit |]
Teleport -> [tyQ| Actor -> (Int * Int) -> Cmd Unit |]
Warp -> [tyQ| Actor -> (Text * (Int * Int)) -> Cmd Unit |]
As -> [tyQ| Actor -> {Cmd a} -> Cmd a |]
RobotNamed -> [tyQ| Text -> Cmd Actor |]
RobotNumbered -> [tyQ| Int -> Cmd Actor |]
Expand Down
1 change: 1 addition & 0 deletions test/integration/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ testScenarioSolutions rs ui key =
, testSolution Default "Testing/1295-density-command"
, testSolution Default "Testing/1356-portals/portals-flip-and-rotate"
, testSolution Default "Testing/144-subworlds/basic-subworld"
, testSolution Default "Testing/144-subworlds/teleport-and-query"
, testSolution Default "Testing/144-subworlds/subworld-mapped-robots"
, testSolution Default "Testing/144-subworlds/subworld-located-robots"
, testSolution Default "Testing/144-subworlds/subworld-shared-structures"
Expand Down
Loading