Files
spacetris/challenge_mode.md
2025-12-20 13:08:16 +01:00

7.8 KiB
Raw Blame History

Spacetris — Challenge Mode (Asteroids) Implementation Spec for VS Code AI Agent

Goal: Implement/extend CHALLENGE gameplay in Spacetris (not a separate mode), based on 100 levels with asteroid prefilled blocks that must be destroyed to advance.


1) High-level Requirements

Modes

  • Existing mode remains ENDLESS.
  • Add/extend CHALLENGE mode with 100 levels.

Core Challenge Loop

  • Each level starts with prefilled obstacle blocks called Asteroids.
  • Level N starts with N asteroids (placed increasingly higher as level increases).
  • Player advances to the next level when ALL asteroids are destroyed.
  • Gravity (and optionally lock pressure) increases per level.

Asteroid concept

Asteroids are special blocks placed into the grid at level start:

  • They are not player-controlled pieces.
  • They have types and hit points (how many times they must be cleared via line clears).

2) Asteroid Types & Rules

Define asteroid types and their behavior:

A) Normal Asteroid

  • hitsRemaining = 1
  • Removed when its row is cleared once.
  • Never moves (no gravity).

B) Armored Asteroid

  • hitsRemaining = 2
  • On first line clear that includes it: decrement hits and change to cracked visual state.
  • On second clear: removed.
  • Never moves (no gravity).

C) Falling Asteroid

  • hitsRemaining = 2
  • On first clear: decrement hits, then becomes gravity-enabled (drops until resting).
  • On second clear: removed.

D) Core Asteroid (late levels)

  • hitsRemaining = 3
  • On each clear: decrement hits and change visual state.
  • After first hit (or after any hit — choose consistent rule) it becomes gravity-enabled.
  • On final clear: removed (optionally trigger bigger VFX).

Important: These are all within the same CHALLENGE mode.


3) Level Progression Rules (100 Levels)

Asteroid Count

  • asteroidsToPlace = level (Level 1 -> 1 asteroid, Level 2 -> 2 asteroids, …)
  • Recommendation for implementation safety:
    • If level becomes too large to place comfortably, still place level but distribute across more rows and allow overlaps only if empty.
    • If needed, implement a soft cap for placement attempts (avoid infinite loops). If cannot place all, place as many as possible and log/telemetry.

Placement Height / Region

  • Early levels: place in bottom 24 rows.
  • Mid levels: bottom 610 rows.
  • Late levels: up to ~half board height.
  • Use a function to define a minRow..maxRow region based on level.

Example guidance:

  • maxRow = boardHeight - 1
  • minRow = boardHeight - 1 - clamp(2 + level/3, 2, boardHeight/2)

Type Distribution by Level (suggested)

  • Levels 19: Normal only
  • Levels 1019: add Armored (small %)
  • Levels 2059: add Falling (increasing %)
  • Levels 60100: add Core (increasing %)

4) Difficulty Scaling

Gravity Speed Scaling

Implement per-level gravity scale:

  • gravity = baseGravity * (1.0f + level * 0.02f) (tune)
  • Or use a curve/table.

Optional additional scaling:

  • Reduced lock delay slightly at higher levels
  • Slightly faster DAS/ARR (if implemented)

5) Win/Lose Conditions

Level Completion

  • Level completes when: asteroidsRemaining == 0
  • Then:
    • Clear board (or keep board — choose one consistent behavior; recommended: clear board for clean progression).
    • Show short transition (optional).
    • Load next level, until level 100.
  • After level 100 completion: show completion screen + stats.

Game Over

  • Standard Tetris game over: stack reaches spawn/top (existing behavior).

6) Rendering / UI Requirements

Visual Differentiation

Asteroids must be visually distinct from normal tetromino blocks.

Provide visual states:

  • Normal: rock texture
  • Armored: plated / darker
  • Cracked: visible cracks
  • Falling: glow rim / hazard stripes
  • Core: pulsing inner core

Minimum UI additions (Challenge):

  • Display LEVEL: X/100
  • Display ASTEROIDS REMAINING: N (or an icon counter)

7) Data Structures (C++ Guidance)

Cell Representation

Each grid cell must store:

  • Whether occupied
  • If occupied: is it part of normal tetromino or an asteroid
  • If asteroid: type + hitsRemaining + gravityEnabled + visualState

Suggested enums:

enum class CellKind { Empty, Tetromino, Asteroid };

enum class AsteroidType { Normal, Armored, Falling, Core };

struct AsteroidCell {
    AsteroidType type;
    uint8_t hitsRemaining;
    bool gravityEnabled;
    uint8_t visualState; // optional (e.g. 0..n)
};

struct Cell {
    CellKind kind;
    // For Tetromino: color/type id
    // For Asteroid: AsteroidCell data
};

8) Line Clear Processing Rules (Important)

When a line is cleared:

  1. Detect full rows (existing).

  2. For each cleared row:

    • For each cell:

      • If kind == Asteroid:

        • hitsRemaining--

        • If hitsRemaining == 0: remove (cell becomes Empty)

        • Else:

          • Update its visual state (cracked/damaged)

          • If asteroid type is Falling/Core and rule says it becomes gravity-enabled on first hit:

            • gravityEnabled = true
  3. After clearing rows and collapsing the grid:

    • Apply asteroid gravity step:

      • For all gravity-enabled asteroid cells: let them fall until resting.
      • Ensure stable iteration (bottom-up scan).
  4. Recount asteroids remaining; if 0 -> level complete.

Note: Decide whether gravity-enabled asteroids fall immediately after the first hit (recommended) and whether they fall as individual cells (recommended) or as clusters (optional later).


9) Asteroid Gravity Algorithm (Simple + Stable)

Implement a pass:

  • Iterate from bottom-2 to top (bottom-up).

  • If cell is gravity-enabled asteroid and below is empty:

    • Move down by one
  • Repeat passes until no movement OR do a while-loop per cell to drop fully.

Be careful to avoid skipping cells when moving:

  • Use bottom-up iteration and drop-to-bottom logic.

10) Level Generation (Deterministic Option)

To make challenge reproducible:

  • Use a seed: seed = baseSeed + level
  • Place asteroids with RNG based on level seed.

Placement constraints:

  • Avoid placing asteroids in the spawn zone/top rows.

  • Avoid creating impossible scenarios too early:

    • For early levels, ensure at least one vertical shaft exists.

11) Tasks Checklist for AI Agent

A) Add Challenge Level System

  • Add currentLevel (1..100) and mode == CHALLENGE.
  • Add StartChallengeLevel(level) function.
  • Reset/prepare board state for each level (recommended: clear board).

B) Asteroid Placement

  • Implement PlaceAsteroids(level):

    • Determine region of rows
    • Choose type distribution
    • Place level asteroid cells into empty spots

C) Line Clear Hook

  • Modify existing line clear code:

    • Apply asteroid hit logic
    • Update visuals
    • Enable gravity where required

D) Gravity-enabled Asteroids

  • Implement ApplyAsteroidGravity() after line clears and board collapse.

E) Level Completion

  • Track asteroidsRemaining.
  • When 0: trigger level transition and StartChallengeLevel(level+1).

F) UI

  • Add level & asteroids remaining display.

12) Acceptance Criteria

  • Level 1 spawns exactly 1 asteroid.

  • Level N spawns N asteroids.

  • Destroying asteroids requires:

    • Normal: 1 clear
    • Armored: 2 clears
    • Falling: 2 clears + becomes gravity-enabled after first hit
    • Core: 3 clears (+ gravity-enabled rule)
  • Player advances only when all asteroids are destroyed.

  • Gravity increases by level and is clearly noticeable by mid-levels.

  • No infinite loops in placement or gravity.

  • Challenge works end-to-end through level 100.


13) Notes / Tuning Hooks

Expose tuning constants:

  • baseGravity
  • gravityPerLevel
  • minAsteroidRow(level)
  • typeDistribution(level) weights
  • coreGravityOnHit rule