Programs: RMife.z80, RMlife2.z80, RMlife2s.z80
Conway's Game of Life is an example of what is known as a two dimensional cellular automaton.
I first came across the concept in my pre-Spectrum days. Starting with a pattern on a piece of grid paper, and using some simple rules, a new pattern could be generated on a fresh grid, and the process repeated as required, often with quite startling results. For example, there is a class of shapes called 'gliders' that can move across the grid. One such shape is shown above. Also, a class of shapes called 'glider guns' that shoot out gliders.
The rules are: for each cell on the grid, the next state can be determined by adding up the number of blocked in or 'on' cells that surround it to the left and right, above and below, and diagonally.
If this number is less than 2,then it is 'off'.
If it is 2, then the state is unchanged.
If it is 3 then it is 'on'. If it is more than 3, it is 'off.'
A parallel in ecosystems is that a population will decline if the density is too low to support reproduction, and will decline also if it is too high to be supported by available resources.
Obviously, doing this by hand is very, very slow and once I had my own Spectrum+, it seemed an ideal project. In the first program, in RMlife.z80, the user is prompted to enter the first configuration on a yellow grid of 20 cells square. The cursor keys are used to move around the grid, and the letter 'p' is used to toggle a cell on and off. On pressing 'enter', the next state of the grid is displayed, and the user is prompted to decide if the process should be continued. The program is written entirely in BASIC. To list it, hit the 'k key, to run it, hit the 'r' key, and to interrupt it when running, hit the space bar while holding the 'Shift' key. The program runs very slowly, however.
The second program, in RMlife2.z80, uses BASIC code to take input from the user, as before, but the next state is determined by a routine in machine code that I first had to write in assembly language. While this was new to me, I felt familiar with the concept of moving data between registers, having programmed a Diehl calculator at school some years before. I used ZEUS assembler software from Crystal Computing and an excellent book called Learn and Use Assembly Language on the ZX Spectrum by Tony Woods. I converted the routine one chunk of logic (e.g. a loop, a conditional statement) at a time, referring to the book for guidance. One point of note is that I needed to multiply two 8 bit numbers together in a subroutine, but the z80 doesn't have its own operation to do this, so I had to code it myself, using a method called 'shift and add'! Anyway, the new program ran much faster than the original, although please note that there is now a delay of a few seconds at the start before the user is prompted for the initial configuration.
The assembled routine was loaded with the first statement of the BASIC program: LOAD "" CODE . This had already been done when I first saved the program and the step has now been commented out.
The routine is run at line 410 in the BASIC program: RANDOMIZE USR 50002, where 50002 is its location in memory.
Looking at this again, I think I should replace the bounded screen with an unbounded 'doughnut', e.g. a glider moving to the right should reappear at the left after hitting the edge of the screen and at the top after hitting the bottom. I'll add this to my to-do list.
The source assembly language code is provided for reference, along with ZEUS, in image RMlife2s.z80. Ideally I wouldn't have included ZEUS, but I couldn't see any other way to make the source code readily visible.