Algorithmic Games is a platform for competitive programming and match making between algorithms. Users can make their own participants to compete in any of the existing arenas, or make their own custom arena and challenge other users to join. Algorithmic Games was previously known as "AI-Tournaments", where "AI" in the name refers to playing against the computer on old video games, like "Hard AI" or "Hard CPU".
See the section Participate if you want to join an arena, then analyze how others have solved the arena until better documentation has been written.
If you want to join the discussions, head on over to the Community handbook and read where we are.
To join an arena, create a public GitHub repository from the participant template and add three topics:
AlgorithmicGamesAlgorithmicGames-Participant- The arena you are entering, written as
Owner--Repository(replace the slash in the arena’s GitHub name with two hyphens). ForAlgorithmicGames/Arena-Kalahathat isAlgorithmicGames--Arena-Kalaha.
Put your algorithm in a file named participant.js in the repository root.
If you tag a repository AlgorithmicGames-retired, it will no longer show up in the participant list.
Name shown in matches. The label comes from your GitHub repository name (your account plus the repo name), not from a separate title field. Naming the repository Easy under your account is enough; in Kalaha it would show as something like YourAccount/Easy.
It's possible to use prefix AlgorithmicGames-Participant{-ArenaName}- on your repository names so your participant repos sort together on GitHub (AlgorithmicGames-Participant-Kalaha-Easy, AlgorithmicGames-Participant-Kalaha-Random, and so on). That prefix is only for your own organization. On the arena page the site trims the shared part for that arena, so ChrisAcrobat/AlgorithmicGames-Participant-Kalaha-Easy can appear as ChrisAcrobat/Easy instead of having multiple participants named AlgorithmicGames-Participant-Kalaha-.
To publish a new arena on the site, create a public GitHub repository. Good examples are Arena-Worm and Arena-Kalaha.
Your repository needs at least:
arena.js, which defines the game rulesproperties.json, which describes settings, team limits, and where the replay page lives- Optional folders
replay/andinterface/for watching matches and human play
Add the topics AlgorithmicGames and AlgorithmicGames-Arena-v1, then create a GitHub release. The site loads published arenas from the latest release, not from an unpublished branch.
When others write participants for your arena, they use your arena topic in the same Owner--Repository form (for example YourName--My-Arena).
Use this while building an arena or participant before everything is ready to be discovered on the site.
On the Setups page you can paste URLs to your arena, replay page, and participants or human interfaces (typically raw.githubusercontent.com links to files in your GitHub repositories) and run test matches.
Your code can use console.log, console.warn, console.error, console.info, console.debug, and console.table. During normal matches those messages are ignored. In Setups, choose the participant-with-console type if you want console output saved in the match log while testing.
Setups fields
| Key | Description | Example |
|---|---|---|
| arena.url | Link to the arena files.arena.js , but to it's parent. |
"https://raw.githubusercontent.com/AlgorithmicGames/Arena-Worm/<release-tag>/" |
| arena.name Optional |
Name shown in the list. Defaults to the URL if empty. |
"Arena-Worm" |
| arena.replay | Link to the replay page. | "https://raw.githubusercontent.com/AlgorithmicGames/Arena-Worm/<release-tag>/replay/" |
| arena.settings Optional |
Starting settings for the match. | {"general":{"seed":"example"}} |
| joinables | Who joins the test match. Each entry is a participant URL, or an object with url and optional name, team, color, and type. |
["https://raw.githubusercontent.com/YourAccount/Your-Participant/main/participant.js",{"url":"https://raw.githubusercontent.com/AlgorithmicGames/Arena-Worm/<release-tag>/interface/","name":"Human","type":"interface","team":1}] |
Setups also offers extra controls to help you test and debug before release.
Each entry in joinables is either a participant URL or an object with a type field:
type |
Meaning |
|---|---|
participant |
Default. Loads participant.js the same way as on the live site. |
participant-with-console |
Same as participant, but saves console.* output to the match log while testing. |
un-sandboxed-participant (not yet supported) |
Old Setups label only. Your code still runs in the same isolated environment as other participants. |
interface |
Opens a web page on your computer for a human player. Uses InterfaceHelper.js. |
interface-p2p |
Human player joins from their own browser. You get a shareable link (and QR code) they open at /join; the interface page does not open automatically on your computer. |
You put your algorithm in participant.js in your repository (Participant template). The arena loads that file when you join a match.
Your script talks to the arena with onmessage and postMessage. The first message is usually setup: settings, opponents, and similar data. After that, each message is something the arena wants you to act on (often in message.data). Reply with postMessage(...) when you are done thinking; the match waits for that answer before it moves on.
A common pattern is to handle setup once, then handle every later message the same way:
onmessage = (init) => {
// use init once (settings, opponents, …)
onmessage = (message) => {
const data = message.data
postMessage({/* your reply */})
}
}You can keep variables in your file between messages if you need to remember state from one turn to the next.
An interface is a normal web page for human players or custom graphics. It uses InterfaceHelper.js instead of participant.js.
Arenas can list built-in human interfaces in properties.json under header.defaultHumanInterfaces (see Kalaha and Worm). In Setups, set "type": "interface" or "interface-p2p" on the joinable entry.
When the page is ready, the match sends settings and opponent information. Game messages arrive on worker.onMessage; reply with message.respond(...). If the arena adds another worker on the same page, your workerAdded callback runs again. When a worker is removed, worker.onKilled runs.
Load InterfaceHelper.js, register your handlers, then tell the match you are ready:
InterfaceHelper.onInit((init, workerAdded) => {
const settings = init.settings
const opponents = init.opponents
workerAdded((worker) => {
worker.onMessage = (message) => message.respond({/* … */})
worker.onKilled = () => {/* slot torn down */}
})
})
InterfaceHelper.signalReady()Read here.
The arena.js and participant.js optional file header has to be valid JSON otherwise it is omitted. The header can be placed anywhere in the file, but at the top is recommended as a standardization.
/**
{}
**//**{}**//**{
"example": true
}**/To load libraries like jQuery and others, copy the files to the repository and add them to the file header. The files have to be referenced locally. Dependencies are loaded in listed order.
/**{
"dependencies": [
"exampleLib.js",
"other/exampleLib.js"
]
}**/- engine262
Algorithmic Games uses engine262 to run arena and participant code safely and consistently between matches. - JSON Editor
Algorithmic Games uses JSON Editor by Jos de Jong, powered by Ace (Ajax.org Cloud9 Editor) and Ajv JSON schema validator, for editing, rendering and validating JSON. - seedrandom
Algorithmic Games uses seedrandom by David Bau for overridingMath.random()to generate repeatable numbers.
Algorithmic Games runs arena and participant code in an isolated JavaScript environment in your browser. Human interface pages are separate and only exchange messages with the match. This limits what user-written code can reach, but no system is perfect.
If you find a way to break out of the participant isolation and read other people’s data, please report it! Confirmed reports are listed on the honorable mentions page once the issue is fixed.
If Algorithmic Games happens to be used in any scientific research, please do tell if something is published! 😃
If you have any doubts, you can request permission here.