mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-08-28 05:27:41 +00:00
parent
cd80cb94d4
commit
1a67dfb842
6 changed files with 609 additions and 43 deletions
444
run.json
444
run.json
File diff suppressed because one or more lines are too long
159
stages/002-plan_app@1/diff.patch
Normal file
159
stages/002-plan_app@1/diff.patch
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
diff --git a/.ai/solitaire-fast-plan.md b/.ai/solitaire-fast-plan.md
|
||||
new file mode 100644
|
||||
index 000000000..9eeab8747
|
||||
--- /dev/null
|
||||
+++ b/.ai/solitaire-fast-plan.md
|
||||
@@ -0,0 +1,144 @@
|
||||
+# Implementation Plan: Python Klondike Solitaire Curses TUI
|
||||
+
|
||||
+This document outlines the concise plan to implement a terminal-based Klondike Solitaire game in Python using the standard library `curses` module, with full game logic, undo history, win detection, a non-interactive smoke test suite, and a unit test suite using `pytest`.
|
||||
+
|
||||
+All files will reside under the directory `solitaire-app/`.
|
||||
+
|
||||
+---
|
||||
+
|
||||
+## 1. Directory Structure
|
||||
+
|
||||
+```text
|
||||
+solitaire-app/
|
||||
+├── requirements.txt # Project dependencies (pytest)
|
||||
+├── main.py # Application entry point (handles --smoke and launches TUI)
|
||||
+├── game_logic.py # Complete pure Python engine for card and game state management
|
||||
+├── tui.py # Curses-based terminal interface layout, input handler, and renderer
|
||||
+└── tests/
|
||||
+ └── test_game_logic.py # Unit tests for game rules, moves, and state transitions
|
||||
+```
|
||||
+
|
||||
+---
|
||||
+
|
||||
+## 2. Technical Stack & Requirements
|
||||
+
|
||||
+- **Language**: Python 3.11+
|
||||
+- **UI Library**: Standard library `curses` (fully playable TUI with color support, keyboard controls, and layout adaptability)
|
||||
+- **Testing**: `pytest` for rules engine verification
|
||||
+- **E2E / Demo Verification**: `python3 main.py --smoke` runs a non-interactive automated smoke test of the game logic and exits 0 on success.
|
||||
+
|
||||
+---
|
||||
+
|
||||
+## 3. Game Engine (game_logic.py)
|
||||
+
|
||||
+The game engine will be completely decoupled from the UI layer to ensure reliable testing.
|
||||
+
|
||||
+### Key Models
|
||||
+
|
||||
+- **`Card`**:
|
||||
+ - `suit`: One of `♠`, `♥`, `♦`, `♣` (or string representation)
|
||||
+ - `rank`: Integer from 1 (Ace) to 13 (King)
|
||||
+ - `face_up`: Boolean
|
||||
+ - `color`: Derived property (Red for ♥/♦, Black for ♠/♣)
|
||||
+
|
||||
+- **`GameState`**:
|
||||
+ - `stock`: List of face-down cards
|
||||
+ - `waste`: List of drawn cards (only the top card is visible and playable)
|
||||
+ - `tableau`: List of 7 columns, each being a list of `Card`s
|
||||
+ - `foundations`: Dict with 4 keys (suits/indices) pointing to lists of card sequences (A to K)
|
||||
+ - `undo_stack`: Stack of serialized or deep-copied previous states
|
||||
+
|
||||
+### Core Operations & Rules (Draw-One Klondike)
|
||||
+
|
||||
+1. **Initialization**:
|
||||
+ - Shuffle a standard 52-card deck.
|
||||
+ - Deal cards to the 7 tableau columns (Column $i$ gets $i$ cards; top card is face_up, others face_down).
|
||||
+ - Remaining cards go to the `stock` pile.
|
||||
+2. **Draw / Recycle**:
|
||||
+ - `draw_card()`: Move 1 card from `stock` to `waste` (face-up).
|
||||
+ - If `stock` is empty, recycle `waste` back to `stock` by reversing and flipping them face-down.
|
||||
+3. **Move Validation & Execution**:
|
||||
+ - **Tableau to Tableau**: A card (or face-up stack) can move to another column if the bottom-most card of the moving stack is 1 rank lower and of the opposite color of the target column's top card. An empty tableau column can only accept a King (rank 13).
|
||||
+ - **Waste to Tableau**: Top of waste can move to a tableau column following the same color/rank rules.
|
||||
+ - **Waste/Tableau to Foundation**: Cards can move to foundations. Foundations build up from Ace (1) to King (13) by same suit.
|
||||
+ - **Auto-Reveal**: If a move exposes a face-down card at the top of a tableau column, it is automatically flipped face-up.
|
||||
+4. **Undo**:
|
||||
+ - Push the full state to `undo_stack` before any mutating game action.
|
||||
+ - `undo()` pops from `undo_stack` and restores the game state.
|
||||
+5. **Win Detection**:
|
||||
+ - `check_win()` returns `True` when all 4 foundations contain 13 cards (or foundations total 52 cards).
|
||||
+
|
||||
+---
|
||||
+
|
||||
+## 4. TUI Layout & Interactions (tui.py)
|
||||
+
|
||||
+The Curses TUI will draw a clean grid layout of the game board.
|
||||
+
|
||||
+### Visual Representation
|
||||
+
|
||||
+```text
|
||||
+ [Stock] [Waste] [F1] [F2] [F3] [F4]
|
||||
+ [#] [ ♦Q ] [ ] [ ] [ ] [ ]
|
||||
+
|
||||
+ [Col 1] [Col 2] [Col 3] [Col 4] [Col 5] [Col 6] [Col 7]
|
||||
+ ♠K [#] [#] [#] [#] [#] [#]
|
||||
+ ♥J [#] [#] [#] [#] [#]
|
||||
+ ♣10 [#] [#] [#] [#]
|
||||
+ ♦9 [#] [#] [#]
|
||||
+ ♠8 [#] [#]
|
||||
+ ♥7 [#]
|
||||
+ ♣6
|
||||
+```
|
||||
+
|
||||
+### Color Setup
|
||||
+- Red cards (♥, ♦) drawn with red text foreground.
|
||||
+- Black cards (♠, ♣) drawn with black or white/blue text.
|
||||
+- Focus highlights (selected cards/piles) drawn with distinct background inversion or terminal style.
|
||||
+
|
||||
+### Control Scheme
|
||||
+
|
||||
+To keep the implementation simple, intuitive, and responsive, the TUI will support a cursor/selection-based movement system:
|
||||
+- **Arrow Keys** or **WASD**: Move cursor between Stock, Waste, Foundations (1-4), and Tableau Piles (1-7).
|
||||
+- **Space / Enter**:
|
||||
+ - If cursor is on Stock: Draw card.
|
||||
+ - If cursor is on a valid card source (Tableau, Waste): Select card/stack.
|
||||
+ - If cursor is on a valid card destination (Tableau, Foundation): Move selected card/stack to this location.
|
||||
+- **'u' Key**: Undo last action.
|
||||
+- **'r' Key**: Restart a new game.
|
||||
+- **'q' Key**: Quit game.
|
||||
+
|
||||
+---
|
||||
+
|
||||
+## 5. Non-Interactive Demo Mode (`--smoke`)
|
||||
+
|
||||
+In `main.py`, if `--smoke` argument is passed, the script will execute a headless simulation:
|
||||
+1. Initialize a deterministic or random game state.
|
||||
+2. Verify stock drawing and recycling logic.
|
||||
+3. Programmatically execute a valid move (e.g., set up a mock board with a valid move, run it, and assert the state change).
|
||||
+4. Verify `undo` reverts the mock state change.
|
||||
+5. Create a nearly complete foundation set, execute the final winning move, and assert that `check_win()` detects the win.
|
||||
+6. Print a clean summary of actions taken and exit with code 0 on success.
|
||||
+
|
||||
+---
|
||||
+
|
||||
+## 6. Testing (tests/test_game_logic.py)
|
||||
+
|
||||
+We will use `pytest` to test rules and operations. Tests will include:
|
||||
+- `test_game_initialization`: Proper card counts, correct dealing distribution.
|
||||
+- `test_draw_and_recycle`: Correct handling of stock depletion and recycling.
|
||||
+- `test_legal_tableau_moves`: Rules on opposite color and rank subtraction.
|
||||
+- `test_foundation_moves`: Building same-suit foundation piles from A to K.
|
||||
+- `test_invalid_moves`: Rejection of illegal moves (e.g., King on non-empty, wrong colors, wrong order).
|
||||
+- `test_undo`: Multi-step undo stability.
|
||||
+- `test_win_detection`: Assuring win status updates correctly on foundation completion.
|
||||
+
|
||||
+---
|
||||
+
|
||||
+## 7. Plan Execution Steps
|
||||
+
|
||||
+1. **Step 1**: Create folder `solitaire-app/` and establish `requirements.txt`.
|
||||
+2. **Step 2**: Implement the engine in `solitaire-app/game_logic.py`.
|
||||
+3. **Step 3**: Implement unit tests in `solitaire-app/tests/test_game_logic.py` and run them with `pytest` to verify absolute correctness of the core game engine.
|
||||
+4. **Step 4**: Implement the non-interactive demo code in `solitaire-app/main.py` controlled by the `--smoke` flag.
|
||||
+5. **Step 5**: Implement the Curses UI layout and loop in `solitaire-app/tui.py` and hook it into `main.py`.
|
||||
+6. **Step 6**: Validate the entire application interactive interface and verify `--smoke` demo exits successfully.
|
||||
diff --git a/status.json b/status.json
|
||||
new file mode 100644
|
||||
index 000000000..905fb370f
|
||||
--- /dev/null
|
||||
+++ b/status.json
|
||||
@@ -0,0 +1,3 @@
|
||||
+{
|
||||
+ "outcome": "succeeded"
|
||||
+}
|
||||
7
stages/002-plan_app@1/response.md
Normal file
7
stages/002-plan_app@1/response.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
I have successfully created and documented a concise implementation plan for a Python Klondike Solitaire terminal-based game (with standard-library `curses` TUI).
|
||||
|
||||
The plan has been written to:
|
||||
* **`.ai/solitaire-fast-plan.md`**
|
||||
|
||||
And the required status file has been written to the workspace root:
|
||||
* **`status.json`** (`{"outcome": "succeeded"}`)
|
||||
6
stages/002-plan_app@1/status.json
Normal file
6
stages/002-plan_app@1/status.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"outcome": "succeeded",
|
||||
"notes": "Stage completed: plan_app",
|
||||
"failure_reason": null,
|
||||
"timestamp": "2026-06-04T18:05:19.277283Z"
|
||||
}
|
||||
31
stages/003-implement_app@1/prompt.md
Normal file
31
stages/003-implement_app@1/prompt.md
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
Goal: Quickly build a terminal-based Klondike solitaire game in Python with a curses TUI
|
||||
|
||||
## Completed stages
|
||||
- **plan_app**: succeeded
|
||||
- Model: gemini-3.5-flash, 61.9k tokens in / 4.6k out
|
||||
- Files: /home/daytona/workspace/fabro/.ai/solitaire-fast-plan.md, /home/daytona/workspace/fabro/status.json
|
||||
|
||||
|
||||
Read .ai/solitaire-fast-plan.md.
|
||||
|
||||
Build the complete app under solitaire-app/ in one focused pass:
|
||||
- pyproject.toml
|
||||
- main.py
|
||||
- src/solitaire_tui/ package
|
||||
- tests/ package
|
||||
- README.md
|
||||
|
||||
Implement:
|
||||
- Card, deck, pile, and GameState types
|
||||
- Initial Klondike deal
|
||||
- Move validation and execution
|
||||
- Stock/waste draw and recycle
|
||||
- Undo
|
||||
- Win detection
|
||||
- Curses UI with board rendering, keyboard navigation, help, new game, and quit
|
||||
- --smoke mode that imports the app, creates a game, renders a text snapshot or summary, and exits without curses interaction
|
||||
|
||||
Run:
|
||||
cd solitaire-app && python3 -m pytest tests/ -v && python3 -m py_compile main.py src/solitaire_tui/*.py && python3 main.py --smoke
|
||||
|
||||
Write status.json at workspace root: outcome=succeeded if the app builds, tests pass, and smoke mode works, outcome=failed with failure_reason otherwise.
|
||||
5
stages/003-implement_app@1/provider_used.json
Normal file
5
stages/003-implement_app@1/provider_used.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"mode": "agent",
|
||||
"provider": "gemini",
|
||||
"model": "gemini-3.5-flash"
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue