Catálogo de API

103 interfaces, y cada una indica
“si está verificada, cuánto tarda y cómo funciona por dentro”

Generado desde el código con python -m openwar3 catalog --write y actualizado junto con el SDK: el modelo no tiene que adivinar qué métodos existen ni cuáles funcionan de verdad. Los mismos datos están en JSON, listos para dárselos a un agente.

58 Observación
28 Comandos
9 Control del juego
6 Sandbox
2 Conexión y utilidades
98 Verificado en partida
0 Experimental
5 Inferido / no probado del todo
103 interfaces

Observación 58

Leen el estado sin cambiar el juego. Casi todas leen directamente el snapshot publicado, sin espera.

Estado completo de todo el mapa (WorldState): .units .players .items .clock .me; las llamadas repetidas dentro de max_age segundos devuelven la misma copia. ⚠ Los trabajadores que están dentro de una mina de oro no aparecen; por defecto se ve todo el mapa (con el modelo lockstep, el cliente local lo tiene todo); solo Game(fair=True) filtra según la visión.

Mecanismo Bloque del mundo W3P Local\War3World_<pid> (el runtime lo publica cada 50 ms, seqlock)

Verificado en partida Snapshot publicado

Unidades enemigas (o 'creep' para creeps, o un número de jugador) vistas por última vez: [(la unidad tal como era entonces, reloj de juego en ese momento, segundos transcurridos)], las más recientes primero. Si la ves morir, se borra de la lista. Tanto en modo justo como en modo normal se registra según "lo que vemos en este momento": es el mapa que un jugador lleva en la cabeza: el ejército que ha explorado, dónde vio por última vez al héroe rival, cuándo abrió el rival su expansión. max_age: solo las de los últimos tantos segundos de juego.

Mecanismo visibleTo de la instantánea push (en cada refresco de la instantánea se registran las unidades enemigas / creeps visibles)

Verificado en partida Snapshot publicado

Tabla de terreno de esta partida, MapInfo: .walkable(x,y) .buildable(x,y) .at(x,y) .bounds (área jugable) .starts (puntos de inicio) .cells (bit0 no transitable, bit1 no edificable). Tarda unos segundos en calcularse al empezar la partida; hasta entonces devuelve None. Los árboles no están incluidos (usa trees()).

Mecanismo Bloque de mapa W3P Local\War3Map_<pid> (el runtime lo calcula por lotes al empezar la partida; IsTerrainPathable para caminar / construir)

Verificado en partida Snapshot publicado

Qué número de jugador soy (0~11).

Mecanismo cabecera del bloque del mundo

Verificado en partida Snapshot publicado

{'gold','lumber','food_used','food_cap','gold_gathered','lumber_gathered'}; player es nuestro jugador por defecto; se puede leer el de cualquier jugador. Si no se puede leer devuelve None; no lo trates como 0.

Mecanismo bloque del mundo players[16]

Verificado en partida Snapshot publicado

Los 16 slots de jugador: Player(id, gold, lumber, food_used, food_cap, gold_gathered, lumber_gathered, race, known).

Mecanismo bloque del mundo players[16]

Verificado en partida Snapshot publicado

Busca una unidad por su par de handles (lo, hi) (el objetivo de la orden, el objetivo de tarea y los eventos dan pares de handles).

Mecanismo bloque del mundo by_handle

Verificado en partida Snapshot publicado

Si es un edificio (torres incluidas). Se decide por velocidad de movimiento 0 en la tabla de unidades; la huella del edificio principal de los No-muertos es 0, así que no lo decidas por la huella.

Mecanismo instantánea + units.json (spd==0 = edificio)

Verificado en partida Snapshot publicado

Nuestros trabajadores (campesino / peón / acólito / fuego fatuo).

Mecanismo instantánea push

Verificado en partida Snapshot publicado

Trabajadores sin nada que hacer: sin orden y sin tarea (no cuentan los que acabas de mandar a trabajar en este tick). ⚠ Volver a dar la orden de recolectar a un trabajador que tiene tarea interrumpe el ciclo de recolección (los ingresos caen a cero).

Mecanismo instantánea push (slot de orden + slot de tarea)

Verificado en partida Snapshot publicado

Nuestros héroes vivos (los muertos están en la lista de resurrección del altar; ver revive).

Mecanismo instantánea push

Verificado en partida Snapshot publicado

Nuestras unidades de combate: ni trabajadores ni edificios.

Mecanismo instantánea push + units.json

Verificado en partida Snapshot publicado

Nuestros edificios (torres y cimientos en construcción incluidos); con types puedes pedir solo algunos tipos, p. ej. {'hbar'}.

Mecanismo instantánea push

Verificado en partida Snapshot publicado

Si este trabajador está construyendo (o va de camino a construir / está ayudando a reparar; incluye lo que acabas de ordenar en este tick). Sáltalo al elegir constructor; si no, los cimientos anteriores se quedarán parados.

Mecanismo instantánea push (orden = código de cuatro caracteres de un edificio, u orden de construir / reparar)

Verificado en partida Snapshot publicado

Este edificio aún no está terminado (vida no llena). ⚠ Un edificio dañado tampoco tiene la vida llena: basta para la apertura, pero una vez empiezan los combates hay que tener en cuenta también el tiempo.

Mecanismo instantánea push (la vida de los cimientos sube desde muy poco hasta el máximo)

Verificado en partida Snapshot publicado

Las minas de oro del mapa. ⚠ La mina de oro enredada de los Elfos de la noche y la mina neutral son dos unidades en las mismas coordenadas; manda a recolectar a la tuya.

Mecanismo instantánea push (ngol/egol/ugol)

Verificado en partida Snapshot publicado

Creeps (neutral hostil). ⚠ De noche la visión se reduce; cuando un campamento lejano queda en la niebla de guerra, los comandos dirigidos a él se rechazan (código de motivo 1001).

Mecanismo instantánea push (owner 12 = neutral hostil)

Verificado en partida Snapshot publicado

{'hp','hp_max','mana','mana_max'} (float, valores en bruto del motor). Para u basta con la unidad obtenida de la instantánea (se sustituye por la copia más reciente).

Mecanismo unidad del bloque del mundo hp/hpMax/mana/manaMax

Verificado en partida Snapshot publicado

{'level','xp','skill_points'}.

Mecanismo unidad del bloque del mundo level/xp/skillPoints

Verificado en partida Snapshot publicado

[{code, level, cooldown, flags}]; los buffs están en buffs(u). Solo las unidades "con detalle" lo tienen (héroes > unidades de jugador > creeps, hasta 256).

Mecanismo detalle del bloque del mundo: habilidades (código / nivel / flags / enfriamiento restante)

Verificado en partida Snapshot publicado

Códigos de buff que tiene la unidad (p. ej. 'BHds' Escudo divino, 'Bslo' Ralentizar). Qué efecto corresponde a cada código: ver data/game/buffs.json.

Mecanismo detalle del bloque del mundo: objetos de habilidad que empiezan por B

Verificado en partida Snapshot publicado

Segundos de enfriamiento que le quedan a esta habilidad (segundos de juego); 0 = se puede lanzar; si la unidad no tiene esa habilidad (o no tiene detalle) devuelve None.

Mecanismo detalle del bloque del mundo: enfriamiento restante de la habilidad (temporizador de la habilidad)

Verificado en partida Snapshot publicado

Códigos de cuatro caracteres de los objetos de las 6 casillas (casilla vacía = None); sin inventario devuelve None.

Mecanismo detalle del bloque del mundo: inventario de 6 casillas

Verificado en partida Snapshot publicado

{'order','target','x','y'}: la orden que la unidad está ejecutando (order es 0x000D00xx o el código de cuatro caracteres de un edificio; 0 = ociosa). target es un par de handles; conviértelo en unidad con g.unit(target).

Mecanismo unidad del bloque del mundo: order / objetivo de la orden / punto objetivo de la orden

Verificado en partida Snapshot publicado

La unidad a la que **realmente ataca / persigue** (si no hay, devuelve None). ⚠ Tras una orden de ataque, el slot de orden se vacía enseguida y el ataque queda en la tarea: para saber "a quién ataca" usa esto, no current_order.

Mecanismo unidad del bloque del mundo: objetivo de tarea

Verificado en partida Snapshot publicado

Reloj de juego del motor (segundos de juego; 0 durante la carga). A velocidad aumentada avanza más rápido que el reloj real.

Mecanismo cabecera del bloque del mundo clockMs (reloj de juego del motor)

Verificado en partida Snapshot publicado

Qué está haciendo este edificio: Production(kind, queue, duration, elapsed, blocked, progress, remaining…); si no hace nada, devuelve None. kind 'queue' (entrenamiento / investigación / héroe; queue tiene como máximo 7 casillas, [0] es lo que se está haciendo) / 'construction' (en construcción) / 'upgrade' (mejora del edificio principal / de una torre); blocked = hay cola pero no ha empezado (casi siempre falta comida: toca construir granjas); progress 0..1. También sirve para los edificios del rival (en modo justo, solo para los edificios visibles).

Mecanismo tabla de producción del bloque del mundo (objetos de habilidad Aque/ABnP/AUnP + tiempo transcurrido que sigue el runtime; error medido < 0.2 segundos de juego)

Verificado en partida Snapshot publicado

Códigos de cuatro caracteres de la cola de entrenamiento / investigación ([0] es lo que se está haciendo); ocioso o no es un edificio de producción = [].

Mecanismo tabla de producción del bloque del mundo

Verificado en partida Snapshot publicado

Toda la producción en curso [(edificio, Production)]. owner igual que en units(): 'me' / 'enemy' / número de jugador / 'all'. Uso profesional: ver qué unidades entrena el rival, qué tecnologías investiga y cuándo sube de tier (cuando has explorado sus edificios).

Mecanismo tabla de producción del bloque del mundo

Verificado en partida Snapshot publicado

Distancia que recorre una unidad terrestre de a a b (a y b pueden ser unidades o (x,y)); si no se puede llegar, None. En mapas con islas, úsalo para saber "si a este campamento de creeps / esta expansión se llega por tierra"; es más fiable que la distancia en línea recta (rodea bosques, acantilados y edificios). Precisión de una celda de 128; los huecos más estrechos que una celda se consideran cerrados.

Mecanismo bloque de mapa (IsTerrainPathable del motor) + bloque de árboles + huella de los edificios; A* en el lado del SDK (celdas de 128)

Verificado en partida Snapshot publicado + cálculo local

Si se puede llegar por tierra (bloque de mapa aún sin calcular = None).

Mecanismo igual que el anterior

Verificado en partida Snapshot publicado + cálculo local

Puntos de giro del camino [(x,y)...] (el último es b); combínalo con path(units, lista_de_puntos) para que las tropas sigan ese camino (esquivar torres, ir por atajos).

Mecanismo igual que el anterior

Verificado en partida Snapshot publicado + cálculo local

Nivel de mantenimiento: {'level': 'none'/'low'/'high', 'income': 1.0/0.7/0.4, 'next_at': comida del siguiente nivel (si no hay = None)}. Sabiduría profesional: quédate en 50 de comida mientras subes a tier 3 / investigas mejoras de ataque y armadura, y sube a 80 solo antes del combate decisivo.

Mecanismo regla fija de la 1.27: 0~50 de comida sin mantenimiento, 51~80 ingresos ×0.7, 81~100 ×0.4

Inferido Snapshot publicado

Experiencia que le falta al héroe para el siguiente nivel (nivel 10 = 0).

Mecanismo bloque del mundo level/xp + fórmula NeedHeroXP de MiscGame

Verificado en partida Snapshot publicado

Agrupa en campamentos los creeps (visibles) del mapa: [{'x','y','units','level','hp','max_level'}], de más cerca a más lejos de nuestra base principal. level = nivel total del campamento (la medida habitual de la dificultad del creeping), hp = vida total. Combínalo con time_to_kill / path_distance para elegir campamento.

Mecanismo instantánea push (creeps a menos de 600 entre sí agrupados en un campamento) + nivel de units.json

Verificado en partida Snapshot publicado

Qué es un código de buff: {'ability','effect','dur','hero_dur','targets'} (p. ej. 'Bslo' -> Ralentizar). Si un código tiene varias filas, devuelve la primera.

Mecanismo data/game/buffs.json (BuffID de AbilityData.slk -> habilidad / efecto / duración)

Verificado en partida Datos locales

Atributos de combate de la unidad, combat.UnitStats: vida / maná máximos, armadura (incluye mejoras de ataque y armadura y la agilidad del héroe), tipo de armadura, velocidad de movimiento, visión de día / de noche, armas (a qué puede atacar, alcance, intervalo de ataque, rango de daño, tipo de ataque, salpicadura). u puede ser una unidad (usa automáticamente las tecnologías de su dueño y el nivel del héroe) o un código de cuatro caracteres (player es nuestro jugador por defecto). Combínalo con .dps_vs(rival) / .hits_to_kill(rival) / combat.time_to_kill(grupo, rival). ⚠ No incluye objetos, auras ni buffs.

Mecanismo tablas de datos (UnitBalance/UnitWeapons/UpgradeData/MiscGame) + niveles de tecnología en tiempo real + nivel del héroe

Verificado en partida Snapshot publicado + carril rápido (un lote cada 5 s)

Cuántos segundos de juego tarda este grupo de unidades en matar a target atacando juntas (usa la vida actual de target; tiene en cuenta counters, armadura y mejoras de ataque y armadura; no tiene en cuenta el movimiento, la salpicadura ni la curación). Uso profesional: al concentrar fuego, ataca primero al que "muere más rápido" (el menor time_to_kill), no al más cercano. Si no se le puede atacar = None.

Mecanismo stats() + vida en tiempo real

Verificado en partida Snapshot publicado

Hora del día dentro del juego (horas, 0~24). La partida empieza a las 8 de la mañana; un día completo = 480 segundos de juego (240 s de día y 240 s de noche, escalados por la velocidad del ciclo día/noche). Si no se puede leer (runtime antiguo / fuera de partida) devuelve None.

Mecanismo zona de extensión del bloque del mundo: GetFloatGameState(GAME_STATE_TIME_OF_DAY)

Verificado en partida Snapshot publicado

Si ahora es de noche (18:00~6:00). Jugada profesional: de noche los creeps duermen (atacas primero sin que te rodeen) y la visión de todas las unidades se reduce (buen momento para emboscadas); los centinelas / unidades de los Elfos de la noche se vuelven invisibles de noche junto a los árboles. Si no se puede leer devuelve None.

Mecanismo zona de extensión del bloque del mundo (de día de 6 a 18 h)

Verificado en partida Snapshot publicado

Segundos de juego que faltan para que el reloj del juego marque la hora hour (p. ej. seconds_until(18) = cuánto falta para el anochecer; útil para planificar el creeping nocturno).

Mecanismo zona de extensión del bloque del mundo + día de 480 s (medido: 20 segundos de juego por hora)

Verificado en partida Snapshot publicado

Objetos en el suelo [Item(addr, handle_lo, handle_hi, type, x, y, life)]. Al recogerlos / usarlos se emite el evento item.removed.

Mecanismo bloque del mundo items[] (solo los del suelo: handle del portador todo FF)

Verificado en partida Snapshot publicado

Árboles vivos (los que tienen tree en targType de DestructableData); si das (x,y), se ordenan de más cerca a más lejos, como máximo limit. Cada uno es un Tree(addr, handle_lo, handle_hi, type, x, y, life) y se puede pasar directamente a gather para talar.

Mecanismo bloque de árboles Local\War3Trees_<pid> (se refresca cada 2 segundos)

Verificado en partida Snapshot publicado

Lo que ha pasado desde la última llamada: unit.appeared / unit.died / unit.removed / unit.damaged / order.changed / hero.levelup / owner.changed / item.appeared / item.removed / game.started (estos salen de comparar publicaciones; precisión = periodo de publicación, 50 ms), además de damage / killed a nivel de motor (el runtime los registra en el hilo del juego en el momento en que ocurren, así que hay uno por **cada golpe**): damage: handle = quien recibe el golpe, .source_addr = quien golpea (conviértelo en unidad con snapshot().unit_by_addr), .value = vida perdida real, .raw_damage = daño antes de armadura, .attack_type (normal/pierce/siege/magic/chaos/hero/spell), .damage_type killed: este golpe lo mató, .source_addr = el asesino y production.done, que el runtime obtiene siguiendo la tabla de producción (precisión = periodo de publicación): unidad = el edificio, .done_code = código de cuatro caracteres de lo terminado, .done_kind = 'training' (unidad / héroe / resurrección) / 'research' / 'construction' (edificio terminado) / 'upgrade' (subida de tier / mejora de torre), .value = segundos de juego que tardó Añadidos el 09-25: spell.cast: unidad = quien lanza, .spell código de cuatro caracteres de la habilidad, b nivel, value segundos de enfriamiento, x,y punto de lanzamiento (se detecta cuando la habilidad entra en enfriamiento; precisión = periodo de publicación) player.left: .player número del jugador que se fue / fue eliminado por derrota; game.ended: se sale de la partida selection.changed: cambió la selección del jugador local (obtén las unidades con g.selection()) message: una línea de un marco de mensajes de la pantalla (avisos del juego, chat, sistema): .text texto completo, .frame número del marco de mensajes, .chat = {'channel', 'sender', 'text'} (si es chat; lo que el jugador escribe en el chat se lee de aquí) ui.click / ui.hover / hotkey / mouse.world: interfaz y entrada (g.ui); .key es la key del lienzo / el atajo tal como se escribió Cada uno es un Event(seq, kind, clock, addr, handle, type, owner, a, b, x, y, value, extra). En modo justo (fair=True) solo llegan: eventos de tus propias unidades, eventos de unidades visibles en este momento (o que lo eran hace menos de 1 segundo), el daño que recibimos / que hacemos, y los eventos locales de interfaz / mensajes / partida.

Mecanismo anillo de eventos Local\War3Events_<pid> (comparación de publicaciones + eventos de daño capturados por el runtime)

Verificado en partida Snapshot publicado

Unidades que tiene seleccionadas ahora el jugador local (la unidad principal primero; como máximo 12). Cuando cambia la selección se emite el evento selection.changed.

Mecanismo zona de extensión del bloque del mundo W3P, selAddrs (el runtime incluye la selección del jugador local en cada publicación)

Verificado en partida Snapshot publicado

Mensajes nuevos en los marcos de mensajes de la pantalla desde la última llamada: [{'text', 'frame', 'repeat', 'seq', 'game_ms'}]. Aquí están los avisos del juego («Necesitas más granjas», «No se puede construir ahí»), el chat y los mensajes del sistema; frame indica de qué marco de mensajes se trata. Son los mismos que los eventos message del flujo de eventos (cada uno con su propio cursor).

Mecanismo memoria compartida Local\War3Msgs_<pid> (mensajes en pantalla capturados por el runtime)

Verificado en partida Snapshot publicado

Nivel de investigación / número de edificios terminados (cuenta la cadena de mejoras: un Castillo también cuenta como htow). player es nuestro jugador por defecto; se puede consultar cualquier jugador.

Mecanismo consulta W3P q_tech (recuento de tecnología del jugador en el motor)

Verificado en partida Carril rápido

Veredicto de viabilidad del motor: 0/220 se puede ordenar; 3 comida, 8 falta oro, 9 falta madera, 32 cola llena, 183 falta un requisito previo, 185 el altar está reviviendo, 221 no existe esa opción / en construcción. ⚠ Para un trabajador que construye un edificio siempre da 221; no sirve para comprobar dónde colocarlo (usa build_near).

Mecanismo consulta W3P q_feasible (comprobación de viabilidad del motor)

Verificado en partida Carril rápido

Muchos can_do de una vez: pairs = [(unidad, código de cuatro caracteres), ...]; devuelve la lista de códigos de veredicto en el mismo orden (los que no se pudieron consultar son None). Al planificar qué construir / entrenar en un tick, pregúntalo todo junto primero: es N veces más rápido que ir can_do por can_do (cerebro de referencia, 09-23: planificación de construcción de 76 -> 25 ms).

Mecanismo consulta W3P q_feasible × N, enviadas en un lote

Verificado en partida Carril rápido × 1

Consulta de una vez muchos recuentos de tecnología / edificios: {código de cuatro caracteres: cantidad o None}.

Mecanismo consulta W3P q_tech × N, enviadas en un lote

Verificado en partida Carril rápido × 1

Si ahora vemos este punto (no está en la niebla de guerra / zona negra). Un bot en modo justo solo debería usar enemigos visibles.

Mecanismo consulta W3P q_visible (visible / niebla de guerra / zona negra)

Verificado en partida Carril rápido

Cuánto oro le queda a la mina.

Mecanismo consulta W3P q_mine_gold (oro restante en la mina según el motor)

Inferido Carril rápido

El capitán de la IA del ordenador: adónde lleva a sus tropas (antes de salir ya sabe qué parte de tu base va a atacar). Solo funciona contra rivales del ordenador; si la unidad no sigue a un capitán, devuelve None.

Mecanismo consulta W3P q_captain (el capitán del ordenador al que sigue la unidad enemiga)

Verificado en partida Carril rápido

La orden actual de la unidad, **incluida la que acabas de dar en este tick** (mientras la instantánea no se pone al día, usa la orden nueva del recibo). ⚠ Partida real del 09-23: hello_bot acababa de mandar a un campesino a construir una granja y, en el mismo tick, rush_bot lo vio "ocioso" en la instantánea y lo mandó a construir un cuartel; la granja se quedaba a medias una y otra vez. Para elegir unidades "ociosas / que no están construyendo", usa esto en lugar de u.order.

Mecanismo orden de la instantánea + comandos de este proceso recién aceptados (recibos)

Verificado en partida Snapshot publicado

Si el oro / la madera actuales alcanzan para comprar code (unidades, edificios; según los precios de units.json). Lo que no está en la tabla de precios se considera siempre asequible. ⚠ Los códigos de subida de tier tienen precio acumulado en la tabla, así que aquí el resultado es conservador; lo que cuenta al final es el recibo del motor.

Mecanismo nuestros recursos de la instantánea push + precios de units.json

Verificado en partida Snapshot publicado

Datos del mapa que se está jugando (openwar3.mapdata.MapData): name_of('HC07') da el nombre de unidades / objetos / habilidades personalizados; también hero_names y tooltip. En los mapas RPG la mayoría de las unidades las crea el propio mapa y no están en la tabla de nombres integrada; si la partida no la arrancó el lanzador (no se encuentra el archivo del mapa), devuelve None.

Mecanismo archivo del mapa (la ruta --map del lanzador): w3u/w3t/w3a + wts; en mapas protegidos lee los TXT del propio mapa

Verificado en partida Lee archivo (la 1.ª vez ~0.1 s)

Comandos 28

Hacen que las unidades actúen. Se aplican en ~1 fotograma, cada uno con su recibo.

Agrupa en un lote los comandos de un tick: with g.batch() as b: g.attack(archers, target) # devuelve Pending; se convierte en recibo al cerrar el bloque g.move(wounded, *home) g.cast(hero, "thunderclap") print(b.sent, b.wait_ms, [r.reason for r in b.receipts]) Cada comando enviado por separado espera una vez a que lo procese el hilo del juego (unos 10 ms); un lote espera una sola vez: así el cerebro de referencia (09-23) bajó una ronda de 48 -> 26 ms. * El arbitraje sigue pasando comando a comando (una unidad reservada recibe en el acto un recibo held y no entra en el lote); * Dentro del bloque los comandos devuelven Pending: leer su .ok antes de cerrar el bloque lanza un error (el recibo aún no existe); después se usa igual que un Receipt; * Una excepción dentro del bloque = se descarta el lote entero (status 97 cancelled) y se liberan las unidades reservadas; * Las consultas (can_do / tech / visible …), build_near y buy no entran en el lote y se preguntan en el acto, como siempre: su resultado se necesita al momento; para preguntar muchas cosas de una vez usa can_do_many / tech_many; * Un with g.batch() anidado se une al lote más externo; con más de 16 comandos, el runtime lo divide automáticamente en tramos (una espera por tramo).

Mecanismo los comandos del bloque se acumulan en un lote que se envía de una vez al cerrar el bloque (se ejecutan en el mismo frame; una sola espera al hilo del juego)

Verificado en partida Carril rápido × 1

Ir a (x,y) sin atacar por el camino (úsalo para retirarte). Puedes pasar una unidad o una lista (reciben la orden juntas en el mismo frame). queue='after': ir después de terminar lo que está haciendo (se inserta tras la orden actual). values[0] del recibo = cuántas órdenes tiene en cola la unidad tras recibir esta (incluida la que está ejecutando).

Mecanismo W3P point: move (bits de extra = modo de cola)

Verificado en partida Carril rápido

Atacar a target. Por defecto usa el clic derecho (sobre un enemigo = atacar a ese en concreto; medido el 09-23: el objetivo de la orden y el objetivo de tarea son esa unidad). ⚠ El objetivo tiene que estar en tu campo de visión; si no se ve, se rechaza (código de motivo 1001). force=True usa la orden de ataque 0x0F (necesaria para atacar a unidades propias / animalillos neutrales). Medido: solo cambia a la orden de ataque sin recordar el objetivo, y la unidad se va a atacar a otro enemigo cercano; no la uses para atacar a un objetivo concreto.

Mecanismo W3P target: comando a un objetivo (clic derecho, smart)

Verificado en partida Carril rápido

Detiene todo lo que esté haciendo (ID de orden 0x000D0004) y también vacía las órdenes en cola.

Mecanismo W3P immediate: stop

Verificado en partida Carril rápido

Mantener posición (no persigue; solo ataca lo que está a su alcance).

Mecanismo W3P immediate: holdposition

Verificado en partida Carril rápido

Atacar el suelo: la artillería dispara a una zona (contra unidades invisibles, contra lo que hay detrás de un bosque, para cerrar un paso). Solo lo aceptan las unidades que pueden atacar el suelo.

Mecanismo W3P point: attackground (unidades de asedio / morteros / catapultas)

Verificado en partida Carril rápido

Cancela: la última casilla de la cola de entrenamiento / investigación (devuelve el dinero), un edificio en construcción (devuelve el 75 %) o un edificio principal que se está mejorando.

Mecanismo W3P immediate: cancel

Verificado en partida Carril rápido

Recorre una serie de puntos en orden (puntos encadenados con Shift: waypoints, esquivar torres, rutas de exploración). Con attack=True, cada tramo es un atacar-mover. Se envía de una vez; hay un recibo por punto (en el orden de points).

Mecanismo un lote: el primer tramo se ejecuta al momento y el resto se inserta en orden inverso con queue='after' (el motor solo permite insertar tras la orden actual)

Verificado en partida Carril rápido × 1

Recolectar oro / talar (target es una mina de oro o un árbol de trees()). ⚠ Asígnalo solo a trabajadores ociosos (idle_workers): repetir la orden a uno con tarea interrumpe el ciclo de recolección. Uso profesional: volver a minar al terminar de construir = gather(worker, mine, queue='after') después de build(...).

Mecanismo W3P target: harvest (mina de oro o árbol)

Verificado en partida Carril rápido

Hace que el trabajador construya code en (x,y) (coordenadas alineadas a 32). Recibo aceptado = la orden del trabajador ya es ese edificio (o la orden de empezar la obra); con queue='after' = entró en la cola de órdenes del trabajador (values[0] del recibo = número en cola). ⚠ Aceptado ≠ construido: el motor también acepta en el acto un punto dentro de un bosque, y el trabajador solo falla al llegar (medido el 09-23); si el dinero se gasta en otra cosa, los cimientos tampoco aparecen. Si no sabes dónde cabe, usa build_near (sigue el resultado y pone en la lista negra los puntos que fallan). Para construir varios seguidos, usa build_queue.

Mecanismo W3P build: orden de construcción; se confirma leyendo la orden del trabajador en el mismo frame

Verificado en partida Carril rápido

Un trabajador construye varios edificios seguidos en orden (encadenados con Shift): plan = [(código de cuatro caracteres, x, y), ...]. Se envía de una vez; los recibos siguen el orden de plan. ⚠ El dinero se descuenta al empezar cada obra (no al encolar): si encolas 3 y solo tienes dinero para 1, los otros dos fallarán cuando el trabajador llegue.

Mecanismo un lote: el primero al momento y el resto en orden inverso con queue='after'

Verificado en partida Carril rápido × 1

Busca alrededor de (x,y), de cerca a lejos, un punto donde quepa code y lo construye. **No bloquea**; puedes llamarlo en cada tick: * hay un intento de este edificio todavía en curso (el trabajador va de camino) -> devuelve ese punto y no repite la orden; * el intento anterior tuvo éxito (aparecieron los cimientos) -> esta vez busca un punto nuevo si hace falta; * el intento anterior falló (el trabajador llegó y vio que no cabía; el motor retiró la orden y no hay cimientos) -> ese punto va a la lista negra 45 segundos y se prueba el siguiente; * falta dinero -> devuelve None directamente (ni prueba ni pone en la lista negra); si se agotan los puntos, devuelve None. ⚠ Por qué hace falta el seguimiento: en partidas reales del 09-23, el motor **aceptaba en el acto** un punto dentro de un bosque y el trabajador solo fallaba al llegar (el recibo del mismo frame no puede detectarlo); y la comprobación de ubicación del motor siempre devuelve 221 para un trabajador que construye, así que tampoco se puede "consultar" antes de construir. Solo los puntos claramente ocupados (el centro del ayuntamiento) se rechazan en el acto.

Mecanismo build punto a punto + seguimiento (aparecen los cimientos = éxito; el trabajador abandona la orden sin cimientos = ese punto a la lista negra)

Verificado en partida Carril rápido × puntos probados

Entrena unidades / investiga tecnologías / mejora el edificio principal (subir de tier = dar al propio edificio principal el código de cuatro caracteres del edificio de destino, p. ej. 'hkee'). Si se rechaza, el reason del recibo dice por qué (falta comida, falta oro, falta madera, cola llena, falta un requisito previo…).

Mecanismo W3P immediate: código de cuatro caracteres; si se rechaza, incluye el código de motivo de viabilidad

Verificado en partida Carril rápido

El héroe aprende una habilidad (código de cuatro caracteres, p. ej. 'AHbz' Ventisca).

Mecanismo W3P learn: solo cuenta como aprendida si bajan los puntos de habilidad

Verificado en partida Carril rápido

Lanza un hechizo. spell es un nombre de orden ('thunderbolt' Martillo de tormenta, 'blizzard', 'holybolt' Luz sagrada…; ver data/order-ids.txt) o un ID de orden. Con target = sobre una unidad; con x,y = sobre el suelo; sin ninguno = sin objetivo (Atronar, Escudo divino, Invocar elemental de agua). Que el recibo diga aceptado solo significa que el motor lo aceptó; para saber si se lanzó, mira si cooldown() entró en enfriamiento o si apareció algo en buffs().

Mecanismo W3P target / point / immediate (según los parámetros)

Verificado en partida Carril rápido

Revive en el altar a un héroe muerto (si no das hero, revive al primero de la lista). Motivos de rechazo frecuentes (aparecen en el reason del recibo): falta comida (los héroes también ocupan comida), falta dinero, murió hace muy poco (solo puede revivir unos 3 segundos de juego después de morir), ya hay una resurrección en curso (al aceptarla, el motor vacía esa casilla en el acto).

Mecanismo W3P revive: lista de héroes muertos -> el altar lanza la resurrección sobre el héroe muerto

Verificado en partida Carril rápido

El héroe va a recoger un objeto del suelo (item sale de items_on_ground). Al recogerlo aparece en el inventario y se emite el evento item.removed para el suelo.

Mecanismo W3P target: clic derecho sobre el objeto

Verificado en partida Carril rápido

Usa el objeto de la casilla slot (0~5) del inventario; admite una unidad objetivo o un punto objetivo. ⚠ Al usar un objeto sobre un punto (p. ej. Ivory Tower), el motor devuelve 0 incluso si tiene éxito, así que el recibo siempre cuenta como aceptado: mira si esa casilla del inventario se vació.

Mecanismo W3P use_item (por número de casilla)

Verificado en partida Carril rápido

Suelta en (x,y) lo que haya en la casilla slot del inventario (el héroe camina hasta allí y lo deja).

Mecanismo W3P item_drop (copia de JASS UnitDropItemPoint: dropitem 0xD0021 a un punto + el objeto como objetivo inmediato)

Verificado en partida Carril rápido

Da lo que haya en la casilla slot del inventario a to (otro héroe / unidad; camina hasta él y se lo entrega). Dárselo a una tienda = venderlo (ver sell_item).

Mecanismo W3P item_drop (copia de JASS UnitDropItemTarget: dropitem sobre una unidad)

Verificado en partida Carril rápido

Vende a una tienda lo que haya en la casilla slot del inventario (el héroe tiene que ir junto a la tienda; solo acepta objetos vendibles y devuelve la mitad del precio).

Mecanismo igual que give_item, con una tienda como objetivo (medido: el Staff of Sanctuary se vende por 125 de oro)

Verificado en partida Carril rápido

Cambia de casilla dentro del inventario (de la casilla slot a la casilla to_slot; si ambas tienen algo, se intercambian). Útil para ordenar las teclas rápidas.

Mecanismo W3P target: orden 0xD0022 + número de casilla, objetivo = el objeto (copia de JASS UnitDropItemSlot)

Verificado en partida Carril rápido

Compra un objeto en una tienda (para el héroe que está junto a la tienda). Si falta un requisito tecnológico, el motor devuelve 0 y no cobra.

Mecanismo W3P buy: la tienda vende al héroe que está al lado

Inferido Carril rápido

Llamada a las armas de los Humanos: los campesinos se convierten en milicia (el ayuntamiento de tier 1 no tiene esta habilidad; solo funciona en el Torreón / Castillo).

Mecanismo W3P immediate: townbellon/off

Verificado en partida Carril rápido

Control del juego 9

Velocidad, pausa, ciclo de publicación, burbujas de diálogo, lienzo, interfaz y entrada, mensajes.

Interfaz y entrada (openwar3.ui.UI): botones y tarjetas de elección clicables, atajos de teclado, clics en el suelo para elegir una posición, a qué apunta el ratón. El juego no recibe el clic sobre un botón; es solo entrada local + dibujo local, así que también es seguro en multijugador.

Mecanismo W3P 74 input_enable + memoria compartida Local\War3Input_<pid> (el runtime recibe la entrada de la ventana)

Verificado en partida Memoria compartida

Pausa / reanuda el juego. Durante la pausa el reloj del motor se detiene, pero por el carril rápido se pueden seguir dando órdenes (el despacho de eventos sigue funcionando).

Mecanismo W3P pause

Verificado en partida Carril rápido

Periodo de publicación del estado del mundo (16~1000 milisegundos; por defecto 50). Cada recopilación cuesta unos 0.5 ms, así que 33 ms no es problema; el valor es único para toda la máquina y gana el último que se escribe.

Mecanismo bloque del mundo requestedPeriodMs

Verificado en partida Snapshot publicado

Muestra un bocadillo de chat sobre la unidad (para retransmisiones / depuración; no afecta al juego). Devuelve False si el bocadillo no apareció; el motivo queda en g.last_say_error.

Mecanismo acción 56

Verificado en partida Canal de control

Escribe una línea en la zona de mensajes de la esquina inferior izquierda del juego (solo se ve en esta máquina). Hay que esperar a que el juego muestre antes un aviso propio (la DLL captura el cuadro de mensajes a partir de ese aviso).

Mecanismo acción 45

Inferido Canal de control

Termina este proceso del juego (farm.py --keep abre automáticamente la siguiente partida según next_game.json).

Mecanismo acción 22

Verificado en partida Canal de control

Lienzo: dibuja sobre la pantalla del juego cuadros de texto, paneles, barras de progreso, imágenes, círculos en el suelo y rutas (openwar3.canvas.Canvas). Lo dibuja el propio runtime, sin crear handles del juego ni cambiar su estado: es seguro también en multijugador; estilo libre (chino, esquinas redondeadas, transparencia).

Mecanismo W3P 73 canvas_enable + memoria compartida Local\War3Canvas_<pid> (el runtime lo dibuja en cada fotograma justo antes de que el juego dibuje el puntero del ratón; el puntero queda por encima)

Verificado en partida Memoria compartida

Pulsa una vez la barra espaciadora en la pantalla de carga de "Pulsa cualquier tecla para continuar". Muchos mapas RPG / de campaña necesitan una tecla al terminar de cargar para empezar (medido el 09-24 con WarChasers: sin pulsarla se queda en la pantalla de carga, con el reloj de juego a 0 y el carril rápido sin vaciarse). openwar3.run la pulsa solo mientras espera a entrar en la partida; normalmente no hace falta llamarla a mano.

Mecanismo PostMessage WM_KEYDOWN/UP de la barra espaciadora a la ventana del juego (sin robar el foco)

Verificado en partida Mensaje de ventana

Sandbox 6

Canal JASS: crear unidades, fijar aliados, cambiar nombres, mostrar texto… para asistentes de RPG y compañeros; solo puede cambiar el mundo en partidas de un jugador y en herramientas locales.

Llama a cualquier native de JASS por su nombre: g.jass.CreateUnit(g.jass.Player(1), "Hpal", x, y, 270.0). Los parámetros I/R/B/S/H se convierten solos (las unidades y objetos se pasan tal cual); en multijugador solo se pueden llamar las de solo lectura. Detalles en openwar3/jass.py y docs/COMPANION_ZH.md.

Mecanismo W3P 70 jass (el runtime busca la native por nombre en su tabla de 1291)

Verificado en partida Carril rápido

Los 16 slots de jugador: controller (user = persona real / computer / neutral…), state (empty / playing / left), human, me, ally (si es aliado mío). En mapas RPG sirve para buscar un slot libre donde poner al compañero y para saber si la partida es de un jugador.

Mecanismo JASS GetPlayerController / GetPlayerSlotState / IsPlayerAlly

Verificado en partida Carril rápido

Crea una unidad en (x,y) (player es por defecto el jugador local) y devuelve la unidad de la instantánea (espera a la siguiente publicación del mundo, ~50 ms); si no se puede crear, devuelve None. La unidad devuelta tiene un atributo más, jass_handle. ⚠ Solo funciona en partidas de un jugador (en multijugador se desincroniza).

Mecanismo JASS CreateUnit + W3P 72 handle -> unidad

Verificado en partida Carril rápido

Fija la relación de alianza del jugador a hacia b: allied = no atacarse + pedirse ayuda; vision = visión compartida; control = control compartido de unidades (b puede mandar las unidades de a); xp = experiencia compartida. both=True fija los dos sentidos a la vez (control solo se fija de a -> b).

Mecanismo JASS SetPlayerAlliance

Verificado en partida Carril rápido

Cambia el nombre del jugador (el que aparece en el marcador, el chat y el panel de aliados). Sirve para ponerle nombre al compañero.

Mecanismo JASS SetPlayerName

Verificado en partida Carril rápido

Conexión y utilidades 2

Estado de la conexión y utilidades de cálculo puro.

Estado de la conexión: pid, publicación del mundo (periodo, tiempo de recopilación), contadores del carril rápido.

Mecanismo bloque del mundo + carril rápido + tabla de reservas

Verificado en partida Cálculo local

El candidato más cercano a to (una unidad o (x,y)); sin candidatos devuelve None.

Mecanismo cálculo puro

Verificado en partida Cálculo local