# Quittungen & Reason-Codes

> Jede Befehlsquittung enthält einen Statuscode und einen Reason-Code. Daran korrigieren sich Bots und Agents selbst: Aus „Warum hat es nicht geklappt?“ wird eine maschinenlesbare Zahl.

Quelle: https://war3ai.com/de/docs/reason-codes/

```python
r = g.train(barracks, "hfoo")
bool(r)        # False
r.status       # 1              -> rejected
r.verdict      # 3              -> nicht genug Nahrung
r.reason       # 'rejected（人口不够）'   (= nicht genug Nahrung)
r.exec_us      # wie viele Mikrosekunden dieser Befehl auf dem Spiel-Thread lief
```

`if r:` entspricht `r.status == 0` (von der Engine angenommen).

## Statuscode `status`

| Code | Name | Bedeutung | Häufige Ursache |
|---|---|---|---|
| 0 | `accepted` | Von der Engine angenommen | — (aber angenommen ≠ erledigt, siehe unten) |
| 1 | `rejected` | Von der Engine abgelehnt | siehe `verdict` |
| 2 | `bad_unit` | Einheit existiert nicht oder Handle passt nicht | Einheit ist schon tot; veraltetes Einheitenobjekt verwendet |
| 3 | `not_owner` | Nicht deine Einheit | Als `player` fremde Einheiten befehligt |
| 4 | `fault` | Ausnahme bei der Ausführung (von der Runtime abgefangen, das Spiel läuft weiter) | Bitte mit Reproduktionsschritten melden |
| 5 | `bad_args` | Falsche Argumente | Koordinaten, Slot-Nummer oder Rawcode falsch |
| 6 | `unsupported` | Nicht unterstützt | Diese Runtime-Version hat die Fähigkeit nicht |
| 7 | `bad_target` | Ungültiges Ziel | Ziel existiert nicht mehr; falscher Zieltyp |
| 8 | `forbidden` | Rolle der Spur erlaubt das nicht | Befehl als `observer` erteilt |
| 97 | `cancelled` | Im Batch-Block wurde eine Ausnahme geworfen, der ganze Batch wurde nicht gesendet | Fehler im Code innerhalb von `with g.batch():` |
| 98 | `held` | Einheit wird von einer höher priorisierten Schicht gehalten, Befehl nicht gesendet | Die Reflex-Schicht des Referenz-Brains oder ein manueller Befehl aus der Konsole hält die Einheit gerade |
| 99 | `timeout` | Zeitüberschreitung | Spiel pausiert / hängt, Deadline überschritten (abgelaufene Befehle werden nicht mehr ausgeführt) |

## Reason-Code `verdict`

Bei einer Ablehnung nennt die Runtime den Grund anhand der engine-eigenen Machbarkeitsprüfung. Du kannst auch vorher fragen, statt direkt zu befehlen: `g.can_do(unit, code)` liefert dieselben Codes.

| Code | Bedeutung | Was tun |
|---|---|---|
| 0 / 220 | Möglich | — |
| 3 | Nicht genug Nahrung | Nahrungsgebäude bauen; mit `g.production(b).blocked` früh erkennen |
| 8 | Nicht genug Gold | Warten; vor dem Befehl `g.can_afford(code)` prüfen |
| 9 | Nicht genug Holz | Mehr Arbeiter ins Holz schicken |
| 32 | Ausbildungswarteschlange voll (7 Plätze) | Nur 1 Einheit einreihen: nachlegen, wenn `g.queue(b)` leer ist |
| 183 | Voraussetzung (Technologie / Gebäude) fehlt | Erst das vorausgesetzte Gebäude bauen, Tier-Up |
| 185 | Gebäude beschäftigt | Der Altar belebt gerade einen Helden wieder; das Hauptgebäude kann nicht aufwerten, solange seine Warteschlange nicht leer ist |
| 221 | Nicht verfügbar / im Bau / in Aufwertung / existiert bereits | Held existiert schon (ist er tot: `revive`); dieser Laden verkauft das nicht |
| 89 | Laden hat die Ware noch nicht | Zu Spielbeginn gibt es Waren erst nach der Lagerzeit aus der Gegenstandstabelle; bei einem neu gebauten Laden zählt die Zeit ab Fertigstellung |
| 1001 | Ziel nicht sichtbar | Ziel steht im Nebel oder in unerforschtem Gebiet; `attack_move` auf seine Position |

## Angenommen ≠ erledigt

Die Quittung sagt nur, dass die Engine den Befehl angenommen hat – sie wird im selben Frame zurückgelesen. Was danach passiert, erfasst sie nicht:

| Befehl | Kann nach „angenommen“ noch scheitern | So prüfst du es |
|---|---|---|
| Bauen | Ein Punkt im Wald wird sofort angenommen, scheitert aber erst, wenn der Arbeiter ankommt | `build_near` verwenden (verfolgt, ob das Fundament erscheint), oder auf `production.done` warten |
| Zaubern | Unterbrochen, kein Mana | Im nächsten Tick prüfen, ob `g.cooldown(u, ability)` läuft |
| Ausbilden | In der Warteschlange, aber zu wenig Nahrung – startet nie | `g.production(b).blocked` |
| Bewegen / Angreifen | Von anderer Logik (oder einer höher priorisierten Schicht) überschrieben | `g.current_target(u)`, `g.order_of(u)` |

## Abfrage-APIs

Diese APIs erteilen keine Befehle, sondern fragen nur die Engine; das Ergebnis steckt im `value` der Quittung (das SDK gibt den Wert direkt zurück):

| API | Rückgabe |
|---|---|
| `g.can_do(u, code)` / `g.can_do_many([(u, code), ...])` | Reason-Code aus der Tabelle oben |
| `g.tech(code, player=None)` / `g.tech_many([...])` | Forschungsstufe / Anzahl fertiger Gebäude (Aufwertungskette eingerechnet) |
| `g.visible(x, y)` | Ob dieser Punkt für uns sichtbar ist |
| `g.gold_left(mine)` | Restgold der Goldmine |
| `g.enemy_ai_plan(enemy_unit)` | Wohin der Anführer des Computergegners seine Truppen führen will (nur bei Computer-KI) |
