Il cheat SELECT+A+B ora controlla il livello: se >= 8 triggera
game_over=3 (finale tragico) invece di game_over=2. Aggiunge anche
un cap level < 8 nel level++ per evitare overflow al livello 9.
Aggiunge un cheat code in engine_update: premendo SELECT+A+B insieme
durante il gameplay si vince il livello corrente (game_over=2, Going
Deeper). Utile per testare rapidamente le schermate di transizione e
avanzare fino al finale (livello 8).
Ricrea i file src/screens/ che erano stati rimossi (death.c,
going_deeper.c, finale.c, screens.c) e aggiorna instructions.c con il
testo allineato allo screenshot dell'utente (FIND THE HATCH, A+DPAD
JUMP, B+DPAD RUN, PRESS B TO CONTINUE).
Ogni schermata testuale (font IBM) ora vive in un file separato nella
sottocartella src/screens/:
- screens.h: dichiarazioni + helper (ending_puttext/putdigit)
- screens.c: implementazione degli helper condivisi
- instructions.c: schermata istruzioni (Window layer)
- death.c: schermata di sconfitta (game_over==1)
- going_deeper.c: transizione livello (game_over==2)
- finale.c: finale tragico (game_over==3, spoiler)
engine.c ora chiama show_instructions(), show_death(),
show_going_deeper(), show_finale() invece di avere il codice inline.
Il titolo resta un'immagine (title_bg.png), non testuale.
Best practice GBDK: il Window layer ha un tile map separato (0x9C00)
rispetto al BG (0x9800). Usando set_win_tiles + SHOW_WIN per il testo
delle istruzioni, il BG map del gameplay non viene mai toccato.
Alla chiusura basta HIDE_WIN: niente garbage, niente flush differito.
Ripristino tile: set_bkg_data (maze) + set_sprite_data (player/enemy/
stamina/level) + draw_map + update_camera + update_player_sprite.
Schermata istruzioni mostrata all'inizio del livello 1, chiudibile con B,
ri-apribile in gioco con SELECT. Testo con font IBM (stesso pattern del
finale game_over==3 e della sconfitta game_over==1).
Contenuto: titolo, obiettivo (find the hatch), controlli (DPAD walk,
A jump abyss, B run), istruzioni di chiusura (press B, select help).
Per fare spazio: rimosso claimed.png (schermata di morte ora testuale
con lo stesso font, stesso pattern del finale).
- assets/claimed.png (160x144, 2-bit GB) usata come schermata di morte al
posto dello schermo nero. Il tile data e' caricato con set_bkg_data
e la mappa 20x18 con set_bkg_tiles; il GAME OVER metasprite resta
sovrapposto sopra l'immagine.
- Going Deeper (game_over==2) ora usa una schermata testuale col font
IBM ('GOING DEEPER / LEVEL N') invece dell'immagine next_level.png.
Necessario per ridurre l'occupazione ROM (la ROM era >32KB con
title_bg + next_level + claimed + maze + tutto il resto) e far
entrare la schermata claimed. Rimosso next_level.c/.h e l'asset.
- engine.c: nuovi helper ending_putdigit per scrivere una cifra;
game_over==2/3 entrambi usano il font IBM per le schermate di
transizione.
- Makefile: rimosso next_level da SRCS e dal clean; aggiunto
claimed.png/png2asset/-c claimed.c.
Verificato via PyBoy: schermata di morte mostra l'immagine claimed
(sfondo nero + carta 128x96 centrata), going deeper mostra il testo
'GOING DEEPER / LEVEL 2'.
The finale text is now 'YOUR TORCH HAS / RUN OUT, / YOU ARE TRAPPED. /
JUST ANOTHER SCREAM / FROM THE DARK. / GAME OVER' — matching the
tragic dark theme of the game. BGP inverted for black background with
white text.
Maze size grows +2/level from 7x7 to 21x21 (cap MAX_MAP_SIZE=21, reached
at level 8). Additional difficulty axes scale with level:
- +1 ghost per level (up to MAX_ENEMIES=8); enemy state moved to arrays,
enemy_logic.c rewritten as a multi-entity loop (own AI, render at OAM
2+i*2, staggered cooldowns).
- Ghost cooldown shrinks: 60 -> ~11 frames between steps.
- Stamina recharge slows: 60 -> 144 frames per point.
- Fog tightens to 3x3 (fog_radius=1) from level 7.
Fog rendering uses a dynamic 16-row centered flush (with wrap) instead of
the fixed rows 2-17 / full 32x32, so the fog stays correct on big mazes
without the multi-frame stall of the full flush.
Game ends after level 8: reaching the hatch at level 8 sets game_over=3
(finale) instead of 2. Finale screen reloads the IBM font and writes
'YOU ESCAPED / THE DARKNESS / LEVEL 8 CLEARED / PRESS START' into the BG
map; START returns to the title (new game starts at level 1).
Verified via PyBoy: sizes 7..21, fog 2->1 at L7, enemies 1..8 (distinct,
on floor, can catch the player), cooldown/recharge scaling, L1 hatch ->
game_over=2, L8 hatch -> game_over=3, finale renders + START->title->L1.
The maze side length is now a runtime global 'map_size' (MAP_SIZE=7 at
level 1, +2 per level, capped at MAX_MAP_SIZE=17), while the maze array
is allocated with the MAX_MAP_SIZE bound. All modules (maze DFS, fog
rendering, player/enemy bounds, hatch and enemy-spawn placement) now use
map_size at runtime.
- globals: maze[MAX_MAP_SIZE][MAX_MAP_SIZE], map_size global, MAX_MAP_SIZE=17.
- maze.c: DFS on map_size; stack/valid arrays made static (WRAM) and sized
for the max maze to avoid hardware-stack overflow; hatch min distance
scales with map_size/2.
- engine.c: sets map_size from level before generate_maze; enemy spawn min
distance scales with map_size/2.
- render.c: flush the full 32x32 background map (the old rows 2-17
optimization broke for large mazes where the 5x5 fog window wraps outside
that range); dynamic bounds; signed/unsigned casts.
- player_logic/enemy_logic: dynamic map_size bounds.
Verified via PyBoy: sizes 7,9,11,13,15,17,17 across levels 1-7, each with
a hatch; rendering and movement intact at 17x17 and at 7x7.
On game over (defeat) + START, restart the maze at the same level the
player had reached instead of resetting to 1. Only starting a new game
from the title screen zeroes the counter. Victory still increments as
before.
Run (B + direction):
- player_logic.c: while holding B + direction with stamina >= 10, each tile
takes 8 frames instead of 16 (move_progress += 2, LERP >>4 unchanged) and
costs 10 stamina per tile. DAS_REPEAT_RUN=2 chains tiles fluidly.
- Falls back silently to normal walk when stamina < 10.
Level progression:
- New global 'level' (starts at 1). title->game resets to 1; reaching the
hatch (victory/Going Deeper) + START increments before engine_init (new
maze); defeat + START resets to 1.
- Top-left HUD 'L<n>' via 3 sprites (OAM 23-25) from new level.png asset
(glyphs L, 0-9), generated by scripts/generate_level.py and converted
with png2asset -keep_duplicate_tiles for predictable tile ordering.
- VRAM base aligned to an EVEN index (8x16 hardware ignores tile LSB) and
placed after the stamina load claim to avoid the shared BG tile block.
- update_level_display() called every frame; hides during game over/title.
Docs: README, doc/gameplay.md and the technical report updated.