90 lines
4.6 KiB
Markdown
90 lines
4.6 KiB
Markdown
------------------------ --------------------------------- --------------------
|
||
[Previous](18-01.html) [Table of Contents](index.html) [Next](18-03.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
### Table-Driven Magic {#Heading4}
|
||
|
||
David Stafford won my first Optimization Challenge by means of a huge
|
||
look-up table and an incredible state machine driven by that table. The
|
||
table didn’t cause David’s entry to exceed the line limit because
|
||
David’s submission included code to generate the table on the fly as
|
||
part of the build process. David has done himself one better this time
|
||
with his QLIFE program; not only does his build process generate a 64K
|
||
table, but it also generates virtually all his code, consisting of
|
||
17,000-plus lines of assembly language spanning another 64K. What David
|
||
has done is write the equivalent of a bitblt compiler for the Game of
|
||
Life; one might in fact call it a Life compiler. What David’s code
|
||
generates is still a general-purpose program; it takes arbitrary seed
|
||
values, and can run for an arbitrary number of generations, so it’s not
|
||
as if David simply hardwired the instructions to draw each successive
|
||
screen. However, it’s a general-purpose program that is exquisitely
|
||
tailored to the task it needs to perform.
|
||
|
||
All the pieces of QLIFE are shown in Listings 18.1 through 18.5, as
|
||
follows: Listing 18.1 is BUILD.BAT, the batch file used to build QLIFE;
|
||
Listing 18.2 is LCOMP.C, the program used to generate the assembler code
|
||
and data file QLIFE.ASM; Listing 18.3 is MAIN.C, the main program for
|
||
QLIFE; Listing 18.4 is VIDEO.C, the video-related functions, and Listing
|
||
18.5 is LIFE.H, the header file. The following sidebar contains David’s
|
||
build instructions, exactly as he wrote them. I certainly won’t have
|
||
room to discuss all the marvelous intricacies of David’s code; I suggest
|
||
you look over these listings until you understand them thoroughly (it
|
||
took me a day to pick them apart) because there’s a lot of neat stuff in
|
||
there, and it’s an approach to performance programming that operates at
|
||
a more efficient, tightly integrated level than you may ever see again.
|
||
One hint: It helps a *lot* to build and run LCOMP.C, redirect its output
|
||
to QLIFE.ASM, and look at the assembly code in that file. This code is
|
||
the entirety of David’s generation engine, and it’s almost impossible to
|
||
visualize its operation without actually seeing it.
|
||
|
||
> * * * * *
|
||
>
|
||
> How To Build Qlife
|
||
>
|
||
> QLIFE is written for Borland C++, but it shouldn’t be too difficult to
|
||
> convert it to work with Microsoft C++. To build QLIFE, run the
|
||
> BUILD.BAT batch file with the size of the life grid on the command
|
||
> line (see below). The command-line options are:
|
||
>
|
||
> -- ----------- -------------------------------------------------------------
|
||
> WIDTH 32 Sets the width of the life grid to 96 cells (divided by 3).
|
||
> HEIGHT 96 Sets the height of the life grid to 96 cells.
|
||
> NOCOUNTER Turns off the generation counter (optional).
|
||
> NODRAW Turns off drawing of the cell map (optional).
|
||
> GEN 1000 Calculates 1,000 generations (optional).
|
||
> -- ----------- -------------------------------------------------------------
|
||
>
|
||
> These *must* be in uppercase. For example, the minimum you really need
|
||
> is “WIDTH 40 HEIGHT 120.” I used “WIDTH 46 HEIGHT 138 NOCOUNTER NODRAW
|
||
> GEN 7000” during testing.
|
||
>
|
||
> If you have selected the GEN option, you will have to press a key to
|
||
> exit QLIFE when it is finished. This is so I could visually compare
|
||
> the result of N generations under QLIFE with N generations under
|
||
> Abrash’s original life program. You should be aware that the program
|
||
> from the listing contains a small bug, which may make it appear that
|
||
> they do not generate identical results. The original program does not
|
||
> display a cell until it changes, so if a cell is alive on the first
|
||
> generation and never dies, then it will never be displayed. This bug
|
||
> is not present in QLIFE.
|
||
>
|
||
> You should have no trouble running QLIFE with cell grids up to
|
||
> 210x200.
|
||
>
|
||
> You *must* have a VGA and at least a 386 to run QLIFE. The 386
|
||
> features that it uses are not integral to the algorithm (they’re a
|
||
> convenience for the code), so feel free to modify QLIFE to run on
|
||
> earlier CPUs if you wish. QLIFE works best if you have a large CPU
|
||
> cache (256K is recommended).
|
||
>
|
||
> —*David Stafford*
|
||
>
|
||
> * * * * *
|
||
|
||
------------------------ --------------------------------- --------------------
|
||
[Previous](18-01.html) [Table of Contents](index.html) [Next](18-03.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
* * * * *
|
||
|
||
Graphics Programming Black Book © 2001 Michael Abrash
|