# 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.

Fuente: https://war3ai.com/es/docs/mods/

Los [esquemas de IA](https://war3ai.com/es/docs/schemes/) 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](https://war3ai.com/es/docs/ui-input/) (botones y tarjetas clicables, atajos de teclado, clics en el suelo), el [lienzo](https://war3ai.com/es/docs/canvas/) (paneles, barras de progreso, rutas), el [canal JASS](https://war3ai.com/es/docs/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`.

```bash
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

```python
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:

```json
{"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](https://war3ai.com/es/docs/schemes/). 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](https://war3ai.com/es/roadmap/)).
- 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).
