Skip to content

v2.17.0 - familias grids/refs cross-coleccion + roguelike a lo grande

Choose a tag to compare

@MauricioPerera MauricioPerera released this 09 Jul 03:35

[2.17.0] — 2026-07-08

Release aditivo sobre 2.16.0 (bump minor, SPEC §7.0): dos frentes
independientes. En el core, la familia declarativa grids y el agregado
cross-colección en refs cierran la tercera etapa de reglas puras-de-datos (SPEC §11),
migrando los 4 perfiles que duplicaban esta lógica en JS. En roguelike, mecánicas
100% data-driven (llaves/puertas, jefe, progresión, permadeath), un solo generador
compartido entre los dos motores, mazmorra en mundo continuo 3D con minimapa, y guardado
persistente. La versión del protocolo sigue en 0.1.

Added — familias declarativas grids + agregado cross-colección en refs (SPEC §11, segunda y tercera etapa)

  • Familia grids declarativa en el core: { rule, emptyRule?, collection|singleton, shape?: { singleton, rowsField?, colsField? }, legend?: { rule, tileTarget, palField?, palMax? } } — valida filas de mapa/escena de ancho uniforme (autoconsistente contra la
    primera fila, o contra una forma fija externa como platform.rows/.cols vía shape) y
    resuelve cada símbolo de legend/fill contra tiles+paleta, sin ejecutar código de perfil.
  • 4 perfiles migrados (mismos rule-ids, cero cambio de comportamiento observable):
    adventure/dungeon (scene-rows/scene-dims/scene-legend-ref, autoconsistente) y
    monster-rpg/tower-defense (map-dims/map-legend-ref, forma fija vía platform) —
    la misma lógica estaba duplicada en JS en los 4.
  • refs[].target acepta agregado cross-colección: arrayField (+ itemField) además
    de collection — el set válido se junta escaneando un array anidado en TODAS las
    entradas de la colección, no solo Object.keys. Cubre "algún X entre N filas otorga el
    valor Y" como dato en vez de código a mano.
  • dungeon.warp-lock migrado: warp.locked exige un item que ALGÚN pickup, en
    CUALQUIER escena, otorgue — antes un Set armado a mano en ruleScenes, ahora una
    entrada declarativa de refs.
  • SPEC §6.1/§11 actualizado (grids + agregado cross-colección documentados; queda como
    "tercera etapa" de reglas puras-de-datos — lo que sigue en rules es lógica genuinamente
    no reducible a forma declarativa sin volverse un DSL). test/profile-descriptor.js cubre
    las formas nuevas del descriptor (31 chequeos, de 28). Suite sin regresiones: mismas 136
    reglas, 190 casos de conformidad, mutation audit 20/20.

Added — roguelike a lo grande: mecánicas por datos, un solo generador, mundo continuo

  • Mecánicas nuevas 100% data-driven en el perfil roguelike y su ejemplo:
    llaves y puertas cerradas (generator.lockChance/keyChance + tiles key/
    lockedDoor; cerraduras mutuas entre salas; la llave abre AMBOS lados de forma
    permanente), jefe custodiando el cofre (boss: tile/hp/damage — bloquea la
    victoria hasta caer), progresión por experiencia (progression.killsPerAtk/
    maxBonus: el ataque sube con las bajas) y permadeath declarativo
    (progression.permadeath). 3 reglas nuevas de perfil (generator-chance,
    boss-fields, progression-fields) → 136 reglas.
  • Solvencia por construcción: toda sala conserva ≥1 salida SIN cerrar, y como el
    cofre aparece donde exploras (generación perezosa), nunca queda tras una puerta
    cerrada — las llaves abren atajos y zonas extra. Verificado como invariante por BFS
    en npm test.
  • Un solo generador, dos motores POR CONSTRUCCIÓN: el visor 2D
    (examples/roguelike.html) deja de duplicar la generación y pasa a importar la
    misma lógica pura
    (game3d-logic.mjs) que usa game3d — renderer fino sobre
    funciones testeadas. build-standalone aprende a inlinear imports relativos de
    módulos ESM (+2 chequeos) y el standalone sigue autocontenido.
  • game3d, mazmorra en mundo continuo: las salas se añaden contiguas a la escena
    al explorar (comparten muro fronterizo, sin celdas duplicadas) y los pisos se
    apilan físicamente en vertical
    — la cámara viaja con el jugador. Minimapa 3D
    del grafo explorado (cubos por sala, pisos apilados, conexiones cerradas en rojo,
    escaleras en azul) renderizado en una segunda pasada. Guardado automático de la
    run en localStorage (rgSave/rgLoad puros y testeados; N = nueva partida; el
    guardado se limpia al ganar o caer en permadeath) y estadísticas de run en los
    overlays (salas, bajas, caídas, profundidad máxima).
  • +17 chequeos en npm test y CI (171 de lógica): solvencia por BFS, cerraduras
    y llaves generadas, unlock que abre ambos lados, jefe que bloquea/daña/cae,
    levelup con tope, permadeath → gameover, save/load ida y vuelta, y el bot
    explorador ONLINE que gana jugando
    (rutea por el grafo conocido, toma salidas
    inexploradas y derrota al jefe antes del cofre).
  • Verificado en navegador en ambos motores: el 2D con la lógica compartida
    (puerta cerrada/llave con los textos del GAME.md) y game3d con guardado +
    restauración tras recargar, nueva partida con N y victoria del explorador por
    eventos de teclado reales — misma firma de run que el test de Node (6 salas,
    1 baja, prof. 5): mismo mundo otra vez.
  • Nota: añadir tiradas al generador cambia los mundos respecto a v2.16.0 — la
    paridad garantizada es entre motores, no con releases anteriores.