KIs verschiedener Leute messen sich auf derselben Karte
Fairness kann nur ein Schiedsrichter garantieren, nicht die Selbstdisziplin der Bots. Bots kommen nie an den Shared Memory: Sie erhalten nur vom Schiedsrichter nach Sicht gefilterte Beobachtungen, können nur Aktionen einreichen, und jede Aktion wird zuerst auf Besitz geprüft.
Sortiert danach, ob Fairness garantiert werden kann
Die Beobachtungsfähigkeit dieses Projekts beruht gerade darauf, dass „der Client den Zustand aller Spieler hält“ – und das gilt genauso für deinen eigenen Rechner. Fairness kann also nur von einem Schiedsrichter kommen, dem alle vertrauen. Zuerst kommt A, mit demselben Protokoll direkt ausbaubar zu B; C ist nur zum Spaß.
Lokale Arena
Ein Rechner, ein Spiel; jeder Bot belegt einen Slot, ein Schiedsrichterprozess erteilt die Befehle für sie
Gehostete Ladder
A auf einem Server; Spieler laden Bots hoch, der Server führt sie in einer Sandbox aus
Jeder am eigenen Rechner
Jeder betreibt Spiel + Bot auf dem eigenen Rechner, Match im LAN
Ein Prozess erteilt die Befehle für beide Seiten
- Orchestrierung Karte wählen, Spiel starten, Volk und Schwierigkeit pro Slot festlegen
- Takt Ein Tick alle T Spielmillisekunden (Standard 200); im Lockstep-Modus pausiert das Spiel, während Beobachtungen verschickt werden
- Beobachtung Snapshot → nach Sicht jedes Slots gefiltert → JSON
- Aktion Prüfen, ob die „Einheit zu diesem Slot gehört“ → Budget (Befehle pro Tick, APM) → per Schnellspur als Batch erteilen
- Aufzeichnung Beobachtungszusammenfassung pro Tick + jede Aktion: als Replay, zur Analyse, als Trainingsdaten
- Entscheidung Slot ohne Gebäude → ausgeschieden; Zeit abgelaufen → nach verbleibender Kampfkraft / Ressourcen
Beobachtung rein, Aktionen raus
Jedes Programm, das JSON senden und empfangen kann, darf antreten – auch ein LLM, das direkt Tick für Tick Aktionen ausgibt. Python-Bots, die mit dem SDK geschrieben sind, brauchen keine Codeänderung.
| Beobachtung | Nur eigene Einheiten + gegnerische Einheiten in eigener Sicht; Creeps und Goldminen je nach Sicht oder ab Spielstart öffentlich |
| Aktionslimit | Max. 32 pro Tick, der Rest wird abgeschnitten (damit Befehlsfluten den Schiedsrichter nicht ausbremsen) |
| Gleiche Einheit | Pro Tick zählt nur der letzte Befehl |
| Zeitbudget | Ticklänge × 0.9; bei Überschreitung verfällt der Tick – wer langsam ist, schadet nur sich selbst, nicht den anderen |
| Lockstep | Wenn strikte Fairness nötig ist: Spiel beim Versand der Beobachtung pausieren und erst fortsetzen, wenn alle Aktionen da sind (oder Timeout) – das Tempo der Rechner beeinflusst das Ergebnis nicht |
| Startpositionen tauschen | Jedes Bot-Paar spielt jede Seite einmal – gleicht Asymmetrien der Karte aus |
| Ladder | Elo / TrueSkill; pro Paar mindestens 20 Spiele vor einem Urteil (bei 2 Spielen ist der kleinste erkennbare Unterschied der Siegquote etwa 60 Prozentpunkte) |
{"t": "obs", "tick": 57, "gameMs": 11400, "me": 1,
"res": {"gold": 320, "lumber": 150, "food": [18, 30]},
"units": [
{"id": 101, "type": "hfoo", "owner": 1,
"x": -4500, "y": 2200, "hp": 380, "hpMax": 420}],
"visibleEnemies": [
{"id": 733, "type": "ogru", "owner": 2,
"x": -3900, "y": 2500, "hp": 700}],
"deadlineMs": 180} id ist eine vom Schiedsrichter vergebene Nummer, die das ganze Spiel über gleich bleibt. {"t": "act", "tick": 57, "actions": [
{"do": "attack", "unit": 101, "target": 733},
{"do": "train", "unit": 5, "code": "hfoo"},
{"do": "cast", "unit": 7, "spell": "thunderbolt", "target": 733},
{"do": "move", "unit": 102, "x": -5000, "y": 2000}]} category == "command" in api.json, mit gleichnamigen Parametern. Ein verspätetes act wird verworfen, der Tick zählt als ausgesetzt. from openwar3 import Bot
class MyBot(Bot):
def on_tick(self, g): # derselbe Code: lokal ist g ein Game, in der Arena ein ArenaGame
for w in g.idle_workers():
g.gather(w, g.nearest(g.gold_mines(), w))
# Lokal: python tools/play.py --bot my_bot.py --fair
# Arena: gleichnamige Methoden, darunter WebSocket – am Bot-Code ändert sich keine Zeile Game durch ArenaGame und ist startklar. Der Reihe nach – erst wenn eins besteht, kommt das nächste
| # | Experiment | Kriterium | Bekannt |
|---|---|---|---|
| 1 | Zwei Slots in einem Spiel, beide ohne eingebaute KI | Die Einheiten beider Seiten bewegen sich nicht | KI-Flag und Schwierigkeitsfeld der Slots sind bekannt |
| 2 | Befehle für andere als den lokalen Slot | Die Bauern des gegnerischen Slots bauen tatsächlich ab | Der wichtigste Punkt: Scheitert er, bleibt nur „ein Client pro Bot, echtes Netzwerkspiel“ |
| 3 | Sicht für beliebige Spielernummer abfragen | Derselbe Punkt liefert für zwei Slots unterschiedliche Ergebnisse | Die Sichtprüfung der Engine akzeptiert jede Spielernummer |
| 4 | Sieg / Niederlage programmatisch bestimmen | Binnen 1 s wissen, wenn alle Gebäude einer Seite zerstört sind | Der Event-Bus bietet einen direkteren Einstieg |
| 5 | Lockstep Pause / Fortsetzen | Aktionen während der Pause sammeln, nach dem Fortsetzen wirksam | Pause verifiziert |
Nebenbei ein Test: Das Referenz-Brain stützt sich derzeit stark auf Informationen über die ganze Karte (etwa das Angriffsziel des Computergegners). Für die Arena muss es auf die Fassaden-API umsteigen und darf nur Einheiten in Sicht nutzen – wie stark ist es ohne Kartenwissen noch?