A.N.A.L.O.G. ISSUE 55 / MARCH 1987 / PAGE 45
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.
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.
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.
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.
○ | |||||||
○ | ○ | ○ | ○ | ||||
○ | |||||||
○ |
○ | ○ | ||||||
○ | ○ | ||||||
○ | ○ | ||||||
○ | ○ | ||||||
○ | ○ | ||||||
○ | ○ | ||||||
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.
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.
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.
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,3 8,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,19 9,2,76,98,228,32,101,228,32,6916 1040 DATA 86,32,169,0,133,12,169,32,13 3,13,162,255,134,128,134,133,7714 1050 DATA 232,134,132,160,22,162,32,16 9,7,76,92,228,169,3,141,15,4409 1060 DATA 210,169,0,141,8,210,141,1,21 0,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,1 69,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,1 1,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,2 40,0,0,0,134,129,1337 1140 DATA 132,130,160,0,177,129,201,25 5,240,6,153,184,13,200,208,244,3222 1150 DATA 169,0,192,40,176,6,153,184,1 3,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,1 65,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,1 89,97,33,153,0,12,200,189,5649 1220 DATA 102,33,153,0,12,96,114,114,1 15,115,102,103,103,115,115,115,5250 1230 DATA 110,113,110,113,116,169,0,13 3,142,141,47,2,32,132,33,32,1506 1240 DATA 148,33,32,169,33,32,237,34,1 69,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,1 2,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,1 57,166,13,160,0,169,69,145,5537 1310 DATA 129,160,17,169,68,145,129,16 5,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,14 1,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,1 11,110,0,51,116,97,114,116,105,4532 1400 DATA 110,103,0,0,0,0,45,111,115,1 16,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,1 69,138,141,22,208,141,10,4704 1430 DATA 212,169,136,141,23,208,169,1 80,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,14 1,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,15 7,0,5,157,0,6,157,0,28 1490 DATA 7,232,208,241,169,0,141,7,21 2,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,2 31,162,3,189,82,35,157,0,208,8684 1530 DATA 202,16,247,96,204,204,204,20 4,204,204,204,204,51,51,51,51,9719 1540 DATA 51,51,51,51,64,96,128,160,23 0,133,208,23,173,10,210,41,7281 1550 DATA 15,10,10,10,10,133,134,173,1 0,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,2 4,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,2 4,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,2 38,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,2 4,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,16 2,3,165,145,157,4,208,24,6970 1690 DATA 105,2,202,16,247,96,0,231,12 9,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,3 2,216,32,169,127,133,146,169,9483 1730 DATA 120,133,145,32,36,36,32,74,3 6,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,12 7,133,128,32,86,32,32,227,34,5201 1780 DATA 96,106,144,6,169,0,133,152,2 40,201,165,152,208,197,169,10,1502 1790 DATA 133,152,166,142,232,224,5,20 8,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,1 25,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,1 69,0,133,151,96,165,146,24,6728 1870 DATA 125,115,37,201,71,144,241,20 1,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,25 5,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,23 3,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,13 3,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,1 29,169,12,133,130,162,15,169,0,6306 2020 DATA 160,15,145,129,136,16,251,16 5,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,1 3,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,9 6,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,20 8,7,162,149,160,39,76,70,39,5960 2150 DATA 165,142,201,4,208,9,32,105,3 8,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,2 0,165,20,201,30,176,168,32,6911 2180 DATA 105,38,32,87,36,240,242,96,3 2,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,9 9,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,11 4,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,13 3,153,169,81,133,129,169,12,133,8610 2310 DATA 130,169,15,133,155,169,15,13 3,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,3 2,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,15 6,16,175,165,129,24,105,4,133,6406 2370 DATA 129,165,130,105,0,133,130,19 8,155,16,154,96,0,1,2,20,1696 2380 DATA 22,40,41,42,165,142,201,4,20 8,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,2 24,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,1 62,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,2 0,201,4,176,16,32,105,38,3370 2480 DATA 32,87,36,240,242,32,86,32,16 9,1,72,208,7,198,131,16,5917 2490 DATA 146,169,0,72,160,0,248,166,1 53,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,1 33,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,15 7,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,1 6,8,0,0,0,56,126,7474 2580 DATA 126,60,24,0,0,0,56,124,124,5 6,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,2 4,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,3 6,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,7 4,74,0,0,128,8938 2830 DATA 128,169,174,128,180,168,165, 128,166,161,179,180,128,172,161,174,49 21 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,11 6,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
.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