Commit graph

33 commits

Author SHA1 Message Date
8a377c2e41 Add recurring-demand mode with shortage tracking
DemandDef gains optional ConsumptionPerTurn and SustainTurns. When
ConsumptionPerTurn > 0 the demand maintains a buffer filled by
deliveries and drained each turn. Shortage fires the first turn the
buffer can't cover consumption; it clears when the buffer refills.
SustainedTurns counts consecutive non-shortage turns, and IsSatisfied
flips to true once it meets SustainTurns — so the victory condition
becomes "no shortage for N consecutive turns" as soon as a mission opts
in. Classic demands (ConsumptionPerTurn = 0) behave exactly as before.

TurnExecutor runs the consumption sub-phase after transfers. Two new
events (DemandShortageStarted / DemandShortageCleared) let the
presentation surface the state later. BoardSnapshot + CampaignLoader
carry the new fields; no existing mission opts in yet, so
campaign_01.json is unaffected.
2026-04-17 22:39:28 +02:00
e3eb10570b Extend campaign_01 to 9 missions with a finale cathedral
Renames mission 7 from "Le Couronnement" to "Le Comptoir" (it only sets
up the tools→gold chain — the coronation is now the final mission) and
adds:

  - Mission 8 "L'Expansion Finale" (12×10): a Forge Est (wood→tools) and
    an Armurerie Est (stone→arms) on new rightmost columns, plus walls
    that force pieces to route around them. An Entrepôt Est demand on
    (11,9) gives the mission its own goal without depending on the old
    demands.
  - Mission 9 "Le Couronnement" (12×12): the Cathédrale occupies row 11
    as three adjacent demands — outils, armes, and or — so the player
    must keep all three transformation chains running simultaneously to
    complete the campaign.

Existing file tests updated for the new count and rename; new
Campaign01Tests asserts structure and non-regressive terrain across all
nine missions.
2026-04-17 22:34:11 +02:00
480c783bd6 Add bidirectional arrows and idle pulsation on piece trajectories
TrajectView now draws an arrow at each endpoint (since pieces oscillate
between start and end, both directions are relevant) and runs a looped
width/alpha tween that breathes between 0.3 and 0.75 over ~2.2s. The
pulse makes stationary relays visually distinct from static board art
without competing with active cargo/particle animations.
2026-04-17 22:31:56 +02:00
1d0999a78e Add cinematic on mission transition (cell pop-in, camera pan, title overlay)
OnMissionAdvanced now plays a three-track cinematic when the auto-advance
fires between missions:
  - Every cell in the rebuilt board pops in with a scale+fade tween
    (0.45s, back ease) so terrain expansion reads as "appearing".
  - The camera smooth-pans + zooms back to the new board center over
    0.7s, undoing any collision zoom that was active.
  - A full-size "Mission N\nName" overlay fades in, holds for ~1.4s,
    then fades out and frees itself.

The per-cell animation doubles as the expansion cue; a dedicated
new-cells-only tween can be layered later if needed. No new engine
surface — hooks onto the existing MissionStartedEvent path.
2026-04-17 22:30:15 +02:00
6c28665c38 Add Delete/Backspace shortcut to remove the selected piece
DetailPanel exposes the currently-shown piece id; Main's key handler
delegates Delete or Backspace to the same path as the Retirer button
when a piece is selected. Harness gains "delete" under key() so UI
tests can exercise the shortcut directly.
2026-04-17 22:23:38 +02:00
c4f6ecbf44 Add collision camera pan/zoom and toast notification
EventAnimator now emits CollisionOccurred at the end of the collision
phase, carrying the struck cell and victim/destroyer identity. Main pans
and zooms the camera onto the cell over 0.45s and shows a fading toast
("Pion détruit par Tour — retourné au stock", or "collision mutuelle"
for same-status ties). The toast fades out after 3s and leaves the
camera framing the collision so the player can inspect the aftermath
before resuming.
2026-04-17 22:21:36 +02:00
1522b70398 Add drag & drop to relocate placed pieces
InputMapper tracks a mouse-down over a placed piece and promotes it to
drag mode once the cursor travels past an 8px threshold. Legal drop
cells (those where the piece's start→end vector still fits a legal
placement) are highlighted in green. Releasing on a legal cell emits a
RelocateRequested signal; Main feeds it to MovePieceCommand, which is
already undoable via the existing history stack.

Escape or releasing on an invalid cell cancels. The harness gains a
relocate() helper so UI tests can script drag-and-drop moves without
synthesizing motion events.
2026-04-17 22:18:50 +02:00
97bca7d7df Add Undo (Ctrl+Z) backed by the WorldSave checkpoint mechanism
GameSim snapshots the state before each undoable command
(PlacePiece / RemovePiece / MovePiece) into a bounded LinkedList stack
(max 32). Undo() pops the last checkpoint and emits StateRestoredEvent,
reusing the presentation rebuild path already wired for QuickLoad.

Ctrl+Z in Main triggers the engine method; the harness exposes undo()
for tests. QuickLoad clears the stack (fresh timeline). Seven unit tests
cover empty stack, place/remove/move undo, reverse-order multiple undos,
rejected commands not checkpointing, and post-simulation rewind.
2026-04-17 22:14:06 +02:00
2537bfe828 Add QuickSave/QuickLoad with full state restore and visual rebuild
BoardState.CaptureSave/RestoreFromSave deep-copy every mutable field
(grid, pieces, demands, transformers, buffers, stock, campaign progress)
into a WorldSave slot. GameSim.QuickSave/QuickLoad expose slotted saves
and emit StateSavedEvent / StateRestoredEvent — the latter carries a
fresh BoardSnapshot so the presentation can rebuild board, pieces,
trajectories, objectives, stock, camera, and control bar in one pass.

F5/F9 trigger it in Main; harness gains quick_save/quick_load commands so
UI tests can checkpoint a scenario and resume without replaying from
scratch. Seven xUnit tests cover the roundtrip (including independence
from post-save mutations, campaign state, and multi-slot isolation).
2026-04-17 22:10:06 +02:00
bd1763f372 Consolidate plans into docs/PLAN.md and document dev loop
Delete autonomous_plan.md (fully shipped), PLAN_playtest.md (all P1-P7
done), PLAN_missions.md and PLAN_leveldesign.md (partial — engine done,
UI polish + 3 final missions + recurring demands + transformer visuals
remain). The surviving TODO list lives in docs/PLAN.md.

Also add the 6-step dev loop to CLAUDE.md (take next topic → implement →
tests → UI test → docs → commit).
2026-04-17 22:09:53 +02:00
eba81400a8 Skip unresolvable domains in firewall allowlist instead of aborting
If DNS resolution transiently fails for one domain, the whole postStart
hook used to exit 1 and leave the container without a firewall. Warn and
continue so the remaining rules still get installed.
2026-04-17 21:13:06 +02:00
3077b2d669 Teach Claude the autonomous devcontainer test recipe in CLAUDE.md
Covers toolchain sanity check, the root-owned .godot permissions pitfall,
build -> smoke -> Harness loop, Python snippet, visual validation loop,
and non-obvious state shape details. Also fixes the stale Windows-only
Godot path mention.
2026-04-17 21:13:05 +02:00
Samuel Bouchet
5146798f5c Document --dangerously-skip-permissions (YOLO) mode in README
Explains why YOLO is reasonable inside this specific container (bind-mount
scope, firewall allow-list, non-root user, no host secrets mounted) and
flags the residual risks worth knowing: uncommitted work in /workspace,
exfiltration via GitHub / Anthropic, no CPU/RAM limits. Key advice: commit
before long autonomous runs.
2026-04-17 20:50:38 +02:00
Samuel Bouchet
c451a50349 Headless Linux dev container: Godot + .NET + Xvfb for autonomous testing
Claude Code running inside the project's dev container can now build the
game, launch a real Godot instance under Xvfb, and drive the automation
harness end-to-end — no Windows dependency.

Dockerfile adds (as root, before USER node):
- X11 / Mesa software GL / audio runtime deps + python3
- .NET SDK 9.0 via upstream dot.net install script -> /usr/local/dotnet
- Godot 4.6.2-stable mono Linux x86_64 -> /opt/godot/godot
- /usr/local/bin/godot-xvfb wrapper: auto-wraps invocations in
  xvfb-run -a --server-args="-screen 0 1280x720x24 ..."

harness.py picks GODOT_BIN from env, defaults to /opt/godot/godot on
Linux, and auto-wraps the subprocess in xvfb-run when DISPLAY is unset.
Windows code path unchanged.

init-firewall.sh adds api.nuget.org to the allowlist so dotnet restore
works post-boot. Godot + .NET SDK are fetched at image build time, before
the firewall exists.

New docs:
- autonomous_plan.md: design rationale, alternatives considered
- README.md: launch instructions for Windows terminal / Docker Desktop /
  VS Code Dev Containers / WSL2 natif
- CLAUDE.md already documents the harness (done in previous commit)

Validation: docker build succeeds; inside the container, dotnet --version
=9.0.313, godot --version=4.6.2.stable.mono, dotnet test=102/102,
python3 tools/automation/smoke.py passes end-to-end with 14 non-black
1280x720 PNGs. Mission 1 screenshot is visually identical to the Windows
build, and Xvfb determinism is a bonus (det_a.png ≡ det_b.png bytewise).
2026-04-17 16:57:56 +02:00
Samuel Bouchet
8f3b1b39e7 Document automation harness usage in CLAUDE.md 2026-04-16 22:37:20 +02:00
Samuel Bouchet
62a208934c Untrack accidentally committed __pycache__; ignore .pyc 2026-04-16 22:35:18 +02:00
Samuel Bouchet
f86b9abecd Add file-IPC automation harness for autonomous game testing
Launching Godot with --automation=<dir> activates an AutomationHarness
node that polls <dir>/inbox/ for JSON command files, executes them via
a thin facade over existing public surfaces (GameSim, InputMapper,
EventAnimator, ControlBar, PieceStockPanel), and writes results plus
screenshots back to disk. The black-box simulation boundary is not
crossed — every command routes through the same signals/methods a real
player would trigger.

A stdlib-only Python helper (tools/automation/harness.py) wraps the
protocol for test scripts and interactive REPLs. Smoke test passes
end-to-end: load mission, place a piece, step 10 turns, capture 14
1280x720 PNGs, handle rejections, quit cleanly. Existing 102 engine
unit tests still green.
2026-04-16 22:34:56 +02:00
Samuel Bouchet
2d1aea0a7a Snapshot campaign system progress before automation harness
Bundles in-flight work on the campaign/missions system (CampaignDef,
MissionDef, TerrainPatch, TransformerDef, MissionChecker, CampaignLoader,
FlavorBanner, transformer rules), plan files, and matching tests. Baseline
commit so the upcoming automation testing harness lands on a clean tree.
2026-04-16 21:22:49 +02:00
358ab48d59 Remove temp plan file, normalize GDD whitespace
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 11:42:07 +02:00
84ab0a1d0f Phase 7: Scroll wheel zoom + camera polish
- Mouse wheel up/down zooms camera in/out
- Zoom clamped between 0.3x and 3x to prevent getting lost
- Updated PLAN.md: marked phases 5-6 as done, added phase 7-8

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:25:09 +02:00
8918140114 Phase 5: Dame (Queen) piece and network levels 7-8
Dame (Queen):
- Moves 1-2 cells in all 8 directions (orthogonal + diagonal)
- Social status 7 (highest — priority over all other pieces)
- Deep burgundy color, letter "D"
- Rare and powerful, forces strategic placement choices

Levels:
- Level 7 "La Dame Blanche": 10x10, walled arena with central fortress,
  1 queen available as a logistics superweapon
- Level 8 "Le Grand Reseau": 12x10, 4 productions + 4 demands,
  two vertical wall corridors, 2 queens, full network challenge

GDD updated with Dame section and status hierarchy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:24:14 +02:00
210be72100 Fix stop reset, piece selection visuals, add trajectory preview and menu button
Bugfixes:
- Stop now fully rebuilds piece visuals (fixes destroyed pieces not
  reappearing and lingering cargo indicators)
- Piece stock buttons use explicit selected/unselected styling instead
  of ambiguous toggle behavior (teal bg + bright border when selected)
- Color dots next to stock buttons match piece colors

Features:
- Clicking a placed piece highlights its start/end cells with piece color
- Back-to-menu button ("← Menu") in top-left returns to level selector
  with fade transition
- DetailPanel shows "Pion" name and has styled remove button

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:21:38 +02:00
43a3e97f28 Add Godot uid for SfxManager
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:11:19 +02:00
450c069854 Juice pass: procedural SFX, particles, polished visuals
Sound (SfxManager.cs):
- Procedural audio synthesis via AudioStreamWav — no external files
- Distinct tones for place, produce, transfer, deliver, move, destroy, victory
- Simple ADSR envelope, sine/triangle waveforms, filtered noise for swooshes

Pieces (PieceView.cs):
- Warm earthy palette: sage green, deep teal, dusty rose, burnt sienna
- Drop shadow under each piece for depth
- 3-stop radial gradient (bright center → main → dark rim)
- Scale bounce on placement (0 → 1.15 → 1.0 with back-out easing)
- Cargo indicator pulses gently when carrying

Trajectories (TrajectView.cs):
- Arrowhead at endpoint showing movement direction
- Antialiased lines with piece-matched colors

Cells (CellView.cs):
- Warmer palette: parchment/walnut board, deep forest production, aged gold demand
- Production flash uses warm golden glow instead of white
- Subtle inner shadow for visual depth

Animations (EventAnimator.cs):
- Production: golden particles burst from production cells
- Transfer: cargo slides with 2-particle trail + back-out whip easing
- Destruction: pieces shrink + spin + red particle explosion
- Victory: 40 confetti particles rain across the screen
- All phases trigger appropriate SFX

UI polish:
- ControlBar: styled buttons with rounded corners, disabled states
- MetricsOverlay: fade-in + scale animation, sequential metric reveals
- ObjectivePanel: animated progress bars, styled fills, green flash on completion
- Main: fade-in/out transitions between level select and gameplay

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:05:55 +02:00
e1218b3eaa Normalize indentation in level_01.json
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 22:52:07 +02:00
4afe20842e Add levels 4-6 to level selector, use grid layout
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 22:39:06 +02:00
672b831fc1 Add Pion piece, surplus stock, and levels 4-6
- Pion (Pawn): orthogonal range 1, social status 1 (lowest), green color
- All existing levels get surplus stock including pawns for player choice
- Level 4 "Le Carrefour": 8x8, dual cargo diagonal routes, center wall block
- Level 5 "Le Labyrinthe": 8x6, wall corridors, knights essential for shortcuts
- Level 6 "Trois Royaumes": 10x8, 3 productions + 3 demands, full network puzzle
- Production interval concept removed (all produce every turn)
- GDD updated with Pion section and 6 level descriptions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 22:03:36 +02:00
a7280b1a5a Overhaul turn mechanics, collision destruction, and visual animations
- New turn order: produce -> transfer -> move -> collision resolution
- Collisions now destroy weaker pieces (status > level > mutual destruction)
  instead of halting the simulation. SimPhase.Collision removed.
- Add piece Level property (all level 1 in proto, prepared for future)
- Production fires every turn (interval concept removed), buffer = Amount
  (default 1, future 2-4), leftovers overwritten each turn
- Transfer tiebreaker: status > level > clockwise direction (alternating
  even/odd turns in y-up coords), replaces distance-to-production
- Demands always accept matching cargo even when already satisfied
- TurnNumber added to all turn events for animation grouping
- Simultaneous animations: produce flash, cargo slide, parallel piece moves
- Camera centering fix + middle-click pan
- GDD updated with new rules + lore section added

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 21:44:12 +02:00
dd43df8820 Add technical files 2026-04-10 17:14:09 +02:00
d1926c2b4d Update PLAN.md: mark Phase 2 as done 2026-04-10 15:35:55 +02:00
3120d9835e Phase 2: cargo-type aware transfers via CargoFilter
Add CargoFilter property to PieceState, auto-assigned at placement
by tracing relay chain back to production. TransferResolver now
enforces cargo-type filtering and uses forward-direction sorting
with cargo-aware distance calculations. Prevents cross-route
contamination on multi-cargo boards.

Level 3 restored to dual-cargo (Wood+Stone) with correct 10R+2K stock.
Two new solvability tests validate filter auto-assignment and chain
propagation. All 60 tests green.
2026-04-10 15:35:37 +02:00
2b3d27d295 Fix transfer direction bug, validate GDD levels via red-green testing
- Fix cargo bouncing in relay chains: piece-to-piece transfers now prefer
  receivers farther from production (forward flow) instead of closer (backward)
- Level 2 stock corrected: 4R+1B → 6R+1B to match required solution
- Level 3 simplified to single cargo type (6R+1K) — dual-cargo on 6x6
  requires engine support for cargo-type filtering (Phase 2)
- Add PLAN.md with prototype roadmap (phases 2-6)
- 57 tests passing
2026-04-10 15:25:25 +02:00
e6eaae43ab Initial commit: Chessistics prototype v0.3
Black box sim engine (commands in, events out) with 3 piece types
(Rook, Bishop, Knight), cargo transfer system with social status
priority, collision detection, and victory/defeat conditions.

57 tests covering rules, simulation, loading, and solvability.
Godot 4 presentation layer scaffolding.
2026-04-10 14:58:03 +02:00