# 📖 Manual de juego — Lesky's Shop (Legisladores del Bosque) > Un duelo de fichas en un tablero donde el verdadero campo de batalla > son **las leyes**: quien gana una ronda dicta una norma en lenguaje libre > que deforma el tablero para todos. Y cuidado: los rivales mienten. --- ## 1. El concepto Es una **campaña contra dos rivales**. Juegas con tus **fichas azules** 🔵 y debes derrotar, uno tras otro, a: 1. **Lesky** 🟡 — un duende legislador con pocos escrúpulos. Tablero **3×3**, **5 rondas**. 2. **The Monster** 🟢 — el jefe. Tablero **4×4**, **2 rondas**, más difícil. Vence a un rival y te llevas su **tesoro**; luego te enfrentas al siguiente. Ganar los dos tesoros = campaña completada. Cada ronda se disputa sobre el tablero, pero las **leyes activas** (el Pergamino) cambian sus valores y reglas. Ganar una ronda otorga el derecho a legislar; legislar bien es lo que gana partidas. ## 2. El tablero El tablero **cambia cada ronda**: se reparte una distribución nueva de valores (las casillas centrales suelen valer más que los bordes, pero la disposición varía). Un ejemplo típico de 3×3: ``` 2 1 2 1 3 1 2 1 2 ``` Las leyes pueden alterar estos valores (doblarlos, anularlos, sumarles puntos…), prohibir casillas o cambiar las reglas de choque. Contra el Monstruo el tablero es **4×4**, con más casillas y más en juego. ## 3. Una ronda, paso a paso 1. Cada jugador coloca sus fichas, una por turno: **3 fichas** en 3×3, **4** en 4×4. 2. La colocación es **simultánea**: tú y el rival elegís casilla a la vez, sin ver la elección del otro. 3. Si elegís **casillas distintas**, cada uno ocupa la suya. 4. Si elegís **la misma casilla**, hay choque (⚔️). Por defecto la casilla queda **disputada**: no es de nadie y no puntúa. Una ley puede cambiarlo (ver modos de choque). 5. Tras colocar todas las fichas se puntúa: **cada uno suma el valor de sus casillas**, con los modificadores de las leyes activas. El que más sume gana la ronda. 6. Si hay empate de puntos, nadie gana la ronda y nadie legisla. > **Cómo se gana la partida:** NO es "al mejor de 3". Se juegan todas las > rondas y gana quien acumule **más puntos totales** sumando todas las rondas, > con el bonus de astucia (**1 🦊 = +3 puntos**). Ver §6. ### Modos de choque | Modo | Qué pasa si ambos eligen la misma casilla | |---|---| | `disputed` *(por defecto)* | La casilla no es de nadie, no puntúa | | `mine_wins` / `red_wins` | Te la quedas tú | | `opponent_wins` / `blue_wins` | Se la queda el rival | | `split` (➗) | Cada uno suma la mitad de su valor | ## 4. Las leyes Al ganar una ronda, dictas una ley **escribiendo una frase libre**: > *"quiero que las esquinas valgan el doble"* > *"prohibido que el rival pise el centro"* > *"si chocamos en una casilla, me la quedo yo"* Un **LLM (Nemotron, en Modal)** traduce tu frase a un efecto estructurado, y **el árbitro (el código) la valida**: si pide algo fuera del vocabulario, números absurdos o una victoria directa, se rechaza. El LLM propone, el código dispone. *(Sin LLM —modo `--sin-llm`— las leyes se eligen de una lista fija. Mismas reglas, menos poesía, y los rivales no mienten.)* ### Vocabulario de efectos | Efecto | Qué hace | Límites | |---|---|---| | `set_value(zona, valor)` | Fija el valor de las casillas | valor 0–9 | | `multiply_value(zona, factor)` | Multiplica el valor | factor 0–3 | | `add_value(zona, cantidad)` | Suma/resta al valor | −3 a +3 | | `forbid_placement(zona, dueño)` | Prohíbe colocar ahí | no vale `all` | | `penalty_zone(zona, dueño, cantidad)` | Puntos extra/menos por ficha en la zona | −3 a +3 | | `bonus_adjacency(dueño, cantidad)` | Puntos por cada par de fichas propias adyacentes | −3 a +3 | | `clash_resolution(modo)` | Cambia la regla de choque | ver tabla de modos | **Zonas (3×3):** `center`, `corners`, `edges`, `row_top/mid/bot`, `col_left/mid/right`, `cell(fila,col)`, `all`. **Zonas (4×4):** igual, con `center` = el cuadrado central 2×2 y filas/columnas medias dobles. **Dueños:** `red`/`mine` (tú), `blue`/`opponent` (rival), `any`. ### El Pergamino - Las leyes activas viven en el **Pergamino**, máximo **3**. - Para promulgar una cuarta hay que **derogar** una existente. - Las leyes se aplican **en orden de promulgación** (importa: "+1 al centro" y luego "×2 al centro" da 8; al revés da 7). - El Pergamino arranca con un par de **leyes del bosque** aleatorias ya activas. ## 5. Rivales tramposos Cuando un rival gana una ronda, también legisla. Pero son ladinos: **lo que anuncian y lo que de verdad meten en el Pergamino pueden no coincidir**. - En el Pergamino verás siempre *lo que anunció*. - Si sospechas, **acúsalo** (botón ⚖️ *Accuse*). El árbitro compara lo anunciado con lo aplicado: - **Mentía** → la ley se deroga, ganas **astucia** 🦊 y bajas la precisión futura del rival (−7% por caza, se arrastra al Monstruo). - **Era honesto** → se ríe de ti y pierdes **1 de astucia**. - Cada ley solo puede juzgarse una vez. Cualquier ley es acusable (incluso las del bosque). *(Sin LLM, los rivales son honestos: las trampas llegan con el modelo.)* ## 6. Astucia, misiones y tienda - La **astucia** 🦊 es tu moneda de ventaja. Al final cuenta fuerte: **cada punto de astucia = +3 puntos** en el marcador total de la partida. - **Misiones secretas:** cada partida tienes un objetivo oculto (controlar bordes, evitar el centro, alinear fichas, sin choques…). Cumplirlo cada ronda da astucia extra. - **Tienda de astucia:** gasta astucia para - 🔎 **espiar** la misión secreta del rival, - 👁️ **revelar** el valor de una casilla oculta, - 🗑️ **derogar** una ley del Pergamino. ## 7. Las voces Los rivales **hablan**: una IA de voz, **Chatterbox** (Resemble AI, ~0.5B, en Modal), clona un timbre distinto para Lesky, el Monstruo y los gnomos a partir de unos segundos de audio de referencia (`assets/voices/`). Cuando un personaje habla, la música baja para escucharlo. Las voces se generan al vuelo y se cachean en disco (frase repetida = instantánea, sin coste). ## 8. Cómo se ejecuta ```bash conda activate smolhack pip install -r requirements.txt # Interfaz gráfica (la demo): abre http://127.0.0.1:7860 gradio app.py # con hot-reload python app.py # igual, sin reload python app.py --sin-llm # sin LLM: leyes de lista fija, rivales honestos # Tests del motor python -m pytest game/test_engine.py -q ``` - **LLM:** Nemotron-Nano-4B servido en **Modal** (endpoint en `game/llm.py`, `MODAL_ENDPOINT_URL`). Define la app en `modal/app.py`. - **Voces (TTS):** **Chatterbox** (Resemble AI) en **Modal** (`tools/tts_modal.py`); las voces de referencia están en `assets/voices/`. ## 9. Consejos del bosque - El centro suele valer más y el rival lo sabe: ir a por él es jugarse un choque. - Una ley defensiva (*"prohibido que el rival pise el centro"*) vale tanto como una ofensiva. - Vigila el orden del Pergamino antes de derogar: quitar una ley antigua puede cambiar el resultado de las que vinieron después. - La astucia pesa el triple al final: cazar una mentira no solo deroga la ley, te da ventaja real en el marcador. - Acusar por sistema sale caro. Acusa cuando la ley *huela* raro: anuncios grandilocuentes con efectos pequeños suelen esconder otra cosa. --- *Proyecto para el Build Small Hackathon (Gradio + Hugging Face + Modal). Arquitectura: el LLM propone, el código dispone — el modelo solo traduce frases a efectos; el estado, la validación y la puntuación son siempre del árbitro en Python. La UI (`ui/`) y la lógica (`game/`) están separadas por el contrato `game.Session`.*