# Recibos y códigos de motivo

> El recibo de cada comando incluye un código de estado y un código de motivo. Son la base para que Bots y agentes se corrijan solos: convierten "por qué no se hizo" en un número legible por máquina.

Fuente: https://war3ai.com/es/docs/reason-codes/

```python
r = g.train(barracks, "hfoo")
bool(r)        # False
r.status       # 1              -> rejected
r.verdict      # 3              -> comida insuficiente
r.reason       # 'rejected（人口不够）'
r.exec_us      # microsegundos que tardó en ejecutarse en el hilo del juego
```

`if r:` equivale a `r.status == 0` (el motor lo aceptó).

## Códigos de estado `status`

| Código | Nombre | Significado | Causas habituales |
|---|---|---|---|
| 0 | `accepted` | El motor lo aceptó | — (pero aceptado ≠ hecho; ver abajo) |
| 1 | `rejected` | El motor lo rechazó | Mira `verdict` |
| 2 | `bad_unit` | La unidad no existe o el handle no coincide | La unidad ya murió; usaste un objeto de unidad caducado |
| 3 | `not_owner` | No es tu unidad | Mandar unidades ajenas con el rol `player` |
| 4 | `fault` | Excepción durante la ejecución (el runtime la contuvo; no tumba el juego) | Repórtalo con los pasos para reproducirlo |
| 5 | `bad_args` | Parámetros incorrectos | Coordenadas, índice de casilla o código de cuatro caracteres mal escritos |
| 6 | `unsupported` | No soportado | Esta versión del runtime no tiene esa capacidad |
| 7 | `bad_target` | Objetivo no válido | El objetivo ya no existe; el tipo de objetivo no es el correcto |
| 8 | `forbidden` | El rol del carril no lo permite | Dar órdenes con el rol `observer` |
| 97 | `cancelled` | Se lanzó una excepción dentro del bloque de lote y no se envió nada del lote | El código dentro de `with g.batch():` dio error |
| 98 | `held` | Una capa de mayor prioridad retiene la unidad y no se envió | La capa de reflejos del cerebro de referencia o las órdenes manuales de la consola tienen esa unidad |
| 99 | `timeout` | Tiempo agotado | Con el juego en pausa o atascado se superó el plazo (los comandos caducados no se ejecutan) |

## Códigos de motivo `verdict`

Cuando hay un rechazo, el runtime explica el motivo con la propia comprobación de viabilidad del motor. También puedes preguntar antes, sin dar la orden: `g.can_do(unidad, código)` devuelve los mismos códigos.

| Código | Significado | Qué hacer |
|---|---|---|
| 0 / 220 | Se puede | — |
| 3 | Comida insuficiente | Construye edificios de comida; `g.production(b).blocked` lo detecta antes |
| 8 | Oro insuficiente | Espera a tener oro; antes de ordenar, usa `g.can_afford(code)` |
| 9 | Madera insuficiente | Manda más trabajadores a talar |
| 32 | Cola de entrenamiento llena (7 huecos) | Solo 1 en la cola: pon el siguiente cuando `g.queue(b)` esté vacía |
| 183 | Falta una tecnología / edificio previo | Construye primero el edificio necesario o sube de tier |
| 185 | Edificio ocupado | El altar está reviviendo a un héroe; el ayuntamiento no puede mejorarse con la cola ocupada |
| 221 | No existe / en construcción / mejorándose / ya existe | Ya tienes ese héroe (si murió, usa `revive`); esta tienda no vende eso |
| 89 | La tienda aún no tiene existencias | Al inicio de la partida, cada objeto aparece según su tiempo de reposición en la tabla de objetos; en una tienda recién construida, se cuenta desde que se termina |
| 1001 | Objetivo no visible | El objetivo está en la niebla o en la máscara negra; usa `attack_move` hacia su posición |

## Aceptado ≠ hecho

El recibo solo indica que "el motor aceptó el comando" y se lee en el mismo fotograma. No cubre lo que pueda pasar después:

| Comando | Puede fallar aunque se haya aceptado | Cómo confirmarlo |
|---|---|---|
| Construir | Un punto dentro de un bosque también se acepta al momento; falla cuando llega el trabajador | Usa `build_near` (comprueba si aparecen los cimientos) o espera a `production.done` |
| Hechizo | Lo interrumpen o falta maná | En el siguiente tick, comprueba si `g.cooldown(u, habilidad)` ha entrado en enfriamiento |
| Entrenar | Entra en la cola, pero sin comida nunca empieza | `g.production(b).blocked` |
| Mover / atacar | Otra lógica (o una capa de mayor prioridad) lo cambia | `g.current_target(u)`, `g.order_of(u)` |

## Interfaces de consulta

Estas interfaces no dan órdenes; solo preguntan al motor. El resultado también va en el `value` del recibo (el SDK devuelve el valor directamente):

| Interfaz | Devuelve |
|---|---|
| `g.can_do(u, code)` / `g.can_do_many([(u, code), ...])` | Los códigos de motivo de la tabla anterior |
| `g.tech(code, player=None)` / `g.tech_many([...])` | Nivel de investigación / número de edificios terminados (cuenta la cadena de mejoras) |
| `g.visible(x, y)` | Si tu bando ve ese punto |
| `g.gold_left(mine)` | Cuánto oro le queda a la mina |
| `g.enemy_ai_plan(unidad_enemiga)` | Adónde va a llevar sus tropas el capitán de la IA rival (solo funciona con la IA del juego) |
