AI schemes
A scheme is a complete AI. Switch with one click in Farsight — even the game in progress can be taken over right away. Export a zip to share with others, import other people's schemes to test them, and every scheme's results are tracked automatically.
A scheme = a complete AI: a folder + a manifest scheme.json + code. Each game instance picks one scheme; you switch with one click in Farsight, and the new scheme can even take over the game in progress right away.
Schemes shared by others are imported into a separate area, kept apart from your own schemes; to change one, use “Copy to mine”.
schemes/
mine/<id>/ mine: ones you wrote, or copied from another scheme to modify (change freely; takes effect next game)
installed/<id>/ installed: zips shared by others are unpacked here (trust must be confirmed before the first run)
brains/xwar3/ built-in: the reference brain (a full AI)
brains/examples/ built-in: the four teaching examples hello / rush / macro / micro, the companion example buddy, and two gameplay mods (Hero Roguelike, Endless Defense)
A scheme doesn’t have to be an AI that plays for you: a kind: mod scheme is a set of gameplay rules — you play, and it sets the challenges. See Gameplay mods.
Using it in Farsight
The “AI schemes” page (sidebar “System → AI schemes”):
| Action | What it does |
|---|---|
| Import scheme (zip) | Installs it into installed/; if the same id is already installed, it asks whether to replace it (after replacing, trust must be confirmed again) |
| Use on instance… | Pick an instance + “Apply now” (stops the current AI; the new scheme takes over this game) or “Apply at next Start test” |
| Copy to mine | Copies it into mine/, sets the author to “me” and the version to 0.1.0, and records which version of which scheme it was copied from |
| Export zip | Packs it as <id>-<version>.zip; sending that to someone is how you share it |
| Open folder | Opens the scheme folder in File Explorer so you can edit the code directly |
| Trust | Required before someone else’s scheme runs for the first time (see “Trust and safety” below) |
| Recent results | Win/loss, duration and end reason for every game this scheme played |
| Delete | Only “mine” and “installed” schemes can be deleted; a scheme an instance is using can’t be |
Instance cards also have a new “AI scheme” row: pick a scheme from the dropdown → “Switch (applies now)”. When the instance isn’t running, the button says “Select”, and the next “Start test” launches the AI with that scheme.
The manifest: scheme.json
{
"format": 1,
"id": "fast-rush",
"name": "Three-minute rush",
"version": "1.2.0",
"author": "Someone",
"description": "One sentence on what strategy this AI plays",
"entry": "rush_bot.py",
"class": "RushBot",
"fair": true,
"hz": 5,
"races": ["human", "orc"],
"license": "MIT"
}
| Field | Required | Description |
|---|---|---|
id | ✔ | Lowercase letters, digits, -, _; 2–41 characters |
entry | ✔ | A .py file in the scheme folder (no absolute paths, no ..) |
kind | Default bot (a subclass of openwar3.Bot that plays for you); mod = a gameplay mod (a subclass of openwar3.Mod; never uses fair mode and isn’t judged by melee rules) | |
class | Name of the Bot (or Mod) subclass in the entry file; if omitted, the last openwar3.Bot subclass in the entry file is used | |
fair | Default true: sees only what’s within vision, the same rule as the Arena. false = full-map visibility, and only then can it use the JASS channel (companions need it) | |
judge | Default true: wins and losses are judged by melee rules. Set it to false for RPG / companion schemes | |
hz | How many times per second on_tick is called; default 5 | |
format | Manifest format version, currently 1; a manifest newer than your local OpenWar3 is rejected with a prompt to update | |
| Others | name, version, author, description, races, license, homepage and forked_from are for display only |
The scheme folder is added to Python’s module search path, so the entry file can import other files in the same folder. Third-party packages (numpy, torch…) aren’t installed automatically — state clearly in description what’s needed.
The smallest scheme needs just two files:
# my_bot.py
from openwar3 import Bot
class MyBot(Bot):
def on_tick(self, g):
for w in g.idle_workers():
mine = g.nearest(g.gold_mines(), w)
if mine:
g.gather(w, mine)
{"id": "my-first", "name": "My first AI", "entry": "my_bot.py"}
Put them in schemes/mine/my-first/ and refresh Farsight to see it. An even easier starting point: pick an example under “Built-in” and click “Copy to mine”.
How schemes run, and results
Schemes are run by the scheme runner (it’s what Farsight’s “Start test / Switch” launches):
python tools/run_scheme.py --inst 20 --scheme builtin/micro --hours 6
- Each instance has one long-running supervisor process, which starts a child process for every game to run the scheme: if the scheme’s code crashes, the supervisor is unaffected; if you change the code of one of your own schemes, the next game automatically uses the new code.
- At the end of each game one results row is recorded: scheme, version, author, win/loss, reason, game duration, error count. The win rates in Farsight are computed from these.
How wins and losses are decided:
| Situation | Recorded as |
|---|---|
| All enemy buildings are gone | Win |
| All our buildings are gone (even if units are still alive — that’s how melee games decide a loss) | Loss |
| All our units are gone | Loss |
| Ended / stopped manually in Farsight | Undecided |
| At the time of switching, the game had already run for more than 60 game seconds (taken over midway) | Counted separately, not included in the win rate |
| The game clock hasn’t moved for a long time | Undecided |
Once a game is decided, the runner closes the score screen, starts the next game according to the “Next game” settings, and the scheme takes over again — you can leave it running all night to build up results. Pausing doesn’t end a game: while paused, the Bot keeps running as usual; only the game clock stops.
Trust and safety
A scheme is code, and when it runs it has the same permissions as you do (it can read and write files and access the network). So:
- Schemes in
installed/are not trusted by default; both Farsight and the runner refuse to run them until you click “Trust”; - Replacing an installed scheme with one that has the same id resets trust (a new version means new code);
- Imports are checked: the zip must be at most 50 MB with at most 2000 files; no absolute paths or
..(so nothing can be written outside the scheme folder); an invalid manifest or a missing entry file is rejected outright.
Before you trust a scheme, click “Open folder” and read through the code. Only take schemes from people you trust.
API (for scripts)
| Endpoint | Description |
|---|---|
GET /api/schemes | Scheme list + results + the scheme each instance has selected and is running |
GET /api/schemes/results?ref= | A scheme’s last 30 games |
POST /api/schemes/import | Import a zip |
GET /api/schemes/export?ref= | Download the zip |
POST /api/schemes/fork | Copy to mine |
POST /api/schemes/trust | Trust |
DELETE /api/schemes?ref= | Delete (refused while an instance is using it) |
POST /api/instances/{n}/scheme | Change an instance’s scheme: take over the current game right away, or apply at the next Start test |
In Python, use the library directly: from openwar3 import schemes (list_schemes, install_zip, export_zip, fork, trust, stats…).
Later: a scheme website
An exported zip is the unit of sharing, so the website only needs to add a layer on top: upload from Farsight with one click; downloads from the website go through exactly the same checks as “Import scheme” and still require confirming trust; results can optionally be reported, and the website aggregates win rates by version. Farsight already has a spot reserved for the “Share to scheme website” button. See the roadmap for progress.