Skip to content

Levels / Progression

The level system provides controlled progression across predefined bonus maps while preserving the main runtime context: MLX display, window, frame loop, hooks, retro buffers, HUD assets, and sprite infrastructure.

It allows the game to switch from one .cub level to the next without restarting the process.

Levels / progression

Sequential bonus map reload without restarting the process

The level system loads the next predefined bonus map in place while preserving the active MLX window, hooks, frame loop, and global bonus UI context.

F4 progression simulation

Current path list is sequential: `maps/bonus/level1.cub` through `level8.cub`.

reused across transitions ✓ MLX display/window✓ frame loop + hooks✓ HUD context✓ sprite core context✓ z-buffer allocation
rebuilt per level ↻ map.grid↻ NO/SO/WE/EA config↻ mandatory wall textures↻ doors[] runtime state↻ pickups[] runtime state↻ player spawn/vectors↻ floor/ceiling colors

level1.cub active.

01
bonus_load_next_level(app)

The transition is staged so the current level remains valid until transfer succeeds.

1 init_app(&next) tmp ctx
2 parse_file(&next, next_path) parse
3 pre-load tex[4] using current MLX MLX
4-6 doors + pickups + sprite capacity bonus
7 free current level-owned data free
8 transfer next -> app and null moved fields transfer
9-13 colors, sprites, vectors, input reset, current++ finalize
02
ownership transfer safety

Moved resources are nulled in the temporary context to avoid double free.

// after transferring next -> app
next.map.grid = NULL;
next.tex_no = NULL;
next.tex[0].img_ptr = NULL;

// if parse/load fails before transfer:
free_app(&next);
// app remains the current valid level
03
t_bonus_levels

Progression state is small and explicit.

paths[]     // ordered level files
count       // registered level count
current     // active level index
active      // progression enabled
start_path  // original CLI map path
transition invariants

The system is deterministic, bounded, and safe to defend.

window and loop stay alivefailed next load keeps current levelmoved fields are nulledfree_app remains safe after transitions

Runtime level state is stored in app->bonus.levels:

  • paths[], the ordered list of bonus level files
  • count, the number of registered levels
  • current, the active level index
  • active, whether progression mode is enabled
  • start_path, the initial map path from CLI

The current sequence is maps/bonus/level1.cub through maps/bonus/level8.cub.

At startup, bonus_levels_init(&app, argv[1]) compares the CLI map path against the registered level paths. If the input path matches, progression mode is activated and parsing starts from bonus_level_current_path(&app).

Path matching supports normalized relative paths and suffix matching, so inputs such as ./maps/bonus/level1.cub still resolve correctly.

Progression is currently manual:

  • F4 calls bonus_load_next_level(app)

If the next level exists and load succeeds, the runtime switches level in place. If there is no next level, or if loading fails, the current level remains valid.

bonus_load_next_level(app) builds the next level in a temporary t_app context, preloads level-specific resources with the existing MLX context, then transfers ownership into the live app only after the new level is ready.

This design avoids restarting the process and keeps window/hook infrastructure intact while replacing level-owned data such as parsed config, map grid, door state, pickup state, and wall textures.

The transition is fail-safe:

  • parse/load/init failure cleans the temporary context only
  • the current level remains valid until ownership transfer succeeds
  • moved fields are nulled in next to avoid double free
  • global cleanup still works after any number of transitions
  • srcs_bonus/levels/levels_api.c
  • srcs_bonus/levels/levels_current.c
  • srcs_bonus/levels/levels_reload.c
  • srcs_bonus/levels/levels_textures.c
  • srcs_bonus/levels/levels_transfer.c
  • srcs/input/input_keys.c
  • srcs/core/main.c