Die 15 Regeln
Jede einzelne stammt aus echten Spielen. Prüf deinen Bot beim Schreiben dagegen – das spart den Großteil der Fehlersuche.
Gib diese Seite zusammen mit api.json an dein LLM – der Bot, den es schreibt, erspart dir viele Umwege.
Zustand lesen
1. Nicht lesbar heißt None, nicht 0
resources(), time_of_day(), production() und cooldown() können alle None zurückgeben (Ladebildschirm, Einheit ohne Detaildaten, Gebäude produziert gerade nichts …). Erst prüfen, dann verwenden:
res = g.resources()
if res is None:
return
2. Einheiten per Handle erkennen, nicht per Adresse
Adressen werden für neue Einheiten wiederverwendet: Eine alte Adresse kann auf eine frisch erschienene Einheit zeigen. Um dir eine Einheit über mehrere Ticks zu merken, speichere u.handle und hol sie mit g.unit(handle) zurück.
3. Der Event-Stream ist global
In production.done und unit.died stecken auch Events von Gegnern und Creeps. Filtere nach ev.owner (oder dem Gebäude-Handle):
if ev.kind == "production.done" and ev.owner == g.me():
...
4. Arbeiter in der Goldmine fehlen im Snapshot
In dem Moment, in dem ein Arbeiter die Goldmine betritt, verschwindet er aus dem Snapshot (unit.removed, nicht tot). Um zu zählen, wie viele an jeder Mine arbeiten, führ selbst Buch und streich keine Einträge anhand des Snapshots – sonst schickst du zusätzliche Arbeiter an volle Minen.
Befehle erteilen
5. „Angenommen“ ≠ erledigt
Auch einen Bauplatz im Wald nimmt die Engine sofort an; scheitern tut der Befehl erst, wenn der Arbeiter ankommt. Fähigkeiten können unterbrochen werden. Die Wirkung siehst du in Snapshot und Events: Zum Bauen build_near (verfolgt, ob das Fundament erscheint), bei Fähigkeiten prüfen, ob g.cooldown() läuft.
6. Unsichtbare Ziele kannst du nicht angreifen
Zielbefehle auf Gegner im Nebel werden mit Reason-Code 1001 abgelehnt. Um einen Gegner im Nebel zu verfolgen, schick attack_move an seine zuletzt gesehene Position.
7. Nur untätigen Einheiten Befehle geben
Denselben Befehl in jedem Tick erneut an dieselbe Einheit zu senden, unterbricht sie: Soldaten zucken auf der Stelle, der Abbauzyklus der Arbeiter beginnt von vorn. Ob eine Einheit untätig ist, prüfst du mit g.order_of(u) (enthält auch die Befehle, die du in diesem Tick gerade erteilt hast), nicht mit u.order aus dem Snapshot (der hinkt noch hinterher).
8. Shift heißt nur „direkt hinter den aktuellen Befehl“
Die Engine kennt kein „ans Ende anhängen“: Sendest du nacheinander B und C mit queue='after', bekommst du A, C, B. Für eine Reihe von Punkten in fester Reihenfolge nimm g.path(units, points), für mehrere Gebäude mit einem Arbeiter g.build_queue(worker, plan) – beide fügen in umgekehrter Reihenfolge ein und erledigen das für dich.
9. Alle Befehle eines Ticks als Batch
Dutzende Befehle einzeln gesendet heißt dutzendmal auf den Spiel-Thread warten; in with g.batch(): verpackt nur einmal.
Wirtschaft & Produktion
10. Maximal 5 Arbeiter pro Goldmine
Mehr bringt kein Einkommen. Das Arbeiterziel richtet sich nach der Zahl der Minen: 5 für Gold pro Mine, plus ein paar für Holz.
11. Nur 1 Einheit in der Ausbildungswarteschlange
Eine volle Warteschlange (7 Plätze) bindet Geld (gemessen: 4 Bauern im Hauptgebäude eingereiht, 300 Gold gebunden, die Eröffnung deutlich langsamer). Erst nachlegen, wenn g.queue(b) leer ist.
12. Bei Nahrungsengpass in die Produktionstabelle schauen
g.production(b).blocked = etwas steht in der Warteschlange, hat aber nicht begonnen – meistens fehlt Nahrung. Das ist einen Schritt früher als „bauen, wenn die Nahrung fast voll ist“: Verlierst du im Kampf viele Einheiten und stockt beim Nachbauen die Warteschlange, weißt du es sofort.
13. Helden sind einzigartig; kein Tier-Up bei belegter Warteschlange des Hauptgebäudes
- Ein toter Held lässt sich nur mit
g.revive(altar)zurückholen; erneutes Ausbilden wird abgelehnt (221). Auch Wiederbeleben kostet Nahrung (ein Held belegt 5). - Solange noch etwas in der Warteschlange des Hauptgebäudes steht, kann es nicht aufgewertet werden (Reason-Code 185, „Gebäude beschäftigt“).
Zeit & Raum
14. Bei 2× Geschwindigkeit nicht nach der Wanduhr warten
Willst du 3 Spielsekunden warten, warte, bis g.clock() um 3 gestiegen ist – nicht sleep(1.5). Bei erhöhter Geschwindigkeit läuft die Engine-Uhr schneller als die Wanduhr.
15. Auf Insel- und Waldkarten keine Luftlinie
Für Creep-Lager und Expansionen g.path_distance(a, b) verwenden (A* am Boden, um Wald, Klippen und Gebäude herum); ist ein Ort unerreichbar, kommt None zurück. Der Punkt mit der kürzesten Luftlinie liegt womöglich auf der anderen Seite des Meeres.
Und noch eine: Schreib für den Fair-Modus
Mit --fair siehst du nur Einheiten, Gegenstände, Produktion und Events in deiner Sicht – genau die Regel der Arena. Schreib schon jetzt für den Fair-Modus, dann musst du für die Arena nichts ändern. Mehr dazu unter Fair-Modus.