packages feed

swarm-0.4: data/scenarios/Tutorials/conditionals.yaml

version: 1
name: Conditionals
description: |
  Learn how to write conditional expressions.
objectives:
  - goal:
      - |
        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`{=entity}
        any time you detect one.
      - |
        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.)
      - |
        As you might expect, `if` can be used to write
        conditional expressions.  However, `if` is not special syntax;
        it is simply a built-in function of type
      - |
        ```
        if : bool -> {a} -> {a} -> a
        ```
      - |
        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`{=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}`{=type}, we just surround a value of type `int`{=type}
        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`{=type}.
      - |
        **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} {}`{=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 {
        n <- as base {count "very small rock"};
        return (n == 4)
      } { return false}
solution: |
  def tL = turn left end;
  def tB = turn back end;
  def x4 = \c. c;c;c;c end;
  def VSR = "very small rock" end;
  def ifC = \c.\t.\e. b <- c; if b t e end;
  def pick = move; ifC (ishere VSR) {grab; return ()} {} end;
  def pickrow = x4 pick; turn back; x4 move end;
  build {
    turn south; x4 (move; tL; pickrow; tL); tB; x4 move; x4 (give base VSR)
  }
robots:
  - name: base
    heavy: true
    dir: [0,1]
    display:
      char: Ω
      attr: robot
    devices:
      - logger
      - 3D printer
      - dictionary
    inventory:
      - [8, compass]
      - [8, solar panel]
      - [8, logger]
      - [8, treads]
      - [8, grabber]
      - [8, scanner]
      - [8, lambda]
      - [8, branch predictor]
      - [8, 3D printer]
      - [0, very small rock]
entities:
  - name: very small rock
    display:
      invisible: true
    description:
      - A small rock.  It is so small, it is practically invisible.
    properties: [portable]
world:
  palette:
    'Ω': [grass, null, base]
    '.': [grass]
    '_': [stone]
    'o': [stone, very small rock]
    '┌': [stone, upper left corner]
    '┐': [stone, upper right corner]
    '└': [stone, lower left corner]
    '┘': [stone, lower right corner]
    '─': [stone, horizontal wall]
    '│': [stone, vertical wall]
  upperleft: [-1, 1]
  map: |
    ┌─────┐
    │Ω....│
    │.o___│
    │._o__│
    │.___o│
    │.__o_│
    └─────┘