Docs Core concepts

Fair mode

A client injected into the game can read the whole map. Fair mode limits your bot to what's within its vision, just like a human player and just like the Arena rules.

This project’s observation capability comes from the fact that the client holds the state of every player: the snapshot contains every unit on the map, including enemies in the fog. That’s handy for debugging, but unfair in a match.

Fair mode makes the SDK filter everything by your vision:

python tools/play.py --bot my_bot.py --fair
python -m openwar3 run my_bot.py --inst 5 --fair
from openwar3 import Game, run
g = Game(inst=5, fair=True)            # use Game directly
run(MyBot, inst=5, fair=True)          # or hand it to the runner

What gets filtered

ContentIn fair mode
UnitsAll of yours + the enemy and neutral units you can see right now
Items on the groundOnly those within your units’ vision (day and night vision are computed separately from the data tables)
Production tableOnly buildings you can see (you can’t see what your opponent is training)
EventsYour own; visible ones (or ones that were visible within the last second); damage dealt by your side

Where vision comes from

  • Every unit in the snapshot carries a visibility mask: bit p = player p can see it right now (only players 0–11 with units on the field count; your own units are always visible to you). u.visible_to(g.me()) reads it directly, with zero wait.
  • For any point, g.visible(x, y) asks the engine (visible / fog / black mask) through the fast lane, at about one frame per call. When a tick needs to check many units, use u.visible_to() from the snapshot instead of calling g.visible() one unit at a time.

Remembering enemies: last_seen

A human player remembers “I just saw a pack of Raiders over there.” The SDK remembers for you too: every time the snapshot refreshes, it records the enemy and creep units you can currently see (last position, HP, time); it removes them once it sees them die, and clears everything between games.

for u, t, age in g.last_seen(max_age=60):         # enemies seen within the last 60 game seconds
    print(u.type, u.x, u.y, f"{age:.0f}s ago")

heroes = [r for r in g.last_seen() if r[0].is_hero]   # where the enemy heroes were last seen
camps  = g.last_seen(owner="creep")                   # creeps you've seen

In fair mode, this is your only source of information about your opponent, just like for a human player. Normal mode also records by vision, so the same code works in both.

Commanding as a specific player

python tools/play.py --bot my_bot.py --player 1 --attach

--player N (or Game(player=N)) makes the bot command as player N, and it can only command player N’s units. To have two AIs fight, open two such channels in the same game.

In local mode, fairness is a convention, not a security boundary

On your own machine, nothing can stop a program from reading the whole map. --fair is a constraint you place on yourself; real matches are guaranteed by the Arena’s referee process: bots never touch shared memory, only receive observations that the referee has filtered by vision, can only submit actions, and every action is checked for unit ownership first.

Why turn it on now

  • The Arena will use exactly these rules. Write for fair mode now, and you won’t have to change a line later;
  • Without full-map information, you find out how good your bot really is (the reference brain currently relies heavily on full-map information, such as the computer captain’s target point, which makes this a good test);
  • Scouting, memory and judgment written under fair mode are the AI capabilities that actually matter.