diff --git a/data/entities.yaml b/data/entities.yaml index ecf685a36..cbee01b20 100644 --- a/data/entities.yaml +++ b/data/entities.yaml @@ -343,7 +343,7 @@ description: - Employs hot lead typesetting to arrange glyphs into a mold for printing. - | - An equipped `linotype` device enables the `format` command: + An equipped `linotype`{=entity} device enables the `format` command: - | `format : a -> text` can turn any value into a suitable text representation. @@ -385,7 +385,7 @@ description: - A simple machine for the textually-inclined; plain but effective. - | - An equipped `wedge` enables the `split` command: + An equipped `wedge`{=entity} enables the `split` command: - | `split : int -> text -> text * text` splits a `text` value into two pieces, one before the given index and one after. @@ -401,7 +401,7 @@ information, made of twisted cotton fibers. Multiple strings can also be woven into larger configurations such as cloth or nets. - | - An equipped `string` device enables several commands for working with + An equipped `string`{=entity} device enables several commands for working with `text` values: - | `format : a -> text` can turn any value into a suitable text @@ -955,13 +955,13 @@ description: - | A dictionary allows a robot to remember definitions and reuse them - later. You can access this ability with either a `def` command, + later. You can access this ability with either a `def`{=snippet} command, which creates a name for an expression or command that is - available from then on, or with a `let` expression, which names an + available from then on, or with a `let`{=snippet} expression, which names an expression or command locally within another expression. - ' def m2 : cmd unit = move; move end' - ' let x : int = 3 in x^2 + 2*x + 1' - - The type annotations in `def` and `let` are optional. + - The type annotations in `def`{=snippet} are optional. properties: [portable] capabilities: [env] @@ -1072,7 +1072,7 @@ char: 'l' description: - "Allows a robot to generate and store messages for later viewing, - using the `log` command, which takes a string. Log messages are + using the `log`{=entity} command, which takes a string. Log messages are also automatically generated by uncaught exceptions." properties: [portable] capabilities: [log] @@ -1363,7 +1363,7 @@ installs a custom handler function that can be activated to respond to keyboard inputs typed at the REPL. - | - `key : text -> key` constructs values of type `key`, for + `key : text -> key` constructs values of type `key`{=entity}, for example `key "Down"` or `key "C-S-x"`. properties: [portable] capabilities: [handleinput] diff --git a/data/scenarios/Challenges/Mazes/easy_spiral_maze.yaml b/data/scenarios/Challenges/Mazes/easy_spiral_maze.yaml index d12aa4bb6..2f262b625 100644 --- a/data/scenarios/Challenges/Mazes/easy_spiral_maze.yaml +++ b/data/scenarios/Challenges/Mazes/easy_spiral_maze.yaml @@ -7,7 +7,7 @@ objectives: - You find yourself in the middle of a large maze. - It's straightforward to get out, but the path is long and dull. - You need to send a robot to the goal square, labelled with an exclamation mark; - you win by `grab`bing the `"goal"`. + you win by `grab`bing the `goal`{=entity}. - Beware! The winding corridors are wider then they look! condition: | j <- robotNamed "judge"; diff --git a/data/scenarios/Challenges/Mazes/invisible_maze.yaml b/data/scenarios/Challenges/Mazes/invisible_maze.yaml index 9e50b6a94..7e607460e 100644 --- a/data/scenarios/Challenges/Mazes/invisible_maze.yaml +++ b/data/scenarios/Challenges/Mazes/invisible_maze.yaml @@ -8,7 +8,7 @@ objectives: - There is a maze, but it can't be seen, only sensed... can you program a robot to navigate it successfully? You need to get a robot to the goal square, labelled with an exclamation mark; you win by `grab`bing - the `"goal"`. + the `goal`{=entity}. - In this challenge, it is guaranteed that the maze is a tree, that is, there are no loops within the maze. condition: | diff --git a/data/scenarios/Challenges/Mazes/loopy_maze.yaml b/data/scenarios/Challenges/Mazes/loopy_maze.yaml index d01d5fe03..4705d478f 100644 --- a/data/scenarios/Challenges/Mazes/loopy_maze.yaml +++ b/data/scenarios/Challenges/Mazes/loopy_maze.yaml @@ -8,7 +8,7 @@ objectives: - There is a maze, but it can't be seen, only sensed... can you program a robot to navigate it successfully? You need to get a robot to the goal square, labelled with an exclamation mark; you win by `grab`bing - the `"goal"`. + the `goal`{=entity}. - In this challenge, you are NOT guaranteed that the maze is a tree, that is, the maze may contain loops. condition: | diff --git a/data/scenarios/Challenges/Sliding Puzzles/3x3.yaml b/data/scenarios/Challenges/Sliding Puzzles/3x3.yaml index 43d485649..349fb92b7 100644 --- a/data/scenarios/Challenges/Sliding Puzzles/3x3.yaml +++ b/data/scenarios/Challenges/Sliding Puzzles/3x3.yaml @@ -21,7 +21,7 @@ objectives: To slide a tile into the empty space, position yourself behind it and `push`. - | - Or, if you prefer, `drill` a tile to cause it to slide + Or, if you prefer, `drill`{=entity} a tile to cause it to slide into the adjacent empty space. However, you must not drill a tile that has nowhere to slide. Also, drilling consumes "ink", which will be replenished after the sliding operation is complete, so avoid drilling too fast in diff --git a/data/scenarios/Challenges/arbitrage.yaml b/data/scenarios/Challenges/arbitrage.yaml index 3d6dab157..65ffc9124 100644 --- a/data/scenarios/Challenges/arbitrage.yaml +++ b/data/scenarios/Challenges/arbitrage.yaml @@ -10,7 +10,7 @@ objectives: - | Each shop offers different wares for trade. Recipes dictate which items may be exchanged - at any given shop. Use the `drill` on a shop to perform + at any given shop. Use the `drill`{=entity} on a shop to perform an exchange. - | As an itinerant merchant, you may exploit market asymmetry diff --git a/data/scenarios/Challenges/blender.yaml b/data/scenarios/Challenges/blender.yaml index 88561aef0..274752fbb 100644 --- a/data/scenarios/Challenges/blender.yaml +++ b/data/scenarios/Challenges/blender.yaml @@ -11,7 +11,7 @@ objectives: `grab` the Amulet of Yoneda from the northwest sanctum while timing your passage carefully to avoid Side Effects (X) on patrol. - | - To unlock a red door, `drill` it with the "door key" equipped. + To unlock a red door, `drill`{=entity} it with the "door key" equipped. condition: | as base {has "Amulet of Yoneda"} prerequisite: diff --git a/data/scenarios/Challenges/bucket-brigade.yaml b/data/scenarios/Challenges/bucket-brigade.yaml index 5a3e3cb92..b6edcba65 100644 --- a/data/scenarios/Challenges/bucket-brigade.yaml +++ b/data/scenarios/Challenges/bucket-brigade.yaml @@ -60,7 +60,7 @@ objectives: - Deliver a "coal lump" to the base. - | To excavate coal from the "lignite mine" (M), a robot needs to - `drill` while in posession of a "bucketwheel excavator". + `drill`{=entity} while in posession of a "bucketwheel excavator". - | To assemble the excavator, you'll need to repurpose some "treads". diff --git a/data/scenarios/Challenges/gopher.yaml b/data/scenarios/Challenges/gopher.yaml index 5601d4eb5..68feed669 100644 --- a/data/scenarios/Challenges/gopher.yaml +++ b/data/scenarios/Challenges/gopher.yaml @@ -15,7 +15,7 @@ objectives: He will burrow (o) underground awhile, then pop up anywhere within the rectangular grassy region to gloat atop his "mound" of dirt for a short time. - `drill` the "mound" while he sits to drive him + `drill`{=entity} the "mound" while he sits to drive him away. Eventually you should wear down his resolve! condition: | try { diff --git a/data/scenarios/Challenges/lights-out.yaml b/data/scenarios/Challenges/lights-out.yaml index fc0fa8722..75a87fd89 100644 --- a/data/scenarios/Challenges/lights-out.yaml +++ b/data/scenarios/Challenges/lights-out.yaml @@ -13,7 +13,7 @@ objectives: - teaser: Extinguish lights goal: - | - `drill` a light to toggle it and its four direct neighbors + `drill`{=entity} a light to toggle it and its four direct neighbors between "off" and "on". - | The puzzle is won when all lights have been extinguished. diff --git a/data/scenarios/Challenges/word-search.yaml b/data/scenarios/Challenges/word-search.yaml index 45887e544..58a21bdb5 100644 --- a/data/scenarios/Challenges/word-search.yaml +++ b/data/scenarios/Challenges/word-search.yaml @@ -7,7 +7,7 @@ seed: 2 creative: false objectives: - goal: - - Use the `drill` command (e.g. "drill down" when on top of the + - Use the `drill`{=entity} command (e.g. "drill down" when on top of the intended letter) to mark the sequence of letters that spells COW within the designated playfield. - | @@ -117,10 +117,10 @@ objectives: /** It's possible we could be one cell away from a marked cell after finishing, either due - to using a directional `drill` command instead of + to using a directional `drill`{=entity} command instead of `drill down`, or due to an apparent bug which does not evaluate the goal condition between the - `drill` and a `move` command. + `drill`{=entity} and a `move` command. */ def moveToMarkedCell = \n. if (n > 0) { diff --git a/data/scenarios/Tutorials/bind2.yaml b/data/scenarios/Tutorials/bind2.yaml index b09bb329f..7700c40d8 100644 --- a/data/scenarios/Tutorials/bind2.yaml +++ b/data/scenarios/Tutorials/bind2.yaml @@ -29,23 +29,23 @@ objectives: - | Every command returns a value. However, some simple commands, like `move`, do not have any meaningful - value to return. Swarm has a special type, `unit`, with only one value, + value to return. Swarm has a special type, `unit`{=type}, with only one value, called `()`. Since there is only one possible value of type - `unit`, returning it does not convey any information. - Thus, the type of `move` is `cmd unit`. + `unit`{=type}, returning it does not convey any information. + Thus, the type of `move` is `cmd unit`{=type}. - | Other commands do return a nontrivial value after executing. - For example, `grab` has type `cmd text`, and returns the name of the + For example, `grab` has type `cmd text`{=type}, and returns the name of the grabbed entity as a text value. - | To use the result of a command later, you need "bind notation", which consists of a variable name and a leftwards-pointing arrow before the command. For example: - | - move; t <- grab; place t + `move; t <- grab; place t` - | In the above example, the result returned by `grab` is assigned - to the variable name `t`, which can then be used later. + to the variable name `t`{=snippet}, which can then be used later. This is useful, for example, if you do not care what you grabbed and just want to move it to another cell, or if you are not sure of the name of the thing being grabbed. diff --git a/data/scenarios/Tutorials/build.yaml b/data/scenarios/Tutorials/build.yaml index e0a671273..ca19efc46 100644 --- a/data/scenarios/Tutorials/build.yaml +++ b/data/scenarios/Tutorials/build.yaml @@ -11,11 +11,11 @@ objectives: build robots to do the work for you. You will start in a base ('Ω') that does not move (at least not yet). - Let's start by building a gardener robot to perform a simple task. - - You can `build` a robot with `build {COMMANDS}`, - where in place of `COMMANDS` you write the sequence + - You can `build` a robot with `build {COMMANDS}`{=snippet}, + where in place of `COMMANDS`{=snippet} you write the sequence of commands for the robot to execute (separated by semicolons). - | - Build a robot to harvest the "flower" and place it next + Build a robot to harvest the `"flower"` and place it next to the water. - | TIP: Newly built robots start out facing the same diff --git a/data/scenarios/Tutorials/conditionals.yaml b/data/scenarios/Tutorials/conditionals.yaml index f3a1d7aa7..8d0b735b8 100644 --- a/data/scenarios/Tutorials/conditionals.yaml +++ b/data/scenarios/Tutorials/conditionals.yaml @@ -5,17 +5,17 @@ description: | objectives: - goal: - | - The 4x4 gray square contains 4 `very small rock`s --- so + The 4x4 gray square contains 4 `very small rock`{=entity}s --- so small they cannot be seen! Your goal is to collect all of them and bring them back to your base; you win when you have all 4. There is one rock in each row and column, but otherwise you can't be sure where they are. Your best bet is - to sweep over the entire 4x4 square and pick up a `very small - rock` any time you detect one. + to sweep over the entire 4x4 square and pick up a `very small rock`{=entity} + any time you detect one. - | - The `ishere` command, with type `text -> cmd bool`, can be used - for detecting the presence of a specific item such as a `very small rock`. - What we need is a way to take the `bool` output from `ishere` + The `ishere` command, with type `text -> cmd bool`{=type}, can be used + for detecting the presence of a specific item such as a `very small rock`{=entity}. + What we need is a way to take the `bool`{=type} output from `ishere` and use it to decide whether to `grab` a rock or not. (Trying to execute `grab` in a cell without anything to grab will throw an exception, causing the robot to crash.) @@ -29,24 +29,26 @@ objectives: It takes a boolean expression and then returns either the first or second subsequent argument, depending on whether the boolean expression is true or false, respectively. - | - The type variable `a` can stand for any type; `{a}` - indicates a *delayed* expression of type `a`. Normally, + The type variable `a`{=type} can stand for any type; `{a}`{=type} + indicates a *delayed* expression of type `a`{=type}. Normally, function arguments are evaluated strictly before the function is called. Delayed expressions, on the other hand, are not evaluated until needed. In this case, we want to make sure that only the correct branch is evaluated. To write a value - of type, say, `{int}`, we just surround a value of type `int` - in curly braces, like `{3}`. This is why arguments to `build` - must also be in curly braces: the type of `build` is `{cmd a} - -> cmd robot`. + of type, say, `{int}`{=type}, we just surround a value of type `int`{=type} + in curly braces, like `{3}`{=type}. This is why arguments to `build` + must also be in curly braces: the type of `build` + is `{cmd a} -> cmd robot`{=type}. - | - TIP: Note that `if` requires a `bool`, not a `cmd bool`! So you cannot directly say - `if (ishere "very small rock") {...} {...}`. Instead you can write `b <- ishere "very small rock"; if b {...} {...}`. You might enjoy writing your own function of - type `cmd bool -> {cmd a} -> {cmd a} -> cmd a` to encapsulate this pattern. + TIP: Note that `if` requires a `bool`{=type}, not a `cmd bool`{=type}! So you cannot directly say + `if (ishere "very small rock") {...} {...}`{=snippet}. + Instead you can write `b <- ishere "very small rock"; if b {...} {...}`{=snippet}. + You might enjoy writing your own function of + type `cmd bool -> {cmd a} -> {cmd a} -> cmd a`{=type} to encapsulate this pattern. - | TIP: the two branches of an `if` must have the same type. In particular, - `if ... {grab} {}` is not - allowed, because `{grab}` has type `{cmd text}` whereas `{}` has type `{cmd unit}`. + `if ... {grab} {}`{=snippet} is not + allowed, because `{grab}` has type `{cmd text}`{=type} whereas `{}` has type `{cmd unit}`{=type}. In this case `{grab; return ()}` has the right type. condition: | try { diff --git a/data/scenarios/Tutorials/craft.yaml b/data/scenarios/Tutorials/craft.yaml index d9cb42a2b..39a30c9ac 100644 --- a/data/scenarios/Tutorials/craft.yaml +++ b/data/scenarios/Tutorials/craft.yaml @@ -9,7 +9,7 @@ description: | objectives: - goal: - Robots can use the `make` command to make things, as long as - they have a `workbench` and the proper ingredients. For + they have a `workbench`{=entity} and the proper ingredients. For example, `make "circuit"` will make a circuit. - Your base has a few trees in its inventory. Select them to see the available recipes. diff --git a/data/scenarios/Tutorials/crash.yaml b/data/scenarios/Tutorials/crash.yaml index 1d4b80783..3751357e9 100644 --- a/data/scenarios/Tutorials/crash.yaml +++ b/data/scenarios/Tutorials/crash.yaml @@ -9,16 +9,16 @@ objectives: - | In this challenge, you should start by sending a robot to walk four steps straight east into the mountain, - crashing deliberately. However, you must make sure it has a `logger`, + crashing deliberately. However, you must make sure it has a `logger`{=entity}, so we can see what command failed. The simplest way to ensure - that is to have it execute the `log` command; `build` will + that is to have it execute the `log`{=entity} command; `build` will ensure it has the devices it needs to execute its commands. For example: - | build {log "Hi!"; turn east; move; move; move; log "3"; move; log "OK"} - | - `wait` for the robot to crash, then execute `view it0` (or whichever - `itN` variable corresponds to the result of the `build` + `wait` for the robot to crash, then execute `view it0`{=snippet} (or whichever + `itN`{=snippet} variable corresponds to the result of the `build` command) to see how far it got. Further instructions should appear in the crashed robot's log and `give` you an opportunity to `salvage` the situation... diff --git a/data/scenarios/Tutorials/def.yaml b/data/scenarios/Tutorials/def.yaml index 6caa34d3e..75cef114d 100644 --- a/data/scenarios/Tutorials/def.yaml +++ b/data/scenarios/Tutorials/def.yaml @@ -9,11 +9,13 @@ objectives: has a flower in its inventory. - | However, it would be extremely tedious to simply type out all the individual - `move` and `turn` commands required. Your base has a `dictionary` device + `move` and `turn` commands required. Your base has a `dictionary`{=entity} device that can be used to define new commands. For example: - | + ``` def m4 : cmd unit = move; move; move; move end - - defines a new command `m4`, with type `cmd unit`, as four consecutive `move` commands. + ``` + - defines a new command `m4`{=snippet}, with type `cmd unit`{=type}, as four consecutive `move` commands. With judicious use of new definitions, it should be possible to complete this challenge in just a few lines of code. @@ -24,10 +26,10 @@ objectives: - | TIP: the type annotation in a definition is optional. You could also write `def m4 = move; move; move; move end`, and Swarm would infer - the type of `m4`. + the type of `m4`{=snippet}. - | TIP: writing function definitions at the prompt is annoying. - You can also put definitions in a `.sw` file and load it + You can also put definitions in a `.sw`{=path} file and load it with the `run` command. Check out https://github.com/swarm-game/swarm/tree/main/editors for help setting up an external editor with things like diff --git a/data/scenarios/Tutorials/farming.yaml b/data/scenarios/Tutorials/farming.yaml index c756aed7a..a05987d8c 100644 --- a/data/scenarios/Tutorials/farming.yaml +++ b/data/scenarios/Tutorials/farming.yaml @@ -11,13 +11,15 @@ objectives: them in order to create a reliable supply. - | In this scenario, you are a bit farther along: in particular, - you now have a few `harvester`s, a few `lambda`s, a few `logger`s, - some `branch predictor`s which + you now have a few `harvester`{=entity}s, a few `lambda`{=entity}s, a few `logger`{=entity}s, + some `branch predictor`{=entity}s which allow robots to evaluate conditional expressions, and some - `strange loops` which enable recursive functions. For example, + `strange loop`{=entity}s which enable recursive functions. For example, one simple, useful recursive function is - | + ``` def forever = \c. c ; forever c end + ``` - Your goal is to acquire 256 lambdas. Of course, in order to accomplish this in a reasonable amount of time, it makes sense to plant a field of lambdas and then program one or more robots to @@ -39,7 +41,7 @@ objectives: language features to unlock. - | To finally complete this tutorial, there is only one thing left for you to do: - use one of your lambdas to make some delicious `curry`. + use one of your lambdas to make some delicious `curry`{=entity}. - Afterwards, you will return to the menu where you can select "Classic game" for the complete game experience. Or, play a "Creative game" if you just want to play around with diff --git a/data/scenarios/Tutorials/grab.yaml b/data/scenarios/Tutorials/grab.yaml index 61aef520a..85d13edb0 100644 --- a/data/scenarios/Tutorials/grab.yaml +++ b/data/scenarios/Tutorials/grab.yaml @@ -9,7 +9,7 @@ objectives: - There are some trees ahead of your robot; `move` to each one and `grab` it. - You can learn more by reading about the grabber device in your inventory. Remember, if the description does not fit in the - lower left info box, you can either hit `Enter` to pop out the + lower left info box, you can either hit **Enter** to pop out the description, or focus the info box in order to scroll. condition: | try { diff --git a/data/scenarios/Tutorials/lambda.yaml b/data/scenarios/Tutorials/lambda.yaml index 592f7e67a..66e3b3af6 100644 --- a/data/scenarios/Tutorials/lambda.yaml +++ b/data/scenarios/Tutorials/lambda.yaml @@ -12,14 +12,16 @@ objectives: the path that repeat four times; it seems like it could be really useful to have a function to repeat a command four times. - | - To write a function, you use lambda syntax: in general, `\x. blah` is the - function which takes an input (locally called `x`) and returns - `blah` as its output (`blah` can of course refer to `x`). For example: + To write a function, you use lambda syntax: in general, `\x. x + 1` is the + function which takes an input (locally called `x`{=snippet}) and returns + the right part as its output which can refer to `x`{=snippet}. For example: - | + ``` def x4 : cmd unit -> cmd unit = \c. c; c; c; c end - - That is, `x4` is defined as the function which takes a command, called `c`, - as input, and returns the command - `c; c; c; c` which consists of executing `c` four times. + ``` + - That is, `x4`{=snippet} is defined as the function which takes a command, + called `c`{=snippet}, as input, and returns the command + `c; c; c; c`{=snippet} which consists of executing `c`{=snippet} four times. condition: | try { teleport self (32,-16); diff --git a/data/scenarios/Tutorials/move.yaml b/data/scenarios/Tutorials/move.yaml index 3257cfbc0..dd9572f39 100644 --- a/data/scenarios/Tutorials/move.yaml +++ b/data/scenarios/Tutorials/move.yaml @@ -10,7 +10,7 @@ objectives: 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. - - Note that you can chain commands with semicolon, `;`. + - 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: | @@ -39,18 +39,18 @@ objectives: 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` device to read about the details. + - 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` 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. + 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`. + 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 `;`, for example: + 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 diff --git a/data/scenarios/Tutorials/place.yaml b/data/scenarios/Tutorials/place.yaml index 833050345..57f060008 100644 --- a/data/scenarios/Tutorials/place.yaml +++ b/data/scenarios/Tutorials/place.yaml @@ -12,7 +12,7 @@ objectives: - Previously you learned how to plunder a plentiful forest for wood. Now you will learn how to plant trees to obtain as much wood as you need. - There is a fast-growing tree (called "spruce") ahead of you. You could `grab` - it as before, but you now have a new device called a `harvester`. + it as before, but you now have a new device called a `harvester`{=entity}. If you `harvest` a tree rather than `grab` it, a new tree will grow in its place after some time. - You can also place items from your inventory on the ground @@ -24,7 +24,7 @@ objectives: by planting more trees. - | TIP: You can get a sneak peak at a feature we will explain later and type - `def t = move; place "spruce"; harvest; end` after which you only need to type `t` + `def t = move; place "spruce"; harvest; end` after which you only need to type `t`{=snippet} instead of retyping the whole command or searching in your command history. condition: | try { diff --git a/data/scenarios/Tutorials/require.yaml b/data/scenarios/Tutorials/require.yaml index 16714fb98..711bc223d 100644 --- a/data/scenarios/Tutorials/require.yaml +++ b/data/scenarios/Tutorials/require.yaml @@ -6,20 +6,20 @@ objectives: - goal: - The `build` command automatically equips devices on the newly built robot that it knows - will be required. For example, if you `build {move}`, some `treads` + will be required. For example, if you `build {move}`, some `treads`{=entity} will automatically be equipped on the new robot since it needs them to `move`. (To see what the `build` command will equip, - you can type `requirements ` where `` is any expression.) + you can type `requirements `{=snippet} where ``{=snippet} is any expression.) - However, sometimes you need a device but `build` can't tell that - you need it. In this case, you can use the special `require` + you need it. In this case, you can use the special `require`{=snippet} command to require a particular device. For example, if you `build {require "3D printer"; move}`, a 3D printer will be equipped on the new robot even though it does not execute any commands that use a 3D printer. - Your goal is to pick a flower on the other side of the river and bring it back to your base. You win when the base has a - `periwinkle` flower in its inventory. - - "Hint: robots will drown in the water unless they have a `boat` device + `periwinkle`{=entity} flower in its inventory. + - "Hint: robots will drown in the water unless they have a `boat`{=entity} device equipped!" condition: | try { diff --git a/data/scenarios/Tutorials/requireinv.yaml b/data/scenarios/Tutorials/requireinv.yaml index 0db079741..2039b9d3f 100644 --- a/data/scenarios/Tutorials/requireinv.yaml +++ b/data/scenarios/Tutorials/requireinv.yaml @@ -5,10 +5,10 @@ description: | objectives: - goal: - In the previous tutorial challenge, you learned how to use - `require` to require specific devices to be equipped. + `require`{=snippet} to require specific devices to be equipped. Sometimes, instead of requiring equipped devices, you require supplies in your inventory. In this case, you can write - `require ` to require a certain number of copies of + `require `{=snippet} to require a certain number of copies of a certain entity to be placed in your inventory. - For example, `build {require 10 "flower"; move; move}` would build a robot with 10 flowers in its inventory. diff --git a/data/scenarios/Tutorials/scan.yaml b/data/scenarios/Tutorials/scan.yaml index c2e25716c..d49650b3f 100644 --- a/data/scenarios/Tutorials/scan.yaml +++ b/data/scenarios/Tutorials/scan.yaml @@ -6,12 +6,12 @@ objectives: - goal: - When you land on an alien planet, all the entities in the world will be unfamiliar to you, but you can learn what they are using - the `scan` command, enabled by a `scanner` device. + the `scan` command, enabled by a `scanner`{=entity} device. - Send one or more robots to move next to some of the unknown entities (marked as ?), scan them (with something like `scan forward` or `scan north`), and then return to the base and execute `upload base`. - For more information about the `scan` and `upload` commands, read - the description of the `scanner` in your inventory. + the description of the `scanner`{=entity} in your inventory. condition: | try { bm <- as base {knows "mountain"}; diff --git a/data/scenarios/Tutorials/type-errors.yaml b/data/scenarios/Tutorials/type-errors.yaml index 5ae863f10..547620daa 100644 --- a/data/scenarios/Tutorials/type-errors.yaml +++ b/data/scenarios/Tutorials/type-errors.yaml @@ -6,18 +6,18 @@ objectives: - goal: - | Let's see what happens when you enter something that does not type check. - Try typing `turn 1` at the REPL prompt. Clearly this is nonsense, and + Try typing `turn 1`{=snippet} at the REPL prompt. Clearly this is nonsense, and the expression will be highlighted in red. To see what the error is, hit Enter. A box will pop up with a type (or parser) error. - "Some other type errors for you to try:" - | - `turn move` + `turn move`{=snippet} - | - `place tree` (without double quotes around "tree") + `place tree`{=snippet} (without double quotes around "tree") - | - `move move` + `move move`{=snippet} - The last expression might give the most confusing error. - Obviously we are just missing a `;` separating the two `move` + Obviously we are just missing a `;`{=snippet} separating the two `move` commands. However, without the semicolon, it looks like `move` is a function being applied to an argument, but of course `move` is not a function. diff --git a/data/scenarios/Tutorials/types.yaml b/data/scenarios/Tutorials/types.yaml index 9dd1baec4..b8db2b8ad 100644 --- a/data/scenarios/Tutorials/types.yaml +++ b/data/scenarios/Tutorials/types.yaml @@ -11,9 +11,9 @@ objectives: REPL prompt (you do not need to execute it). If the expression type checks, its type will be displayed in gray text at the top right of the window. - For example, if you try typing `move`, you can see that it has - type `cmd unit`, which means that `move` is a command which + type `cmd unit`{=type}, which means that `move` is a command which returns a value of the unit type (also written `()`). - - As another example, you can see that `turn` has type `dir -> cmd unit`, + - As another example, you can see that `turn` has type `dir -> cmd unit`{=type}, meaning that `turn` is a function which takes a direction as input and results in a command. - "Here are a few more expressions for you to try (feel free to try others as well):" diff --git a/data/scenarios/Tutorials/world101.yaml b/data/scenarios/Tutorials/world101.yaml index 7301d5497..5c7cd402d 100644 --- a/data/scenarios/Tutorials/world101.yaml +++ b/data/scenarios/Tutorials/world101.yaml @@ -16,7 +16,7 @@ objectives: build more advanced devices and produce more robots, you'll need to explore, gather resources, and set up some automated production pipelines. - - At this point you may want to create an external `.sw` file + - At this point you may want to create an external `.sw`{=path} file with useful definitions you create. You can then load it via the `run` command. See https://github.com/swarm-game/swarm/tree/main/editors @@ -47,7 +47,7 @@ objectives: send out a robot to harvest something, try programming it to come back to the base when it is done. Then, execute `salvage` to get the harvester back, so you can reuse it in another robot later." - - One of the next things you will probably want is a `lambda`, so you can + - One of the next things you will probably want is a `lambda`{=entity}, so you can define and use parameterized commands. Scan some things and use the process of elimination to find one. Since lambdas regrow, once you find one, try getting it with `harvest`. diff --git a/src/Swarm/Game/Failure.hs b/src/Swarm/Game/Failure.hs index 3e4c0e921..e1475716e 100644 --- a/src/Swarm/Game/Failure.hs +++ b/src/Swarm/Game/Failure.hs @@ -12,12 +12,13 @@ import Data.Yaml (ParseException) data SystemFailure = AssetNotLoaded Asset FilePath LoadingFailure + deriving (Show) data AssetData = AppAsset | NameGeneration | Entities | Recipes | Scenarios | Script deriving (Eq, Show) data Asset = Achievement | Data AssetData | History | Save - deriving (Show) + deriving (Show, Eq) data Entry = Directory | File deriving (Eq, Show) @@ -27,3 +28,4 @@ data LoadingFailure | EntryNot Entry | CanNotParse ParseException | CustomMessage Text + deriving (Show) diff --git a/src/Swarm/Game/Scenario/Objective.hs b/src/Swarm/Game/Scenario/Objective.hs index 15976eaa3..0593e1512 100644 --- a/src/Swarm/Game/Scenario/Objective.hs +++ b/src/Swarm/Game/Scenario/Objective.hs @@ -20,6 +20,7 @@ import Swarm.Game.Scenario.Objective.Logic as L import Swarm.Language.Pipeline (ProcessedTerm) import Swarm.Util (reflow) import Swarm.Util.Lens (makeLensesNoSigs) +import Swarm.Language.Syntax (Syntax) ------------------------------------------------------------ -- Scenario objectives @@ -66,7 +67,7 @@ instance FromJSON PrerequisiteConfig where -- | An objective is a condition to be achieved by a player in a -- scenario. data Objective = Objective - { _objectiveGoal :: [Markdown.Node] + { _objectiveGoal :: [Markdown.Document Syntax] , _objectiveTeaser :: Maybe Text , _objectiveCondition :: ProcessedTerm , _objectiveId :: Maybe ObjectiveLabel @@ -84,7 +85,7 @@ instance ToSample Objective where -- | An explanation of the goal of the objective, shown to the player -- during play. It is represented as a list of paragraphs. -objectiveGoal :: Lens' Objective [Markdown.Node] +objectiveGoal :: Lens' Objective [Markdown.Document Syntax] -- | A very short (3-5 words) description of the goal for -- displaying on the left side of the Objectives modal. diff --git a/src/Swarm/TUI/Controller.hs b/src/Swarm/TUI/Controller.hs index eb60a2a31..a89956ee5 100644 --- a/src/Swarm/TUI/Controller.hs +++ b/src/Swarm/TUI/Controller.hs @@ -211,7 +211,7 @@ handleMainMenuEvent menu = \case getTutorials :: ScenarioCollection -> ScenarioCollection getTutorials sc = case M.lookup tutorialsDirname (scMap sc) of Just (SICollection _ c) -> c - _ -> error "No tutorials exist!" + _ -> error $ "No tutorials exist: " ++ show sc -- | If we are in a New Game menu, advance the menu to the next item in order. --