IA de distintas personas, frente a frente en el mismo mapa
La justicia solo la puede garantizar un árbitro, no la buena voluntad del Bot. El Bot nunca toca la memoria compartida: solo recibe las observaciones que el árbitro filtra por visión, solo puede enviar acciones y cada acción se valida antes por propiedad.
Ordenados por “¿se puede garantizar la justicia?”
La capacidad de observación del proyecto nace de que “el cliente guarda el estado de todos los jugadores”, y eso también vale en tu propia máquina. Por eso la justicia solo puede venir de un árbitro en el que todos confíen. Primero A; el mismo protocolo escala directamente a B; C es solo para divertirse.
Arena local
Una máquina, una partida; cada Bot ocupa un slot y el proceso árbitro da las órdenes por ellos
Ladder alojado
A, trasladado a un servidor; los jugadores suben su Bot y el servidor lo ejecuta en un sandbox
Cada uno en su equipo
Cada persona ejecuta juego + Bot en su máquina y juegan por LAN
Un proceso que da las órdenes de ambos bandos
- Orquestación Elige el mapa, inicia la partida, fija raza y dificultad por slot
- Ritmo Un tick cada T milisegundos de juego (200 por defecto); en modo lockstep, el juego se pausa mientras se envían las observaciones
- Observación Snapshot → filtrado por la visión de cada slot → JSON
- Acciones Valida “la unidad pertenece a este slot” → presupuesto (acciones por tick, APM) → envío por lotes por el carril rápido
- Registro Resumen de la observación de cada tick + cada acción: repetible, analizable, útil como datos de entrenamiento
- Veredicto Un slot sin edificios → eliminado; tiempo agotado → se decide por fuerza militar / recursos restantes
Entra la observación, sale la acción
Cualquier programa que envíe y reciba JSON puede jugar, incluso un LLM que emita acciones tick a tick. Un Bot de Python escrito con el SDK no necesita cambios.
| Observación | Solo unidades propias + enemigos dentro de tu visión; creeps y minas de oro según visión o públicos desde el inicio |
| Límite de acciones | Máximo 32 por tick; el resto se descarta (para que el spam de comandos no ralentice al árbitro) |
| Misma unidad | En un tick solo cuenta la última acción |
| Presupuesto de tiempo | Duración del tick × 0.9; si se agota, ese tick se pasa. El lento sale perdiendo sin frenar a los demás |
| Lockstep | Si se exige justicia estricta, el juego se pausa al enviar observaciones y se reanuda cuando llegan todas (o hay timeout): la velocidad de cada máquina no influye en el resultado |
| Intercambio de inicio | Cada pareja de Bots juega una vez desde cada lado, para eliminar la asimetría del mapa |
| Ladder | Elo / TrueSkill; al menos 20 partidas por pareja antes de sacar conclusiones (con 2 partidas, la diferencia mínima detectable en tasa de victorias es de unos 60 puntos porcentuales) |
{"t": "obs", "tick": 57, "gameMs": 11400, "me": 1,
"res": {"gold": 320, "lumber": 150, "food": [18, 30]},
"units": [
{"id": 101, "type": "hfoo", "owner": 1,
"x": -4500, "y": 2200, "hp": 380, "hpMax": 420}],
"visibleEnemies": [
{"id": 733, "type": "ogru", "owner": 2,
"x": -3900, "y": 2500, "hp": 700}],
"deadlineMs": 180} id es un identificador estable asignado por el árbitro, fijo durante toda la partida. {"t": "act", "tick": 57, "actions": [
{"do": "attack", "unit": 101, "target": 733},
{"do": "train", "unit": 5, "code": "hfoo"},
{"do": "cast", "unit": 7, "spell": "thunderbolt", "target": 733},
{"do": "move", "unit": 102, "x": -5000, "y": 2000}]} category == "command", con los mismos nombres de parámetro. Un act que llega tarde se descarta y ese tick cuenta como pasado. from openwar3 import Bot
class MyBot(Bot):
def on_tick(self, g): # mismo código: en local g es Game; en la Arena, ArenaGame
for w in g.idle_workers():
g.gather(w, g.nearest(g.gold_mines(), w))
# En local: python tools/play.py --bot my_bot.py --fair
# En la Arena: mismos métodos, por debajo va WebSocket; el código del Bot no cambia ni una línea Game por ArenaGame. En orden; si uno no pasa, no se hace el siguiente
| # | Experimento | Criterio | Ya sabemos |
|---|---|---|---|
| 1 | Abrir 2 slots en una partida, ninguno con la IA integrada | Las unidades de ambos lados no se mueven | Se conocen el indicador de IA del slot y el campo de dificultad |
| 2 | Dar órdenes a slots distintos del local | Los campesinos del slot enemigo van de verdad a la mina | El más crítico: si falla, hay que pasar a “un cliente por Bot, con partida en red real” |
| 3 | Consultar la visión de cualquier jugador | El mismo punto da resultados distintos para dos slots | La comprobación de visibilidad del motor acepta cualquier número de jugador |
| 4 | Detectar victoria / derrota por programa | Saber en menos de 1 s que un bando perdió todos sus edificios | El bus de eventos tiene una entrada más directa |
| 5 | Pausa / reanudación en lockstep | Recoger acciones durante la pausa y aplicarlas al reanudar | Pausa ya verificada |
Una prueba de paso: hoy el cerebro de referencia depende mucho de la información de todo el mapa (por ejemplo, el objetivo de ataque de la IA rival). Para la Arena tendrá que usar la fachada y solo unidades dentro de su visión. Sin la información de todo el mapa, ¿cuánto nivel le queda?