If you like to hack, here's what's going on in Xlife (followed by the current
to-do list).

DATA REPRESENTATION

The program represents the universe as a linked list of 8 by 8 tiles.  For fast
access by coordinate address, the tiles are also threaded onto lists depending
from a hash table; hash coordinates to go to a bucket, chase links to find the
tile that actally matches.  The implementation is in tile:fetchtile(); the
relevant type descriptions are in tile.h.

Actually, there are potentially multiple universes or `patterns', (see the
`pattern' type in tile.h), each with its own hash table, tile list and
population info.  At present, the program uses two; the active list and
the tentative.  The active list is the state of the universe; the tentative
list holds patterns loaded via 'l' (flippable and rotatable) which haven't
yet been merged into the active list.  Functions which may operate on
either take a context pointer argument.

Tiles contain a union called a `cellbox' which is interpreted differently
depending on whether the program is in 2-state or N-state mode.  Exceedingly
hairy code by jcrb packs all the 2-state info into 4 unigned longs for
speed and compactness. The n-state member uses a simple 8x8 array.

The tile size is variable.  Which member of the cellbox union we use
to compute the tile allocation size for malloc() depends on how much
internal state each cell carries (major cases are two-state and n-state).
Thus, we can add more union members to the cellbox type without worrying that
all simulations will incur higher memory costs.

Each cellbox stores the tile state for both this and the previous
generation.  This is so X can be told to display only *changed* cells.

ORGANIZATION

Most X event handling and knowledge of X structures is concentrated in main.c
along with the main event-processing loop.  The evolution function and
rule-definition helpers live in generate.c.  The utils file is a grab-bag of
useful junk.

Xlife's code is mostly pretty straightforward (all Xlib; no widgets).  There
are three interesting patches of hair:

1) jcrb's Life evolution code, mentioned above.  Bit-banging gone berserk.
   This is optimized for space, using only one bit per cell rather than the
   minimum of 8 a more conventional array representation would require.

2) esr's parser for n-state evolution rules --- uses a twisty recursion to
   implement wildcarding.

3) callahan's load queue request and intelligent-inclusion stuff in file.c.
   The idea here is to be able to queue up inclusion requests into a load
   script for later saving.

WHY THIS IS NOT A BITMAP EDITOR

Yes, you can use it as one, providing you can use the idisyncratic save file
format.  But it isn't really one.  The data representation is tuned for very
large but sparse `pictures', and (at present) it only handles up to 8 colors.

ETIQUETTE TIP FOR HACKERS

The program now uses a uniform indent style, what EMACS calls C++ mode, instead
of the three different modes that were mixed in it before, making it harder to
read.  Please try to stick with this style as you hack.  If you absolutely
can't stand it, use GNU indent to bash the whole thing into your preferred
style.

THINGS THAT STILL NEED DOING

Expose events don't restore the tentative pattern.  This should be fixed!

The globals for handling tentative-pattern transformations are messy.
Create translation-and-rotation members in the pattern structure, have
the rendering code apply them uniformly.  This would also eliminate the
distinction between displayline/trdisplayline, displaybox/trdisplaybox, etc.

Next step after that: permit multiple tentatives.

Read different file formats (bitmap....) as new #-section types

lifeconv should really be made more 'useful' and convert from other formats
(pbm, x bitmap, etc).

Allow state colors and the highlight box color to be set on the command line
or from X resources.

