Prequel
primitive recursive driven programming


Maze

(This example requires web workers.)

Theseus, after finding the Minotaur and without Ariadne's string, needs your help to escape back from the labirinth.

0 ← moves (min moves: 0)

Play Setup Hide Show Shuffle     Move: Left Forward Right

Run Pause Stop

0
0
0
← calls
← instructions
← memory (max use: 0)


Prequel program

Edit Save Debug

Module: RANDOM-WALK

options := MAZE.CAN.MOVE.FORWARD
options += MAZE.CAN.MOVE.LEFT
options += MAZE.CAN.MOVE.RIGHT
IF options = 0 # dead end
turnLeft :~ 2
IF turnLeft = 1
MAZE.TURN.LEFT()
ELSE
MAZE.TURN.RIGHT()
ENDIF
ENDIF
randomOption :~ options
IF MAZE.CAN.MOVE.LEFT = 1
IF randomOption = 0
MAZE.TURN.LEFT()
ENDIF
randomOption--
ENDIF
IF MAZE.CAN.MOVE.RIGHT = 1
IF randomOption = 0
()

Input:

MAZE.CELL.CURRENT
  Theseus' current position in 2D coordinates.
  -> e.g. [0, 0]
MAZE.FACING
  Theseus' current facing.
  -> 0 north-facing
  -> 1 east-facing
  -> 2 south-facing
  -> 3 west-facing
MAZE.CAN.MOVE.FORWARD
MAZE.CAN.MOVE.LEFT
MAZE.CAN.MOVE.RIGHT
MAZE.CAN.MOVE.BACKWARDS
  Check whether Theseus can move from his current position.
  -> 1 if he can
  -> 0 if he cannot
MAZE.CELL.FORWARD
MAZE.CELL.LEFT
MAZE.CELL.RIGHT
MAZE.CELL.BACKWARDS
  Adjacent 2D coordinates to the current position.
  -> e.g. [1, 0]
MAZE.CELLS.VISITED
  List of cells already visited.
  -> e.g. [[0, 0], [1, 0]]
MODULE.CALL.ARGS
  Holds the list of arguments passed with MODULE.CALL.
  -> [arg1, ..., argN]

Procedures:

MAZE.MOVE.FORWARD()
  Move Theseus to MAZE.CELL.FORWARD.
  Restart program counter.
  Note that it fails if MAZE.CAN.MOVE.FORWARD equals 0.
MAZE.TURN.LEFT()
MAZE.TURN.RIGHT()
  Change Theseus' facing by 90 degrees.
  Restart program counter.
MAZE.CELL.WAS.VISITED(&bool, cell)
  Check whether a cell has been visited.
  Shorthand for MAZE.CELL.IN.CELLS(&bool, cell, MAZE.CELLS.VISITED).
  -> bool: name of variable to hold the result
  -> cell: 2D coordinates (e.g. [0, 0])
  Alternative syntax: bool := MAZE.CELL.WAS.VISITED(cell)
MAZE.CELL.NORTH(&northCell, cell)
  Get an adjacent cell corresponding to the north position of cell.
  E.g. from [0, 0] get [0, -1].
  -> northCell: name of variable to hold the result
  -> cell: 2D coordinates (e.g. [0, 0])
  Alternative syntax: northCell := MAZE.CELL.NORTH(cell)
MAZE.CELL.EAST(&eastCell, cell)
  Get an adjacent cell corresponding to the east position of cell.
  E.g. from [0, 0] get [1, 0].
  -> eastCell: name of variable to hold the result
  -> cell: 2D coordinates (e.g. [0, 0])
  Alternative syntax: eastCell := MAZE.CELL.EAST(cell)
MAZE.CELL.SOUTH(&southCell, cell)
  Get an adjacent cell corresponding to the south position of cell.
  E.g. from [0, 0] get [0, 1].
  -> southCell: name of variable to hold the result
  -> cell: 2D coordinates (e.g. [0, 0])
  Alternative syntax: southCell := MAZE.CELL.SOUTH(cell)
MAZE.CELL.WEST(&westCell, cell)
  Get an adjacent cell corresponding to the west position of cell.
  E.g. from [0, 0] get [-1, 0].
  -> westCell: name of variable to hold the result
  -> cell: 2D coordinates (e.g. [0, 0])
  Alternative syntax: westCell := MAZE.CELL.WEST(cell)
MAZE.MAKE.CELL(&cell, x, y)
  Create a cell from its x and y coordinates.
  -> cell: name of variable to hold the result
  -> x: x coordinate
  -> y: y coordinate
  Alternative syntax: cell := MAZE.MAKE.CELL(x, y)
MAZE.CELL.X(&x, cell)
  Get the x coordinate from a cell.
  -> x: name of variable to hold the result
  -> cell: 2D coordinates (e.g. [0, 0])
  Alternative syntax: x := MAZE.CELL.X(cell)
MAZE.CELL.Y(&y, cell)
  Get the y coordinate from a cell.
  -> y: name of variable to hold the result
  -> cell: 2D coordinates (e.g. [0, 0])
  Alternative syntax: y := MAZE.CELL.Y(cell)
MAZE.CELL.IN.CELLS(&bool, cell, cells)
  Check whether a cell is in a list of cells.
  -> bool: name of variable to hold the result
  -> cell: 2D coordinates (e.g. [0, 0])
  -> cells: list of 2D coordinates (e.g. [[0, 0], [1, 0]])
  Alternative syntax: bool := MAZE.CELL.IN.CELLS(cell, cells)
MAZE.CELLS.ARE.CONNECTED(&bool, cell1, cell2)
  Check whether it is possible to go from cell1 to cell2.
  -> bool: name of variable to hold the result
  -> cell: 2D coordinates (e.g. [0, 0])
  Alternative syntax: bool := MAZE.CELLS.ARE.CONNECTED(cell1, cell2)
  Note that cell1 and cell2 must be orthogonally adjacent.
  Also note that either cell1 or cell2 must have been visited.
MAZE.CELLS.ARE.EQUAL(&bool, cell1, cell2)
  Check whether two cells are the same.
  -> bool: name of variable to hold the result
  -> cell: 2D coordinates (e.g. [0, 0])
  Alternative syntax: bool := MAZE.CELLS.ARE.EQUAL(cell1, cell2)
MODULE.CALL(&retvar1, ..., &retvarM, @modname, arg1, ..., argN)
  Start executing module modname, copying N arguments and expecting M return values.
  -> retvar: name of variable to hold the corresponding return value retval
  -> modname: name of module to start executing
  -> arg: value to be copied to the list MODULE.CALL.ARGS
  Alternative syntax: retvar1, ..., retvarM := MODULE.CALL(@modname, arg1, ..., argN)
  Note that recursive module calls are not allowed.
MODULE.RETURN(retval1, ..., retvalM)
  Return M values from the current module.
  Resume execution at the next instruction of the corresponding MODULE.CALL.
  -> retval: value to be copied to the corresponding variable retvar

Additional examples can be found on GitHub.