Files
Light_And_Dark/AGENTS.md
T
Lena d56540785f flyer boss, town
flyer boss adjustments, town addition
2026-10-05 15:04:20 +02:00

4.4 KiB

AGENTS.md

Project

"Light & Dark" — a 2D light/shade platformer prototype (Python 3.10 + pygame).

  • Main game: light_and_dark/main.py (single large file, ~9500 lines, no tests)
  • Level editor: light_and_dark/level_editor_v43.html (standalone HTML/JS, no build step)
  • Levels: light_and_dark/data/world/rooms/room_0N.json
  • Data/config: light_and_dark/data/config/*.json, data/items/*.json, data/objects/*.json, data/enemies/*.json

Standard session start

  1. git status + git log --oneline -5 to see uncommitted/untracked work (currently room_08/room_09/room_boss_fly_refight and the Boss_fly_token.png sprite are untracked/WIP).
  2. Read the specific file(s) the request touches before editing; follow existing style.
  3. After edits, always verify (see below).

Verification

  • python -m py_compile light_and_dark/main.py (must pass after any edit)
  • Validate touched JSON: python -c "import json; json.load(open('<path>', encoding='utf-8'))"
  • To confirm the game boots: run python light_and_dark/main.py with a short timeout; no traceback in the first lines = OK (the window blocks, so it will time out).

Pitfalls / conventions

  • Python booleans are True/False — never true/false in main.py (this once crashed startup). JSON files use lowercase true.
  • Don't add code comments unless asked. Match surrounding style.
  • Rooms load through normalize_room_json + Room (main.py) which rewrite JSON into the game format; keep new room JSON keys mirrored there (e.g. trigger/ability-door flags).

Key systems (in main.py unless noted)

  • Saves: lantern-only. save_game / apply_save_data. Quest progress, broken doors, defeated bosses persist ONLY on lantern interaction.
  • Trigger walls (trigger_wall_blocking): meta keys quest, quest_complete, quest_turned_in, lock_when_pass (appears once walked through), open_on_miniboss_dead, open_on_boss_dead (released once the room's boss is slain; also hides/inerts moving platforms while the boss lives).
  • Exits: "requires_boss_dead": true hides the exit and disables it while the room's boss is alive (used for boss doors and refight rooms). The editor round-trips this flag (checkbox in the Exit properties).
  • Bosses (BOSS_DEFS_DEFAULT): boss_id -> {name, room, refight_room, token_name, token_sprite}. boss_01 = Gloom Warden (legacy room_boss_01, not in the current build); boss_02 = Sky Terror (flying, room_08, refight room_boss_fly_refight). A boss drops its token in its world room (not during a refight); tokens feed the Boss Diary (boss_diary) and the Combat Master upgrades them for the Hard fight. Token art is per-boss via boss_token_sprite(boss_id).
  • Boss aggro: once the player first enters a boss's detection_range in Light form, Enemy.boss_engaged latches and the boss chases forever (ignores range and Shade).
  • Flying boss (behavior: "flyer", config enemy_types.json → boss_flyer.flyer): hovers/bobs, slam-dives (shockwave poison=False), summons expiring minions, AOE rings, homing shots. Casts _flyer_max_casts() skills per slam-cycle — normal 1 (2 at phase2_hp_pct), hard 2 (3 at hard_phase3_hp_pct); self.flyer_hard is set by start_refight(..., "hard").
  • Ability doors (AbilityDoor): kind = "ranged" (shot open, persists in broken_doors) or "shade" (solid in light, passable in shade + a shade_door_grace window after form switch; ejected to nearest edge after grace).
  • Quests (QUEST_DEFS_DEFAULT): objective "shade": True counts kills only in shade form. Rewards via guaranteed_item (one-time) or pool (repeatable). Items by item_id (e.g. necklace_placeholder = "Plain Necklace").
  • Minibosses: stay defeated per room (DEFEATED_MINIBOSSES) until a lantern save in a different room, then respawn.
  • Enemies: insta-die on hazard contact with no drops (hazard_kill flag); normal enemies respawn on room re-entry.
  • Chests (RewardChest): spawn coin CoinPickups above the chest top (not center, which clips into the platform).
  • Shade-kills quest (first_kills_shade in room 6): interactable/prompted only while in shade form (QuestManager.requires_shade).

Editor (level_editor_v43.html)

  • Link lines: drawLinkLinesForCanvas — exits with a spawn_id missing in the target room draw NO line (avoids stale-coordinate artifacts).
  • Keyboard shortcuts live in the window keydown handler: V/P/E/N/O switch tools, F fit, Esc deselect, Ctrl+Z/Y/C/X/V/D.