- Nou format de pack AE26 v1 (XOR + djb2), eina `pack_resources`,
regeneració automàtica de `build/resources.pack` a cada build.
- `Resource::Helper` amb init/shutdown, fallback a disc només en Debug
(apunta al source tree); Release exigeix pack present.
- Callers de YAML migrats a `loadFile`+deserialize des de buffer.
- Arrel neta: el pack viu a `build/`, eliminat `sync_data`.
- Placeholder font -> `ari-w9500-condensed-display`; esborrades variants
bold/condensed no usades a `data/fonts/`.
Abans el binari només arrencava si la CWD era la que contenia data/
(típicament build/). Executat des de qualsevol altra carpeta no trobava
keys.yaml, paletes, etc. i es moria al carregar el primer recurs.
Patró seguit de ../aee: Resource::Helper guarda un data root absolut
i resolve(rel) el prefixa davant de rutes no absolutes. Director fa
setDataRoot(SDL_GetBasePath()) com a primera acció del ctor, així tots
els loaders posteriors hi passen sense canvis al call site.
Migrats a Resource::Helper::resolve els loaders que obrien std::ifstream
directament amb el path rebut: Locale, KeyConfig, Player, Map, Tilemap
i EntityLoader. Els que ja usaven Resource::Helper::loadFile
(Resource::Cache, PaletteLoader) hereten el fix automàticament.
Els fitxers de system_folder_ (config.yaml, debug.yaml, postfx.yaml,
crtpi.yaml) es passen com a rutes absolutes i resolve() les deixa
intactes, així no es veuen afectats.
Test targets (test_entities_smoke, test_scene_flow) enllacen ara
resource_helper.cpp perquè el seu codi passa per Helper::resolve. Els
tests corren amb CWD = repo root, on les rutes "data/..." funcionen
amb data root buit sense canviar cap assert.
Verificat executant el binari des de build/, /tmp i / — tots tres
troben els recursos i arrenquen correctament, tant en debug com en
release (release sempre arranca a LOGO).
Afegit `Map::Info` (POD trivialment copiable) que empaqueta playfield,
pitch, grid, tile_size, tilemap_origin + 2 punters a funció (collides,
inside_playfield). `Map::makeInfo()` el construeix a partir dels globals
del namespace.
`Player` ara rep `const Map::Info&` al ctor i en guarda una còpia plana
(`map_`), substituint totes les lectures de `Map::*` per `map_.*`. La
inclusió `#include "game/map/map.hpp"` puja al header per la dependència
de `Map::Info`; player.cpp deixa d'incloure'l (transitiu).
Només el Player es desacobla — momies, roques i `loadFromLevel`
continuen llegint `Map::*` directament, com diu la nota original del
audit (mentre hi hagi un Map global actiu, l'acoblament és acceptable).
Si quan s'acabi PATCH-01 algun consumidor extra chirría, COUP-02b en
una rama nova.
Smoke tests 13/13 OK; log Game start → Bye! sota xvfb-run idèntic al
baseline. clang-tidy i cppcheck nets sobre els fitxers modificats.
Refs: docs/audit-game.md (COUP-02).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Map no té estat d'instància (tots els membres són inline globals) i el
ctor ja s'havia eliminat a HC-03. Convertit a `namespace Map`: callers
no canvien perquè la sintaxi `Map::grid_cols`/`Map::collides(...)` és
idèntica. Pattern consistent amb `Options`, que és l'altre mòdul sense
estat al game/.
`0xFF000000U` passa a `constexpr std::uint32_t ALPHA_MASK` local amb
comentari. No s'ha mogut a defines.hpp perquè només s'usa dins de
Tilemap::render; si apareix a altres llocs es podrà centralitzar.
`renderBackground`, `renderSarcsRow`, `getSarcRowBottomY` i els índexs de
paleta `HUD_BG/WALL/FLOOR/SARC` no tenien callers: el Tilemap s'encarrega
del render visual i els sarcs passaran a ser actors sprite. `getSarcRect`
es queda (la usa `collides`). Includes orfes de `screen.hpp`,
`resource_cache.hpp` i `defines.hpp` eliminats. DEAD-04 (ctor Map)
ja es va resoldre durant HC-03.
El bloc `geometry:` de pyramid.yaml porta les 9 constants base (grid, sarc,
pitch, HUD, murs); els derivats (corridor, board, origin, playfield) es
recalculen al `Map::loadFrom()`. `constexpr` passa a `const` on calia i
els membres estàtics adopten snake_case. Desbloqueja la iteració
"pirámide a pirámide" sense recompilar.