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.
Command | Description |
---|---|
grid | Maze grid object |
image | Image object |
rand | Random number generator |
pixel | Pixel 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.
Subcommand | Description |
---|---|
grid cell | Converts an i j pair to a cell ID |
grid cells | The number of cells in the grid |
grid cellto | The ID of the cell in a given direction |
grid clear | Clears the grid, i.e., unlinks all linked cells |
grid cols | The number of columns in the grid |
grid deadends | Cell IDs of dead-end cells |
grid distances | Distances of all cells from a given cell |
grid i | Converts a cell ID to an i coordinate |
grid ij | Converts a cell ID to an i j pair |
grid j | Converts a cell ID to a j coordinate |
grid linked | Are two cells linked? |
grid linkedto | Is a cell linked to the cell in a given direction? |
grid link | Links two adjacent cells |
grid links | The cells to which a cell is linked |
grid longest | The longest path in the grid |
grid neighbors | The cells adjacent to a given cell |
grid render | Render an image that depicts the grid |
grid rows | The number of rows in the grid |
grid text | Render a string that depicts the grid |
grid unlink | Unlink 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:
Option | Description |
---|---|
-cellsize pixels | A cell's height and width in pixels. Defaults to 10. |
-borderwidth pixels | The 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:
Option | Description |
---|---|
-cellwidth chars | A cell's width in monospace characters. Defaults to 3. |
-autowidth margin | Size cells to the data, leaving a margin. Defaults to 1. |
-datalist list | A list of data strings to include in each cell |
-datadict dict | A 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.
Subcommand | Description |
---|---|
image clear | Clears an image to a given color |
image dump | Dumps the pixel content to stdout |
image get | Gets a pixel from the image |
image height | An image's height in pixels |
image put | Sets a pixel in the image |
image save | Saves the image to disk |
image width | An 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:
Algorithm | Description |
---|---|
backtracker | A good basic maze with good river. |
bintree | A dirt simple, not very satisfactory maze. |
huntandkill | Similar to backtracker; better memory usage, but slower. |
sidewinder | Slightly 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.
Subcommand | Description |
---|---|
pixel from | Constructs a pixel from components |
pixel red | Extracts the red component from a pixel |
pixel green | Extracts the green component from a pixel |
pixel blue | Extracts the blue component from a pixel |
pixel alpha | Extracts 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.
Subcommand | Description |
---|---|
rand bool | Generates a random boolean |
rand range | Generates an integer from a range |
rand sample | Selects 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