# 예제 Bot

> 단순한 것부터 복잡한 것까지 네 가지 예제입니다. 모두 바로 실행할 수 있고, 로직 하나하나가 SDK 기능 하나에 대응합니다. 완전한 레퍼런스 브레인도 함께 제공합니다.

출처: https://war3ai.com/ko/docs/examples/

예제는 모두 `brains/examples/`에 있으며, 뒤의 예제가 앞의 예제를 상속해 새로운 것만 더합니다. 순서대로 읽기를 권장합니다.

| 예제 | 배우는 내용 | 실행 |
|---|---|---|
| `hello_bot.py` | 채집(금광 하나에 5명, 금광이 차면 벌목), 일꾼 생산(대기열에 1개만), 식량 건물 건설, 멈춘 건설 부지 이어 짓기. 네 종족 모두 실행 가능 | `python tools/play.py --bot brains/examples/hello_bot.py` |
| `rush_bot.py` | 병영과 제단(없으면 `build_near`로 건설), 영웅 우선 생산(죽으면 부활), 스킬 포인트가 있으면 습득, 한 웨이브가 모이면 공격 이동 | `… --bot brains/examples/rush_bot.py` |
| `macro_bot.py` | 건설 순서 + 다 지으면 알아서 금광 복귀(Shift), 식량이 막히면 즉시 보충, 병영 대기열 1개, 공격/방어 업그레이드, 티어 업과 고급 유닛, **실제 지상 이동 거리**로 목표를 고르고 경로를 따라 이동 | `… --bot brains/examples/macro_bot.py --speed 200` |
| `micro_bot.py` | 운영 위에서 전투를 맡음: 가장 빨리 잡을 수 있는 적 점사, 체력 낮은 유닛 빼기, 영웅 생존, 밤에 이길 수 있는 크립 캠프 골라 사냥, 적이 본진 앞까지 오면 수비 복귀. 한 틱의 명령은 한 배치로 전송 | `… --bot brains/examples/micro_bot.py --fair` |

> **참고**
>
> `hello_bot`과 `rush_bot`의 주석에는 실제 게임에서 겪은 함정이 기록되어 있습니다. 예를 들어 "매번 첫 번째 일꾼에게 건설을 맡겼더니 농장 3채가 모두 반쯤 지은 건설 부지로 남았다", "하드코딩한 병영 좌표가 하필 숲이라 3분 동안 한 채도 짓지 못했다" 같은 것들입니다. 코드보다 주석을 읽는 편이 얻는 것이 더 많습니다.

## hello_bot: 경제

```python
# 종족 -> (일꾼, 본진 건물들, 식량 건물)
RACES = {
    "h": ("hpea", {"htow", "hkee", "hcas"}, "hhou"),
    "o": ("opeo", {"ogre", "ostr", "ofrt"}, "otrb"),
    "u": ("uaco", {"unpl", "unp1", "unp2"}, "uzig"),
    "e": ("ewsp", {"etol", "etoa", "etoe"}, "emow"),
}
MINE_CAP = 5            # 금광 하나에 일꾼 최대 5명(더 늘려도 수입이 늘지 않음)
LUMBER_CREW = 5         # 벌목 인원: 금광마다 채금 5명 + 이 인원 = 일꾼 목표
```

세 가지를 합니다. 쉬고 있는 일꾼은 금을 캐러 보냅니다(금광마다 몇 명인지 직접 기록하고, 금광이 차면 벌목하러 보냄). 일꾼이 부족하면 생산합니다(대기열에는 1개만). 식량이 거의 차면 건설 중이 아닌 일꾼을 찾아 본진 건물 옆에 식량 건물을 짓습니다(휴먼과 오크는 멈춘 건설 부지에 일꾼을 보내 이어 짓기도 함).

## rush_bot: 병력 생산과 출격

`hello_bot`에 세 가지를 더합니다. 병영과 제단이 없으면 짓습니다. 제단에서 영웅을 뽑고(**죽었으면 먼저 부활**, 영웅은 유일함), 스킬 포인트가 있으면 배웁니다. 병력이 8기 모이면 전원을 적 본진 건물로 공격 이동시키고, 병력이 크게 줄면 본진으로 돌아와 다시 모읍니다. 틱마다 전투를 끊지 않도록 쉬고 있는 병력에게만 명령합니다.

## macro_bot: 운영 기본기

```python
TECH = {
    "h": dict(order=["halt", "hbar", "hbla", "hlum"], altar="halt", hero="Hamg", skills=["AHwe", "AHbz", "AHab"],
              barracks="hbar", soldiers=["hfoo", "hrif", "hkni"], smith="hbla", upgrades=["Rhme", "Rhar", "Rhra", "Rhla"],
              tiers=["hkee", "hcas"]),
    ...
}
```

프로 선수가 매 게임 하는 몇 가지 일이며, 각각이 SDK 기능 하나에 대응합니다. 건설 순서표 + `gather(..., queue="after")`로 다 지으면 금광 복귀, `production().blocked`로 식량 막힘 감지, `g.queue`로 병영 대기열을 1개로 유지, `can_do`로 다음 단계 공격/방어 업그레이드를 연구할 수 있는지 엔진에 질의, 티어 업과 고급 유닛(실게임 교훈: 계속 1티어에 머물다가 23분에 3티어 기사와 그리폰에게 밀려 전멸), `path_distance`로 목표 선택, `path()`로 경유점을 따라 이동.

## micro_bot: 전투가 시작된 뒤

```python
def _fight(self, g, army, foes, home, now):
    ...
    visible = [e for e in foes if e.visible_to(me)]              # 보이지 않는 대상은 거부됨(1001)
    atk = [s for s in (g.stats(u) for u in fighters) if s]
    target = min(visible, key=lambda e: _ttk(g, atk, e))         # 가장 가까운 적이 아니라 가장 빨리 잡을 수 있는 적
    idle_or_other = [u for u in fighters if g.current_target(u) is None
                     or g.current_target(u).handle != target.handle]
    if idle_or_other:
        g.attack(idle_or_other, target)
```

실게임: 5분 동안 1497틱, 명령 3023개, 오류 0건.

## 레퍼런스 브레인: 완전한 AI

`brains/xwar3/`는 멀티를 가져가고, 크립을 사냥하고, 출격까지 하는 완전한 AI이며, 세 계층으로 나뉩니다.

| 계층 | 위치 | 주기 | 하는 일 |
|---|---|---|---|
| 전략 레이어 | `strategy/` | 초 단위 | AMAI 방식의 다중 전략 선택과 전환, 건설표, 카운터 유닛, 영웅 선택. 선택 사항으로 [LLM 운영 코치](https://war3ai.com/ko/docs/llm-coach/) |
| 반사 레이어 | `reflex/`(독립 프로세스 4개) | 100 ms 단위 | 생존, 시전, 점사, 장비 줍기 |
| 승률 모델 | `worldmodel/` | — | 싸워서 이길 수 있는지 판단(추론 서브셋) |

여러 프로세스가 **점유 테이블**로 유닛을 공유하고, 우선순위에 따라 누구의 명령을 따를지 정합니다: 사람 95 > 생존 90 > 스킬 회피 85 > 시전 80 > 장비 줍기 70 > … > 전략 50 > 작업 배정 45. 여러분의 Bot은 테이블에서 `bot`이라는 신분을 쓰며, 기본 우선순위는 50입니다.

> **주의**
>
> 레퍼런스 브레인은 SDK의 저수준 계층(`w3cmd` / `act`)을 직접 사용하고, 맵 전체 정보에 크게 의존합니다. "아이디어" 참고용으로는 좋지만 LLM이 그대로 베끼게 하는 것은 권장하지 않습니다. 레퍼런스 브레인에는 AMAI 데이터가 필요합니다. `start.bat`이 처음 배포할 때 AMAI의 공개 저장소에서 받아와 생성합니다(AMAI는 자체 라이선스이며, 생성물은 git에 포함되지 않습니다. 실패했다면 `start.bat setup`으로 다시 시도하세요).

레퍼런스 브레인을 시작하는 가장 쉬운 방법은 [Farsight 콘솔](https://war3ai.com/ko/docs/console/)을 쓰는 것입니다. "인스턴스와 게임 시작" 페이지에서 인스턴스 번호를 체크하고 "테스트 시작"을 누르세요.
