Official result Game of Life -contest

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
Dr beep
Manic Miner
Posts: 381
Joined: Mon Oct 01, 2018 8:53 pm

Official result Game of Life -contest

Post by Dr beep »

In december I started a contest to make a version of Game of Life
on the ZX Spectrum in the shortest code possible.

The contest ran until Easter 2024.

The rules for the sizecoding contest
1) The rules of GAME OF LIFE must be followed:
a) Any live cell with fewer than two live neighbours dies, as if by underpopulation.
b) Any live cell with two or three live neighbours lives on to the next generation.
c) Any live cell with more than three live neighbours dies, as if by overpopulation.
d) Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
2) The size of the code counts. If your code uses ROM-routines only the CALL to the routine counts
Example : CALL #DAF = 3 bytes for CLS RST 16 = 1 byte for print
3) All tricks are allowed, like using the value of BC after the USR-command that holds the startaddress,
decompressing code etc...
4) The program must have some kind of editor to set/reset colonies.
5) After starting the game the game keeps running until a key is pressed to stop.
6) (symbol) shift can be skipped as a valid keypress to stop the game.
7) After stopping the game you return to the editor.
8) There is a keycombination to stop the game and clear the screen.
9) There is a keycombination to stop the game and NOT clear the screen.
10) The screen is at least 32x24 in size.
11) The screen goes around on same line/colom. A glider will keep moving and reappear on the opposite site
of the screen it went out.
12) Deadline is 2nd Easter 23:59 CET.
13) Sent your game (source and TAP/Z80) to [email protected]
14) DO NOT TELL OTHERS THE SIZE OF YOUR CODE!
15) You can always update your game when you made it shorter.
16) After the contest all contesters are mentioned in a rankinglist
17) All games will be published too.

The contest had 2 participants who sent in their program

Tom Dalby 166 bytes
Peter Featherstone 333 bytes

So the winner of the contest is Tom Dalby, but how did he do it?
He had a program working following the rules but he used rule 4 in the most shortened way.
He doubted his solution so he sent in 2 versions, 1 with a full editor and second with THE MOST TERRIBLE EDITOR POSSIBLE!
His second editor only moves right and moves over the screen to the next line when at end. At the end of the screen it returns
to first field at top. So when you make a mistake you need to scroll the entire screen. Incredibly userunfriendly, but
it is SOME KIND OF EDITOR that works within the rules.

Peter, like Tom, also used the sysvar LASTK to read the keys. Rule 6 was added to make the use of this variable possible
since symbol shift and shift are not stored with this variable. He could have won A LOT OF BYTES by deleting the randomize-option.
This was not a rule. However... even with skipping the randomize option the code would still be larger than Tom's version
so Tom is the definitive winner.

I will add my own version too. I made a version in 148 bytes WITH A REASONABLE EDITOR but unlike Tom and Peter
I not only used the attributefile for display but I also stored the information about each cell in the attributefile itself.

Have fun with the sent in programs.

https://www.mediafire.com/file/ghsvrry5 ... t.zip/file


Johan "Dr Beep" Koelman
User avatar
TomD
Manic Miner
Posts: 379
Joined: Tue Nov 13, 2018 9:47 am
Location: Leeds UK
Contact:

Re: Official result Game of Life -contest

Post by TomD »

Thanks for sharing the code was a fun compo. If anybody is remotely interested this was my best effort with a "good" editor and a frame iteration counter, a whopping 217bytes :-)

TomD

Code: Select all

; --------------------------------------------------------------------------------------------
; Game of Life 32x24
; includes editor & iteration counter
; 217bytes
; --------------------------------------------------------------------------------------------
; Rules:
;   1) Any live cell with fewer than two live neighbours dies, as if by underpopulation.
;   2) Any live cell with two or three live neighbours lives on to the next generation.
;   3) Any live cell with more than three live neighbours dies, as if by overpopulation.
;   4) Any dead cell with exactly three live neighbours becomes a live cell, as if by
;      reproduction.
; --------------------------------------------------------------------------------------------
ROM_LKEYP EQU 0x5C08 ; SysVar for last key pressed
MEM_ATTR  EQU 0x5800 ; screen ATTR start
MEM_DATA  EQU 0x7800 ; buffer start
ROM_PRINT EQU 0x203C
LIVECELL EQU 0x11
DEADCELL EQU 0x38
org 0x7700
; --------------------------------------------------------------------------------------------
; editor
;   Keys (uses Sinclair 2 joystick layout):
;   - '1' left, '2' right, '3' down, '4' up 
;   - '5' toggle cell on/off
;   - '6' clear board
;   - '0' start simulation
; --------------------------------------------------------------------------------------------
_main:
	ld b,6
	ld hl,_txt+3
_clrtxt:
	ld (hl),'0'
	inc hl
	djnz _clrtxt
	call 0xdaf ; ROM CLS routine
	ld h,MEM_ATTR/256 ; hl=MEM_ATTR (l already 0x00 after CLS)
	ld d,MEM_DATA/256 ; de=MEM_DATA (e always 0x00 after CLS)
	jr _onclear ; on clear just clear buffer using screen as screen already correct
_editor: 
	ld de,_txt
	ld bc,9
	call ROM_PRINT
_txtdone:
	ld hl,MEM_DATA
	ld de,MEM_ATTR
_onclear:
	ld bc,768
	ldir
; hl=0x7b00, de=0x5b00, bc=0x0000
_keypress:
	halt ; needed as ROM routine doesn't properly register keypress without it
	ld hl,ROM_LKEYP
	ld a,(hl)
	sub '0'
	jr z,_simulation
	ld (hl),0x00 ; clear last key press
_cursor: 
	ld hl,MEM_ATTR ; modified elsewhere in code
	set 7,(hl) ; flashing cursor
	ld de,-1 ; de=0xffff
	dec a
	jr z,_movecursor ; '1' left?
	inc de
	inc de ; de=0x0001
	dec a
	jr z,_movecursor ; '2' right?
	ld e,32	; de=0x0020
	dec a
	jr z,_movecursor ; '3' down?	
	ld de,-32 ; de=0xffe0
	dec a	
	jr nz,_nomove ; '4' up? (if remove up/down cursor movement can save another 11bytes, left/right can reach all cells but would be slow)
_movecursor: 
	call _yadder ; use routine from simulation, some redundant code but saves space
	ld (_cursor+1),hl
	jr _txtdone ; redraw screen to clear old cursor
_nomove: 
	dec a
	jr nz,_notoggle ; '5' toggle cell?
	set 5,h	; move to buffer memory
	ld a,(hl)
	xor %00101001 ; toggle cell on/off
	ld (hl),a
	jr _txtdone ; redraw screen to show new cell
_notoggle: 
	dec a
	jr z,_main ; '6' clear and start again?
	jr _keypress ; not a valid key so just loop to get next key press
; --------------------------------------------------------------------------------------------
; main simulation loop
;   - '1' - '4' will stop simulation and move cursor as per editor
;   - '5' will stop simulation and toggle cell on/off at last cursor pos
;   - '6' will stop simulation and clear
;   - '0' will keep simulation running i.e. does nothing
;   any other key will stop simulation and enter editor with cursor at last position
; --------------------------------------------------------------------------------------------
_simulation: 
	ld hl,MEM_ATTR 
_checkneighbours: 
	push hl	
	ld bc,0x1f00 ; b=0x1f for use later & reset counter
	call _ydec
	call _xdec
	call _yinc
	call _yinc
	call _xinc
	call _xinc
	call _ydec
	call _ydec ; c=count of live cells 0-8
	pop hl	
	call _addcell ; add in current cell
	ld a,c
	sub 3
	ld c,LIVECELL
	jr z,_updatecell ; 3 -> live	
	dec a
	jr z,_nochange ; 4 -> stay the same
	ld c,DEADCELL ; everything else -> dead
_updatecell:
	set 5,h	; move to buffer memory from screen
	ld (hl),c
	res 5,h ; move back to screen
_nochange:
	inc hl ; next cell to check
	ld a,h
	cp (MEM_ATTR/256)+3 ; if at end of board then stop checking and start next simulation loop
	jr nz,_checkneighbours
	ld hl,_txt+8 ; update counter
_addit:
	inc (hl)
	ld a,(hl)
	cp '9'+1
	jp nz,_editor
	ld (hl),'0'
	dec hl
	jr _addit
_xinc: 
	inc hl ; x+1
	ld a,l
	and b
	jr z,_ydec ; if over right boundary wrap to left
_addcell: 
	bit 0,(hl) ; live cell?
	ret z
	inc c ; if so add 1
	ret
_xdec: 
	dec hl ; x-1
	ld a,l
	and b
	cp b
	jr nz,_addcell ; if over left boundary wrap to right
_yinc: 
	ld de,32 ; y+1
_yadder:
	add hl,de
	ld a,h
	cp (MEM_ATTR/256)+3
	jr nz,_ytopcheck ; if over bottom boundary wrap to top
	ld h,MEM_ATTR/256
_ytopcheck:
	cp (MEM_ATTR/256)-1
	jr nz,_addcell
	ld h,(MEM_ATTR/256)+2
	jr _addcell		
_ydec: 
	ld de,-32 ; y-1
	jr _yadder
_txt:
	defb 22,0,13
Retro enthusiast and author of Flynn's Adventure in Bombland, The Order of Mazes & Maze Death Rally-X. Check them out at http://tomdalby.com
Post Reply