From 1c0b36c8ef714573a2d86f9b024b757aab5515e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondr=CC=8Cej=20S=CC=8Cebek?= Date: Sun, 29 Sep 2024 17:33:37 +0200 Subject: [PATCH 01/10] Use new wall in ove tutorial --- data/entities.yaml | 13 ++ data/scenarios/Tutorials/move.yaml | 286 ++++++----------------- data/scenarios/Tutorials/move_surveil.sw | 47 ++-- 3 files changed, 107 insertions(+), 239 deletions(-) diff --git a/data/entities.yaml b/data/entities.yaml index c492aa884..14a0ad5d9 100644 --- a/data/entities.yaml +++ b/data/entities.yaml @@ -635,6 +635,19 @@ ############################################################ ### Utility ################################################ ############################################################ +- name: wall + display: + char: '+' + attr: entity + description: + - A wall + properties: [known, boundary] + +# following are "legacy" walls that do not connect automatically, +# but require explicitly plaing each one - this can be used for +# precise control, but in most cases the simple 'wall' is better +# because the 'boundary' updates it to look nice + - name: upper left corner display: attr: entity diff --git a/data/scenarios/Tutorials/move.yaml b/data/scenarios/Tutorials/move.yaml index 9df927214..577831b45 100644 --- a/data/scenarios/Tutorials/move.yaml +++ b/data/scenarios/Tutorials/move.yaml @@ -6,10 +6,15 @@ objectives: - id: move_to_first_flower teaser: Get the flower goal: - - Robots can use the `move` command to move forward one unit in the direction they are currently facing. - - To complete this challenge, move your robot two spaces to the right, to the coordinates `(2,0)` marked with the purple `flower`{=entity}. - - Note that you can chain commands with semicolon, `;`{=snippet}. - - You can open this popup window at any time to remind yourself of the goal using **Ctrl+G**. + - | + Robots can use the `move` command to move forward one unit in the direction they are currently facing. + + To complete this challenge, move your robot two spaces to the right, to the coordinates `(2,0)` + marked with the purple `flower`{=entity}. + + Note that you can chain commands with semicolon, `;`{=snippet}. + + You can open this popup window at any time to remind yourself of the goal using **Ctrl+G**. condition: | r <- robotNamed "check"; w <- as r {count "Win"}; @@ -17,16 +22,20 @@ objectives: - id: move_along_corridor teaser: Down the corridor goal: - - Good! Now you need to learn how to effectively repeat actions. - | + Good! Now you need to learn how to effectively repeat actions. + Previously you could move twice by chaining the move command: - - | - ``` - move; move - ``` - - To reuse that command without having to retype it press the upward arrow on your keyboard. This will allow you to select previous commands. - - Ahead of you is a six steps long corridor. Move to its end, i.e. the coordinates `(8,0)` marked with the second purple `flower`{=entity}. - - You can open this popup window at any time to remind yourself of the goal using **Ctrl+G**. + + `move; move`{=snippet} + + To reuse that command without having to retype it press the upward arrow on your keyboard. + This will allow you to select previous commands. + + Ahead of you is a six steps long corridor. Move to its end, i.e. the coordinates `(8,0)` marked + with the second purple `flower`{=entity}. + + You can open this popup window at any time to remind yourself of the goal using **Ctrl+G**. condition: | r <- robotNamed "check"; w <- as r {count "Win"}; @@ -35,16 +44,24 @@ objectives: - id: move_northeast_corner teaser: To northeast corner goal: - - Well done! In addition to `move`, you can use the `turn` command to turn your robot, for example, `turn right` or `turn east`. - - Switch to the inventory view in the upper left (by clicking on it or typing **Alt+E**) and select the `treads`{=entity} device to read about the details. If the bottom-left info panel is not big enough to read the whole thing, you can hit **Enter** on the `treads`{=entity} device to pop out the description, or you can focus the info panel (with **Alt+T** or by clicking) and scroll it with arrow keys or **PgUp**/**PgDown**. When you're done reading, you can come back to the REPL prompt by clicking on it or typing **Alt+R**. - - Afterwards, move your robot to the coordinates `(8,4)` in the northeast corner marked with two flowers. - | + Well done! In addition to `move`, you can use the `turn` command to turn your robot, for example, + `turn right` or `turn east`. + + Switch to the inventory view in the upper left (by clicking on it or typing **Alt+E**) and select + the `treads`{=entity} device to read about the details. + If the bottom-left info panel is not big enough to read the whole thing, you can hit **Enter** + on the `treads`{=entity} device to pop out the description, or you can focus the info panel + (with **Alt+T** or by clicking) and scroll it with arrow keys or **PgUp**/**PgDown**. + When you're done reading, you can come back to the REPL prompt by clicking on it or typing **Alt+R**. + + Afterwards, move your robot to the coordinates `(8,4)` in the northeast corner marked with two flowers. + Remember, you can chain commands with `;`{=snippet}, for example: - - | - ``` - move;move;move;move - ``` - - You can open this popup window at any time to remind yourself of the goal using **Ctrl+G**. + + `move; move; move; move`{=snippet} + + You can open this popup window at any time to remind yourself of the goal using **Ctrl+G**. condition: | r <- robotNamed "check"; w <- as r {count "Win"}; @@ -83,52 +100,31 @@ known: world: palette: '.': [blank] - '*': [blank, flower, check] - 'X': [blank, null, 1P flower] - 'Y': [blank, null, 2P flower] - 'Z': [blank, null, 3P flower] # FIRST ROOM - '┌': [blank, upper left corner] - '┐': [blank, upper right corner, 1S down and horizontal] - '└': [blank, lower left corner] - '┘': [blank, lower right corner, 1S up and horizontal] - '─': [blank, horizontal wall] - '│': [blank, vertical wall] + '0': [blank, wall] + 'A': [blank, flower, check] # SECOND ROOM - '1': [blank, vertical wall] - '-': [blank, null, 1P horizontal] - '|': [blank, null, 1P vertical] - 'c': [blank, null, 1P upper right, 1S left and vertical] - 'b': [blank, null, 1P lower right] - 'd': [blank, null, 1P horizontal, 2S up and horizontal] + '1': [blank, null, 1P wall] + 'B': [blank, null, 1P flower] # THIRD ROOM - '2': [blank, null, 1P horizontal] - '~': [blank, null, 2P horizontal] - '/': [blank, null, 2P vertical] - 'R': [blank, null, 2P upper right] - 'L': [blank, null, 2P upper left, 3S down and horizontal] - 'K': [blank, null, 2P vertical, 3S left and vertical] + '2': [blank, null, 2P wall] + 'C': [blank, null, 2P flower] # FOURTH ROOM - '3': [blank, null, 2P vertical] - '_': [blank, null, 3P horizontal] - '\': [blank, null, 3P vertical] - 'A': [blank, null, 3P lower left corner] - 'B': [blank, null, 3P lower right] - 'C': [blank, null, 3P upper right] - 'D': [blank, null, 3P upper left] + '3': [blank, null, 3P wall] + 'D': [blank, null, 3P flower] upperleft: [-1, 9] map: | - D_________C - \........Z\ - \..D______B - \..\....... - \..A___L~~R - \......3.Y/ - A______K../ - ......./../ - ┌───┐--d22c - │..*1....X| - └───┘-----b + 33333333333 + 3........D3 + 3..33333333 + 3..3....... + 3..33332222 + 3......2.C2 + 33333332..2 + .......2..2 + 00000111111 + 0..A0....B1 + 00000111111 # Font inspiration and a nicely visible separator: # # ███████ ██ ██ █████ ██████ ███ ███ @@ -152,178 +148,28 @@ robots: system: true program: run "scenarios/Tutorials/move_check.sw" ################# - ## HORIZONTAL ## + ## WALLS ## ################# - - name: 1P horizontal - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="horizontal wall", room=1]); - m - - name: 2P horizontal - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="horizontal wall", room=2]); - m - - name: 3P horizontal - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="horizontal wall", room=3]); - m - ################# - ## VERTICAL ## - ################# - - name: 1P vertical - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="vertical wall", room=1]); - m - - name: 2P vertical - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="vertical wall", room=2]); - m - - name: 3P vertical - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="vertical wall", room=3]); - m - ################# - ## CORNERS ## - ################# - # the order is: - # up left up right - # D+----+C - # | | - # | | - # A+----+B - # low left low right - ######### - ## A ## - ######### - - name: 3P lower left corner - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="lower left corner", room=3]); - m - ######### - ## B ## - ######### - - name: 1P lower right - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="lower right corner", room=1]); - m - - name: 3P lower right - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="lower right corner", room=3]); - m - ######### - ## C ## - ######### - - name: 1P upper right - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="upper right corner", room=1]); - m - - name: 2P upper right - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="upper right corner", room=2]); - m - - name: 3P upper right - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="upper right corner", room=3]); - m - ######### - ## D ## - ######### - - name: 2P upper left - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="upper left corner", room=2]); - m - - name: 3P upper left - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="upper left corner", room=3]); - m - ################# - ## SEPARATORS ## - ################# - # 1 - - name: 1S down and horizontal - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="S", entity="down and horizontal wall", room=1]); - m - - name: 1S up and horizontal - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="S", entity="up and horizontal wall", room=1]); - m - # 2 - - name: 1S left and vertical - system: true - program: | - def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="S", entity="left and vertical wall", room=2]); - m - - name: 2S up and horizontal + - name: 1P wall system: true program: | def main = \a. return noop end m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="S", entity="up and horizontal wall", room=2]); + main [entity="wall", room=1]); m - # 3 - - name: 3S left and vertical + - name: 2P wall system: true program: | def main = \a. return noop end m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="S", entity="left and vertical wall", room=3]); + main [entity="wall", room=2]); m - - name: 3S down and horizontal + - name: 3P wall system: true program: | def main = \a. return noop end m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="S", entity="down and horizontal wall", room=3]); + main [entity="wall", room=3]); m ################# ## GARDENERS ## @@ -333,21 +179,21 @@ robots: program: | def main = \a. return noop end m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="flower", room=1]); + main [entity="flower", room=1]); m - name: 2P flower system: true program: | def main = \a. return noop end m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="flower", room=2]); + main [entity="flower", room=2]); m - name: 3P flower system: true program: | def main = \a. return noop end m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [action="P", entity="flower", room=3]); + main [entity="flower", room=3]); m entities: - name: Win diff --git a/data/scenarios/Tutorials/move_surveil.sw b/data/scenarios/Tutorials/move_surveil.sw index 0ef13e609..f48c48863 100644 --- a/data/scenarios/Tutorials/move_surveil.sw +++ b/data/scenarios/Tutorials/move_surveil.sw @@ -1,3 +1,19 @@ +/* MOVE TUTORIAL - PLACEMENT ROBOT PROGRAM + +The wall tutorial places entities as the player progresses +through the rooms. The difficulty arises from the rooms +being so small (we don't want to overwhelm the player) +that the next room has to be placed in an INSTANT. + +To solve this the program returns peculiar type Cmd (Cmd Unit). +The program is instantly run by the robot so the run and setup +is guaranteed to happen in one tick and return the rest of the computation. + +1. SETUP - scans the location and create the entity +2. SURVEIL - wait for the location to change +3. PLACE the entity +*/ + def repeat : Int -> (Int -> Cmd Unit) -> Cmd Unit = \n. \c. if (n == 0) {} {c n; repeat (n-1) c} end @@ -5,18 +21,12 @@ end def elif = \b.\t.\e. {if b t e} end def else = \e. e end -def act_lazy: Text -> Text -> Cmd (Cmd Unit) = \a.\e. instant $ - if (a == "S") { - if (e != "") { create e } {}; - return (swap e; log $ a ++ ": " ++ e) - } $elif (a == "G") { - return (grab; log a) - } $elif (a == "P") { - if (e != "") { create e } {}; - return (place e; log $ a ++ ": " ++ e) - } $else { - return (fail $ "Finished waiting for check but I don't know what to do: '" ++ a ++ "'") - } +def safe_place: Text -> Cmd Unit = \e. + try { + place e; log $ "placed: " ++ e + } { + log $ "ERROR: could not place: " ++ e + } end def position: Int -> (Int * Int) = \room. @@ -31,21 +41,18 @@ def position: Int -> (Int * Int) = \room. } end -def room_changes = \room. if (room == 1) {1} {2} end - -def main: [action: Text, entity: Text, room: Int] -> Cmd (Cmd Unit) = \args. +def main: [entity: Text, room: Int] -> Cmd (Cmd Unit) = \args. let pos = position args.room in log $ format args; target <- as self {teleport self pos; scan down}; log $ "at position" ++ format pos ++ ": " ++ format target; - act <- act_lazy args.action args.entity; + create args.entity; return ( // first room optimization - actively wait for one tick to see if the change occured target2 <- as self {teleport self pos; scan down}; if (args.room == 1 && target == target2) { turn forward } {}; - let changes = room_changes args.room in has_changed <- if (target != target2) { log "changed in first tick - skipping one wait"; @@ -56,11 +63,13 @@ def main: [action: Text, entity: Text, room: Int] -> Cmd (Cmd Unit) = \args. return $ target != target3 }; let changed = if has_changed {1} {0} in - repeat (changes - changed) (\i. + // for later rooms a wall appears and then a door is opened + let change_count = if (args.room == 1) {1} {2} in + repeat (change_count - changed) (\i. log $ "sleeping until " ++ format pos ++ " changes (countdown: " ++ format i ++ ")"; surveil pos; wait 1000000; ); - act + safe_place args.entity ) end \ No newline at end of file From 7c8f8f997614bad2c4274a012ff660dd6cd72f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondr=CC=8Cej=20S=CC=8Cebek?= Date: Sun, 29 Sep 2024 19:46:20 +0200 Subject: [PATCH 02/10] Rewrite to use instant wait --- data/scenarios/Tutorials/move.yaml | 44 ++++++++------ data/scenarios/Tutorials/move_surveil.sw | 76 +++++++----------------- 2 files changed, 47 insertions(+), 73 deletions(-) diff --git a/data/scenarios/Tutorials/move.yaml b/data/scenarios/Tutorials/move.yaml index 577831b45..e47de9b66 100644 --- a/data/scenarios/Tutorials/move.yaml +++ b/data/scenarios/Tutorials/move.yaml @@ -13,7 +13,7 @@ objectives: marked with the purple `flower`{=entity}. Note that you can chain commands with semicolon, `;`{=snippet}. - + You can open this popup window at any time to remind yourself of the goal using **Ctrl+G**. condition: | r <- robotNamed "check"; @@ -154,23 +154,26 @@ robots: system: true program: | def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [entity="wall", room=1]); - m + instant ( + run "scenarios/Tutorials/move_surveil.sw"; + main [entity="wall", room=1] + ) - name: 2P wall system: true program: | def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [entity="wall", room=2]); - m + instant ( + run "scenarios/Tutorials/move_surveil.sw"; + main [entity="wall", room=2] + ) - name: 3P wall system: true program: | def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [entity="wall", room=3]); - m + instant ( + run "scenarios/Tutorials/move_surveil.sw"; + main [entity="wall", room=3] + ) ################# ## GARDENERS ## ################# @@ -178,23 +181,26 @@ robots: system: true program: | def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [entity="flower", room=1]); - m + instant ( + run "scenarios/Tutorials/move_surveil.sw"; + main [entity="flower", room=1] + ) - name: 2P flower system: true program: | def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [entity="flower", room=2]); - m + instant ( + run "scenarios/Tutorials/move_surveil.sw"; + main [entity="flower", room=2] + ) - name: 3P flower system: true program: | def main = \a. return noop end - m <- instant (run "scenarios/Tutorials/move_surveil.sw"; - main [entity="flower", room=3]); - m + instant ( + run "scenarios/Tutorials/move_surveil.sw"; + main [entity="flower", room=3] + ) entities: - name: Win display: diff --git a/data/scenarios/Tutorials/move_surveil.sw b/data/scenarios/Tutorials/move_surveil.sw index f48c48863..09260d588 100644 --- a/data/scenarios/Tutorials/move_surveil.sw +++ b/data/scenarios/Tutorials/move_surveil.sw @@ -1,34 +1,6 @@ -/* MOVE TUTORIAL - PLACEMENT ROBOT PROGRAM - -The wall tutorial places entities as the player progresses -through the rooms. The difficulty arises from the rooms -being so small (we don't want to overwhelm the player) -that the next room has to be placed in an INSTANT. - -To solve this the program returns peculiar type Cmd (Cmd Unit). -The program is instantly run by the robot so the run and setup -is guaranteed to happen in one tick and return the rest of the computation. - -1. SETUP - scans the location and create the entity -2. SURVEIL - wait for the location to change -3. PLACE the entity -*/ - -def repeat : Int -> (Int -> Cmd Unit) -> Cmd Unit = - \n. \c. if (n == 0) {} {c n; repeat (n-1) c} -end - def elif = \b.\t.\e. {if b t e} end def else = \e. e end -def safe_place: Text -> Cmd Unit = \e. - try { - place e; log $ "placed: " ++ e - } { - log $ "ERROR: could not place: " ++ e - } -end - def position: Int -> (Int * Int) = \room. if (room == 1) { (3,0) @@ -41,35 +13,31 @@ def position: Int -> (Int * Int) = \room. } end -def main: [entity: Text, room: Int] -> Cmd (Cmd Unit) = \args. +def wait_until_change = \pos. \original. \cont. + surveil pos; + wait 1024; + current <- as self {teleport self pos; scan down}; + if (current != original) { + cont current; + } { + wait_until_change pos original cont + } +end + +def main: [entity: Text, room: Int] -> Cmd Unit = \args. let pos = position args.room in log $ format args; - target <- as self {teleport self pos; scan down}; - log $ "at position" ++ format pos ++ ": " ++ format target; + original <- as self {teleport self pos; scan down}; + log $ "surveil position" ++ format pos ++ ": " ++ format original; create args.entity; - return ( - // first room optimization - actively wait for one tick to see if the change occured - target2 <- as self {teleport self pos; scan down}; - if (args.room == 1 && target == target2) { - turn forward - } {}; - has_changed <- - if (target != target2) { - log "changed in first tick - skipping one wait"; - return true - } $else { - target3 <- as self {teleport self pos; scan down}; - if (target != target3) { log "changed in second tick - skipping one wait" }{}; - return $ target != target3 - }; - let changed = if has_changed {1} {0} in + log $ "sleeping until " ++ format pos ++ " changes"; + wait_until_change pos original ( \after_change. // for later rooms a wall appears and then a door is opened - let change_count = if (args.room == 1) {1} {2} in - repeat (change_count - changed) (\i. - log $ "sleeping until " ++ format pos ++ " changes (countdown: " ++ format i ++ ")"; - surveil pos; - wait 1000000; - ); - safe_place args.entity + if (args.room == 1) { + place args.entity + } { + log $ "sleeping until " ++ format pos ++ " changes again"; + wait_until_change pos after_change (\_. place args.entity) + }; ) end \ No newline at end of file From 263113f2f8e34fc663c9a081dff80968f85d365e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondr=CC=8Cej=20S=CC=8Cebek?= Date: Sun, 29 Sep 2024 19:51:20 +0200 Subject: [PATCH 03/10] cleanup --- data/scenarios/Tutorials/move.yaml | 10 +++++----- data/scenarios/Tutorials/move_surveil.sw | 12 +++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/data/scenarios/Tutorials/move.yaml b/data/scenarios/Tutorials/move.yaml index e47de9b66..413d35a91 100644 --- a/data/scenarios/Tutorials/move.yaml +++ b/data/scenarios/Tutorials/move.yaml @@ -161,7 +161,7 @@ robots: - name: 2P wall system: true program: | - def main = \a. return noop end + def main = \a. noop end instant ( run "scenarios/Tutorials/move_surveil.sw"; main [entity="wall", room=2] @@ -169,7 +169,7 @@ robots: - name: 3P wall system: true program: | - def main = \a. return noop end + def main = \a. noop end instant ( run "scenarios/Tutorials/move_surveil.sw"; main [entity="wall", room=3] @@ -180,7 +180,7 @@ robots: - name: 1P flower system: true program: | - def main = \a. return noop end + def main = \a. noop end instant ( run "scenarios/Tutorials/move_surveil.sw"; main [entity="flower", room=1] @@ -188,7 +188,7 @@ robots: - name: 2P flower system: true program: | - def main = \a. return noop end + def main = \a. noop end instant ( run "scenarios/Tutorials/move_surveil.sw"; main [entity="flower", room=2] @@ -196,7 +196,7 @@ robots: - name: 3P flower system: true program: | - def main = \a. return noop end + def main = \a. noop end instant ( run "scenarios/Tutorials/move_surveil.sw"; main [entity="flower", room=3] diff --git a/data/scenarios/Tutorials/move_surveil.sw b/data/scenarios/Tutorials/move_surveil.sw index 09260d588..cd476ac22 100644 --- a/data/scenarios/Tutorials/move_surveil.sw +++ b/data/scenarios/Tutorials/move_surveil.sw @@ -15,11 +15,13 @@ end def wait_until_change = \pos. \original. \cont. surveil pos; - wait 1024; + timeout <- random 10000; + wait timeout; current <- as self {teleport self pos; scan down}; if (current != original) { cont current; } { + log $ "no change after " ++ format timeout ++ " ticks - continue"; wait_until_change pos original cont } end @@ -31,13 +33,13 @@ def main: [entity: Text, room: Int] -> Cmd Unit = \args. log $ "surveil position" ++ format pos ++ ": " ++ format original; create args.entity; log $ "sleeping until " ++ format pos ++ " changes"; - wait_until_change pos original ( \after_change. - // for later rooms a wall appears and then a door is opened + wait_until_change pos original ( \changed. if (args.room == 1) { place args.entity } { + // for later rooms a wall appears and then a door is opened log $ "sleeping until " ++ format pos ++ " changes again"; - wait_until_change pos after_change (\_. place args.entity) - }; + wait_until_change pos changed (\_. place args.entity) + } ) end \ No newline at end of file From 59ba6cec7cdc6684c3d96f650684d267344a263e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondr=CC=8Cej=20S=CC=8Cebek?= Date: Sun, 29 Sep 2024 21:10:41 +0200 Subject: [PATCH 04/10] make wall unwalkable --- data/entities.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/entities.yaml b/data/entities.yaml index 14a0ad5d9..bf026dcec 100644 --- a/data/entities.yaml +++ b/data/entities.yaml @@ -641,7 +641,7 @@ attr: entity description: - A wall - properties: [known, boundary] + properties: [unwalkable, known, boundary] # following are "legacy" walls that do not connect automatically, # but require explicitly plaing each one - this can be used for From 4dd5ff9b13321030906cda95585cd11455a54c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondr=CC=8Cej=20S=CC=8Cebek?= Date: Sun, 29 Sep 2024 21:11:49 +0200 Subject: [PATCH 05/10] simplify check --- data/scenarios/Tutorials/move.yaml | 20 +++----- data/scenarios/Tutorials/move_check.sw | 70 +++++++++++--------------- 2 files changed, 35 insertions(+), 55 deletions(-) diff --git a/data/scenarios/Tutorials/move.yaml b/data/scenarios/Tutorials/move.yaml index 413d35a91..e516b2ebe 100644 --- a/data/scenarios/Tutorials/move.yaml +++ b/data/scenarios/Tutorials/move.yaml @@ -16,9 +16,7 @@ objectives: You can open this popup window at any time to remind yourself of the goal using **Ctrl+G**. condition: | - r <- robotNamed "check"; - w <- as r {count "Win"}; - return (w >= 1) + as base {l <- whereami; return (l == (2,0))} - id: move_along_corridor teaser: Down the corridor goal: @@ -37,9 +35,7 @@ objectives: You can open this popup window at any time to remind yourself of the goal using **Ctrl+G**. condition: | - r <- robotNamed "check"; - w <- as r {count "Win"}; - return (w >= 2) + as base {l <- whereami; return (l == (8,0))} prerequisite: move_to_first_flower - id: move_northeast_corner teaser: To northeast corner @@ -55,7 +51,7 @@ objectives: (with **Alt+T** or by clicking) and scroll it with arrow keys or **PgUp**/**PgDown**. When you're done reading, you can come back to the REPL prompt by clicking on it or typing **Alt+R**. - Afterwards, move your robot to the coordinates `(8,4)` in the northeast corner marked with two flowers. + Afterwards, move your robot to the coordinates `(8,4)` in the northeast corner marked with another flower. Remember, you can chain commands with `;`{=snippet}, for example: @@ -63,9 +59,7 @@ objectives: You can open this popup window at any time to remind yourself of the goal using **Ctrl+G**. condition: | - r <- robotNamed "check"; - w <- as r {count "Win"}; - return (w >= 3) + as base {l <- whereami; return (l == (8,4))} prerequisite: move_along_corridor - goal: - Good job! You are now ready to move and turn on your own. @@ -73,9 +67,7 @@ objectives: - Remember you can press the upward arrow on your keyboard to select previous commands. - You can open this popup window at any time to remind yourself of the goal using **Ctrl+G**. condition: | - r <- robotNamed "check"; - w <- as r {count "Win"}; - return (w >= 4) + as base {l <- whereami; return (l == (8,8))} prerequisite: move_northeast_corner solution: | // 0 @@ -146,7 +138,7 @@ robots: ################# - name: check system: true - program: run "scenarios/Tutorials/move_check.sw" + program: instant (run "scenarios/Tutorials/move_check.sw") ################# ## WALLS ## ################# diff --git a/data/scenarios/Tutorials/move_check.sw b/data/scenarios/Tutorials/move_check.sw index b734dea54..f5b180780 100644 --- a/data/scenarios/Tutorials/move_check.sw +++ b/data/scenarios/Tutorials/move_check.sw @@ -1,67 +1,55 @@ -def until = \c. b <- c; if b {} {until c} end -def untilSafe = \c. until ( try { c } { return false } ) end - -def orM = \p1.\p2. b1 <- p1; if b1 {return true} {p2} end +def until = \cond. \c. b <- cond; if b {} {c; until cond c} end def abs = \x. if (x >= 0) {x} {-x} end -def baseIsAt = \l. +// TRICK: +// we only check for base at this location +// so we can sleep for as long as base will take to get here +def get_dist = \l. \bl. + abs (fst l - fst bl) + abs (snd l - snd bl) +end + +def waitForBaseAt = \l. \get_timeout. loc <- as base {whereami}; - // TRICK: - // we only check for base at this or neighbor location - // so we can sleep for as long as base will take to get there - let dist = abs (fst l - fst loc) + abs (snd l - snd loc) in - if (dist > 2) { - wait $ dist - 1 - } {}; - return (loc == l) + if (loc == l) { + return true + } { + wait (get_timeout l loc); + waitForBaseAt l get_timeout + } end def room1 = // l <- whereami; let l = (2, 0) in - untilSafe (baseIsAt l); - instant ( - create "Win"; - // open door - turn east; move; grab; - ) + waitForBaseAt l (\_. \_. 1); + log "room 1 done"; + // open door + turn east; move; grab; end def room2 = let l = (8, 0) in teleport self l; - untilSafe (baseIsAt l); - instant ( - create "Win"; - // open doors - turn north; move; grab; - turn west; move; grab; - ) + waitForBaseAt l get_dist; + log "room 2 done"; + // open doors + turn north; move; grab; + turn west; move; grab; end def room3 = - let l = (7, 4) in - teleport self l; - untilSafe $ orM (baseIsAt l) (baseIsAt (8, 4)); - instant ( - create "Win"; - // open door - turn west; move; grab; - ) -end - -def room4 = - let l = (8, 8) in + let l = (8, 4) in teleport self l; - untilSafe (baseIsAt l); - create "Win"; + waitForBaseAt l get_dist; + log "room 3 done"; + // open door + turn west; move; move; grab; end def main = room1; room2; room3; - room4; end main \ No newline at end of file From 65c6ef60f2b58d40906d20e24f6ad385e98b83d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondr=CC=8Cej=20S=CC=8Cebek?= Date: Sun, 29 Sep 2024 21:25:55 +0200 Subject: [PATCH 06/10] Use invisible door --- data/scenarios/Tutorials/move.yaml | 10 ++++++---- data/scenarios/Tutorials/move_check.sw | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/data/scenarios/Tutorials/move.yaml b/data/scenarios/Tutorials/move.yaml index e516b2ebe..91b28c7e8 100644 --- a/data/scenarios/Tutorials/move.yaml +++ b/data/scenarios/Tutorials/move.yaml @@ -194,9 +194,11 @@ robots: main [entity="flower", room=3] ) entities: - - name: Win + - name: door display: - char: W - attr: gold + char: 'D' + attr: entity + invisible: true description: - - This entity signals that the objective has been met. + - A wall + properties: [boundary] \ No newline at end of file diff --git a/data/scenarios/Tutorials/move_check.sw b/data/scenarios/Tutorials/move_check.sw index f5b180780..a00ec1c27 100644 --- a/data/scenarios/Tutorials/move_check.sw +++ b/data/scenarios/Tutorials/move_check.sw @@ -1,6 +1,8 @@ def until = \cond. \c. b <- cond; if b {} {c; until cond c} end def abs = \x. if (x >= 0) {x} {-x} end +def open_door = create "door"; swap "door" end + // TRICK: // we only check for base at this location // so we can sleep for as long as base will take to get here @@ -24,7 +26,7 @@ def room1 = waitForBaseAt l (\_. \_. 1); log "room 1 done"; // open door - turn east; move; grab; + turn east; move; open_door; end def room2 = @@ -33,8 +35,8 @@ def room2 = waitForBaseAt l get_dist; log "room 2 done"; // open doors - turn north; move; grab; - turn west; move; grab; + turn north; move; open_door; + turn west; move; open_door; end def room3 = @@ -43,7 +45,7 @@ def room3 = waitForBaseAt l get_dist; log "room 3 done"; // open door - turn west; move; move; grab; + turn west; move; move; open_door; end def main = From f706f461270fdeb9e9abb0793b22c438147e9fcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondr=CC=8Cej=20S=CC=8Cebek?= Date: Sun, 29 Sep 2024 21:32:11 +0200 Subject: [PATCH 07/10] remove whitespace --- data/entities.yaml | 2 -- data/scenarios/Tutorials/move.yaml | 20 ++++++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/data/entities.yaml b/data/entities.yaml index bf026dcec..d2a348344 100644 --- a/data/entities.yaml +++ b/data/entities.yaml @@ -642,12 +642,10 @@ description: - A wall properties: [unwalkable, known, boundary] - # following are "legacy" walls that do not connect automatically, # but require explicitly plaing each one - this can be used for # precise control, but in most cases the simple 'wall' is better # because the 'boundary' updates it to look nice - - name: upper left corner display: attr: entity diff --git a/data/scenarios/Tutorials/move.yaml b/data/scenarios/Tutorials/move.yaml index 91b28c7e8..34768e838 100644 --- a/data/scenarios/Tutorials/move.yaml +++ b/data/scenarios/Tutorials/move.yaml @@ -11,7 +11,7 @@ objectives: To complete this challenge, move your robot two spaces to the right, to the coordinates `(2,0)` marked with the purple `flower`{=entity}. - + Note that you can chain commands with semicolon, `;`{=snippet}. You can open this popup window at any time to remind yourself of the goal using **Ctrl+G**. @@ -22,17 +22,17 @@ objectives: goal: - | Good! Now you need to learn how to effectively repeat actions. - + Previously you could move twice by chaining the move command: `move; move`{=snippet} To reuse that command without having to retype it press the upward arrow on your keyboard. This will allow you to select previous commands. - + Ahead of you is a six steps long corridor. Move to its end, i.e. the coordinates `(8,0)` marked with the second purple `flower`{=entity}. - + You can open this popup window at any time to remind yourself of the goal using **Ctrl+G**. condition: | as base {l <- whereami; return (l == (8,0))} @@ -43,20 +43,20 @@ objectives: - | Well done! In addition to `move`, you can use the `turn` command to turn your robot, for example, `turn right` or `turn east`. - + Switch to the inventory view in the upper left (by clicking on it or typing **Alt+E**) and select the `treads`{=entity} device to read about the details. If the bottom-left info panel is not big enough to read the whole thing, you can hit **Enter** on the `treads`{=entity} device to pop out the description, or you can focus the info panel (with **Alt+T** or by clicking) and scroll it with arrow keys or **PgUp**/**PgDown**. When you're done reading, you can come back to the REPL prompt by clicking on it or typing **Alt+R**. - + Afterwards, move your robot to the coordinates `(8,4)` in the northeast corner marked with another flower. - + Remember, you can chain commands with `;`{=snippet}, for example: - + `move; move; move; move`{=snippet} - + You can open this popup window at any time to remind yourself of the goal using **Ctrl+G**. condition: | as base {l <- whereami; return (l == (8,4))} @@ -201,4 +201,4 @@ entities: invisible: true description: - A wall - properties: [boundary] \ No newline at end of file + properties: [boundary] From e62831de24a2770b3fa0237ca60cef9242d67b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondr=CC=8Cej=20S=CC=8Cebek?= Date: Sun, 29 Sep 2024 22:01:46 +0200 Subject: [PATCH 08/10] Ignore not craftable wall --- src/swarm-doc/Swarm/Doc/Gen.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/swarm-doc/Swarm/Doc/Gen.hs b/src/swarm-doc/Swarm/Doc/Gen.hs index 7d988017c..830ed65f7 100644 --- a/src/swarm-doc/Swarm/Doc/Gen.hs +++ b/src/swarm-doc/Swarm/Doc/Gen.hs @@ -328,7 +328,8 @@ startingInventory = Map.fromList . map swap . E.elems . view robotInventory ignoredEntities :: Set Text ignoredEntities = Set.fromList - [ "upper left corner" + [ "wall" + , "upper left corner" , "upper right corner" , "lower left corner" , "lower right corner" From d1a526be6f3b286173b10288dc12f6ebdb6d76ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondr=CC=8Cej=20S=CC=8Cebek?= Date: Sun, 29 Sep 2024 22:02:37 +0200 Subject: [PATCH 09/10] Apply suggestion --- data/entities.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/entities.yaml b/data/entities.yaml index d2a348344..23615f0ef 100644 --- a/data/entities.yaml +++ b/data/entities.yaml @@ -643,7 +643,7 @@ - A wall properties: [unwalkable, known, boundary] # following are "legacy" walls that do not connect automatically, -# but require explicitly plaing each one - this can be used for +# but require explicitly placing each one - this can be used for # precise control, but in most cases the simple 'wall' is better # because the 'boundary' updates it to look nice - name: upper left corner From 13ff298b48ffdb1f8ad5692836aa0dfb237cb6c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondr=CC=8Cej=20S=CC=8Cebek?= Date: Mon, 30 Sep 2024 13:00:39 +0200 Subject: [PATCH 10/10] Remove unnecessary snippet code annotation --- data/scenarios/Tutorials/move.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/scenarios/Tutorials/move.yaml b/data/scenarios/Tutorials/move.yaml index 34768e838..dcaa2769d 100644 --- a/data/scenarios/Tutorials/move.yaml +++ b/data/scenarios/Tutorials/move.yaml @@ -25,7 +25,7 @@ objectives: Previously you could move twice by chaining the move command: - `move; move`{=snippet} + `move; move` To reuse that command without having to retype it press the upward arrow on your keyboard. This will allow you to select previous commands. @@ -55,7 +55,7 @@ objectives: Remember, you can chain commands with `;`{=snippet}, for example: - `move; move; move; move`{=snippet} + `move; move; move; move` You can open this popup window at any time to remind yourself of the goal using **Ctrl+G**. condition: |