January 02, 2005

The Ramble Chronicles: Matrix Coordinates

I want to talk about random maze generation, but I've got some more infrastructure to get out of the way first. This essay is about the Tcl implementation of Ramble rather than the game design, so pass on by if the code doesn't interest you.

As I noted in the Efficient Matrices chapter of The Ramble Chronicles, the size of a matrix is usually denoted m*n, and the coordinates are i and j where 1 <= i <= m and 1 <= j <= n. The nuisance about coordinates is that about half the time you want to deal with i and j as a pair (i.e., when saving a particular pair of coordinates for later) and the other half the time you want to deal with them individually (i.e., when doing computations). The normal way to store a pair of coordinates is as a list:

set i 4
set j 2
set pair [list $i $j]

Tcl's lset and lindex commands nicely support both forms; given the above assignments, for example, the following two statements are identical:

set a [lindex $matrix $i $j]
set a [lindex $matrix $pair]

Nevertheless, no matter which way you choose to store your coordinates, you're going to find yourself wanting to convert them to the other form on a regular basis--if only because writing Tcl commands to be as forgiving as lindex and lset is a royal pain. Hence, I define the following infrastructure: the i, j, and ij commands:

set pair [ij 4 5]
set i [i $pair]
set j [j $pair

These are implemented simply, as follows:

# Create an i,j pair
proc ij {i j} { list $i $j }

# Get i from an i,j pair
proc i {ij} { lindex $ij 0 }

# Get j from an i,j pair
proc j {ij} { lindex $ij 1 }

Trivial, you might say; but they are more expressive (and more concise) than the list and lindex calls they replace, especially when used in complex expressions.

Posted by Will Duquette at January 2, 2005 07:36 PM