Mods de juego
Un esquema no tiene por qué ser una IA que juega por ti: también puede ser un conjunto de reglas. Juegas tú en la ventana del juego y el mod prepara el inicio, genera enemigos, da recompensas, te pone botones y tarjetas de elección en pantalla y decide el resultado. Hereda de openwar3.Mod: un archivo, un modo de juego.
Los esquemas de IA son de dos tipos: kind: bot es una IA que juega por ti; kind: mod es un conjunto de reglas: juegas tú en la ventana del juego y el mod plantea el reto: cómo se prepara el inicio, qué enemigos aparecen según el tiempo o los eventos, qué recompensas da, qué botones y tarjetas te pone en pantalla y cuándo se gana.
Un mod solo usa capacidades que ya existen: Interfaz y entrada (botones y tarjetas clicables, atajos de teclado, clics en el suelo), el lienzo (paneles, barras de progreso, rutas), el canal JASS (crear unidades, cambiar atributos, dar objetos) y el flujo de eventos (muertes, subidas de nivel, habilidades lanzadas, chat).
Dos ejemplos
Se eligen en Farsight, en “Esquemas de IA” → “Integrados”:
| Mod | Cómo se juega | Capacidades que usa |
|---|---|---|
Roguelike de héroe builtin/hero-roguelike | Solo tienes un paladín y los monstruos te rodean en oleadas desde todos los lados; cada vez que subes de nivel eliges una de tres mejoras en el centro de la pantalla (el juego se pausa mientras eliges); si aguantas 10 oleadas ganas, y si muere el héroe pierdes | g.ui.choice (tarjetas clicables + pausa), eventos hero.levelup / killed / spell.cast, -help en el chat, JASS para cambiar los atributos del héroe y dar objetos |
Defensa sin fin builtin/endless-defense | Los monstruos salen del punto de inicio contrario y cargan contra tu edificio principal siguiendo una línea roja en el suelo; cada oleada que resistes da oro; pulsa el botón en pantalla o F7 para llamar antes a la siguiente oleada, con recompensa ×1.5; pulsa F8 y haz clic izquierdo en el suelo para poner una torre de flechas gratis (clic derecho para cancelar) | g.ui.button, g.ui.hotkey, g.ui.mouse (captura de clics en el suelo), panel / barra de progreso / ruta del lienzo, JASS para generar monstruos y dar oro |
Cada ejemplo tiene unas 150 líneas; el código está en brains/examples/mod_hero_roguelike.py y brains/examples/mod_endless_defense.py.
python tools/play.py --bot brains/examples/mod_hero_roguelike.py --inst 9 # lanza una partida, el mod toma el control y tú juegas en la ventana del juego
Escribe un mod
from openwar3 import Mod
class Survive(Mod):
name = "survive"
def on_start(self, g):
super().on_start(g) # comprueba que es una partida de un jugador + neutraliza al rival del ordenador
self.foe = self.wave_player(g) # un jugador de una ranura vacía hace de «jugador de oleadas»: sin alianzas con nadie y sin IA del ordenador
self.every(30, self.wave) # una oleada cada 30 segundos de juego (se detiene durante la pausa)
g.ui.hotkey("F7", lambda g, ev: self.wave(g))
def wave(self, g):
self.spawn_ring(g, self.foe, "ugho", 6, self.home(g), 1400, attack_to=self.home(g))
def on_event(self, g, ev):
if ev.kind == "unit.died" and ev.type == "htow":
self.finish("loss", "Han destruido el edificio principal")
Mod añade lo siguiente a Bot:
| Método / atributo | Descripción |
|---|---|
on_start / on_tick / on_event / on_end | Igual que en Bot; si sobrescribes on_start / on_tick, llama primero a super() |
every(segundos, fn, first=) / after(segundos, fn) | Temporizadores que avanzan con el tiempo de juego; el callback es fn(g) |
finish(result, reason) | Termina la partida ('win' / 'loss' / 'unknown'): el ejecutor se detiene en el siguiente tick, dibuja un panel con el resultado en el centro de la pantalla y los resultados del esquema se registran según esto |
wave_player(g) | El primer jugador de ranura vacía, para usarlo como jugador de oleadas |
spawn_ring(g, jugador, unidad, cantidad, centro, radio, attack_to=) | Crea unidades en un anillo; aunque una oleada tenga decenas, no se atasca; devuelve handles de JASS |
alive_of(g, jugador) / attack_move_all(g, jugador, punto) | Las unidades vivas de un jugador / todas atacan-mueven hacia ese punto (llámalo cada pocos segundos y los monstruos te seguirán) |
home(g) / hud(g, título, líneas) | Posición de nuestro edificio principal / panel de información arriba a la derecha |
neutralize_ai = True | Neutraliza al rival del ordenador al empezar: sus unidades se pausan cada 5 segundos y su oro y su madera se ponen a cero. Los mapas de enfrentamiento siempre tienen un ordenador, y cuando el mod pone sus propias reglas no conviene que moleste |
single_player_only = True | Se niega a ejecutarse si hay otros jugadores humanos (el JASS que cambia el mundo desincronizaría a los demás) |
linger_s = 6 | Cuando hay resultado, cuántos segundos se queda en la pantalla del resultado antes de terminar |
finish() también funciona en Bot: un Bot normal también puede declarar el final por su cuenta.
Convertirlo en esquema y compartirlo
En scheme.json pon "kind": "mod" y define una subclase de Mod en el archivo de entrada:
{"id": "survive", "name": "Resiste 10 oleadas", "kind": "mod", "entry": "survive.py", "class": "Survive"}
Un mod nunca usa el modo justo (es el árbitro que plantea el reto: necesita ver todo el mapa y cambiar el mundo) y su resultado no se decide con las reglas de las partidas competitivas (lo comunica finish); aunque el manifiesto incluya fair / judge, no tienen efecto. Exportar el zip, importar, confiar y los resultados funcionan exactamente igual que en los esquemas de Bot; ver Esquemas de IA. Un mod también es código: antes de ejecutar por primera vez el mod de otra persona, también hay que confirmar la confianza.
Medido
2026-09-25, en la instancia de prueba:
- Roguelike de héroe: sale la primera oleada y el panel de arriba a la derecha se va actualizando; al subir el héroe a nivel 3 → aparecen las tarjetas en el centro de la pantalla y el reloj de juego se detiene; dos clics en tarjetas → se aplican dos mejoras (fuerza 22 → 27) y el reloj vuelve a correr.
- Defensa sin fin: el panel, la ruta en el suelo y el botón están ahí; F8 + clic en el suelo → aparece una torre defensiva junto al edificio principal; pulsar el botón antes de limpiar la oleada actual → aviso «esta oleada aún no está limpia».
Límites
- Solo en partidas de un jugador: crear unidades y cambiar atributos pasa por el canal JASS, que en multijugador desincroniza. Lo impone el modelo lockstep; los modos multijugador tendrán que esperar a un canal de sincronización (ver la hoja de ruta).
- El mod ve todo el mapa: es quien plantea el reto, no un jugador.
- En los mapas de enfrentamiento, el rival del ordenador solo queda «neutralizado», no eliminado (eliminarlo activaría la condición de victoria de las reglas de enfrentamiento).