# Write a Bot with an LLM

> No coding required: you explain how you want it to play, and the LLM writes the code. Copy the prompt template, describe your strategy, run it, then have the model revise it.

Source: https://war3ai.com/en/docs/ai-bot/

This is for people who play Warcraft but don't code, and for developers who want to save time. The whole process is a conversation: **you describe the strategy → the model writes code → you play a game → you tell the model what happened → it revises**.

> **Tip**
>
> First set up your environment with [Quickstart](https://war3ai.com/en/docs/quickstart/) and get `hello_bot` running (you'll see peasants go mine gold). That way, when something goes wrong, you can tell whether it's the environment or the Bot.

## 1. Prepare materials for the model

How well the model writes depends mostly on whether it has read the right materials. Pick the option that matches your tool:

| What you're using | How to give it the materials |
|---|---|
| **A coding agent that can read your repo** (Claude Code, Cursor, Codex, etc.) | Open it in the repo directory and have it read `docs/BOT_HANDBOOK_ZH.md`, `docs/api.json` and one example first (`brains/examples/macro_bot.py` for economy, `micro_bot.py` for fighting) |
| **A chat model with web access** | Have it read [`https://war3ai.com/llms-full.txt`](https://war3ai.com/en/llms-full.txt) first — the entire site's docs are in that one file |
| **Web chat without web access** | Paste the handbook, [`api.json`](https://war3ai.com/en/api.json) and one example file after your prompt |
| **A local model** (LM Studio, Ollama) | Same as above. A context window of 32K tokens or more is recommended; otherwise the handbook and the API reference won't fit |

If you want a particular pro technique, also paste the matching recipe from the [Pro Playbook Cookbook](https://war3ai.com/en/docs/cookbook/).

## 2. Copy this prompt

Replace "The strategy I want" at the end with your own words — the more specific, the better:

```text
You are writing an AI (in Python) for Warcraft III 1.27. Use only the Game methods listed in api.json;
don't invent methods that don't exist. Follow the style of rush_bot.py: subclass openwar3.Bot and implement on_start(g) and on_tick(g).

Rules:
- on_tick is called about 5 times per second and must be fast (don't sleep inside it).
- Values that can't be read are None, not 0 — check before using them.
- Commands return a receipt (Receipt); `if r:` means "the engine accepted it"; when it wasn't accepted, `r.reason` says why
  (not enough food, not enough gold, target not visible, you already have this hero…) — try again next tick or try something else.
- To attack a specific enemy, use g.attack(units, enemy); the enemy must be in vision — ones you can't see are rejected.
- A dead hero must be revived with g.revive(altar); you can't train another one.
- Build with g.build_near(worker, building_code, x, y): it finds a spot that fits, tracks the result, and does nothing when you can't afford it.
- To know "what just happened" (who died, who took damage, a hero leveled up, an item dropped), implement on_event(g, ev).
- Don't re-issue the same command to the same unit every tick (it interrupts what the unit is doing); give orders to "idle" units.
- Only assign workers from idle_workers() to harvesting. At most 5 workers per gold mine.
- Queue only 1 unit at a time in training (queue the next when g.queue(building) is empty); to detect being food blocked, check g.production(building).blocked.
- When a tick issues many commands, wrap them in with g.batch(): (it waits on the game thread only once).
- To choose what to attack, use g.time_to_kill(my_group, enemy) (accounts for counters and armor); to choose where to go, use g.path_distance (returns None if unreachable).
- In fair mode you can only see what's in vision; for enemies you saw earlier, use g.last_seen().
- Units are four-character codes (Human Peasant hpea, Footman hfoo, Barracks hbar…), spells are order strings (thunderbolt Storm Bolt,
  blizzard Blizzard, holybolt Holy Light…, full table in data/order-ids.txt), and learning skills uses four-character codes (AHtb, AHbz…).

The strategy I want:
<Write it here in plain words, for example:
  "Human. At the start, 5 peasants on gold and 1 on lumber; Archmage first; two Barracks making Footmen and Riflemen;
   once I have 12 units, take the hero and attack the enemy expansion; retreat home when the hero drops below 30% HP;
   when creeping, go for the camps closest to home first.">
```

### How to describe your strategy clearly

Models struggle most with vague requests. Instead of "play more aggressively", this kind of information is much more useful:

- **Race and heroes**: which hero first, and the skill order (e.g. Archmage: Water Elemental, Blizzard, Water Elemental…).
- **Build order**: at which peasant count to build Barracks, when to tier up, how many Barracks.
- **Army composition**: Footmen + Riflemen? At what count do you move out?
- **Attack and retreat conditions**: how many units before attacking, what hero HP triggers a retreat, go home and rebuild after taking heavy losses.
- **Creeping**: creep or not, when (after nightfall?), only camps you can beat?
- **Fair or not**: if you plan to enter the Arena later, say "only use enemies visible in vision".

## 3. Run it

Save the model's code as `brains/my_bot.py`, then:

```bash
python tools/play.py --bot brains/my_bot.py --race 1 --difficulty 2
```

To see results faster, add `--speed 200` (2× game speed).

## 4. Have it revise

- **It errors out**: paste the **entire error** back to the model verbatim and say "fix this".
- **It plays badly**: describe **what you saw in the game**, not what you guess the cause is. For example: "the hero just stands at home", "units trickle in one at a time", "peasants crowd onto one mine".
- **You want to add a new tactic**: add one thing at a time, play a game to confirm nothing broke, then add the next.

> **Note**
>
> A coding agent that can run commands itself can take over steps 3 and 4 as well: play a game, read the logs and receipts, change the code, run again. For how to give it enough information, see [Agent self-iteration](https://war3ai.com/en/docs/agent-loop/).

## 5. Common problems

| Symptom | Most likely cause |
|---|---|
| Nothing moves | Wrong instance number (`--inst`), or the game hasn't started yet |
| Peasants don't mine | Orders were given to peasants who were already working; only assign from `idle_workers()` |
| Houses never get built | Use `build_near` instead of hard-coded coordinates; check whether the receipt's `reason` says you can't afford it |
| The hero never comes out | Check the `train` receipt: not enough food? Or did the hero die (use `revive`)? |
| The hero doesn't cast spells | The skill wasn't learned (`learn`) or there's no mana; after casting, check whether `cooldown()` shows a cooldown |
| Units twitch tick after tick | Commands are being re-issued every tick; only order idle units |
| No units come out and gold keeps rising | You're food blocked: check `g.production(barracks).blocked` |
| The model used methods that don't exist | Stress "only use methods in api.json" again in the prompt, and paste the complete api.json |

## Going further

- Every API and the underlying mechanism behind each one: [API reference](https://war3ai.com/en/api/);
- The reference brain (`brains/xwar3/strategy`) is a complete AI that expands, creeps and attacks. You can have the model read it for ideas, but it uses lower-level APIs, so copying it directly isn't recommended;
- Once you're on the [Arena](https://war3ai.com/en/arena/), you'll only be able to see enemies in vision — add `--fair` now to hold yourself to that, and you won't need changes later.
