Plataforma

Un runtime, un protocolo, el juego como entorno programable

W3 Runtime se inyecta en el juego original y, en el hilo del juego, recoge el mundo entero, ejecuta comandos e informa de los resultados. Tu IA solo tiene que decir “qué hacer” y habla con él mediante un protocolo versionado de memoria compartida.

Capas

Las capas inferiores no saben que existen las superiores

La capa de interfaz no tiene ni una línea de lógica sobre “atacar o no”; los cerebros no se importan entre sí y solo dependen del SDK. Es la condición para que exista la Arena: la plataforma solo necesita “capa de interfaz + árbitro”, y cualquier cerebro se puede conectar.

Tu agente / Bot
Cualquier modelo, cualquier lenguaje
Claude CodeCursorChatGPTQwen en localBot en PythonIA de referencia
Decisión
import openwar3 · o pasarela WebSocket / JSON · MCP
OpenWar3 SDK
Python · openwar3
Game / Botsnapshot w3worldcarril rápido w3fastcombat (cálculo de combate)pathing (rutas)w3claim (arbitraje)canvas (lienzo)jass (canal JASS)schemes (esquemas)
Interfaz
Mundo publicado cada 50 ms · comandos en ~1 fotograma · un recibo por comando
Protocolo W3P v2
Memoria compartida · cero copias · versionado
War3WorldWar3EventsWar3MapWar3TreesWar3Fast (carriles de comandos)War3Canvas (lienzo)
Protocolo
Ejecución por lotes en el hilo del juego · 4~8 µs por comando · 4 ms de presupuesto por vaciado
W3 Runtime
Se ejecuta en el hilo del juego
Publicador del estado del mundoFlujo de eventosEjecutor de comandos semánticosConsultasPermisos y perspectivaLienzo propioLlamadas JASSAdaptación de versionesSalud y disyuntores
Runtime
War3.exe 1.27 · juego original, sin modificar ningún archivo en disco
Información en tiempo real

Todo el mapa, cada 50 ms

El runtime recoge la información de una vez en el hilo del juego y la publica en memoria compartida; el cliente la lee directamente, sin volver a hacer cola en el hilo del juego. Una recogida tarda una mediana de 0.5 ~ 0.9 ms (100 ~ 120 unidades), y el desglose de tiempos queda siempre en la cabecera del bloque del mundo.

Jugadores ×16

Oro, madera, comida y límite, total recolectado, raza

Unidades ×1024

Tipo, dueño, coordenadas, vida y maná, orden actual y su objetivo, a quién ataca realmente, nivel, experiencia y puntos de habilidad, visibilidad para cada jugador

Detalle de unidades ×256

12 habilidades (nivel, enfriamiento restante), 8 buffs, 6 casillas de inventario; prioridad a los héroes

Producción ×128

Entrenamiento / investigación / construcción / mejora: cola, duración total, tiempo transcurrido, si está bloqueada

Objetos en el suelo ×256

Tipo, posición, durabilidad; recogerlos o usarlos genera un evento

Árboles ×4096

Posición y vida de los destructibles, actualizadas cada 2 segundos

Mapa

Malla transitable / edificable en celdas de 128, área jugable, puntos de inicio; se calcula en los primeros segundos de partida

Tiempo

Reloj de juego del motor, hora del juego (día y noche), velocidad, si hay partida en curso

Flujo de eventos Buffer circular de 8192 entradas, cada una con número de secuencia; si lees demasiado lento y se sobrescriben, el SDK lo detecta
unit.appearedunit.diedunit.removedunit.damagedorder.changedowner.changedhero.levelupitem.appeareditem.removedspell.castselection.changedmessageplayer.leftgame.startedgame.ended damage · Cada golpe, a nivel de motorkilled · Cada golpe, a nivel de motor production.done · También los del rival
Comandos semánticos

El camino lo decide el runtime

Recolectar, retirarse, lanzar hechizos… todo es “que una unidad haga algo”, pero dentro del motor cada caso sigue un camino distinto. Toda esa experiencia vive en el runtime: tú dices qué hacer y él lo ejecuta con una receta verificada y, en el mismo fotograma, devuelve como recibo la orden de antes y después del comando.

  • Un lote por envío, ejecutado en el mismo fotograma
  • Cada comando con recibo: código de estado + código de motivo del motor + tiempo de ejecución
  • Cola con Shift, waypoints, construcción en cadena
  • Consultas: niveles de tecnología, viabilidad, visibilidad, oro restante en la mina, objetivo de ataque de la IA rival
Recibos y códigos de motivo
moveattack_moveattackstopholdpatrolattack_groundgatherrepairbuildbuild_nearbuild_queuetraincancellearncastrallyrevivepick_upuse_itemdrop_itemgive_itemsell_itembuypathcall_to_armspausebatch
Baja latencia

Lo lento nunca fue cruzar procesos

Leer y escribir memoria compartida cuesta nanosegundos; leer un snapshot, ~0.05 ms. El canal antiguo era lento porque cada petición competía por un único cerrojo de toda la máquina y luego esperaba a que el juego volviera a leer mensajes (una vez por fotograma, 16 ~ 33 ms). El cerebro de referencia pasaba el 93% de su tiempo real esperando eso.

Antes · canal de control20 ~ 40 ms / petición
  1. Competir por el mutex global de la máquina
  2. Enviar un mensaje al hilo del juego
  3. Esperar a que el juego lea mensajes (una vez por fotograma)
  4. Esperar el evento de finalización y liberar el cerrojo

Con 6 procesos a la vez, el caudal se atasca en unas 88 peticiones/s.

Ahora · carril rápido~1 fotograma, por lotes
  1. Cada cliente tiene su propio carril: un escritor y un lector, sin cerrojos
  2. Se ejecuta dentro del despacho de eventos del hilo del juego (cientos de veces por segundo); sin envíos pendientes, el coste es de unas pocas comparaciones de enteros
  3. 16 comandos por envío, todos ejecutados en el mismo despacho; cada vaciado tiene un presupuesto de 4 ms
  4. Cada comando lleva un plazo: al reanudar tras una pausa, los comandos caducados no se ejecutan

El recibo de cada comando incluye su tiempo de ejecución, y la cabecera del carril guarda el más lento y cuánto tardó el último vaciado: se ve al instante dónde está la lentitud.

NivelCanalLatenciaQuién lo usaEstado
0 Snapshot publicado + flujo de eventos ~0.4 ms por lectura; uno nuevo cada 50 ms (ajustable a 16 ms) Todos los Bots Verificado en partida
1 Carril rápido ~1 fotograma; mediana de 0.06 ms con 6 procesos concurrentes, ~3000 comandos/s Por defecto en el SDK Verificado en partida
2 Canal de control 20 ~ 40 ms Respaldo y algunas operaciones de interfaz Verificado en partida
3 Pasarela (WebSocket / JSON) Nivel 1 + ~1 ms Cualquier lenguaje, páginas web, LLM (MCP), otra máquina Verificado en partida

Medido (instancia de prueba 1.27, 2026-09-23 / 24)

Caudal de comandos
Antes 88
3000 comandos/s
6 procesos concurrentes
Espera mediana con concurrencia
Antes 67 ms
0.06 ms
Canal de control antiguo → carril rápido
16 comandos
Antes 121 ms
13 ms
Uno a uno → en un solo lote
8 movimientos
Antes 68~99 ms
6.5~10 ms
with g.batch()
Una recogida del estado del mundo
Antes 11.8 ms
0.58 ms
En el hilo del juego; reutiliza las regiones de memoria ya confirmadas como legibles
Un comando al inicio de la partida
Antes 4~10 ms
4~8 µs
El muestreador señaló un log síncrono; ahora es asíncrono
Una ronda del cerebro de referencia
Antes 0.15~0.56 s
0.02~0.07 s
Partida de 39 minutos, 0 errores de tarea
Ronda más lenta del cerebro de referencia
Antes 1.3~3.2 s
0.24~0.42 s
Ninguna ronda ≥ 2 s en toda la partida

Notas de ingeniería: en los 3 primeros minutos, cada comando era 1000 veces más lento

Tras añadir el tiempo de ejecución a cada comando, vimos que en los primeros minutos de partida, a partir del segundo comando de cada lote, cada uno tardaba 4 ~ 10 ms, y hacia los 180 segundos de juego bajaba de golpe a unos pocos microsegundos. Con el muestreador del hilo del juego integrado en el runtime tomamos 1700 muestras, y el 93% caía en la propia función de log del runtime, que abría y cerraba el archivo de log de forma síncrona en cada línea; y al inicio de la partida, cada orden del motor escribía una línea. Con el log de depuración desactivado por defecto y la escritura a disco asíncrona, un comando en el segundo 14 de partida tarda solo 4 ~ 8 µs.

Creemos en lo que se mide, no en lo que se supone.

Permisos y perspectiva

Cada carril tiene un rol

La validación de propiedad y el filtrado por visión se hacen en el runtime: la capa de ejecución del motor no comprueba a quién pertenece una unidad, así que hay que hacerlo aquí. Dos IA enfrentadas son simplemente dos carriles player en la misma partida.

RolQué veQué puede hacer
player Todo lo propio + enemigos y neutrales dentro de su visión (modo justo) Solo puede mandar unidades propias
Jugadores, tu Bot
observer Todo el mapa No puede dar órdenes; puede consultar, controlar la cámara y leer el HUD
Dirección, comentaristas, análisis posterior
Soporte multiversión · P4

Sin adivinar, sin cuelgues

Las versiones 1.24 ~ 1.28 comparten la misma estructura de motor, ideal para “un runtime + varios perfiles”. A partir de 1.29, y en Reforged, el motor es otro; no se promete compatibilidad automática.

  1. Identificación Lee el recurso de versión y el hash de Game.dll para elegir el perfil
  2. Tabla de símbolos Las recetas referencian nombres de símbolos, no números; cada símbolo incluye su convención de llamada y la forma de sus parámetros
  3. Firmas de respaldo En versiones desconocidas, busca firmas de bytes al inicio de las funciones y solo usa una coincidencia única
  4. Autocomprobación al arrancar Cada símbolo se verifica sin efectos secundarios; las capacidades que fallan se marcan como no disponibles
  5. Lista de capacidades Si el SDK ve que una capacidad no está disponible, lanza un error claro al llamarla, en vez de devolver 0 en silencio
Alta disponibilidad

Un bug en un Bot no debe tumbar la partida

Por eso cada IA corre en su propio proceso: un puntero nulo dentro del proceso del juego tumba la partida entera; si cae un proceso independiente, solo se detiene ese bando.

MecanismoCómoEstado
No arrastrar al juego Todas las llamadas al juego protegidas contra excepciones; presupuesto de 4 ms por vaciado (temporizador de alta precisión) Listo
Clientes aislados Un carril por cliente, cada uno con su cuota; si uno se cuelga, no bloquea a los demás Listo
Lo caducado no se ejecuta Cada comando lleva un plazo; al caducar solo se marca, no se ejecuta, y no se repite al reanudar tras una pausa Listo
Observable Tiempo de ejecución de cada comando; el desglose de cada recogida va en la cabecera del bloque del mundo Listo
Reconexión El SDK se reconecta solo al cambiar de partida o de proceso Parcial
Disyuntor por capacidad Si una capacidad falla N veces seguidas → se marca como no disponible y se emite un evento; el resto sigue igual Planificado
Capa de extensión

Crea lo tuyo dentro del juego

Los comandos semánticos permiten a la IA jugar como un jugador; la capa de extensión te permite cambiar lo que el jugador ve y vive: dibujar tu propia interfaz clicable y llamar a todas las funciones que usan los autores de mapas. Los dos caminos se separan según “¿es seguro en multijugador?”.

Lienzo Seguro en multijugador
0.27 ~ 0.34 ms coste por fotograma (9 elementos, ~63 fotogramas/s)
  • Cuadros de texto, paneles, barras de progreso, imágenes, círculos pegados al terreno, rutas con flechas
  • Anclado a una unidad, a coordenadas del mundo o a una posición de pantalla; cualquier fuente (incluido el chino), esquinas redondeadas, transparencia, cualquier color
  • Lo dibuja el propio runtime: no crea objetos del juego ni cambia su estado
  • Una línea de Python por elemento; también por HTTP o escribiendo directamente en memoria compartida
  • Botones y tarjetas de elección clicables, resaltados al pasar el ratón; se dibujan debajo del puntero del ratón y el juego no recibe el clic que les das
Documentación del lienzo
Canal JASS Un jugador · herramientas locales
1291 funciones JASS, llamadas directamente por nombre
  • Crear unidades, cambiar atributos, efectos, paneles, diálogos, sonido, cámara, niebla, clima…
  • Consola Farsight, línea de comandos, HTTP y Python, con la misma forma de escribir scripts
  • Los efectos habituales, en una línea cada uno: texto flotante, líneas entre puntos, círculos de alcance, diálogo con retrato, filtros a pantalla completa
  • En multijugador solo se permiten funciones de lectura, para evitar desincronizaciones
Documentación del canal JASS
LienzoFunciones gráficas de JASS
Quién dibuja El runtime El propio juego
Multijugador Seguro: solo se dibuja en tu pantalla Solo en partidas de un jugador
Estilo Libre: fuentes, esquinas redondeadas, transparencia, imágenes Estilo nativo del juego
Sigue a Unidad / coordenadas del mundo / posición de pantalla Depende de la función
Coste 0.2 ~ 0.35 ms por fotograma ~13 ms por llamada
1291 funciones, por uso
Efectos visuales 80 Paneles de interfaz 146 Cámara 44 Sonido y música 50 Niebla y visión 25 Unidades 161 Objetos 63 Héroes 32 Jugadores / alianzas / recursos 71 Disparadores / temporizadores 62 Terreno / clima 45 Flujo de la partida 57

Lo que hace el jugador entra directamente en el flujo de eventos

El runtime informa directamente de lo que hace el jugador: qué botón dibujado pulsó, qué atajo de teclado usó, en qué punto del suelo hizo clic, a quién seleccionó, qué habilidad lanzó y qué escribió en el chat. Los eventos de disparador del propio juego (entrar en una región, botones de diálogo, flechas del teclado) se pueden seguir conectando con un disparador vacío: se registran solo los eventos, sin condiciones ni acciones, y se cuenta cuántas veces se ha ejecutado.