MazeGen

MazeGen is a tool for creating Mazes. It provides both a Rust API (viewable via cargo doc) and a Molt API (documented in this book).

My goals for MazeGen are as follows:

  • To provide a use case for Molt, and especially for Molt's Rust API, so that I can find rough spots and look for improvements.
  • To build some useful bindings for other Rust crates, e.g., image.
    • Some of these may become crates in their own right.
  • To learn more about the Rust ecosystem and the crates that are available (Molt goes out of its way to avoid dependencies).
  • To have fun writing Rust code and playing with mazes.

Your mileage may vary.

API Reference

This section documents MazeGen's Molt API.

CommandDescription
gridMaze grid object
imageImage object
randRandom number generator
pixelPixel type

grid -- Maze Grid Object

A grid, represented in Rust as the Grid struct, is a rectangular array of cells, each of which can be linked to the cells north, south, east, and west of it. The process of creating a maze involves "carving out" links within a grid.

In TCL, a grid is represented as a Molt object: a molt command whose subcommands correspond more or less to the methods of the Grid struct. The grid constructor creates instances of the grid object command.

Cell IDs and Coordinates

Each cell in the grid has a unique cell ID, an integer from 0 to N-1, where N is the number of cells in the grid. A cell can also be referenced by its (i,j) row/column coordinates. Cell (0,0) is at the top-left; Rows i extend down, and the columns j extend to the right.

Cell Directions

A cell can have up to four neighbors, which are to the north, south, east, or west.

Constructor

Syntax: grid name rows cols

The grid command creates a grid object, a Molt binding to a Rust Grid struct. The new grid is a Molt command called name; the command provides access to the newly created grid, which will have the given number of rows and columns. Returns the name.

$ grid mygrid 10 20
mygrid
$ mygrid rows
10
$ mygrid cols
20
$

Object Command

Syntax: grid subcommand ?args...?

The grid object command has the following subcommands.

SubcommandDescription
grid cellConverts an i j pair to a cell ID
grid cellsThe number of cells in the grid
grid celltoThe ID of the cell in a given direction
grid clearClears the grid, i.e., unlinks all linked cells
grid colsThe number of columns in the grid
grid deadendsCell IDs of dead-end cells
grid distancesDistances of all cells from a given cell
grid iConverts a cell ID to an i coordinate
grid ijConverts a cell ID to an i j pair
grid jConverts a cell ID to a j coordinate
grid linkedAre two cells linked?
grid linkedtoIs a cell linked to the cell in a given direction?
grid linkLinks two adjacent cells
grid linksThe cells to which a cell is linked
grid longestThe longest path in the grid
grid neighborsThe cells adjacent to a given cell
grid renderRender an image that depicts the grid
grid rowsThe number of rows in the grid
grid textRender a string that depicts the grid
grid unlinkUnlink two adjacent cells

grid cell


Syntax: grid cell i j

Returns the cell ID corresponding to row i, column j. Rows are indexed from 0 to M-1, and columns are indexed from 0 to N-1.

grid cells


Syntax: grid cells

Returns the number of cells in the grid.

grid cellto


Syntax: grid cellto cell north|south|east|west

Returns the ID of the cell to the north, south, east or west of the given cell, or the empty string if there is no such cell.

grid clear


Syntax: grid clear

Clears all links from the grid, returning it to its initial state.

grid cols


Syntax: grid cols

Returns the number of columns in the grid.

grid deadends


Syntax: grid deadends

Returns a list of the IDs of all dead-end cells in the grid. A cell is a dead-end if it is linked to only one other cell.

grid distances


Syntax: grid distances cell -list|-dict

Computes the minimum distance from the given cell to every other cell. By default, or if the -list option is given, returns a list of distances by cell ID. If the -dict option is given, returns a Molt dictionary of distances by cell ID.

$ set list [$grid distances 0]                   ;# Distances from cell 0 as a list
$ set to35 [lindex $list 35]                     ;# Distance from 0 to cell 35
$ array set distances [grid distances 0 -dict]   ;# Distances from cell 0 as a dict
$ set to35 $distances(35)                        ;# Distance from 0 to cell 35

grid i


Syntax: grid i cell

Gets the row index of the cell with the given ID.

grid ij


Syntax: grid ij cell

Gets the row/column coordinates of the cell with the given ID as a two-element list.

$ set pair [$grid ij 35]      ;# Get the I/J coordinates of cell 35
$ set i [lindex $pair 0]
$ set j [lindex $pair 1]
$ lassign [$grid ij 35] i j   ;# Once Molt implements lassign

grid j


Syntax: grid j cell

Gets the column index of the cell with the given ID.

grid link


Syntax: grid link cell1 cell2

Links the cell cell1 to cell2 given their IDs. The two cells must be adjacent. Note: links are always bidirectional.

$ $grid link $cell1 $cell2
$ $grid linked $cell1 $cell2
1
$ $grid linked $cell2 $cell1
1

grid linked


Syntax: grid linked cell1 cell2

Returns true if cell cell1 is linked to cell2, given their IDs, and false otherwise.

grid linkedto


Syntax: grid linkedto cell north|south|east|west

Returns true if the given cell is linked to its neighbor in the given direction.

grid links


Syntax: grid links cell

Returns a list of the IDs of the cells that are linked to the given cell.

grid longest


Syntax: grid longest

Returns the longest path through the grid as a list of cell IDs.

grid neighbors


Syntax: grid neighbors cell

Returns a list of the IDs of the cells that are neighbors of the given cell.

grid render


Syntax: grid render filename ?options...?

Renders the grid as an image, saving it to the file with the given name. Valid options are as follows:

OptionDescription
-cellsize pixelsA cell's height and width in pixels. Defaults to 10.
-borderwidth pixelsThe width of the border between cells, in pixels. Defaults to 1.

grid rows


Syntax: grid rows

Returns the number of rows in the grid.

grid text


Syntax: grid text ?options...?

Returns a string that represents the maze in ASCII characters. The options are as follows:

OptionDescription
-cellwidth charsA cell's width in monospace characters. Defaults to 3.
-autowidth marginSize cells to the data, leaving a margin. Defaults to 1.
-datalist listA list of data strings to include in each cell
-datadict dictA dictionary of data strings to include in each cell

The caller can provide data to be written into the cells. The data is given in one of two forms:

  • As a -datalist, a list containing one value for each cell in the grid; the list index is used as the cell ID. To leave a cell empty, set the corresponding list item to the empty string.

  • As a -datadict, a dictionary of values by cell ID. To leave a cell empty, set its value to the empty string or omit its ID from the dictionary.

The -cellwidth gives the actual width of each cell in monospace characters; if data is given, it will be truncated to fit the width. If -autowidth is also given, the width will be set to the length of the longest value plus twice the margin, so that the data can be presented without truncation. In this case, the -cellwidth becomes the minimum width.

$ grid mygrid 3 5
...
$ mygrid text
+---+---+---+---+---+
|                   |
+   +---+---+   +   +
|   |       |   |   |
+   +---+   +---+   +
|           |       |
+---+---+---+---+---+

$ mygrid text -autowidth 1 -datalist [mygrid distances 0]
+---+---+---+---+---+
| 0   1   2   3   4 |
+   +---+---+   +   +
| 1 | 6   5 | 4 | 5 |
+   +---+   +---+   +
| 2   3   4 | 7   6 |
+---+---+---+---+---+
$

grid unlink


Syntax: grid unlink cell1 cell2

Unlinks the two cells (if they were linked). The two cells must be adjacent. Note: all links are bidirectional; unlinking cell1 from cell2 also unlinks cell2 from cell1.

image -- Image Object

An image object is a Molt object that wraps an RgbaImage from the image crate and allows it to be manipulated in various ways. The image constructor creates instances of the image object command.

Pixels

Pixels are represented as Molt pixel values; see the pixel command for more details.

Constructor

Syntax: image name width height

The image command creates an image object, a Molt binding to a Rust RgbaImage struct. The new image object is a Molt command called name; the command provides access to the newly created image, which will have the given width and height in pixels. Returns the name.

The image will initially be full of transparent pixels: #000000.00.

$ image myimage 32 32
myimage
$ myimage width
32
$ myimage height
32
$

Object Command

Syntax: image subcommand ?args...?

The image object command has the following subcommands.

SubcommandDescription
image clearClears an image to a given color
image dumpDumps the pixel content to stdout
image getGets a pixel from the image
image heightAn image's height in pixels
image putSets a pixel in the image
image saveSaves the image to disk
image widthAn image's width in pixels

image clear


Syntax: image clear ?fill?

Clears the image's pixels by setting them to the given fill color, which must be a pixel value. The fill defaults to white, #FFFFFF.

$image clear #000000    ;# Clear to black
$image clear #000000.00 ;# Clear to transparent

image dump


Syntax: image dump

Dumps the image's pixels to standard output, one pixel per row. Used for debugging.

$ image fred 16 16
fred
$ image dump
[0,0]: Rgba([0, 0, 0, 0])
[0,1]: Rgba([0, 0, 0, 0])
[0,2]: Rgba([0, 0, 0, 0])
...

image get


Syntax: image get x y

Gets the pixel at the given (x,y) coordinates.

$ $image get 10 15
#123456

image height


Syntax: image height

Returns an image's height in pixels.

image put


Syntax: image put x y ?pixel?

Sets the pixel at the given (x,y) coordinates to the given pixel value, which defaults to black, #000000.

$image put 10 15 #0000FF   ;# Set pixel at 10,15 to blue

image save


Syntax: image save filename

Attempts to save the the image to the given file. The image type is determined by the image crate from the file's file type.

image width


Syntax: image width

Returns an image's width in pixels.

maze -- Maze Constructor

The maze command creates grid objects containing mazes produced one of a number of algorithms. This command is a stopgap; in the long run, there will be a distinct command for each useful kind of maze, with appropriate options.

maze


Syntax: maze algorithm name rows columns

Creates a grid object called name containing a maze produced by the given algorithm. The new grid will have the given number of rows and columns. The backtracker algorithm is the best of these for practical use, but could be elaborated for even better results. (I've got some Java code somewhere that parameterizes it nicely.)

The algorithms are as follows:

AlgorithmDescription
backtrackerA good basic maze with good river.
bintreeA dirt simple, not very satisfactory maze.
huntandkillSimilar to backtracker; better memory usage, but slower.
sidewinderSlightly better than bintree

pixel -- Pixel Type

Syntax: pixel subcommand ?args...?

The pixel command provides access to the image crate's Rgba pixel type: red/green/blue plus the alpha channel. This is useful for creating pixel art.

SubcommandDescription
pixel fromConstructs a pixel from components
pixel redExtracts the red component from a pixel
pixel greenExtracts the green component from a pixel
pixel blueExtracts the blue component from a pixel
pixel alphaExtracts the alpha component from a pixel

Pixel Representation

The string representation of a pixel is a standard web RGB hex string, one byte per color, with an optional suffix for the alpha channel: "#rrggbb?.aa?". Some examples:

  • #000000 black, alpha is 255
  • #00ff00 green, alpha is 255
  • #ffffff white, alpha is 255
  • #ffffff.ff white, alpha is 255
  • #ffffff.00 white, alpha is 0 (fully transparent)
  • #ffffff.80 white, alpha is 128 (half transparent)

The hex digits are case-insensitive.

Note: the "." is a little odd; but it simplifies the logic if we allow large pixel components in the future. Without the ".", "#0123456789AB" could be interpreted as three RGB values, "0123", "4567", and "89AB", or three RGB values and an alpha, "012", "345", "678", "9AB".

pixel from


Syntax: pixel from r g b ?a?

Constructs a pixel value given its red, green, blue, and alpha components as integers from 0 to 255. If omitted, the alpha component defaults to 255. Returns the pixel value.

pixel red


Syntax: pixel red pixel

Extracts the red component from a pixel as an integer.

pixel green


Syntax: pixel green pixel

Extracts the green component from a pixel as an integer.

pixel blue


Syntax: pixel blue pixel

Extracts the blue component from a pixel as an integer.

pixel alpha


Syntax: pixel alpha pixel

Extracts the alpha component from a pixel as an integer.

rand -- Random Number Generator

Syntax: rand subcommand ?args...?

The rand command provides access to the rand crate's thread_rng. It has the following subcommands.

SubcommandDescription
rand boolGenerates a random boolean
rand rangeGenerates an integer from a range
rand sampleSelects an item randomly from a list

rand bool


Syntax: rand bool ?prob?

Returns either a 1 or 0, both with probability 0.5. If given, prob must be a number between 0.0 and 1.0 indicating the probability of getting a 1.

TODO: Rejects prob if it is exactly 0.0 or 1.0. That might be a nuisance.

rand range


Syntax: rand range ?start? end

Randomly selects and returns a number in the range start to (end - 1). The start value defaults to 0.

rand sample


Syntax: rand sample list...

Randomly selects and returns an element from a list. The list can be provided as a single value, or as multiple elements on the command line, i.e., the two calls shown below both return a random letter "a", "b", "c", "d", or "e".

rand sample a b c d e

set list [list a b c d e]
rand sample $list