# Profi-Kochbuch

> Der Vorsprung guter Spieler steckt größtenteils in Dutzenden kleiner Gewohnheiten. Diese Seite übersetzt gängige Profi-Techniken eine nach der anderen in SDK-Code – jeder Abschnitt lässt sich direkt in on_tick kopieren.

Quelle: https://war3ai.com/de/docs/cookbook/

Konventionen: `g` ist das `Game`, `home` ist unsere Hauptbasis (`g.my_buildings({"htow", "hkee", "hcas"})[0]`), `now = g.clock()`. Details zur API findest du in der [API-Referenz](https://war3ai.com/de/api/), vollständige lauffähige Beispiele unter [Beispiel-Bots](https://war3ai.com/de/docs/examples/).

> **Tipp**
>
> Wenn ein LLM eine bestimmte Technik einbauen soll, gib ihm das passende Rezept samt Code mit. Das wirkt viel besser als die Bitte, „professioneller zu spielen“.

## I. Wirtschaft

### 1. Arbeiter nie untätig, 5 pro Mine

```python
for w in g.idle_workers():                                   # nur untätige zuweisen (neue Befehle an beschäftigte unterbrechen das Sammeln)
    mine = g.nearest([m for m in g.gold_mines() if crew[m.addr] < 5], w)
    g.gather(w, mine) if mine else g.gather(w, g.trees(w.x, w.y, limit=1)[0])
```

Merk dir selbst, wie viele du jeder Mine zugewiesen hast (`crew`): Arbeiter in einer Goldmine sind nicht im Snapshot. Vollständiges Beispiel in `hello_bot.py`.

### 2. Nur 1 in die Warteschlange, kein gebundenes Gold

```python
for b in g.my_buildings({"hbar"}):
    if not g.queue(b):                                       # erst den nächsten einreihen, wenn sie leer ist
        g.train(b, "hfoo")
```

### 3. Nie an der Nahrung hängen bleiben

```python
stuck = any(p.blocked for _b, p in g.all_production("me"))  # eingereiht, aber nicht gestartet = nicht genug Nahrung
res = g.resources()
if stuck or res["food_cap"] - res["food_used"] <= 6:
    g.build_near(builder, "hhou", home.x, home.y)
```

`blocked` greift einen Schritt früher als „fast voll“: Verlierst du im Kampf einen Teil der Armee und stockt beim Nachbauen die Warteschlange, weißt du es sofort.

### 4. Bauabfolge + danach selbst zur Mine zurück (Shift-Rückkehr zur Mine)

```python
spot = g.build_near(w, "hbar", home.x, home.y)
if spot:
    g.gather(w, mine, queue="after")                         # nach dem Bau zurück zur Mine, im nächsten Tick nicht erneut suchen
```

Ein Bauer baut mehrere Gebäude nacheinander: `g.build_queue(w, [("hhou", x1, y1), ("hhou", x2, y2)])`. Das Gold wird erst bei Baubeginn abgezogen.

### 5. Tier-up-Timing, Angriffs-/Rüstungs-Upgrades

```python
if not g.queue(hall) and g.can_do(hall, "hkee") in (0, 220):   # das Hauptgebäude kann nur mit leerer Warteschlange ausbauen (sonst 185)
    g.upgrade(hall, "hkee")
p = g.production(hall)                                          # Tier-up-Fortschritt
if p and p.kind == "upgrade":
    print(f"Hauptgebäude braucht noch {p.remaining:.0f} Sekunden")
for sm in g.my_buildings({"hbla"}):
    if not g.queue(sm):
        ok = [u for u, v in zip(UPS, g.can_do_many([(sm, u) for u in UPS])) if v in (0, 220)]
        if ok:
            g.research(sm, ok[0])
```

### 6. Expansion: die nächste Mine nach Laufweg wählen

```python
mines = [m for m in g.gold_mines() if g.dist(m, home) > 1500 and not taken(m)]
best = min(mines, key=lambda m: g.path_distance(home, m) or 1e9)   # Minen auf Inseln liefern None -> landen ganz hinten
```

## II. Aufklärung und Informationen

### 7. Sehen, was der Gegner macht

```python
for b, p in g.all_production("enemy"):          # was sichtbare gegnerische Gebäude trainieren / erforschen / aufwerten
    print(b.type, p.kind, p.queue, f"{p.progress:.0%}" if p.progress is not None else "hängt")
```

Kombiniert mit Events: `ev.kind == "production.done" and ev.owner != g.me()` – was der Gegner gerade fertiggestellt hat.

### 8. Merken, was du gesehen hast (Kriegsnebel)

```python
for u, t, age in g.last_seen(max_age=60):       # Gegner, die in den letzten 60 Spielsekunden gesehen wurden (letzte Position und TP)
    ...
hero_seen = [r for r in g.last_seen() if r[0].is_hero]   # wo der gegnerische Held zuletzt war
```

Im Fair-Modus ist das deine einzige Informationsquelle über den Gegner – genau wie bei einem menschlichen Spieler.

### 9. Wo der Computergegner angreifen will (nur Computer-KI)

```python
plan = g.enemy_ai_plan(some_enemy_soldier)      # wohin sein Computer-Captain unterwegs ist
```

Der Computer legt seinen Zielpunkt fest, bevor er losmarschiert – zieh deine Armee rechtzeitig dorthin zurück.

## III. Creepen

### 10. Nachts creepen

```python
if g.is_night():                                 # 18 ~ 6 Uhr: Creeps schlafen (du triffst zuerst, ohne umzingelt zu werden), alle sehen weniger weit
    ...
wait = g.seconds_until(18)                       # Spielsekunden bis zum Einbruch der Nacht (ein Tag hat 480 Sekunden)
```

### 11. Nur Lager angreifen, die du schaffst

```python
from openwar3 import combat
mine = [g.stats(u) for u in army]
def ttk(target): return combat.time_to_kill(mine, g.stats(target), target_hp=target.hp) or 1e9
camp = [c for c in g.creeps() if g.dist(c, center) < 600]
ours = max(ttk(c) for c in camp)                                 # wie lange es dauert, dieses Lager zu räumen (grob)
theirs = g.time_to_kill(camp, weakest_of_mine) or 1e9            # wie lange sie brauchen, um unsere schwächste Einheit zu töten
if ours < theirs and g.reachable(center, camp[0]):
    g.attack_move(army, camp[0].x, camp[0].y)
```

Vollständiges Beispiel: `_maybe_creep` in `micro_bot.py`.

## IV. Mikro

### 12. Fokusfeuer: das angreifen, was am schnellsten stirbt, nicht das Nächste

```python
target = min(visible_enemies, key=lambda e: g.time_to_kill(fighters, e) or 1e9)
g.attack([u for u in fighters if (g.current_target(u) or target).handle != target.handle], target)
```

Befiehl nur den Einheiten, die es noch nicht angreifen (`current_target`), damit du die anderen nicht unterbrichst.

### 13. Verwundete zurückziehen

```python
for u in army:
    if u.hp < u.hp_max * 0.35:
        g.move(u, *toward(home, u, 500))       # 500 Richtung Basis zurückziehen; dieselbe Einheit 3 Sekunden lang nicht erneut ziehen
```

Fokusfeuer erkennen: Trifft dieselbe Einheit in `damage`-Events kurz hintereinander Schaden aus mehreren Quellen, ist sie umzingelt.

### 14. Helden am Leben halten, keine EP verschenken

```python
for h in g.my_heroes():
    if h.hp < h.hp_max * 0.4:
        g.move(h, home.x, home.y)
        g.use_item(h, slot_of(h, "phea"))       # Heiltrank: Platznummer über inventory(h) finden
```

### 15. Konter: die richtige Einheit auf das richtige Ziel

```python
s = g.stats(u)
best = max(enemies, key=lambda e: s.dps_vs(g.stats(e)))   # Büchsenschützen auf Greifenreiter (Durchbohrend gegen leichte Rüstung ×2), Greifenreiter auf Fußsoldaten (Magie gegen schwere Rüstung ×2)
```

Die Kontertabelle stammt aus den Spieldaten: `combat.damage_multiplier("pierce", "small") == 2.0`.

### 16. Flanken und Wegführung: Türme umgehen

```python
route = g.walk_path(army_center, target)        # Knickpunkte des kürzesten Bodenwegs
g.path(army, route, attack=True)                # nacheinander per Angriffsbewegung durch jeden Punkt
```

Um Türme zu umgehen, markierst du den Bereich um jeden Turm im Wegfindungsraster als unpassierbar und berechnest dann die Route:

```python
grid = g.grid().copy()
for t in towers:
    grid.block_area(t.x, t.y, 800)             # Turmreichweite 700 + Puffer
route = grid.path((army_x, army_y), (target.x, target.y))
```

### 17. Die Befehle eines Ticks als ein Batch senden

```python
with g.batch():
    g.attack(melee, target_a)
    g.attack(ranged, target_b)
    g.move(wounded, *home_xy)
    g.cast(hero, "thunderclap")
```

Dutzende Befehle warten nur einmal auf den Spiel-Thread (gemessen: 8 Bewegungen 68 ms → 6.5 ms).

### 18. Belagerung: Artillerie greift den Boden an

```python
g.attack_ground(mortars, tower.x, tower.y)       # Mörsertrupps / Katapulte feuern auf eine Fläche (hinter Bäumen, unsichtbare Einheiten)
```

## V. Helden

### 19. Skill-Reihenfolge

```python
SKILLS = {"Hamg": ["AHwe", "AHbz", "AHwe", "AHbz", "AHwe", "AHmt"]}   # Wasserelementar, Blizzard … Stufe-6-Ultimate Massenteleportation
info = g.hero_info(h)
if info and info["skill_points"]:
    g.learn(h, SKILLS[h.type][learned_count])  # abgelehnt (Stufe zu niedrig fürs Ultimate)? auf die nächste Stufe warten
```

### 20. Wurde der Zauber wirklich gewirkt?

```python
r = g.cast(h, "thunderbolt", target=enemy_hero)
# im nächsten Tick:
if g.cooldown(h, "AHtb"):                         # Abklingzeit läuft = wirklich gewirkt; angenommen ≠ gewirkt
    ...
```

### 21. Tränke kaufen, zurück in die Stadt

```python
g.buy(shop, "phea")                               # der Held steht neben dem Laden
g.use_item(hero, slot, x=home.x, y=home.y)        # Stadtportal-Schriftrolle (Gegenstand auf einen Punkt benutzen)
```

## VI. Nachbesprechung

- Schreib die Entscheidungen jedes Ticks ins Log (`print` landet im Ausführungsfenster) und nutze `g.say(einheit, "Rückzug")`, um sie im Spiel zu sehen;
- `production.done`-Events enthalten „wie viele Sekunden es gedauert hat“ – erstelle daraus deine eigene Bau-Timeline (in welcher Sekunde der erste Held kam, wann dein Tier-up fertig war) und vergleiche sie mit der von Top-Spielern;
- Lass den Agent sich selbst auswerten: siehe den Spielbericht in [Agent-Selbstiteration](https://war3ai.com/de/docs/agent-loop/).
