Las quince reglas
Cada una se aprendió a base de errores en partidas reales. Repásalas al escribir un Bot y te ahorrarás la mayor parte de la depuración.
Dale esta página junto con api.json a un LLM y el Bot que escriba dará muchos menos rodeos.
Leer el estado
1. Lo que no se puede leer es None, no 0
resources(), time_of_day(), production() y cooldown() pueden devolver None (cargando, la unidad no tiene detalle, el edificio no está produciendo…). Compruébalo antes de usarlo:
res = g.resources()
if res is None:
return
2. Identifica las unidades por handle, no por dirección
Las direcciones se reutilizan para unidades nuevas: una dirección antigua puede acabar apuntando a una unidad recién creada. Para recordar una unidad entre ticks, guarda u.handle y recupérala con g.unit(handle).
3. El flujo de eventos es global
production.done y unit.died incluyen también los del rival y los de los creeps. Filtra por ev.owner (o por el handle del edificio):
if ev.kind == "production.done" and ev.owner == g.me():
...
4. Los trabajadores dentro de una mina de oro no están en el snapshot
Cuando un trabajador entra en la mina desaparece del snapshot (unit.removed, no ha muerto). Para contar cuántos hay en cada mina, lleva tu propia cuenta y no la recortes según el snapshot; si no, mandarás más gente a minas que ya están llenas.
Dar comandos
5. Recibo “aceptado” ≠ hecho
El motor acepta al momento incluso un punto de construcción dentro de un bosque; falla cuando llega el trabajador. Las habilidades pueden interrumpirse. El efecto se ve en el snapshot y en los eventos: para construir, usa build_near (comprueba si aparecen los cimientos) y, para los hechizos, mira si g.cooldown() ha entrado en enfriamiento.
6. No se puede atacar lo que no se ve
Un comando con objetivo sobre un enemigo en la niebla se rechaza con el código de motivo 1001. Para perseguir a un enemigo en la niebla, usa attack_move hacia la última posición donde se le vio.
7. Da órdenes solo a las unidades ociosas
Repetir el mismo comando a la misma unidad en cada tick la interrumpe: las tropas se quedan temblando en el sitio y el ciclo de recolección de los trabajadores vuelve a cero. Para saber si una unidad está “ociosa”, usa g.order_of(u) (incluye lo que acabas de ordenar en este tick), no u.order del snapshot (el snapshot aún no se ha puesto al día).
8. Shift solo “inserta después de la orden actual”
El motor no tiene “añadir al final”: si envías B y C seguidos con queue='after', obtienes A, C, B. Para recorrer una serie de puntos en orden, usa g.path(units, puntos), y para que un trabajador construya varios edificios seguidos, g.build_queue(worker, plan): ambos insertan en orden inverso y lo resuelven por ti.
9. Los comandos de un tick, en un solo lote
Enviar decenas de comandos uno a uno supone esperar decenas de veces al hilo del juego; dentro de with g.batch(): solo se espera una vez.
Economía y producción
10. Como máximo 5 trabajadores por mina
Más no aumenta los ingresos. El objetivo de trabajadores depende del número de minas: 5 al oro por mina, más unos cuantos a la madera.
11. Solo 1 en la cola de entrenamiento
Llenar los 7 huecos deja el dinero bloqueado en la cola (en una prueba, el ayuntamiento tenía 4 campesinos en cola y 300 de oro bloqueado, y el inicio de partida fue mucho más lento). Pon el siguiente cuando g.queue(b) esté vacía.
12. Si falta comida, mira la tabla de producción
g.production(b).blocked = hay algo en cola pero no ha empezado; casi siempre, por falta de comida. Va un paso por delante de “construir cuando la comida esté casi al límite”: si pierdes un montón de tropas en un combate y la cola se atasca al reponerlas, lo sabes al instante.
13. El héroe es único, y sin la cola del ayuntamiento vacía no se sube de tier
- Si el héroe muere, solo puedes usar
g.revive(altar); entrenar otro se rechaza (221). Revivir también requiere comida (un héroe ocupa 5). - No se puede mejorar el ayuntamiento mientras quede algo en su cola (código de motivo 185, “edificio ocupado”).
Tiempo y espacio
14. A velocidad 2× no esperes según el reloj real
Para esperar 3 segundos de juego, comprueba que g.clock() haya avanzado 3; no uses sleep(1.5). Con la velocidad aumentada, el reloj del motor avanza más rápido que el reloj real.
15. En mapas con islas o bosques, no uses la distancia en línea recta
Para elegir campamentos de creeps o expansiones, usa g.path_distance(a, b) (A* por tierra, rodeando bosques, acantilados y edificios); si no hay camino, devuelve None. El punto más cercano en línea recta puede estar al otro lado del mar.
Una más: escribe en modo justo
Con --fair solo se ven las unidades, objetos, producción y eventos dentro de tu visión; es la regla de la Arena. Si escribes ya en modo justo, no tendrás que cambiar nada para la Arena. Más detalles en Modo justo.