A.N.A.L.O.G. ISSUE 55 / MARCH 1987 / PAGE 45

Life
in the
Fast
Lane

48K Disk

The classic
gets an update
to keep you mesmerized.

by James Hague

Back in 1970, before the home computer industry had taken off, a mathematician by the name of John Horton Conway created a program known simply as Life. Life mathematically simulated the formation and destruction of colonies of “cells.” The almost-limitless possibilities introduced by this rather simple program captured the imagination of practically everyone who “just wanted to try it once.” Over the next few years, wherever a computer existed, Life—in one form or another—was sure to be found. ANALOG Computing published an ST version in issue 49.

Now it’s the eighties. Life can be found floating around in various public domain libraries, as well as in most college and university computer labs. The concept behind the “game” is just as enticing as it was back in 1970, but incredibly slow BASIC programs with Xs representing cells just don’t cut it anymore. Simply determining the outcome of a single colony of cells may take anywhere from several minutes to several hours, depending on the quality of the implementation.

Finally, Life has been given a complete overhaul, in an effort to bring it up to par for this decade. Herein, I present Life in the Fast Lane.

Typing it in.

Listing 1 is the BASIC data for Life in the Fast Lane. Do not type this as if it were a BASIC program. Instead, use Clayton Walnum’s M/L Editor (see page 41) as a means to get all of those numbers safely locked away in a binary file on disk. If you name the resulting file AUTORUN.SYS and place it on a disk containing DOS.SYS (DUP.SYS isn’t necessary), Life in the Fast Lane will automatically load and run when your computer’s turned on. XL and XE owners should hold down the OPTION key during power-up, in order to disable BASIC. If you choose a different filename, use option L from the DOS menu to get the program up and running.

Listing 2 for this offering is included, for those who are interested in assembly language programming. You do not need to type it in.

Creating a colony.

Plug a joystick into port 1, and you’re ready to begin. First of all, note that the screen is divided into three distinct sections. The upper portion contains vital information about the cell colony. The center of the screen is where the actual cells are located. And at the very bottom is a message line which will relay important information to you from the computer.

The joystick controls the flashing square cursor located in the center of the board. Pushing the joystick in any of the eight standard directions will slide the cursor in the corresponding direction.

To place a cell on the board, press the trigger and, with a ding, a cell will appear. Press the trigger again and the cell will instantly vanish. You can hold down the trigger while moving around, in order to “draw” lines of cells. Cells can be placed on any of the 256 board squares, but the real fun is in deciding exactly which ones.

What you’re actually doing is creating the first “generation” of your cell colony. When you’re satisfied with the colony’s architecture, a quick press of the START key will crank up the “Life” computer, which will determine the future of the cells.

There are two other keys that are active during the editing process. The SELECT key will change the current mode as displayed on the far right of the second line from the top of the screen. The mode determines exactly how the cells will be regenerated, but don’t worry about it for now. Pressing ESC (ESCape) instantly erases all cells from the board, providing a cleab slate to work with.

Let there be Life.

Once START has been pressed, the real fun begins. This program is similar to Joel Gluck’s Bounce (the original of which appeared in Our Game, issue 15), in that you’re responsible for setting things up, but are nothing more than an innocent bystander once control is relinquished to the computer. It is this aspect—sitting back and watching your creation—that’s responsible for the popularity of both the original Life and the more recent Bounce. (In its three incarnations, Bounce has become one of ANALOG’s most popular programs).

The cell colony is regenerated according to a few simple rules. First, a cell that is surrounded by fewer than two or more than three neighboring cells will be killed. Next, if an empty square is bordered by exactly three cells, a new cell will grow in the empty spot. Finally, if a cell is a neighbor of two or three other cells, that cell will survive. Figure 1 shows a small cell colony and how it would regenerate according to these rules. Note that each square on the board is bordered by eight others. These simple rules can transform your colony into a thriving populace—or, just as easily, crumble it into dust.

Figure 1. — Sample cell regeneration.

GENERATION 1
GENERATION 2
GENERATION 3 — STABLE POPULATION

The cell colony will continue to regenerate until one of four things happen: (1) you press a console key (START, SELECT or OPTION) to turn off the Life computer and return to the editing screen; (2) the cell colony reaches a stable population—meaning that, according to the aforementioned rules, no cells will grow or die—in this case, you’ll be returned to the editor; (3) the cell colony repeats—meaning that it continually grows and dies in a short pattern—press a console key to abort; and (4) the cell colony completely dies out.

Pressing the SPACE BAR while the Life computer is running will temporarily pause things until a different key is pressed.

Statistics and modes.

The information at the top of the screen supplies you with statistics—some vital, some frivolous—about the current colony. On the very top line is the number of the current generation. While editing the board, this will be 1. While the Life computer is running, it’s important to note that the generation number is incremented after changes are made to the current generation.

The second line contains more statistics. The first value is the current cell population. Obviously, when it reads 0, the colony is no more. The maximum population is limited by the number of squares on the board, and is therefore 256.

The next value is the number of cells that originally started out in the colony. This is used to determine just how much a certain colony has reproduced. For instance, if the starting population is 40 and the current population is 120, then there’s been a threefold increase in the number of living cells. The next-to-last value is for the most cells that have been recorded so far, or, in other words, the highest population.

Finally, we come to a three-letter mnemonic, which represents the current mode the Life computer is in. This is the mode selected while editing the screen. I realized that some people may want to change modes midway through the life of a cell colony, so I added a special feature to allow this capability.

As you already know, pressing a console key will abort the Life computer and allow you to edit the board. The catch is as follows: the cell statistics are only reset if you make a change to the colony. This lets you shut down the Life computer, switch modes and restart, without affecting the colony in any way. The following modes have been provided:

RGN — ReGular Noisy. In this mode, cell growth/death is animated and is accompanied by pleasant-sounding chords. Each generation lasts for about one second.

RGQ — ReGular Quiet. This is the same as RGN, except that the sound is turned off.

SSN — Single Step Noisy. In this mode, after each generation you will be prompted to press the joystick trigger, in order to progress to the next generation. This allows you to watch exactly how the fate of each cell is determined. You can hold down the trigger to speed through successive generations.

SSQ — Single Step Quiet. This is the same as SSN, except that the sound is turned off.

FST — FaST. This mode really shows the speed and power of machine language. Both the animation and sound effects are bypassed, thus simplifying the Life computer’s task immensely. This mode can speed through about twenty or so generations per second, so the screen really appears to be alive! There are two major uses for this mode: if you want to quickly find out exactly how many generations a colony will survive, or if you want to get the big picture of the birth and death of a colony.

Exploring Life.

It’s easy to spend hours upon hours experimenting Life in the Fast Lane. There are, for all practical purposes, an infinite number of possible cell colonies. So here are a couple of ideas and observations I’ve made after a few hours experimentation, to get you started.

Once you get Life in the Fast Lane up and running, I know you’ll want a quick demonstration of its power, so here’s a simple one. Draw a horizontal row of cells across the screen about midway between the top and bottom, and turn on the Life computer. Within seconds, the population will have more than quadrupled, forming one large colony. This colony will spread outward, eventually breaking up into several subcolonies. Finally, around generation 33, six small, infinitely-repeating colonies will be formed. Press a console key to stop. Try this in each of the different modes, to gain a better understanding of how and when to use each one.

It won’t take long to be able to identify certain small groups of cells that either repeat or are stable. A block of four cells is a stable configuration. A row or column of three cells will repeat forever and ever. There are many other such patterns, but you should be able to pick up on them after logging in a few hours with your Atari.

The ultimate goal of all Life enthusiasts is to develop a colony that survives infinitely, without getting stuck in a pattern. This feat is probably impossible, but that doesn’t seem to have stopped people from trying. Colonies have been devised that can last for around 300 generations, but not much progress has been made beyond that point. If you ever get a colony going that surpasses the 300th generation or higher, I want to know about it!

It’s amazing how realistically some colonies behave. They start as a small clump and move outward from this position, as if new territory is being explored. Sometimes a small subcolony will be started, in an effort to colonize the area more fully. More than once, I’ve had several small colonies created, only to be destroyed by a larger colony that “attacks” each one in sequence.

Many people claim that the behavior of certain cell colonies represents real-life beliefs or morals. I’m not going to agree or disagree with this idea, but it is a fact that a cell colony fashioned in the shape of a swastika, if correctly positioned, will die within four generations.

Go ahead and type in Life in the Fast Lane. Maybe you’ll see pretty little pulsating creatures on a computer screen; maybe you’ll see more…


James Hague attends North Texas State University and is a member of the Dallas Atari Computer Enthusiasts. He has been programming an Atari 800 in both BASIC and assembly language since 1982.


Listing 1.
M/L Editor data.

1000 DATA 255,255,0,32,251,32,216,32,54,32,32,106,32,32,4,42,9134
1010 DATA 32,107,33,32,110,36,32,203,38,76,13,32,216,165,128,48,3532
1020 DATA 24,169,0,133,77,32,114,35,32,86,35,165,128,208,10,32,2320
1030 DATA 16,36,230,135,165,135,141,199,2,76,98,228,32,101,228,32,6916
1040 DATA 86,32,169,0,133,12,169,32,133,13,162,255,134,128,134,133,7714
1050 DATA 232,134,132,160,22,162,32,169,7,76,92,228,169,3,141,15,4409
1060 DATA 210,169,0,141,8,210,141,1,210,141,3,210,141,5,210,96,6909
1070 DATA 162,0,189,0,224,157,0,8,189,0,225,157,0,9,189,0,2946
1080 DATA 226,157,0,10,189,0,227,157,0,11,232,208,229,162,63,189,9822
1090 DATA 152,32,157,16,8,202,16,247,169,8,141,244,2,96,0,0,2631
1100 DATA 0,255,0,0,255,255,255,255,0,0,255,0,0,0,208,208,7493
1110 DATA 208,208,208,208,208,208,11,11,11,11,11,11,11,11,0,0,6402
1120 DATA 0,15,8,8,11,11,0,0,0,240,16,16,208,208,11,11,52
1130 DATA 8,8,15,0,0,0,208,208,16,16,240,0,0,0,134,129,1337
1140 DATA 132,130,160,0,177,129,201,255,240,6,153,184,13,200,208,244,3222
1150 DATA 169,0,192,40,176,6,153,184,13,200,208,246,96,160,14,162,9161
1160 DATA 80,165,252,32,247,33,144,32,44,33,165,143,76,44,33,160,4067
1170 DATA 61,162,16,165,139,32,44,33,165,138,76,44,33,160,66,162,4202
1180 DATA 80,165,139,32,44,33,165,138,76,44,33,160,71,162,16,165,4290
1190 DATA 141,32,44,33,165,140,72,134,136,74,74,74,74,5,136,153,4086
1200 DATA 0,12,200,104,41,15,5,136,153,0,12,200,96,160,76,166,4851
1210 DATA 142,189,92,33,153,0,12,200,189,97,33,153,0,12,200,189,5649
1220 DATA 102,33,153,0,12,96,114,114,115,115,102,103,103,115,115,115,5250
1230 DATA 110,113,110,113,116,169,0,133,142,141,47,2,32,132,33,32,1506
1240 DATA 148,33,32,169,33,32,237,34,169,62,141,47,2,96,162,0,2570
1250 DATA 134,138,134,139,134,140,134,141,134,144,232,134,143,96,162,8,8761
1260 DATA 189,160,33,157,192,2,202,16,247,96,24,24,24,24,200,86,3769
1270 DATA 0,0,0,162,0,138,157,0,12,157,240,12,232,224,240,208,1387
1280 DATA 245,162,10,189,86,34,157,2,12,202,16,247,162,35,189,97,6635
1290 DATA 34,157,21,12,202,16,247,169,101,133,129,169,12,133,130,162,8182
1300 DATA 15,169,66,157,82,12,169,67,157,166,13,160,0,169,69,145,5537
1310 DATA 129,160,17,169,68,145,129,165,129,24,105,20,133,129,165,130,6805
1320 DATA 105,0,248,33,243,34,133,130,202,16,218,160,70,140,81,12,6264
1330 DATA 200,140,98,12,200,140,165,13,200,140,182,13,169,54,141,48,6445
1340 DATA 2,169,34,141,49,2,169,133,141,0,2,169,34,141,1,2,632
1350 DATA 169,192,141,14,212,32,247,32,32,5,33,32,19,33,32,33,8421
1360 DATA 33,76,67,33,112,112,112,198,0,12,130,134,112,6,6,6,362
1370 DATA 6,6,6,6,6,6,6,6,6,6,6,6,6,6,134,112,5802
1380 DATA 2,65,54,34,39,37,46,37,50,33,52,41,47,46,26,48,7102
1390 DATA 111,112,117,108,97,116,105,111,110,0,51,116,97,114,116,105,4532
1400 DATA 110,103,0,0,0,0,45,111,115,116,0,0,0,0,0,45,5834
1410 DATA 111,100,101,72,169,10,141,23,208,141,10,212,169,154,141,0,6792
1420 DATA 2,169,34,141,1,2,104,64,72,169,138,141,22,208,141,10,4704
1430 DATA 212,169,136,141,23,208,169,180,141,0,2,169,34,141,1,2,2720
1440 DATA 104,64,72,169,70,141,22,208,141,10,212,165,134,141,23,208,8648
1450 DATA 169,206,141,0,2,169,34,141,1,2,104,64,72,169,10,141,2493
1460 DATA 23,208,141,10,212,169,133,141,0,2,169,34,141,1,2,104,2323
1470 DATA 64,162,0,138,157,0,3,232,208,250,96,32,227,34,162,0,6741
1480 DATA 138,157,244,34,239,35,0,4,157,0,5,157,0,6,157,0,28
1490 DATA 7,232,208,241,169,0,141,7,212,169,3,141,29,208,142,12,6371
1500 DATA 208,170,157,8,208,202,16,250,169,20,141,111,2,160,0,162,6377
1510 DATA 15,189,66,35,153,72,4,153,72,5,153,72,6,153,72,7,1347
1520 DATA 200,202,16,237,192,128,208,231,162,3,189,82,35,157,0,208,8684
1530 DATA 202,16,247,96,204,204,204,204,204,204,204,204,51,51,51,51,9719
1540 DATA 51,51,51,51,64,96,128,160,230,133,208,23,173,10,210,41,7281
1550 DATA 15,10,10,10,10,133,134,173,10,210,41,3,24,105,6,5,9454
1560 DATA 134,133,134,96,165,132,10,10,10,168,162,7,185,144,35,157,5607
1570 DATA 80,8,200,202,16,246,166,132,232,224,16,144,2,162,0,134,7518
1580 DATA 132,96,24,24,60,118,126,60,24,0,8,28,60,118,126,60,364
1590 DATA 24,0,0,28,62,118,126,60,24,0,0,24,62,119,126,60,9932
1600 DATA 24,0,0,24,60,127,119,60,24,0,0,24,60,126,119,62,9920
1610 DATA 24,0,0,24,60,126,118,62,28,0,0,24,60,126,118,60,9922
1620 DATA 28,8,0,24,60,126,110,60,24,24,0,24,60,126,110,60,9964
1630 DATA 56,16,0,24,60,126,110,124,56,0,0,24,60,126,238,124,3522
1640 DATA 24,0,240,35,235,36,0,24,60,238,254,60,24,0,0,24,1237
1650 DATA 124,238,126,60,24,0,0,56,124,110,126,60,24,0,16,56,9206
1660 DATA 60,110,126,60,24,0,165,147,24,105,160,141,1,210,165,148,7523
1670 DATA 141,0,210,165,147,240,2,198,147,96,164,146,162,9,189,64,8804
1680 DATA 36,153,0,3,200,202,16,246,162,3,165,145,157,4,208,24,6970
1690 DATA 105,2,202,16,247,96,0,231,129,129,0,0,129,129,231,0,5527
1700 DATA 162,0,173,31,208,201,7,240,1,232,134,137,96,173,31,208,9630
1710 DATA 201,7,208,5,169,0,133,137,96,72,165,137,240,4,104,169,7924
1720 DATA 0,96,104,96,162,237,160,36,32,216,32,169,127,133,146,169,9483
1730 DATA 120,133,145,32,36,36,32,74,36,162,255,142,252,2,232,134,9272
1740 DATA 147,134,149,134,152,134,151,134,128,169,0,133,20,165,152,240,9959
1750 DATA 2,198,152,165,20,201,2,144,6,32,20,37,76,147,36,173,3128
1760 DATA 252,2,201,28,208,8,32,46,38,169,255,141,252,2,32,87,6116
1770 DATA 36,240,224,106,176,11,169,127,133,128,32,86,32,32,227,34,5201
1780 DATA 96,106,144,6,169,0,133,152,240,201,165,152,208,197,169,10,1502
1790 DATA 133,152,166,142,232,224,5,208,2,162,0,134,142,32,67,33,4569
1800 DATA 76,157,236,36,231,37,36,0,0,53,115,101,0,106,111,121,2763
1810 DATA 115,116,105,99,107,0,116,111,0,112,108,97,99,101,0,99,2860
1820 DATA 101,108,108,115,0,111,110,0,98,111,97,114,100,255,32,140,6374
1830 DATA 37,173,120,2,166,151,208,12,201,15,240,48,133,150,169,8,7536
1840 DATA 133,151,208,19,166,150,221,125,37,208,12,189,125,37,133,150,8603
1850 DATA 169,8,56,229,151,133,151,166,150,165,145,24,125,105,37,168,8278
1860 DATA 201,64,144,4,201,185,144,5,169,0,133,151,96,165,146,24,6728
1870 DATA 125,115,37,201,71,144,241,201,192,176,237,133,146,132,145,198,4434
1880 DATA 151,169,0,133,149,76,36,36,1,1,1,0,255,255,255,0,5382
1890 DATA 0,0,1,255,0,0,1,255,0,0,1,255,10,9,11,0,8452
1900 DATA 6,5,7,0,14,13,174,16,208,240,4,202,134,149,96,165,8079
1910 DATA 151,208,251,165,149,208,247,162,1,134,149,134,143,202,134,144,2505
1920 DATA 32,241,37,248,177,129,240,25,169,0,145,129,165,138,56,233,385
1930 DATA 1,133,138,133,140,165,139,233,0,133,139,133,141,162,150,208,1804
1940 DATA 23,169,10,145,129,165,138,24,105,1,133,138,133,140,165,139,8166
1950 DATA 105,0,133,139,133,141,162,30,216,169,15,133,147,134,148,32,7809
1960 DATA 247,32,232,37,227,38,32,5,33,32,19,33,76,33,33,165,549
1970 DATA 146,56,233,71,74,74,74,72,133,129,169,0,133,130,162,3,5492
1980 DATA 6,129,38,130,202,16,249,104,10,10,24,101,129,133,129,165,6339
1990 DATA 130,105,0,133,130,165,129,24,105,100,133,129,165,130,105,12,6285
2000 DATA 133,130,165,145,56,233,48,74,74,74,168,96,165,139,208,4,7755
2010 DATA 165,138,240,50,169,102,133,129,169,12,133,130,162,15,169,0,6306
2020 DATA 160,15,145,129,136,16,251,165,129,24,105,20,133,129,165,130,7900
2030 DATA 105,0,133,130,202,16,231,32,132,33,32,247,32,32,5,33,2334
2040 DATA 32,33,33,32,19,33,96,173,252,2,201,33,208,45,165,20,5738
2050 DATA 72,32,86,32,162,39,189,184,13,157,224,16,202,16,247,162,9901
2060 DATA 158,160,38,32,216,32,173,252,2,201,33,240,249,162,39,189,1664
2070 DATA 224,16,157,184,13,202,16,247,104,133,20,96,0,0,0,0,536
2080 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,48,97,117,6079
2090 DATA 115,101,100,255,72,169,0,133,20,104,197,20,240,8,72,32,4616
2100 DATA 87,36,240,245,104,96,169,0,96,32,74,36,165,139,208,11,6055
2110 DATA 165,138,208,7,162,79,160,39,76,70,39,162,255,142,252,2,8791
2120 DATA 232,134,228,38,223,39,157,32,255,39,165,153,208,7,162,219,1232
2130 DATA 160,39,76,70,39,162,119,160,39,32,216,32,32,126,40,208,5695
2140 DATA 79,165,139,208,11,165,138,208,7,162,149,160,39,76,70,39,5960
2150 DATA 165,142,201,4,208,9,32,105,38,32,87,36,240,201,96,201,8017
2160 DATA 2,144,18,173,16,208,240,191,162,182,160,39,32,216,32,32,7670
2170 DATA 87,36,240,239,96,169,0,133,20,165,20,201,30,176,168,32,6911
2180 DATA 105,38,32,87,36,240,242,96,32,216,32,169,120,32,182,38,7061
2190 DATA 96,0,46,111,0,99,101,108,108,115,0,104,97,118,101,0,2831
2200 DATA 98,101,101,110,0,112,108,97,99,101,100,0,111,110,0,116,3287
2210 DATA 104,101,0,98,111,97,114,100,255,0,0,0,0,0,0,0,7938
2220 DATA 0,0,0,0,44,101,116,0,116,104,101,114,101,0,98,101,2820
2230 DATA 0,108,105,102,101,1,255,0,0,0,0,0,0,0,0,52,6297
2240 DATA 104,101,0,99,101,108,108,0,99,111,108,111,110,121,0,104,4160
2250 DATA 97,115,0,100,105,101,100,255,0,0,0,48,114,101,115,115,3885
2260 DATA 0,116,114,105,103,103,101,114,0,102,111,114,0,110,101,120,4590
2270 DATA 116,0,103,101,110,101,114,97,116,105,111,110,255,0,0,0,3779
2280 DATA 0,0,224,39,219,40,35,101,108,108,0,112,111,112,117,108,5386
2290 DATA 97,116,105,111,110,0,104,97,115,0,115,116,97,98,105,108,5060
2300 DATA 105,122,101,100,255,169,0,133,153,169,81,133,129,169,12,133,8610
2310 DATA 130,169,15,133,155,169,15,133,156,169,0,133,154,162,7,188,8386
2320 DATA 118,40,177,129,201,10,208,2,230,154,202,16,242,166,154,160,2466
2330 DATA 21,177,129,208,6,224,3,208,32,240,8,224,2,240,26,224,9807
2340 DATA 3,240,22,230,153,166,153,157,224,15,165,129,24,105,21,157,8035
2350 DATA 224,13,165,130,105,0,157,224,14,165,129,24,105,1,133,129,5952
2360 DATA 165,130,105,0,133,130,198,156,16,175,165,129,24,105,4,133,6406
2370 DATA 129,165,130,105,0,133,130,198,155,16,154,96,0,1,2,20,1696
2380 DATA 22,40,41,42,165,142,201,4,208,3,76,39,41,162,7,169,4705
2390 DATA 0,157,88,8,189,144,35,157,96,8,202,16,242,160,0,166,7710
2400 DATA 153,189,224,13,133,129,189,224,14,133,130,189,224,15,208,4,9669
2410 DATA 169,11,208,2,169,12,145,129,202,208,230,162,7,134,131,166,1157
2420 DATA 131,188,162,41,162,0,185,178,41,157,88,8,200,232,224,8,9445
2430 DATA 208,244,166,131,188,170,41,162,0,185,178,41,157,96,8,200,8696
2440 DATA 232,224,220,40,215,41,8,208,244,165,142,240,4,201,2,208,1493
2450 DATA 34,166,157,189,242,41,141,0,210,189,248,41,141,2,210,189,1521
2460 DATA 254,41,141,4,210,165,131,24,105,161,141,1,210,141,3,210,8611
2470 DATA 141,5,210,169,0,133,20,165,20,201,4,176,16,32,105,38,3370
2480 DATA 32,87,36,240,242,32,86,32,169,1,72,208,7,198,131,16,5917
2490 DATA 146,169,0,72,160,0,248,166,153,189,224,13,133,129,189,224,2967
2500 DATA 14,133,130,189,224,15,208,40,169,10,145,129,165,138,24,105,7793
2510 DATA 1,133,138,165,139,105,0,133,139,197,141,240,2,144,34,165,9084
2520 DATA 138,197,140,144,28,165,138,133,140,165,139,133,141,76,119,41,8581
2530 DATA 169,0,145,129,165,138,56,233,1,133,138,165,139,233,0,133,9593
2540 DATA 139,198,153,208,178,32,86,32,165,143,24,105,1,133,143,165,7405
2550 DATA 144,105,0,133,144,216,166,157,232,224,6,208,2,162,0,134,9198
2560 DATA 157,32,247,32,32,5,33,32,33,33,104,96,0,8,16,24,7986
2570 DATA 32,40,48,56,56,48,40,32,24,16,8,0,0,0,56,126,7474
2580 DATA 126,60,24,0,0,0,56,124,124,56,24,0,0,0,56,124,9046
2590 DATA 124,24,0,0,0,0,24,60,60,24,0,0,0,0,0,60,5150
2600 DATA 60,24,216,41,211,42,0,0,0,0,0,56,56,24,0,0,6563
2610 DATA 0,0,0,56,56,0,0,0,0,0,0,24,24,0,0,0,3714
2620 DATA 243,230,217,204,193,182,121,114,108,102,96,91,60,57,53,50,5919
2630 DATA 47,45,32,74,36,169,0,141,197,2,141,198,2,141,200,2,6233
2640 DATA 169,110,162,42,141,48,2,142,49,2,169,60,32,182,38,208,5728
2650 DATA 74,162,9,238,197,2,169,1,32,182,38,208,62,202,16,243,8999
2660 DATA 169,120,32,182,38,208,52,162,9,206,197,2,169,1,32,182,6926
2670 DATA 38,208,40,202,16,243,169,60,32,182,38,208,30,162,3,189,8002
2680 DATA 141,43,157,196,2,202,16,247,169,170,162,42,141,48,2,142,7786
2690 DATA 49,2,169,127,133,128,32,87,36,240,251,96,112,112,112,112,9244
2700 DATA 112,112,112,112,112,112,112,112,112,112,66,130,42,65,110,42,4924
2710 DATA 0,0,0,0,0,0,0,33,110,97,108,111,103,0,35,111,1094
2720 DATA 109,112,117,116,105,110,103,0,112,114,101,115,101,110,116,115,6846
2730 DATA 0,0,0,0,0,0,0,0,112,112,112,112,112,112,70,197,4660
2740 DATA 42,6,6,6,6,6,112,6,112,112,6,7,112,112,112,6,812
2750 DATA 65,170,42,0,0,10,0,0,0,0,10,0,10,10,10,10,4031
2760 DATA 0,10,212,42,143,43,10,10,10,0,0,0,0,74,0,0,5833
2770 DATA 0,0,74,0,74,0,0,0,0,74,0,0,0,0,0,0,4102
2780 DATA 0,10,0,0,0,0,10,0,10,10,10,0,0,10,10,10,3620
2790 DATA 0,0,0,0,0,74,0,0,0,0,74,0,74,0,0,0,5010
2800 DATA 0,74,0,0,0,0,0,0,0,10,0,0,0,0,10,0,3198
2810 DATA 10,0,0,0,0,10,0,0,0,0,0,0,0,74,74,74,6210
2820 DATA 74,0,74,0,74,0,0,0,0,74,74,74,74,0,0,128,8938
2830 DATA 128,169,174,128,180,168,165,128,166,161,179,180,128,172,161,174,4921
2840 DATA 165,128,128,0,0,0,0,0,35,50,37,33,52,37,36,0,6997
2850 DATA 34,57,0,0,0,0,0,128,128,128,128,170,161,173,165,179,9756
2860 DATA 128,128,168,161,167,181,165,128,128,128,128,64,64,64,64,112,7580
2870 DATA 114,101,115,115,64,64,115,116,97,114,116,64,64,64,64,70,4293
2880 DATA 26,150,226,2,227,2,0,32,0,0,0,0,0,0,0,0,5295

Listing 2.

	.OPT	OBJ,NOLIST
;
;LIFE IN THE FAST LANE
;Atari 8-bit Ver 1.00 04-20-86
;Copyright 1986 Analog Computing
;Programmed by James Hague
;
;----------------
; SYSTEM EQUATES
;----------------
;
;Page zero
;
DOSINI	=	$0C
RTCLOK	=	$14
ATRACT	=	$4D
;
;Misc.
;
VDSLST	=	$0200
SDLSTL	=	$0230
WSYNC	=	$D40A
SDMCTL	=	$022F
CONSOL	=	$D01F
RANDOM	=	$D20A
STICK0	=	$0278
TRIG0	=	$D010
NMIEN	=	$D40E
CH	=	$02FC
CHBAS	=	$02F4
OLDSET	=	$E000
;
;Audio
;
SKCTL	=	$D20F
AUDCTL	=	$D208
AUDF1	=	$D200
AUDC1	=	$D201
AUDF2	=	$D202
AUDC2	=	$D203
AUDF3	=	$D204
AUDC3	=	$D205
;
;P/M Graphics
;
GRACTL	=	$D01D
GPRIOR	=	$026F
PMBASE	=	$D407
HPOSP0	=	$D000
HPOSP1	=	$D001
HPOSP2	=	$D002
HPOSP3	=	$D003
HPOSM0	=	$D004
HPOSM1	=	$D005
HPOSM2	=	$D006
HPOSM3	=	$D007
SIZEP0	=	$D008
SIZEP1	=	$D009
SIZEP2	=	$D00A
SIZEP3	=	$D00B
SIZEM	=	$D00C
;
;Colors
;
PCOLR0	=	$02C0
PCOLR1	=	$02C1
PCOLR2	=	$02C2
PCOLR3	=	$02C3
COLOR0	=	$02C4
COLOR1	=	$02C5
COLOR2	=	$02C6
COLOR3	=	$02C7
COLBAK	=	$02C8
HCOLR0	=	$D016
HCOLR1	=	$D017
;
;System Routines
;
SIOINV	=	$E465
SETVBV	=	$E45C
XITVBL	=	$E462
;
;-------------------
; PROGRAM VARIABLES
;-------------------
	*=	$80
;
;Global misc.
;
VBICTL	.DS	1	;VBI CTrL. flag
PNT1	.DS	2	;Misc. PoiNTer
TEMP	.DS	1	;TEMP storage
IMAGE	.DS	1	;IMAGE pointer
COLTIM	.DS	1	;COLor TIMer
BORDER	.DS	1	;BORDER color
CURSOR	.DS	1	;CURSOR color
COLMSK	.DS	1	;COLor MaSK
CONKEY	.DS	1	;CONsole KEY flg
;
;Cell Database
;
POP	.DS	2	;bcd POPulation
MOST	.DS	2	;bcd max pop.
MODE	.DS	1	;growth MODE
GENER	.DS	2	;bcd GENERation
;
;Placement routines
;
CURX	.DS	1	;CURsor X pos.
CURY	.DS	1	;CURsor Y pos.
SOUND	.DS	1	;SOUND flag
TONE	.DS	1	;sound TONE
PRESS	.DS	1	;trig PRESS flag
DIR	.DS	1	;stick DIRect.
DIST	.DS	1	;cursor DISTance
SELECT	.DS	1	;SELECT key time
;
;Regeneration
;
ACTIVE	.DS	1	;ACTIVE cells
COUNT	.DS	1	;temp COUNTer
ROW	.DS	1	;current ROW
COL	.DS	1	;current COLUMN
CHORD	.DS	1	;current CHORD #
;
;Color Constants
;
@GENTXT	=	$C8	;GENer label
@GENNUM	=	$56	;GENer number
@GR0BAK	=	$00	;GR.0 BAcKground
@GR0LUM	=	$0A	;GR.0 text LUM.
@NUM1	=	$8A	;NUMber color 1
@NUM2	=	$88	;NUMber color 2
@BOARD	=	$18	;BOARD squares
@CELL	=	$46	;CELLs
;
;Misc. Constants
;
EOL	=	$FF	;EOL character
;
;-------------
; GLOBAL DATA
;-------------
;
	*=	$00
PM	.DS	$0300	;Player/Missile
MISSL	.DS	$0100	;memory...
PL0	.DS	$0100
PL1	.DS	$0100
PL2	.DS	$0100
PL3	.DS	$0100
CHSET	.DS	$0400	;New CHar SET
DISP	.DS	480	;DISPlay memory
BOARD	=	DISP+102
TEXT	=	DISP+440
CADRL	.DS	$0100	;Regeneration
CADRH	.DS	$0100	;data storage...
CTYPE	.DS	$0100
TSAVE	.DS	40	;Temp buffer
;
;------------------
; PROGRAM MAINLINE
;------------------
;
	*=	$2000
RESET
	CLD		;Kill decimal
	JSR	SETSYS	;Set-up system
	JSR	REDEFINE	;Redef. chset
	JSR	TITLE	;Do title scrn.
	JSR	SETUP	;Set-up program
MAIN	JSR	PLACE	;Place cells
	JSR	LIFE	;Create life!
	JMP	MAIN	;Loop forever
;
;-----------------
; VBLANK MAINLINE
;-----------------
;
VBI
	CLD		;Kill decimal
	LDA	VBICTL	;Get VBI flag
	BMI	NOVBI	;If <0, exit
	LDA	#0	;else, turn off
	STA	ATRACT	;attract mode
	JSR	ANIMATE	;Animate cells
	JSR	BCOLOR	;Do border color
	LDA	VBICTL	;Get flag again
	BNE	NOVBI	;If not 0, exit
	JSR	DING	;Do ding sound
	INC	CURSOR	;Flash cursor...
	LDA	CURSOR
	STA	COLOR3
NOVBI	JMP	XITVBL	;Bye-bye VBI!
;
;---------------
; SET-UP SYSTEM
;---------------
;
;Among other things, set up
;the VBI and any variables
;associated with it that
;need be initialized only once.
;
SETSYS
	JSR	SIOINV	;Init sounds...
	JSR	QUIET
	LDA	#<RESET	;Steal the
	STA	DOSINI	;reset vector...
	LDA	#>RESET
	STA	DOSINI+1
	LDX	#$FF	;Init VBI
	STX	VBICTL	;variables...
	STX	COLTIM
	INX
	STX	IMAGE
	LDY	#<VBI
	LDX	#>VBI
	LDA	#7
	JMP	SETVBV
;
;----------------
; SHUT OFF SOUND
;----------------
;
;This is a general purpose
;routine that initializes
;sound channels 1,2 & 3.  It is
;not responsible for handling
;routine-specific flags.
;
QUIET
	LDA	#3	;Initialize
	STA	SKCTL	;sound and
	LDA	#0	;turn off
	STA	AUDCTL	;channels 1,2
	STA	AUDC1	;and 3...
	STA	AUDC2
	STA	AUDC3
	RTS
;
;------------------
; REDEFINE CHARSET
;------------------
;
;Move charset
;
REDEFINE
	LDX	#0	;Move set from
MOVSET	LDA	OLDSET,X	;$E000 to
	STA	CHSET,X	;RAM...
	LDA	OLDSET+$0100,X
	STA	CHSET+$0100,X
	LDA	OLDSET+$0200,X
	STA	CHSET+$0200,X
	LDA	OLDSET+$0300,X
	STA	CHSET+$0300,X
	INX
	BNE	MOVSET
;
;Redefine a few chars
;
	LDX	#63	;Redefine chars
REDEF	LDA	CHRDAT,X	;2 thru 10 as
	STA	CHSET+16,X	;the arena's
	DEX		;borders
	BPL	REDEF
;
;Install new set
;
	LDA	#>CHSET
	STA	CHBAS
	RTS
;
;Character data
;
CHRDAT	.BYTE	$00,$00,$00,$FF
	.BYTE	$00,$00,$FF,$FF
;
	.BYTE	$FF,$FF,$00,$00
	.BYTE	$FF,$00,$00,$00
;
	.BYTE	$D0,$D0,$D0,$D0
	.BYTE	$D0,$D0,$D0,$D0
;
	.BYTE	$0B,$0B,$0B,$0B
	.BYTE	$0B,$0B,$0B,$0B
;
	.BYTE	$00,$00,$00,$0F
	.BYTE	$08,$08,$0B,$0B
;
	.BYTE	$00,$00,$00,$F0
	.BYTE	$10,$10,$D0,$D0
;
	.BYTE	$0B,$0B,$08,$08
	.BYTE	$0F,$00,$00,$00
;
	.BYTE	$D0,$D0,$10,$10
	.BYTE	$F0,$00,$00,$00
;
;---------------
; PRINT MESSAGE
;---------------
;
;This routine prints an EOL
;terminated internally-coded
;string on the message line.
;
;Call with:
;  x reg. - lo byte of string
;  y reg. - hi byte of string
;
PRINT
	STX	PNT1	;Save string
	STY	PNT1+1	;address
	LDY	#0
DOCHAR	LDA	(PNT1),Y	;Get a char
	CMP	#EOL	;EOL?
	BEQ	PADIT	;Yes, pad line.
	STA	TEXT,Y	;No, show char
	INY		;and do the
	BNE	DOCHAR	;next one
;
;Pad rest of line with blanks
;
PADIT	LDA	#0	;Blank char
DOPAD	CPY	#40	;All done?
	BCS	PREXIT	;Yes, return.
	STA	TEXT,Y	;No, show blank
	INY		;Loop until
	BNE	DOPAD	;line is done
PREXIT	RTS
;
;----------------------------
; NUMERICAL DISPLAY ROUTINES
;----------------------------
;
;Show generation number
;
SHOGEN
	LDY	#14	;Screen offset
	LDX	#80	;Color mask
	LDA	GENER+1	;Print...
	JSR	BCD
	LDA	GENER
	JMP	BCD
;
;Show population
;
SHOPOP
	LDY	#61	;Screen offset
	LDX	#16	;Color mask
	LDA	POP+1	;Print...
	JSR	BCD
	LDA	POP
	JMP	BCD
;
;Show starting pop.
;
SHOSTRT
	LDY	#66	;Screen offset
	LDX	#80	;Color mask
	LDA	POP+1	;Print...
	JSR	BCD
	LDA	POP
	JMP	BCD
;
;Show largest pop.
;
SHOMOST
	LDY	#71	;Screen offset
	LDX	#16	;Color mask
	LDA	MOST+1	;Print...
	JSR	BCD
	LDA	MOST	;Fall into BCD..
;
;Print 2 BCD digits
;
;Call with:
;  a reg. - BCD data
;  x reg. - color mask+16
;  y reg. - offset from DISP
;
BCD
	PHA		;Save BCD data
	STX	COLMSK	;Save color mask
	LSR	A	;Move upper 4
	LSR	A	;bits into lower
	LSR	A	;4 bits...
	LSR	A
	ORA	COLMSK	;make it ATASCII
	STA	DISP,Y	;and show it.
	INY		;Goto next pos.
	PLA		;Get original #
	AND	#$0F	;mask upper half
	ORA	COLMSK	;make it ATASCII
	STA	DISP,Y	;and show it.
	INY		;Goto next pos.
	RTS		;and leave.
;
;-----------
; SHOW MODE
;-----------
;
SHOMODE
	LDY	#76	;Screen offset
	LDX	MODE	;Get mode #
	LDA	LET1,X	;Print first
	STA	DISP,Y	;letter of mode
	INY
	LDA	LET2,X	;Print second
	STA	DISP,Y	;letter...
	INY
	LDA	LET3,X	;and print
	STA	DISP,Y	;final letter
	RTS
;
;Mode data
;
LET1	.SBYTE	+64,"RRSSF"
LET2	.SBYTE	+64,"GGSSS"
LET3	.SBYTE	+64,"NQNQT"
;
;---------------------
; MAIN SET-UP ROUTINE
;---------------------
;
SETUP
	LDA	#0	;Set mode to
	STA	MODE	;0 (RGN)
	STA	SDMCTL	;Turn DMA off
	JSR	SETCELL	;Set cell data
	JSR	SETCOLR	;Set colors
	JSR	SETDISP	;Set-up display
	JSR	SETPM	;Set PM grphics
	LDA	#62	;Enable DMA for
	STA	SDMCTL	;screen and PM
	RTS		;and exit!
;
;--------------------
; INIT CELL DATABASE
;--------------------
;
;Reset all cell variables except
;MODE which does not need to be
;changed when the cells are.
;
SETCELL
	LDX	#0	;Clear out the
	STX	POP	;population...
	STX	POP+1
	STX	MOST	;largest pop...
	STX	MOST+1
	STX	GENER+1	;Set generation
	INX		;to 1 (BCD)
	STX	GENER
	RTS
;
;---------------
; SET UP COLORS
;---------------
;
SETCOLR
	LDX	#8	;Do 9 color regs
COLR	LDA	COLORS,X	;Get a color
	STA	PCOLR0,X	;& put in reg.
	DEX		;Repeat til done
	BPL	COLR
	RTS
;
;Initial colors
;
COLORS
	.BYTE	@BOARD	;PCOLR0
	.BYTE	@BOARD	;PCOLR1
	.BYTE	@BOARD	;PCOLR2
	.BYTE	@BOARD	;PCOLR3
	.BYTE	@GENTXT	;COLOR0
	.BYTE	@GENNUM	;COLOR1
	.BYTE	@GR0BAK	;COLOR2
	.BYTE	0	;COLOR3
	.BYTE	0	;COLBAK
;
;---------------------
; SET-UP MAIN DISPLAY
;---------------------
;
;Clear display memory
;
SETDISP
	LDX	#0	;Clear 480 bytes
	TXA		;in two blocks
CLRD	STA	DISP,X	;of 240 each...
	STA	DISP+240,X
	INX
	CPX	#240
	BNE	CLRD
;
;Print labels
;
	LDX	#10	;Print
PRL1	LDA	GLABEL,X	;"GENERATION:"
	STA	DISP+2,X	;on line 0...
	DEX
	BPL	PRL1
	LDX	#35	;Print cell
PRL2	LDA	LABELS,X	;data labels
	STA	DISP+21,X	;on line 1...
	DEX
	BPL	PRL2
;
; Draw borders
;
	LDA	#<[DISP+101]	;Draw the
	STA	PNT1	;long sections
	LDA	#>[DISP+101]	;of the
	STA	PNT1+1	;border
	LDX	#15	;(15 chars long)
BDRAW	LDA	#66	;Print a piece
	STA	DISP+82,X	;of top line
	LDA	#67	;and the bottom
	STA	DISP+422,X	;line plus
	LDY	#0	;part of the
	LDA	#69	;left side
	STA	(PNT1),Y
	LDY	#17	;and finally
	LDA	#68	;a piece of the
	STA	(PNT1),Y	;right!
	LDA	PNT1	;Add 20 to the
	CLC		;address of the
	ADC	#20	;current line so
	STA	PNT1	;that we'll know
	LDA	PNT1+1	;where to print
	ADC	#0	;the next side
	STA	PNT1+1	;chars.
	DEX		;Finish drawing!
	BPL	BDRAW
;
	LDY	#70	;Add upper left
	STY	DISP+81	;corner,
	INY		;upper right,
	STY	DISP+98
	INY		;lower left,
	STY	DISP+421
	INY		;and finally the
	STY	DISP+438	;lower right!
;
;Point to main DL
;
	LDA	#<DL
	STA	SDLSTL
	LDA	#>DL
	STA	SDLSTL+1
;
;Start up DLIs
;
	LDA	#<DLI1	;Point to first
	STA	VDSLST	;DLI...
	LDA	#>DLI1
	STA	VDSLST+1
	LDA	#192	;Enable DLIs and
	STA	NMIEN	;VBIs
;
;Show cell data
;
	JSR	SHOGEN	;Show generation
	JSR	SHOPOP	;current pop.
	JSR	SHOSTRT	;starting pop.
	JSR	SHOMOST	;Maximum pop.
	JMP	SHOMODE	;and mode
;
;Main display list
;
DL	.BYTE	112,112,112
	.BYTE	198,<DISP,>DISP
	.BYTE	130
	.BYTE	134
	.BYTE	112
	.BYTE	6,6,6,6,6,6,6,6,6
	.BYTE	6,6,6,6,6,6,6,6
	.BYTE	134
	.BYTE	112
	.BYTE	2
	.BYTE	65,<DL,>DL
;
;Misc. display data
;
GLABEL	.SBYTE	"GENERATION:"
LABELS	.SBYTE	"Population "
	.SBYTE	"Starting    Most"
	.SBYTE	"     Mode"
;
;------------------
; MAIN SCREEN DLIs
;------------------
;
;Set the text luminance for
;the label line (1)
;
DLI1	PHA		;Save acc.
	LDA	#@GR0LUM	;Set text
	STA	HCOLR1	;luminance
	STA	WSYNC	;Wait for sync
	LDA	#<DLI2	;and point to
	STA	VDSLST	;next dli...
	LDA	#>DLI2
	STA	VDSLST+1
	PLA		;Restore acc.
	RTI
;
;Set colors for the numbers on
;line 2
;
DLI2	PHA		;Save acc.
	LDA	#@NUM1	;Set number
	STA	HCOLR0	;color 1,
	STA	WSYNC	;wait for sync,
	LDA	#@NUM2	;and set number
	STA	HCOLR1	;color 2
	LDA	#<DLI3	;Point to next
	STA	VDSLST	;dli...
	LDA	#>DLI3
	STA	VDSLST+1
	PLA		;Restore acc.
	RTI
;
;Set colors for the cells and
;border of board
;
DLI3	PHA		;Save acc.
	LDA	#@CELL	;Set cell color
	STA	HCOLR0
	STA	WSYNC	;Wait for sync
	LDA	BORDER	;and set border
	STA	HCOLR1	;color
	LDA	#<DLI4	;Point to final
	STA	VDSLST	;dli...
	LDA	#>DLI4
	STA	VDSLST+1
	PLA		;Restore acc.
	RTI
;
;Set text luminance for message
;line
;
DLI4	PHA		;Save acc
	LDA	#@GR0LUM	;Set text
	STA	HCOLR1	;luminance, and
	STA	WSYNC	;wait for sync
	LDA	#<DLI1	;Point back to
	STA	VDSLST	;first dli...
	LDA	#>DLI1
	STA	VDSLST+1
	PLA		;Restore acc.
	RTI
;
;----------------------
; CLEAR MISSILE MEMORY
;----------------------
;
CLRMISS
	LDX	#0	;Fill missile
	TXA		;memory with
CCLR	STA	MISSL,X	;zeroes
	INX
	BNE	CCLR
	RTS
;
;--------------------
; SET-UP PM GRAPHICS
;--------------------
;
;Clear pm memory
;
SETPM
	JSR	CLRMISS	;Clear missiles
	LDX	#0	;Clear players
	TXA		;0-3...
PMCLR	STA	PL0,X
	STA	PL1,X
	STA	PL2,X
	STA	PL3,X
	INX
	BNE	PMCLR
;
;Init pm
;
	LDA	#>PM	;Point to pm
	STA	PMBASE	;memory
	LDA	#3	;Turn on pm
	STA	GRACTL	;graphics
	STX	SIZEM	;Set missl. size
	TAX		;Set all players
SETSIZE	STA	SIZEP0,X	;to
	DEX		;quadruple width
	BPL	SETSIZE
	LDA	#20	;Set priority
	STA	GPRIOR	;w/5th player on
;
;Draw board squares
;
	LDY	#0	;Draw squares
SQ1	LDX	#15	;in players 0-3
SQ2	LDA	SQRDAT,X	;Get data byte
	STA	PL0+72,Y	;and put it in
	STA	PL1+72,Y	;each player...
	STA	PL2+72,Y
	STA	PL3+72,Y
	INY		;Next pm byte
	DEX		;Finish up a set
	BPL	SQ2	;of 4 squares
	CPY	#128
	BNE	SQ1	;Complete board
;
	LDX	#3	;Set player
MOVSQ	LDA	PLHPOS,X	;horizontal
	STA	HPOSP0,X	;positions...
	DEX
	BPL	MOVSQ
	RTS
;
;Square data
;
SQRDAT	.BYTE	$CC,$CC,$CC,$CC
	.BYTE	$CC,$CC,$CC,$CC
	.BYTE	$33,$33,$33,$33
	.BYTE	$33,$33,$33,$33
;
;Player horiz. positions
;
PLHPOS	.BYTE	64,96,128,160
;
;-------------------------
; VB BORDER COLOR HANDLER
;-------------------------
;
BCOLOR
	INC	COLTIM	;Add 1 to timer
	BNE	OLDCOL	;If not 0, exit
	LDA	RANDOM	;Get random #
	AND	#$0F	;Make it <16
	ASL	A	;Mult by 16...
	ASL	A
	ASL	A
	ASL	A
	STA	BORDER	;Save the result
	LDA	RANDOM	;Get random #
	AND	#3	;Make it <4,
	CLC		;add 6, and add
	ADC	#6	;it to previous
	ORA	BORDER	;result for the
	STA	BORDER	;new color!
OLDCOL	RTS
;
;-------------------
; VB CELL ANIMATION
;-------------------
;
ANIMATE
	LDA	IMAGE	;Get image #
	ASL	A	;and multiply
	ASL	A	;it by 8 for an
	ASL	A	;index into the
	TAY		;cell data
	LDX	#7	;Copy 8 bytes
ANIM	LDA	CELIMG,Y	;from the data
	STA	CHSET+80,X	;table into
	INY		;char number 10
	DEX
	BPL	ANIM
	LDX	IMAGE	;Point to next
	INX		;image
	CPX	#16	;Last one done?
	BCC	ANXIT	;No, exit
	LDX	#0	;Yes, reset it
ANXIT	STX	IMAGE	;Save new num
	RTS
;
;Cell image data
;
CELIMG
	.BYTE	$18,$18,$3C,$76
	.BYTE	$7E,$3C,$18,$00
;
	.BYTE	$08,$1C,$3C,$76
	.BYTE	$7E,$3C,$18,$00
;
	.BYTE	$00,$1C,$3E,$76
	.BYTE	$7E,$3C,$18,$00
;
	.BYTE	$00,$18,$3E,$77
	.BYTE	$7E,$3C,$18,$00
;
	.BYTE	$00,$18,$3C,$7F
	.BYTE	$77,$3C,$18,$00
;
	.BYTE	$00,$18,$3C,$7E
	.BYTE	$77,$3E,$18,$00
;
	.BYTE	$00,$18,$3C,$7E
	.BYTE	$76,$3E,$1C,$00
;
	.BYTE	$00,$18,$3C,$7E
	.BYTE	$76,$3C,$1C,$08
;
	.BYTE	$00,$18,$3C,$7E
	.BYTE	$6E,$3C,$18,$18
;
	.BYTE	$00,$18,$3C,$7E
	.BYTE	$6E,$3C,$38,$10
;
	.BYTE	$00,$18,$3C,$7E
	.BYTE	$6E,$7C,$38,$00
;
	.BYTE	$00,$18,$3C,$7E
	.BYTE	$EE,$7C,$18,$00
;
	.BYTE	$00,$18,$3C,$EE
	.BYTE	$FE,$3C,$18,$00
;
	.BYTE	$00,$18,$7C,$EE
	.BYTE	$7E,$3C,$18,$00
;
	.BYTE	$00,$38,$7C,$6E
	.BYTE	$7E,$3C,$18,$00
;
	.BYTE	$10,$38,$3C,$6E
	.BYTE	$7E,$3C,$18,$00
;
	.INCLUDE	#D:FLIFE2.M65
	*=	$02E0
	.WORD	RESET
	.END
;LIFE IN THE FAST LANE
;Atari 8-bit Ver 1.00 4-20-86
;Copyright 1986 Analog Computing
;Programmed by James Hague
;
;Part II
;
;-----------------
; VB DING HANDLER
;-----------------
;
DING
	LDA	SOUND	;Get sound vol.
	CLC		;add distortion
	ADC	#$A0	;value
	STA	AUDC1	;and set it
	LDA	TONE	;Set proper
	STA	AUDF1	;frequency
	LDA	SOUND	;If vol is 0
	BEQ	XITDING	;then exit!
	DEC	SOUND	;Else lower vol
XITDING	RTS
;
;--------------
; DRAW CURSOR
;--------------
;
;The cursor consists of missles
;zero thru three.
;
DRAWCUR
	LDY	CURY	;Move 10 bytes
	LDX	#9	;of cursor shape
CDRAW	LDA	CURDAT,X	;data into
	STA	MISSL,Y	;missile memory
	INY
	DEX
	BPL	CDRAW
;
	LDX	#3	;Set horizontal
	LDA	CURX	;positions for
SETCHP	STA	HPOSM0,X	;the 4
	CLC		;missiles.  Each
	ADC	#2	;one is two
	DEX		;units away from
	BPL	SETCHP	;previous
	RTS		;missile.
;
;Cursor shape data: 8 bytes of
;actual data plus leading and
;trailing zeroes to make motion
;easier.
;
CURDAT	.BYTE	0,231,129,129,0
	.BYTE	0,129,129,231,0
;
;----------------------
; CONSOLE KEY ROUTINES
;----------------------
;
;Init console key flag
;
;Set CONKEY to 0 if no console
;keys are pressed, else set it
;to 1
;
INITCON
	LDX	#0
	LDA	CONSOL	;Get keys
	CMP	#7	;If not down
	BEQ	NOCKEY	;set to 0,
	INX		;else set to 1
NOCKEY	STX	CONKEY
	RTS
;
;Check console keys
;
;Return 0 in acc. if no console
;keys are pressed, else return
;the value of CONSOL in acc.
;
CHKCON
	LDA	CONSOL	;Any console
	CMP	#7	;keys pressed?
	BNE	CCHK1	;No, check more!
	LDA	#0	;Yes, zero key
	STA	CONKEY	;flag and return
	RTS		;a zero!
;
CCHK1	PHA		;Save CONSOL
	LDA	CONKEY	;Flag clear?
	BEQ	CCHK2	;Yes, go do it!
	PLA		;No, get CONSOL
	LDA	#0	;back and return
	RTS		;a zero!
;
CCHK2	PLA		;A legal press!!
	RTS		;Return CONSOL!
;
;------------------------
; CELL PLACEMENT HANDLER
;------------------------
;
;Initialize
;
PLACE
	LDX	#<MSG0	;Print instruc-
	LDY	#>MSG0	;tion message
	JSR	PRINT
	LDA	#127	;Init cursor
	STA	CURY	;coordinates...
	LDA	#120
	STA	CURX
	JSR	DRAWCUR	;Draw cursor
	JSR	INITCON	;Set key flag
	LDX	#$FF	;Clear any stray
	STX	CH	;keypresses
	INX		;Clear important
	STX	SOUND	;variables...
	STX	PRESS
	STX	SELECT
	STX	DIST
	STX	VBICTL	;Set VB mode
;
;Main placement loop
;
CLRCLOK	LDA	#0	;Clear clock
	STA	RTCLOK
	LDA	SELECT	;Decrement the
	BEQ	HANGON	;select key
	DEC	SELECT	;timer, if set.
;
HANGON	LDA	RTCLOK	;If 1/30 sec
	CMP	#2	;has elapsed,
	BCC	NOTYET	;handle the
	JSR	MOVECUR	;cursor and
	JMP	CLRCLOK	;reset the clock
;
NOTYET	LDA	CH	;If escape is
	CMP	#28	;pressed, call
	BNE	NOESC	;the cell clear/
	JSR	CLEAR	;reset routine
	LDA	#$FF	;And clear the
	STA	CH	;keyboard!
;
NOESC	JSR	CHKCON	;If no console
	BEQ	HANGON	;keys, go loop!
	ROR	A	;If start is
	BCS	NOSTRT	;pressed
	LDA	#127	;put the VB
	STA	VBICTL	;on hold,
	JSR	QUIET	;kil sound,
	JSR	CLRMISS	;clear cursor,
	RTS		;and leave!
;
NOSTRT	ROR	A	;If select is
	BCC	NEWMODE	;pressed, handle
	LDA	#0	;it, otherwise
	STA	SELECT	;clear the sel-
	BEQ	HANGON	;ect key timer.
NEWMODE	LDA	SELECT	;If timer is
	BNE	HANGON	;set, then bye!
	LDA	#10	;A legal press!
	STA	SELECT	;Reset key timer
	LDX	MODE	;and add 1 to
	INX		;the current
	CPX	#5	;mode making
	BNE	MODEOK	;sure it isn't
	LDX	#0	;greater than 4
MODEOK	STX	MODE
	JSR	SHOMODE	;Show new mode
	JMP	HANGON	;and loop!
;
;Instruction message
;
MSG0	.SBYTE	"  Use joystick to "
	.SBYTE	"place cells on "
	.SBYTE	"board"
	.BYTE	EOL
;
;----------------
; CURSOR HANDLER
;----------------
;
MOVECUR
	JSR	CHKTRIG	;Check trigger
	LDA	STICK0	;If cursor is
	LDX	DIST	;moving, then
	BNE	MOVING	;go move it!
	CMP	#15	;If stick is
	BEQ	XITMOVE	;pushed, then
	STA	DIR	;start up the
	LDA	#8	;cursor and go
	STA	DIST	;slie it!
	BNE	SLIDE
;
MOVING	LDX	DIR	;The cursor is
	CMP	OPDIR-5,X	;moving!  If
	BNE	SLIDE	;the stick is
	LDA	OPDIR-5,X	;being pulled
	STA	DIR	;in the direc-
	LDA	#8	;tion opposite
	SEC		;of cursor
	SBC	DIST	;motion, reverse
	STA	DIST	;its direction!
;
SLIDE	LDX	DIR	;Calculate new
	LDA	CURX	;cursor x coord
	CLC		;and make sure
	ADC	XOFF-5,X	;it is legal...
	TAY
	CMP	#64
	BCC	HOLDIT
	CMP	#185
	BCC	DOY	;Its legal!
;
HOLDIT	LDA	#0	;Stop all motion
	STA	DIST	;if a bad coord
XITMOVE	RTS		;is found.
;
DOY	LDA	CURY	;Calculate new
	CLC		;y coord and
	ADC	YOFF-5,X	;make sure it
	CMP	#71	;is legal...
	BCC	HOLDIT
	CMP	#192
	BCS	HOLDIT
	STA	CURY	;Save new y and
	STY	CURX	;new x, then
	DEC	DIST	;record move
	LDA	#0	;and clear the
	STA	PRESS	;trigger flag
	JMP	DRAWCUR	;Re-draw cursor!
;
;Movement data
;
XOFF	.BYTE	1,1,1,0,$FF,$FF,$FF
	.BYTE	0,0,0
YOFF	.BYTE	1,$FF,0,0,1,$FF,0,0
	.BYTE	1,$FF
OPDIR	.BYTE	10,9,11,0,6,5,7,0
	.BYTE	14,13
;
;-----------------
; TRIGGER HANDLER
;-----------------
;
CHKTRIG
	LDX	TRIG0	;If trigger is
	BEQ	YESCHK	;pressed, the
	DEX		;trigger flag
	STX	PRESS	;is clear, and
NOCHK	RTS		;the cursor is
YESCHK	LDA	DIST	;aligned on a
	BNE	NOCHK	;square, then
	LDA	PRESS	;process it
	BNE	NOCHK
;
	LDX	#1	;Set trigger
	STX	PRESS	;flag
	STX	GENER	;Set generation
	DEX		;to one
	STX	GENER+1	;Calculate scrn
	JSR	CONVERT	;addr of cursor
	SED		;Decimal mode!
	LDA	(PNT1),Y	;If on a space
	BEQ	ADDCELL	;add a cell
;
	LDA	#0	;Remove a cell!
	STA	(PNT1),Y
	LDA	POP	;Subtract (bcd)
	SEC		;one from the
	SBC	#1	;colony popula-
	STA	POP	;tion, max. pop.
	STA	MOST	;and starting
	LDA	POP+1
	SBC	#0
	STA	POP+1
	STA	MOST+1
	LDX	#150	;Go set proper
	BNE	SETSND	;ding sound
;
ADDCELL	LDA	#10	;Add a cell!
	STA	(PNT1),Y
	LDA	POP	;Add 1 to the
	CLC		;colony popula-
	ADC	#1	;tion, max. pop.
	STA	POP	;and starting
	STA	MOST	;pop...
	LDA	POP+1
	ADC	#0
	STA	POP+1
	STA	MOST+1
	LDX	#30	;Go set sound
;
SETSND	CLD		;Decimal off!
	LDA	#15	;Set correct
	STA	SOUND	;add/remove
	STX	TONE	;sound
	JSR	SHOGEN	;Show updated
	JSR	SHOPOP	;cell data...
	JSR	SHOSTRT
	JMP	SHOMOST
;
;----------------------
; COORDINATE CONVERTER
;----------------------
;
;Convert cursor pm coordinates
;to a screen memory address
;
;Call with:
;  curx  - cursor pm x coord.
;  cury  - cursor pm y coord.
;
;Return:
;  pnt1  - base line address
;  y reg - column offset
;
CONVERT
	LDA	CURY	;Convert pm y
	SEC		;coord to board
	SBC	#71	;row number
	LSR	A	;(0 to 15)...
	LSR	A
	LSR	A
	PHA		;Save the result
	STA	PNT1	;and put it into
	LDA	#0	;the work area
	STA	PNT1+1
	LDX	#3	;Now multiply
MULT16	ASL	PNT1	;the column num
	ROL	PNT1+1	;by 20 to
	DEX		;determine the
	BPL	MULT16	;offset from the
	PLA		;beginning of
	ASL	A	;board memory.
	ASL	A	;This takes 2
	CLC		;steps: 1st
	ADC	PNT1	;mult the column
	STA	PNT1	;by 16, then by
	LDA	PNT1+1	;4; now add the
	ADC	#0	;two results and
	STA	PNT1+1	;save the mess!
	LDA	PNT1	;Finally, add
	CLC		;the offset to
	ADC	#<[DISP+100]	;the start
	STA	PNT1	;of board memory
	LDA	PNT1+1	;for the base
	ADC	#>[DISP+100]	;line
	STA	PNT1+1	;address! WHEW!
;
	LDA	CURX	;Convert the
	SEC		;cursor pm x
	SBC	#48	;coord to the
	LSR	A	;column offset
	LSR	A	;from the base
	LSR	A	;line addres,
	TAY		;and put it in
	RTS		;the y reg!
;
;-------------------
; CLEAR/RESET CELLS
;-------------------
;
CLEAR
	LDA	POP+1	;If cell pop. is
	BNE	CLEAROK	;0, then there
	LDA	POP	;is no reason to
	BEQ	XITCLR	;clear them!
;
CLEAROK	LDA	#<BOARD	;If some
	STA	PNT1	;cells exist,
	LDA	#>BOARD	;fill the
	STA	PNT1+1	;16x16 board
	LDX	#15	;area with
CLRROW	LDA	#0	;0s (spaces)...
	LDY	#15
CLRCOL	STA	(PNT1),Y
	DEY
	BPL	CLRCOL
	LDA	PNT1	;Add 20 to cur-
	CLC		;rent screen
	ADC	#20	;address to get
	STA	PNT1	;address of
	LDA	PNT1+1	;next line...
	ADC	#0
	STA	PNT1+1
	DEX
	BPL	CLRROW
;
	JSR	SETCELL	;Reset cell data
	JSR	SHOGEN	;Display new
	JSR	SHOPOP	;cell data...
	JSR	SHOMOST
	JSR	SHOSTRT
XITCLR	RTS		;Return!
;
;-----------------
; CHECK FOR PAUSE
;-----------------
;
;Only the accumulator is used!
;
PAUSE	LDA	CH	;Space bar
	CMP	#33	;pressed?
	BNE	NOPAUSE	;Nope, leave!
	LDA	RTCLOK	;Yes! Save
	PHA		;clock value,
	JSR	QUIET	;shut up, and
	LDX	#39	;save whatever
TCOPY1	LDA	TEXT,X	;text is on
	STA	TSAVE,X	;the message
	DEX		;line...
	BPL	TCOPY1
	LDX	#<PAUSED	;and print a
	LDY	#>PAUSED	;special
	JSR	PRINT	;message
;
PAUZ	LDA	CH	;Wait for
	CMP	#33	;a different
	BEQ	PAUZ	;key.
	LDX	#39	;When one is
TCOPY2	LDA	TSAVE,X	;found, res-
	STA	TEXT,X	;tore the old
	DEX		;message line...
	BPL	TCOPY2
	PLA		;Restore clock
	STA	RTCLOK
NOPAUSE	RTS		;And go back!
;
;Pause message
;
PAUSED	.SBYTE	"                "
	.SBYTE	" Paused"
	.BYTE	EOL
;
;---------------
; DELAY ROUTINE
;---------------
;
;Call with:
;  acc. - # of jiffies to wait
;
;Return a non-0 number if a
;console key aborts the delay
;else return a 0.
;
;Only the accumulator is used!
;
DELAY
	PHA		;Clear RTCLOK...
	LDA	#0
	STA	RTCLOK
DELAY2	PLA		;Wair until time
	CMP	RTCLOK	;is up, or until
	BEQ	TIMESUP	;a console key
	PHA		;is pressed
	JSR	CHKCON
	BEQ	DELAY2
	PLA
	RTS
TIMESUP	LDA	#0
	RTS
;
;-------------------
; MAIN LIFE ROUTINE
;-------------------
;
LIFE
	JSR	INITCON	;Init console
	LDA	POP+1	;If population
	BNE	DOLIFE	;is zero, then
	LDA	POP	;print a message
	BNE	DOLIFE	;saying so and
	LDX	#<MSG1	;exit...
	LDY	#>MSG1
	JMP	DOMSG
;
DOLIFE	LDX	#$FF	;Clear keyboard
	STX	CH
	INX		;Use the first
	STX	CHORD	;chord
NEXTGEN	JSR	SCAN	;Scan board
	LDA	ACTIVE	;If no cells are
	BNE	UNSTAB	;active then the
	LDX	#<MSG5	;population has
	LDY	#>MSG5	;stabilized!
	JMP	DOMSG	;(right Zink?)
UNSTAB	LDX	#<MSG2	;Unsatble, so
	LDY	#>MSG2	;print life
	JSR	PRINT	;message
	JSR	GROWTH	;Regenerate!
	BNE	XITLIFE	;If aborted, bye
	LDA	POP+1	;If new popu-
	BNE	CONT	;lation is 0,
	LDA	POP	;then the colony
	BNE	CONT	;is dead, so
	LDX	#<MSG3	;print a message
	LDY	#>MSG3	;and exit...
	JMP	DOMSG
;
CONT	LDA	MODE	;If in FaST mode
	CMP	#4	;check for pause
	BNE	NOTFST	;or console key
	JSR	PAUSE	;then jump right
	JSR	CHKCON	;into the next
	BEQ	NEXTGEN	;generation
	RTS
;
NOTFST	CMP	#2	;If in Single
	BCC	REGULAR	;Step mode,
SSTEP	LDA	TRIG0	;check for a
	BEQ	NEXTGEN	;trigger press,
	LDX	#<MSG4	;print a message
	LDY	#>MSG4	;to the user,
	JSR	PRINT	;check console
	JSR	CHKCON	;keys, and
	BEQ	SSTEP	;repeat!
	RTS
;
REGULAR	LDA	#0	;If in ReGular
	STA	RTCLOK	;mode, wait 1/2
REGWAIT	LDA	RTCLOK	;a sec while
	CMP	#30	;checking for a
	BCS	NEXTGEN	;pause or a
	JSR	PAUSE	;console key...
	JSR	CHKCON
	BEQ	REGWAIT
	RTS
;
DOMSG	JSR	PRINT	;Print message,
	LDA	#120	;wait a while,
	JSR	DELAY	;and then
XITLIFE	RTS		;exit life!
;
;Life related messages
;
MSG1	.SBYTE	" No cells have bee"
	.SBYTE	"n placed on the boa"
	.SBYTE	"rd"
	.BYTE	EOL
MSG2	.SBYTE	"           Let the"
	.SBYTE	"re be life!"
	.BYTE	EOL
MSG3	.SBYTE	"        The cell c"
	.SBYTE	"olony has died"
	.BYTE	EOL
MSG4	.SBYTE	"   Press trigger f"
	.SBYTE	"or next generation"
	.BYTE	EOL
MSG5	.SBYTE	"     Cell populati"
	.SBYTE	"on has stabilized"
	.BYTE	EOL
;
;-------------------
; PLAYFIELD SCANNER
;-------------------
;
;Return # of active cells in
;ACTIVE and information about
;these cells in CADRL, CADRH,
;and CTYPE
;
SCAN
	LDA	#0	;Clear cell
	STA	ACTIVE	;counter, and
	LDA	#<[BOARD-21]	;move
	STA	PNT1	;board address
	LDA	#>[BOARD-21]	;into
	STA	PNT1+1	;PNT1...
;
	LDA	#15	;Init row index
	STA	ROW
DOROW	LDA	#15	;Init column
	STA	COL	;index
DOCOL	LDA	#0	;Clear counter
	STA	COUNT
	LDX	#7	;Scan 8 times
SEARCH	LDY	SCANADD,X	;Get offset
	LDA	(PNT1),Y	;Is there a
	CMP	#10	;cell here?
	BNE	NOCELL	;No, ignore it!
	INC	COUNT	;Yes, add 1 to
NOCELL	DEX		;the counter and
	BPL	SEARCH	;keep searching!
;
	LDX	COUNT	;If the current
	LDY	#21	;char is a space
	LDA	(PNT1),Y	;with 3 friends
	BNE	ACELL	;then grow a
	CPX	#3	;cell here
	BNE	NOACT
	BEQ	RECORD
ACELL	CPX	#2	;If it is a cell
	BEQ	NOACT	;with 2 or 3
	CPX	#3	;friends, keep
	BEQ	NOACT	;it alive, else
RECORD	INC	ACTIVE	;kill it!
	LDX	ACTIVE	;Record any
	STA	CTYPE,X	;changes that
	LDA	PNT1	;are made to the
	CLC		;cell colony...
	ADC	#21	;(the cell is 21
	STA	CADRL,X	;bytes ahead of
	LDA	PNT1+1	;the current
	ADC	#0	;address in
	STA	CADRH,X	;PNT1)
;
NOACT	LDA	PNT1	;Add 1 to PNT1
	CLC		;so it points
	ADC	#1	;to the next
	STA	PNT1	;board square...
	LDA	PNT1+1
	ADC	#0
	STA	PNT1+1
	DEC	COL	;Loop until 16
	BPL	DOCOL	;cols are done!
	LDA	PNT1	;Add 4 to PNT1
	CLC		;so it points
	ADC	#4	;to the first
	STA	PNT1	;square in the
	LDA	PNT1+1	;next row...
	ADC	#0
	STA	PNT1+1
	DEC	ROW	;Loop until 16
	BPL	DOROW	;rows are done!
	RTS
;
;Scan data
;
SCANADD	.BYTE	0,1,2,20
	.BYTE	22,40,41,42
;
;----------------------
; GROWTH/DEATH HANDLER
;----------------------
;
;Put growth/death characters
;in proper places on board
;
GROWTH
	LDA	MODE	;If in FaST mode
	CMP	#4	;then skip the
	BNE	DOFX	;fancy animation
	JMP	FSTMODE	;and just do it!
DOFX	LDX	#7	;Init the
SETCHAR	LDA	#0	;growth/death
	STA	CHSET+88,X	;chars...
	LDA	CELIMG,X
	STA	CHSET+96,X
	DEX
	BPL	SETCHAR
;
	LDY	#0	;Find all of the
	LDX	ACTIVE	;board locations
PLOT1	LDA	CADRL,X	;where active
	STA	PNT1	;cells or spaces
	LDA	CADRH,X	;are, and place
	STA	PNT1+1	;growth or death
	LDA	CTYPE,X	;characters
	BNE	DYING	;there so we can
	LDA	#11	;animate them...
	BNE	PLOTIT
DYING	LDA	#12
PLOTIT	STA	(PNT1),Y
	DEX
	BNE	PLOT1
;
;Now animate the growing and
;dying cells along with sound
;effects if the current mode
;permits.
;
	LDX	#7	;Handle 8 frames
	STX	TEMP
GROW	LDX	TEMP	;Get growth
	LDY	GROIMG,X	;image # and
	LDX	#0	;copy the image
GROANIM	LDA	IMAGES,Y	;into
	STA	CHSET+88,X	char 11...
	INY
	INX
	CPX	#8
	BNE	GROANIM
	LDX	TEMP	;Get death
	LDY	DIEIMG,X	;image # and
	LDX	#0	;copy the image
DIEANIM	LDA	IMAGES,Y	;into
	STA	CHSET+96,X	;char 12...
	INY
	INX
	CPX	#8
	BNE	DIEANIM
;
	LDA	MODE	;If mode does
	BEQ	DOCHORD	;not allow sound
	CMP	#2	;then skip the
	BNE	TIMEOUT	;sound routine
DOCHORD	LDX	CHORD	;otherwise
	LDA	NOTE1,X	;generate the
	STA	AUDF1	;appropriate
	LDA	NOTE2,X	;3 note chord...
	STA	AUDF2
	LDA	NOTE3,X
	STA	AUDF3
	LDA	TEMP	;Set volume and
	CLC		;distortion
	ADC	#$A1	;(same for all 3
	STA	AUDC1	;channels)...
	STA	AUDC2
	STA	AUDC3
;
TIMEOUT	LDA	#0	;Now wait a
	STA	RTCLOK	;short while
SLEEP	LDA	RTCLOK	;Get clock
	CMP	#4	;Time up?
	BCS	GROMORE	;Yes!
	JSR	PAUSE	;No, check pause
	JSR	CHKCON	;and console key
	BEQ	SLEEP	;and loop!
	JSR	QUIET	;A console key
	LDA	#1	;is pressed so
	PHA		;set return
	BNE	REPLOT	;value to 1
;
GROMORE	DEC	TEMP	;Do all frames
	BPL	GROW	;and when done
FSTMODE	LDA	#0	;set return
	PHA		;value to 0
;
;Update board and cell data
;
REPLOT	LDY	#0
	SED		;Decimal mode!
PLOT2	LDX	ACTIVE	;Get the
	LDA	CADRL,X	;address of each
	STA	PNT1	;of the active
	LDA	CADRH,X	;cells and put
	STA	PNT1+1	;it into PNT1
	LDA	CTYPE,X	;Get cell type
	BNE	DODIE	;Cell is dying!
	LDA	#10	;Its growing so
	STA	(PNT1),Y	;show a fully
	LDA	POP	;grown cell and
	CLC		;add one to the
	ADC	#1	;cell population
	STA	POP	;(in decimal
	LDA	POP+1	;mode of course)
	ADC	#0
	STA	POP+1
	CMP	MOST+1	;If the cell pop
	BEQ	CKMOST	;is greater than
	BCC	PLOTNXT	;(or=to) the
CKMOST	LDA	POP	;highest pop so
	CMP	MOST	;far, then copy
	BCC	PLOTNXT	;POP into MOST..
NEWMOST	LDA	POP
	STA	MOST
	LDA	POP+1
	STA	MOST+1
	JMP	PLOTNXT
DODIE	LDA	#0	;Its dying so
	STA	(PNT1),Y	;plot a blank
	LDA	POP	;space and
	SEC		;subtract 1 from
	SBC	#1	;the population
	STA	POP
	LDA	POP+1
	SBC	#0
	STA	POP+1
PLOTNXT	DEC	ACTIVE	;Loop til
	BNE	PLOT2	;ACTIVE is 0!
;
XITGRO	JSR	QUIET	;No sound!
	LDA	GENER	;Add 1 to
	CLC		;generation (we
	ADC	#1	;are still in
	STA	GENER	;decimal mode)
	LDA	GENER+1
	ADC	#0
	STA	GENER+1
	CLD		;No decimal!
	LDX	CHORD	;Add 1 to chord
	INX		;number making
	CPX	#6	;sure it is not
	BNE	CHORDOK	;greater than
	LDX	#0	;5...
CHORDOK	STX	CHORD
	JSR	SHOGEN	;Show new cell
	JSR	SHOPOP	;data...
	JSR	SHOMOST
	PLA		;and return the
	RTS		;correct value!
;
;Regeneration image data
;
GROIMG	.BYTE	0,8,16,24
	.BYTE	32,40,48,56
DIEIMG	.BYTE	56,48,40,32
	.BYTE	24,16,8,0
;
IMAGES	.BYTE	0,0,56,126
	.BYTE	126,60,24,0
;
	.BYTE	0,0,56,124
	.BYTE	124,56,24,0
;
	.BYTE	0,0,56,124
	.BYTE	124,24,0,0
;
	.BYTE	0,0,24,60
	.BYTE	60,24,0,0
;
	.BYTE	0,0,0,60
	.BYTE	60,24,0,0
;
	.BYTE	0,0,0,56
	.BYTE	56,24,0,0
;
	.BYTE	0,0,0,56
	.BYTE	56,0,0,0
;
	.BYTE	0,0,0,24
	.BYTE	24,0,0,0
;
;Chord data
;
NOTE1	.BYTE	243,230,217
	.BYTE	204,193,182
NOTE2	.BYTE	121,114,108
	.BYTE	102,96,91
NOTE3	.BYTE	60,57,53
	.BYTE	50,47,45
;
;---------------------
; INTRO & TITLE STUFF
;---------------------
;
;Do quickie intro
;
TITLE
	JSR	INITCON	;Init console
	LDA	#0	;Clear colors...
	STA	COLOR1
	STA	COLOR2
	STA	COLBAK
	LDA	#<IDL	;Point to intro
	LDX	#>IDL	;display list...
	STA	SDLSTL
	STX	SDLSTL+1
	LDA	#60	;Wait a sec...
	JSR	DELAY
	BNE	GOTOIT
	LDX	#9	;"Fade on" the
FADEON	INC	COLOR1	;magazine
	LDA	#1	;credits...
	JSR	DELAY
	BNE	GOTOIT
	DEX
	BPL	FADEON
	LDA	#120	;Let it hang
	JSR	DELAY	;around for a
	BNE	GOTOIT	;sec, then
	LDX	#9	;fade to black..
FADEOFF	DEC	COLOR1
	LDA	#1
	JSR	DELAY
	BNE	GOTOIT
	DEX
	BPL	FADEOFF
	LDA	#60	;Pause a little
	JSR	DELAY	;before showing
	BNE	GOTOIT	;the title
;
;Display title screen
;
	LDX	#3	;Set-up the
CLOAD	LDA	TCOLORS,X	;proper
	STA	COLOR0,X	;title screen
	DEX		;colors...
	BPL	CLOAD
	LDA	#<TDL	;Install the new
	LDX	#>TDL	;display list...
	STA	SDLSTL
	STX	SDLSTL+1
	LDA	#127	;Turn on cell
	STA	VBICTL	;animation
TWAIT	JSR	CHKCON	;and wait for
	BEQ	TWAIT	;a console key!
GOTOIT	RTS		;AHHhhhhh.
;
;Intro display list
;
IDL	.BYTE	112,112,112
	.BYTE	112,112,112,112,112
	.BYTE	112,112,112,112,112
	.BYTE	112
	.BYTE	66
	.WORD	ISCRN
	.BYTE	65
	.WORD	IDL
;
;Intro screen data
;
ISCRN	.SBYTE	"       Analog Com"
	.SBYTE	"puting presents    "
	.SBYTE	"    "
;
;Title screen display list
;
TDL	.BYTE	112,112,112
	.BYTE	112,112,112
	.BYTE	70
	.WORD	TSCRN
	.BYTE	6,6,6,6,6
	.BYTE	112
	.BYTE	6
	.BYTE	112,112
	.BYTE	6,7
	.BYTE	112,112,112
	.BYTE	6
	.BYTE	65
	.WORD	TDL
;
;Title screen data
;
TSCRN	.BYTE	0,0,10,0,0,0,0,10,0
	.BYTE	10,10,10,10,0,10,10,10
	.BYTE	10,0,0
;
	.BYTE	0,0,74,0,0,0,0,74,0,74
	.BYTE	0,0,0,0,74,0,0,0,0,0
;
	.BYTE	0,0,10,0,0,0,0,10,0,10
	.BYTE	10,10,0,0,10,10,10,0,0
	.BYTE	0
;
	.BYTE	0,0,74,0,0,0,0,74,0,74
	.BYTE	0,0,0,0,74,0,0,0,0,0
;
	.BYTE	0,0,10,0,0,0,0,10,0,10
	.BYTE	0,0,0,0,10,0,0,0,0,0
;
	.BYTE	0,0,74,74,74,74,0,74,0
	.BYTE	74,0,0,0,0,74,74,74,74
	.BYTE	0,0
;
	.SBYTE	+128,"  IN THE FAST "
	.SBYTE	+128,"LANE  "
	.SBYTE	"     CREATED BY    "
	.SBYTE	" "
	.SBYTE	+128,"    JAMES  HAG"
	.SBYTE	+128,"UE    "
	.SBYTE	+64,"    PRESS  STAR"
	.SBYTE	+64,"T    "
;
;Title screen colors
;
TCOLORS	.BYTE	$46,$1A,$96