A Z80 Sandbox Competition Game in which developers can write bots to compete on the most efficient algorithm to be King Of The Grid!
game.mp4
Example of a single competition.
- See rules.cpp for exact rules (how often, what values etc).
- World size: 32x32 cells
- Two bots (or programs) spawn in top-left and bottom-right corners
- Each bot has a set of energy. See rules.cpp for exact values.
- Bots run on Z80 CPU. See CPUs section.
- Food (static) and prey (moves) are spawned periodically.
- Food is not spawned evenly: random noise is applied using FastNoiseLite on rules described on seasons.cpp
- Both can move around, eat, scan environment and clone themselves. See bot_api.h
- Bot that survives the longest, wins.
- If both bots survive for too long, it's a draw.
Web version can be built with Emscripten framework.
make kotg-web
cd bin
python3 -m http.server 8000
# Open http://localhost:8000/kotg.html in browser
- Have
cmake
andgcc
installed. git submodule update --init --recursive
- Do
make
- To test an example bot do
make testbot
. This example runs the bot against itself.
Go into folder with two (or one) of your programs, they must have .bin
extension.
Run: kotg <program1> [<program2>] [<seed>]
.
Game outputs files recording-xxx.txt
, which you can play with asciinema:
asciinema play recording-xxx.txt
# or, to share the game on the web
asciinema upload recording-xxx.txt
Export KOTG_AUTOPLAY=1
to play results automatically.
Export KOTG_AUTOUPLOAD=1
to upload them automatically with a review URL.
Have all your programs (2+) placed into current folder.
Run kotg
In this mode, each pair of programs will play against one another twice on the same seed. That way both bots have a chance.
This process is deterministic too. You can specify MASS_SEED
environment variable with seed
from previous play out and have the process repeated exactly for debugging purposes.
Any game session can be replicated. Given a session outcome AAA BBB 1338, you can just pass these arguments to kotg and play the game again.
Every game is deterministic: given two programs and a seed, it will play out exactly the same. That way, when you loose in a mass session, you can replicate the session with your target in order to adjust to your opponent's behavior.
- Each bot runs on a Z80-equipped virtual machine, with limited Z80-ticks per game tick. So if your bot thinks a lot, it is going to be outrun.
- Bots can perform action according to API. See bot_api.h
printf
is supported for debugging.- Each action consumes energy.
- When bot decides to take action, execution stops until action is done.
- Program address starts at address 0, and program can be of size of up to 65536
- Last 8192 (0xE000 - 0xFFFF) of memory are potentially SHARED across all bots, if enabled. That way they can communicate.
- Bots can clone (or fork) themselves in order to spread, fork-bomb style, or hibernate to preserve energy.
By default, bots do not have shared memory between themselves, e.g. every instance has 0x0000 - 0xFFFF memory all
to itself. If bot calls bot_enable_shared_memory()
, last 8192 bytes (0xE000 - 0xFFFF) of its memory becomes sharable.
- Any write to addresses 0xE000 - 0xFFFF will be stored for all bots that have enabled shared memory.
- Any read will return shareable memory – potentially written by other instances of a bot.
Keep in mind, that
- When shared memory is enabled, "local" memory region 0xE000 - 0xFFFF is lost, therefore shared memory shall be enabled as soon as possible.
- If your stack pointer (SP) is located in that region – which is typically default – you will see unexpected issues, therefore take care to set SP to 0xE000 on init. On z88dk, this is done using "-pragma-define=REGISTER_SP=57344", on sdcc you will need to have a custom crt0. (which sdcc-backend does).
- By default, shared memory is initialized with zeros.
Memory Region | Description, when shared memory is enabled. |
---|---|
0x0000 - 0xDFFF | Program memory (including stack) |
0xE000 - 0xFFFF | Shared memory across all friendly bots |
-
Install sdcc (Mac:
brew install sdcc
Ubuntu:sudo apt install sdcc
Windows: here) -
Include
bot_api.h
andsdcc-backend.asm
from bot-api folder in your project. -
See example bot for an example on how to build with SDCC.
-
Do
make
, or run the following script:sdasz80 -o sdcc-backend.rel sdcc-backend.asm sdcc -mz80 --no-std-crt0 test_bot.c sdcc-backend.rel -o test-bot-sdcc.ihx objcopy --input-target=ihex --output-target=binary test-bot-sdcc.ihx test-bot-sdcc.bin
-
Download z88dk or install z88dk from sources:
# dependencies on Ubuntu sudo apt install -y cmake git build-essential libxml2 libxml2-dev m4 perl # dependencies on Mac brew install gmp libxml2 pkgconf # add the following to your bashrc # export CFLAGS="-I/opt/homebrew/include" # export LDFLAGS="-L/opt/homebrew/lib" git clone --recursive https://github.com/z88dk/z88dk.git cd z88dk # takes a while (10+m) ./build.sh -p zx ./build.sh -k -p test sudo make install
-
Include
bot_api.h
andz88dk-backend.asm
from bot-api folder in your project. -
See example bot for an example on how to build with C and z88dk. It uses CMake, but you can build with just zcc:
zcc +test z88dk-backend.asm <program>.c -o mybot.bin
-
If you prefer assembly, see section below.
Have the following example.c
and copy bot_api.h
and z88dk-backend.asm
into your folder.
#include "bot_api.h"
#include <stdio.h>
int main()
{
bot_move_right();
bot_move_left();
}
Then simply do:
zcc +test z88dk-backend.asm test_bot.c -o example.bin
- Make sure your code has base address (
.ORG
) of 0. - For communication, see below.
- Other than that, your bot can do whatever!
See z88dk-backend.asm on how bot interacts with the world.
To call a system call, load call number into register a A
and them do
defb $ED, $FE
This is an illegal z80 instruction that emulator will understand and stop exection to process
your input. Both input (like energy) and output are taken/returned into argument HL
.
See line 10 for exact syscall codes.
To print a character, do syscall 1
:
ld a, 1
ld l, 'H'
defb $ED, $FE
printf
s are supported- GDB support can be added if project kicks off.