Updated terminal client REPL to work with refactored GameState structure where current_batter/pitcher/catcher are now LineupPlayerState objects instead of integer IDs. Also standardized all documentation to properly show 'uv run' prefixes for Python commands. REPL Updates: - terminal_client/display.py: Access lineup_id from LineupPlayerState objects - terminal_client/repl.py: Fix typos (self.current_game → self.current_game_id) - tests/unit/terminal_client/test_commands.py: Create proper LineupPlayerState objects in test fixtures (2 tests fixed, all 105 terminal client tests passing) Documentation Updates (100+ command examples): - CLAUDE.md: Updated pytest examples to use 'uv run' prefix - terminal_client/CLAUDE.md: Updated ~40 command examples - tests/CLAUDE.md: Updated all test commands (unit, integration, debugging) - app/*/CLAUDE.md: Updated test and server startup commands (5 files) All Python commands now consistently use 'uv run' prefix to align with project's UV migration, improving developer experience and preventing confusion about virtual environment activation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
769 lines
20 KiB
Markdown
769 lines
20 KiB
Markdown
# Terminal Client - Game Engine Testing Tool
|
||
|
||
## Overview
|
||
|
||
Interactive REPL (Read-Eval-Print Loop) terminal UI for testing the game engine directly without WebSockets or frontend dependencies. Built with Python's `cmd` module, Click, and Rich for a polished CLI experience.
|
||
|
||
**Purpose**: Rapid iteration on game engine development without needing to build/maintain a web frontend during core logic development.
|
||
|
||
**Key Feature**: Persistent in-memory state - the game engine `state_manager` stays loaded throughout your REPL session, allowing you to test gameplay flow without losing state between commands.
|
||
|
||
## Usage Modes
|
||
|
||
### Interactive REPL (Recommended)
|
||
|
||
Start the interactive shell for persistent in-memory state:
|
||
|
||
```bash
|
||
uv run python -m terminal_client
|
||
# Or: source .venv/bin/activate && python -m terminal_client
|
||
|
||
# Then type commands interactively:
|
||
⚾ > new_game
|
||
⚾ > defensive
|
||
⚾ > offensive
|
||
⚾ > resolve
|
||
⚾ > quick_play 10
|
||
⚾ > status
|
||
⚾ > quit
|
||
```
|
||
|
||
**Advantages**:
|
||
- ✅ Game state stays in memory across commands
|
||
- ✅ Fast iteration - no process startup overhead
|
||
- ✅ Natural workflow like `psql` or `redis-cli`
|
||
- ✅ Persistent event loop prevents database connection issues
|
||
|
||
### Standalone Commands (Alternative)
|
||
|
||
Run individual commands with persistent config file:
|
||
|
||
```bash
|
||
uv run python -m terminal_client new-game
|
||
uv run python -m terminal_client defensive --alignment normal
|
||
uv run python -m terminal_client offensive --approach power
|
||
uv run python -m terminal_client resolve
|
||
```
|
||
|
||
**Note**: Config file (`~/.terminal_client_config.json`) remembers current game between commands.
|
||
|
||
## Architecture
|
||
|
||
### Design Decisions
|
||
|
||
**Why Terminal UI?**
|
||
- ✅ Zero frontend overhead - test game logic immediately
|
||
- ✅ No WebSocket complexity - direct function calls to GameEngine
|
||
- ✅ Fast iteration - change code, test instantly
|
||
- ✅ Easy debugging - logs and state visible in same terminal
|
||
- ✅ CI/CD ready - can be scripted for automated testing
|
||
|
||
**Why Click over Typer?**
|
||
- ✅ Already installed (FastAPI dependency)
|
||
- ✅ Battle-tested and stable (v8.1.8)
|
||
- ✅ Python 3.13 compatible
|
||
- ✅ No version compatibility issues
|
||
|
||
**Why Rich?**
|
||
- ✅ Beautiful formatted output (colors, panels, tables)
|
||
- ✅ Clear game state visualization
|
||
- ✅ Better testing UX than plain print statements
|
||
|
||
**Why REPL (cmd module)?**
|
||
- ✅ Single persistent process - state manager stays in memory
|
||
- ✅ Persistent event loop - no database connection conflicts
|
||
- ✅ Command history and readline support
|
||
- ✅ Tab completion (future enhancement)
|
||
|
||
### Technology Stack
|
||
|
||
```python
|
||
click==8.1.8 # CLI framework (already installed via FastAPI)
|
||
rich==13.9.4 # Terminal formatting and colors
|
||
cmd (stdlib) # REPL framework (built into Python)
|
||
```
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
terminal_client/
|
||
├── __init__.py # Package marker
|
||
├── __main__.py # Entry point - routes to REPL or CLI
|
||
├── repl.py # Interactive REPL with cmd.Cmd
|
||
├── main.py # Click CLI standalone commands
|
||
├── display.py # Rich formatting for game state
|
||
├── config.py # Persistent configuration file manager
|
||
└── CLAUDE.md # This file
|
||
```
|
||
|
||
## REPL Commands Reference
|
||
|
||
All commands in interactive REPL mode. Use underscores (e.g., `new_game` not `new-game`).
|
||
|
||
### new_game
|
||
|
||
Create a new game with lineups and start it (all-in-one).
|
||
|
||
```
|
||
⚾ > new_game [--league sba|pd] [--home-team N] [--away-team N]
|
||
|
||
Examples:
|
||
new_game
|
||
new_game --league pd
|
||
new_game --home-team 5 --away-team 3
|
||
```
|
||
|
||
Automatically:
|
||
1. Creates game in database
|
||
2. Generates 9-player lineups for both teams
|
||
3. Starts the game
|
||
4. Sets as current game
|
||
|
||
### defensive
|
||
|
||
Submit defensive decision.
|
||
|
||
```
|
||
⚾ > defensive [--alignment TYPE] [--infield DEPTH] [--outfield DEPTH] [--hold BASES]
|
||
|
||
Options:
|
||
--alignment normal, shifted_left, shifted_right, extreme_shift
|
||
--infield in, normal, back, double_play
|
||
--outfield in, normal, back
|
||
--hold Comma-separated bases (e.g., 1,3)
|
||
|
||
Examples:
|
||
defensive
|
||
defensive --alignment shifted_left
|
||
defensive --infield double_play --hold 1,3
|
||
```
|
||
|
||
### offensive
|
||
|
||
Submit offensive decision.
|
||
|
||
```
|
||
⚾ > offensive [--approach TYPE] [--steal BASES] [--hit-run] [--bunt]
|
||
|
||
Options:
|
||
--approach normal, contact, power, patient
|
||
--steal Comma-separated bases (e.g., 2,3)
|
||
--hit-run Enable hit-and-run
|
||
--bunt Attempt bunt
|
||
|
||
Examples:
|
||
offensive
|
||
offensive --approach power
|
||
offensive --steal 2 --hit-run
|
||
```
|
||
|
||
### resolve
|
||
|
||
Resolve the current play.
|
||
|
||
```
|
||
⚾ > resolve
|
||
```
|
||
|
||
Both defensive and offensive decisions must be submitted first.
|
||
Displays play result with dice roll, runner advancement, and updated state.
|
||
|
||
### status
|
||
|
||
Display current game state.
|
||
|
||
```
|
||
⚾ > status
|
||
```
|
||
|
||
Shows score, inning, outs, runners, and pending decisions.
|
||
|
||
### quick_play
|
||
|
||
Auto-play multiple plays with default decisions.
|
||
|
||
```
|
||
⚾ > quick_play [COUNT]
|
||
|
||
Examples:
|
||
quick_play # Play 1 play
|
||
quick_play 10 # Play 10 plays
|
||
quick_play 27 # Play ~3 innings
|
||
```
|
||
|
||
Perfect for rapidly advancing game state for testing.
|
||
|
||
### box_score
|
||
|
||
Display box score.
|
||
|
||
```
|
||
⚾ > box_score
|
||
```
|
||
|
||
### list_games
|
||
|
||
List all games in state manager (in memory).
|
||
|
||
```
|
||
⚾ > list_games
|
||
```
|
||
|
||
Shows active games with current game marked.
|
||
|
||
### use_game
|
||
|
||
Switch to a different game.
|
||
|
||
```
|
||
⚾ > use_game <game_id>
|
||
|
||
Example:
|
||
use_game a1b2c3d4-e5f6-7890-abcd-ef1234567890
|
||
```
|
||
|
||
### config
|
||
|
||
Show configuration.
|
||
|
||
```
|
||
⚾ > config
|
||
```
|
||
|
||
Displays config file path and current game.
|
||
|
||
### clear
|
||
|
||
Clear the screen.
|
||
|
||
```
|
||
⚾ > clear
|
||
```
|
||
|
||
### quit / exit
|
||
|
||
Exit the REPL.
|
||
|
||
```
|
||
⚾ > quit
|
||
⚾ > exit
|
||
```
|
||
|
||
Or press Ctrl+D.
|
||
|
||
---
|
||
|
||
## Standalone Commands Reference
|
||
|
||
For running individual commands outside REPL mode.
|
||
|
||
### new-game
|
||
```bash
|
||
uv run python -m terminal_client new-game [OPTIONS]
|
||
|
||
Options:
|
||
--league TEXT League (sba or pd) [default: sba]
|
||
--game-id TEXT Game UUID (auto-generated if not provided)
|
||
--home-team INTEGER Home team ID [default: 1]
|
||
--away-team INTEGER Away team ID [default: 2]
|
||
|
||
Example:
|
||
uv run python -m terminal_client start-game --league sba
|
||
uv run python -m terminal_client start-game --game-id <uuid> --home-team 5 --away-team 3
|
||
```
|
||
|
||
### Defensive Decision
|
||
```bash
|
||
uv run python -m terminal_client defensive [OPTIONS]
|
||
|
||
Options:
|
||
--game-id TEXT Game UUID (uses current if not provided)
|
||
--alignment TEXT Defensive alignment [default: normal]
|
||
Values: normal, shifted_left, shifted_right, extreme_shift
|
||
--infield TEXT Infield depth [default: normal]
|
||
Values: in, normal, back, double_play
|
||
--outfield TEXT Outfield depth [default: normal]
|
||
Values: in, normal, back
|
||
--hold TEXT Comma-separated bases to hold (e.g., 1,3)
|
||
|
||
Example:
|
||
uv run python -m terminal_client defensive --alignment shifted_left
|
||
uv run python -m terminal_client defensive --infield double_play --hold 1,3
|
||
```
|
||
|
||
### Offensive Decision
|
||
```bash
|
||
uv run python -m terminal_client offensive [OPTIONS]
|
||
|
||
Options:
|
||
--game-id TEXT Game UUID (uses current if not provided)
|
||
--approach TEXT Batting approach [default: normal]
|
||
Values: normal, contact, power, patient
|
||
--steal TEXT Comma-separated bases to steal (e.g., 2,3)
|
||
--hit-run Hit-and-run play (flag)
|
||
--bunt Bunt attempt (flag)
|
||
|
||
Example:
|
||
uv run python -m terminal_client offensive --approach power
|
||
uv run python -m terminal_client offensive --steal 2 --hit-run
|
||
```
|
||
|
||
### Resolve Play
|
||
```bash
|
||
uv run python -m terminal_client resolve [OPTIONS]
|
||
|
||
Options:
|
||
--game-id TEXT Game UUID (uses current if not provided)
|
||
|
||
Example:
|
||
uv run python -m terminal_client resolve
|
||
```
|
||
|
||
Resolves the current play using submitted defensive and offensive decisions.
|
||
Displays full play result with dice rolls, runner advancement, and updated game state.
|
||
|
||
### Game Status
|
||
```bash
|
||
uv run python -m terminal_client status [OPTIONS]
|
||
|
||
Options:
|
||
--game-id TEXT Game UUID (uses current if not provided)
|
||
|
||
Example:
|
||
uv run python -m terminal_client status
|
||
```
|
||
|
||
### Box Score
|
||
```bash
|
||
uv run python -m terminal_client box-score [OPTIONS]
|
||
|
||
Options:
|
||
--game-id TEXT Game UUID (uses current if not provided)
|
||
|
||
Example:
|
||
uv run python -m terminal_client box-score
|
||
```
|
||
|
||
### Quick Play
|
||
```bash
|
||
uv run python -m terminal_client quick-play [OPTIONS]
|
||
|
||
Options:
|
||
--count INTEGER Number of plays to execute [default: 1]
|
||
--game-id TEXT Game UUID (uses current if not provided)
|
||
|
||
Example:
|
||
uv run python -m terminal_client quick-play --count 10
|
||
uv run python -m terminal_client quick-play --count 27 # Full inning
|
||
```
|
||
|
||
**Use Case**: Rapidly advance game state for testing specific scenarios (e.g., test 9th inning logic).
|
||
|
||
Submits default decisions (normal alignment, normal approach) and auto-resolves plays.
|
||
|
||
### List Games
|
||
```bash
|
||
uv run python -m terminal_client list-games
|
||
|
||
Example:
|
||
uv run python -m terminal_client list-games
|
||
```
|
||
|
||
Shows all active games in the state manager.
|
||
|
||
### Use Game
|
||
```bash
|
||
uv run python -m terminal_client use-game <game_id>
|
||
|
||
Example:
|
||
uv run python -m terminal_client use-game a1b2c3d4-e5f6-7890-abcd-ef1234567890
|
||
```
|
||
|
||
Switch to a different game (sets as "current" game for subsequent commands).
|
||
|
||
## Usage Patterns
|
||
|
||
### Typical REPL Testing Workflow
|
||
|
||
```bash
|
||
# Start REPL
|
||
uv run python -m terminal_client
|
||
# Or: source .venv/bin/activate && python -m terminal_client
|
||
|
||
# Create and play a game
|
||
⚾ > new_game
|
||
⚾ > defensive
|
||
⚾ > offensive
|
||
⚾ > resolve
|
||
⚾ > status
|
||
|
||
# Continue playing
|
||
⚾ > defensive --alignment shifted_left
|
||
⚾ > offensive --approach power
|
||
⚾ > resolve
|
||
|
||
# Or use quick-play to auto-advance
|
||
⚾ > quick_play 10
|
||
|
||
# Check final state
|
||
⚾ > status
|
||
⚾ > quit
|
||
```
|
||
|
||
**Advantages**: Game state stays in memory throughout the session!
|
||
|
||
### Testing Specific Scenarios
|
||
|
||
```bash
|
||
# Test defensive shifts
|
||
uv run python -m terminal_client start-game
|
||
uv run python -m terminal_client defensive --alignment shifted_left --infield double_play
|
||
uv run python -m terminal_client offensive
|
||
uv run python -m terminal_client resolve
|
||
|
||
# Test stealing
|
||
uv run python -m terminal_client start-game
|
||
uv run python -m terminal_client defensive
|
||
uv run python -m terminal_client offensive --steal 2,3 # Double steal
|
||
uv run python -m terminal_client resolve
|
||
|
||
# Test hit-and-run
|
||
uv run python -m terminal_client defensive
|
||
uv run python -m terminal_client offensive --hit-run
|
||
uv run python -m terminal_client resolve
|
||
|
||
# Advance to late game quickly
|
||
uv run python -m terminal_client start-game
|
||
uv run python -m terminal_client quick-play --count 50 # ~6 innings
|
||
uv run python -m terminal_client status
|
||
```
|
||
|
||
### Multiple Games
|
||
|
||
```bash
|
||
# Start game 1
|
||
uv run python -m terminal_client start-game
|
||
# ... play some ...
|
||
|
||
# Start game 2
|
||
uv run python -m terminal_client start-game
|
||
# ... play some ...
|
||
|
||
# List all games
|
||
uv run python -m terminal_client list-games
|
||
|
||
# Switch back to game 1
|
||
uv run python -m terminal_client use-game <game-1-uuid>
|
||
uv run python -m terminal_client status
|
||
```
|
||
|
||
## Display Features
|
||
|
||
### Game State Panel
|
||
- **Game Info**: UUID, league, status
|
||
- **Score**: Away vs Home
|
||
- **Inning**: Current inning and half
|
||
- **Outs**: Current out count
|
||
- **Runners**: Bases occupied with lineup IDs
|
||
- **Current Players**: Batter, pitcher (by lineup ID)
|
||
- **Pending Decision**: Enhanced display showing what action is needed next (Added 2025-10-28)
|
||
- Shows "⚠️ WAITING FOR ACTION" header when play is pending
|
||
- Displays specific message: "The defense needs to submit their decision" or "Ready to resolve play"
|
||
- Shows exact command to run next: `defensive [OPTIONS]`, `offensive [OPTIONS]`, or `resolve`
|
||
- Color-coded for clarity (yellow warning + cyan command hints)
|
||
- **Last Play**: Result description
|
||
|
||
### Play Result Panel
|
||
- **Outcome**: Hit type (GB, FB, LD, etc.)
|
||
- **Result Description**: Human-readable play result
|
||
- **Dice Roll**: Actual d20 roll with context
|
||
- **Outs/Runs**: Changes from play
|
||
- **Runner Movement**: Base-by-base advancement
|
||
- **Updated Score**: Current score after play
|
||
|
||
### Color Coding
|
||
- ✅ Green: Success messages, runs scored
|
||
- ❌ Red: Error messages, outs recorded
|
||
- ℹ️ Blue: Info messages
|
||
- ⚠️ Yellow: Warning messages
|
||
- Cyan: Game state highlights
|
||
|
||
## Implementation Details
|
||
|
||
### Persistent Event Loop (REPL Mode)
|
||
|
||
The REPL uses a single persistent event loop for the entire session:
|
||
|
||
```python
|
||
def __init__(self):
|
||
# Create persistent event loop
|
||
self.loop = asyncio.new_event_loop()
|
||
asyncio.set_event_loop(self.loop)
|
||
|
||
def _run_async(self, coro):
|
||
# Reuse same loop for all commands
|
||
return self.loop.run_until_complete(coro)
|
||
|
||
def do_quit(self, arg):
|
||
# Clean up on exit
|
||
self.loop.close()
|
||
```
|
||
|
||
**Why**: Prevents database connection pool conflicts that occur when creating new event loops for each command.
|
||
|
||
### Game State Management
|
||
|
||
**REPL Mode**: Game state manager stays in memory throughout the session.
|
||
- In-memory state persists across all commands
|
||
- O(1) state lookups
|
||
- Perfect for testing gameplay flow
|
||
|
||
**Standalone Mode**: Uses persistent config file (`~/.terminal_client_config.json`).
|
||
- Stores current game UUID between command invocations
|
||
- Set automatically by `new-game` or `use-game`
|
||
- Used as default if `--game-id` not specified
|
||
|
||
### Async Command Pattern
|
||
|
||
All commands use the same async pattern:
|
||
```python
|
||
@cli.command()
|
||
@click.option('--game-id', default=None)
|
||
def some_command(game_id):
|
||
async def _some_command():
|
||
gid = UUID(game_id) if game_id else get_current_game()
|
||
# ... async operations ...
|
||
state = await game_engine.some_method(gid)
|
||
display.show_something(state)
|
||
|
||
asyncio.run(_some_command())
|
||
```
|
||
|
||
This allows direct async calls to GameEngine without WebSocket overhead.
|
||
|
||
### Error Handling
|
||
|
||
- **Click Abort**: Raises `click.Abort()` on errors (clean exit)
|
||
- **Rich Display**: All errors shown with colored formatting
|
||
- **Logger**: Exceptions logged with full traceback
|
||
- **User-Friendly**: Clear error messages (not stack traces)
|
||
|
||
## Testing with Terminal Client
|
||
|
||
### Unit Test Scenarios
|
||
|
||
```bash
|
||
# Test game startup validation
|
||
uv run python -m terminal_client start-game
|
||
# Should fail: No lineups set
|
||
|
||
# Test invalid decisions
|
||
uv run python -m terminal_client defensive --alignment invalid_value
|
||
# Should fail: ValidationError
|
||
|
||
# Test resolve without decisions
|
||
uv run python -m terminal_client resolve
|
||
# Should fail: No decisions submitted
|
||
```
|
||
|
||
### Integration Test Scenarios
|
||
|
||
```bash
|
||
# Full game flow
|
||
uv run python -m terminal_client start-game
|
||
# ... set lineups via database directly ...
|
||
uv run python -m terminal_client start-game # Retry
|
||
uv run python -m terminal_client quick-play --count 100
|
||
uv run python -m terminal_client status
|
||
# Verify: Game status = "completed"
|
||
|
||
# State persistence
|
||
uv run python -m terminal_client start-game
|
||
# Note the game UUID
|
||
uv run python -m terminal_client quick-play --count 10
|
||
# Kill terminal
|
||
# Restart and use same UUID
|
||
uv run python -m terminal_client use-game <uuid>
|
||
uv run python -m terminal_client status
|
||
# Verify: State recovered from database
|
||
```
|
||
|
||
## Limitations
|
||
|
||
### Current Limitations (Phase 2)
|
||
1. **No Lineup Management**: Must set lineups via database directly
|
||
2. **No Player Data**: Shows lineup IDs only (no names/stats)
|
||
3. **Simple Box Score**: Only shows final scores (no detailed stats)
|
||
4. **No Substitutions**: Cannot make mid-game substitutions
|
||
5. **No AI Decisions**: All decisions manual (no AI opponent)
|
||
|
||
### Future Enhancements (Post-MVP)
|
||
- Interactive lineup builder
|
||
- Player name/stat display from league API
|
||
- Full box score with batting stats
|
||
- Substitution commands
|
||
- AI decision simulation
|
||
- Play-by-play export
|
||
- Replay mode for completed games
|
||
|
||
## Development Notes
|
||
|
||
### Adding New Commands
|
||
|
||
```python
|
||
# In main.py
|
||
@cli.command('new-command')
|
||
@click.option('--some-option', default='value', help='Description')
|
||
def new_command(some_option):
|
||
"""Command description for help text."""
|
||
async def _new_command():
|
||
# Implementation
|
||
pass
|
||
|
||
asyncio.run(_new_command())
|
||
```
|
||
|
||
### Adding New Display Functions
|
||
|
||
```python
|
||
# In display.py
|
||
def display_new_thing(data: SomeModel) -> None:
|
||
"""Display new thing with Rich formatting."""
|
||
panel = Panel(
|
||
Text("Content here"),
|
||
title="[bold]Title[/bold]",
|
||
border_style="color",
|
||
box=box.ROUNDED
|
||
)
|
||
console.print(panel)
|
||
```
|
||
|
||
### Logging
|
||
|
||
All commands use the module logger:
|
||
```python
|
||
logger = logging.getLogger(f'{__name__}.main')
|
||
|
||
logger.info("Game started")
|
||
logger.error("Failed to resolve play", exc_info=True)
|
||
```
|
||
|
||
Logs appear in both terminal and `backend/logs/app_YYYYMMDD.log`.
|
||
|
||
## Troubleshooting
|
||
|
||
### Command Not Found
|
||
```bash
|
||
# Wrong
|
||
python terminal_client/main.py # ❌
|
||
|
||
# Correct
|
||
uv run python -m terminal_client start-game # ✅
|
||
```
|
||
|
||
### Import Errors
|
||
```bash
|
||
# Ensure you're in backend directory
|
||
cd backend
|
||
|
||
# Recommended: Use UV (auto-activates venv)
|
||
uv run python -m terminal_client start-game
|
||
|
||
# Alternative: Manually activate venv
|
||
source .venv/bin/activate
|
||
python -m terminal_client start-game
|
||
```
|
||
|
||
### Game Not Found
|
||
```bash
|
||
# Check active games
|
||
uv run python -m terminal_client list-games
|
||
|
||
# Use specific game ID
|
||
uv run python -m terminal_client status --game-id <uuid>
|
||
```
|
||
|
||
### Validation Errors
|
||
Check logs for detailed error messages:
|
||
```bash
|
||
tail -f logs/app_$(date +%Y%m%d).log
|
||
```
|
||
|
||
## Performance
|
||
|
||
### REPL Mode
|
||
- **Startup Time**: ~500ms (one-time on launch)
|
||
- **Command Execution**: <50ms (in-memory state lookups)
|
||
- **State Display**: <50ms (Rich rendering)
|
||
- **Quick Play (10 plays)**: ~4-5 seconds (includes 0.3s sleeps per play)
|
||
- **Memory**: ~10MB for active game state
|
||
|
||
### Standalone Mode
|
||
- **Per-Command Startup**: ~500ms (process + imports)
|
||
- **Command Execution**: <100ms (direct function calls)
|
||
- **Database Queries**: 50-100ms (config file + state recovery)
|
||
|
||
**REPL is significantly faster for iterative testing!**
|
||
|
||
## Configuration File
|
||
|
||
Location: `~/.terminal_client_config.json`
|
||
|
||
```json
|
||
{
|
||
"current_game_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
||
}
|
||
```
|
||
|
||
Automatically managed by:
|
||
- `new_game` command (sets current)
|
||
- `use_game` command (changes current)
|
||
- `config --clear` command (clears current)
|
||
|
||
## Related Documentation
|
||
|
||
- **Game Engine**: `../app/core/game_engine.py`
|
||
- **State Manager**: `../app/core/state_manager.py`
|
||
- **Game Models**: `../app/models/game_models.py`
|
||
- **Backend Guide**: `../CLAUDE.md`
|
||
|
||
## Recent Updates
|
||
|
||
### 2025-10-28: Enhanced Status Display
|
||
|
||
**Improvement**: Added user-friendly pending action guidance to status command.
|
||
|
||
**Changes**:
|
||
- Status display now shows prominent "⚠️ WAITING FOR ACTION" section when play is pending
|
||
- Provides specific guidance based on game state:
|
||
- "The defense needs to submit their decision" → Run `defensive [OPTIONS]`
|
||
- "The offense needs to submit their decision" → Run `offensive [OPTIONS]`
|
||
- "Ready to resolve play - both teams have decided" → Run `resolve`
|
||
- Command hints color-coded (yellow warnings + cyan command text + green command names)
|
||
- Makes testing workflow clearer by showing exactly what to do next
|
||
|
||
**Location**: `terminal_client/display.py:75-97`
|
||
|
||
**Usage Example**:
|
||
```bash
|
||
⚾ > status
|
||
|
||
╭─────────────────────────── Game State ───────────────────────────╮
|
||
│ ... │
|
||
│ │
|
||
│ ⚠️ WAITING FOR ACTION │
|
||
│ ──────────────────────────────────────── │
|
||
│ The defense needs to submit their decision. │
|
||
│ Run: defensive [OPTIONS] │
|
||
│ │
|
||
╰───────────────────────────────────────────────────────────────────╯
|
||
```
|
||
|
||
---
|
||
|
||
**Created**: 2025-10-26
|
||
**Author**: Claude
|
||
**Purpose**: Testing tool for Phase 2 game engine development
|
||
**Status**: ✅ Complete - Interactive REPL with persistent state working perfectly!
|
||
**Last Updated**: 2025-10-28
|