# 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 2–4 rows. - Mid levels: bottom 6–10 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 1–9: Normal only - Levels 10–19: add Armored (small %) - Levels 20–59: add Falling (increasing %) - Levels 60–100: 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 Spacetris 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: ```cpp 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 ---