# Manual Outcome Testing Feature **Date**: 2025-10-29 **Status**: Implemented (Experimental) **Purpose**: Allow manual specification of play outcomes for testing specific scenarios --- ## Overview Added two new terminal client commands to support testing specific game scenarios without random dice rolls: 1. **`list_outcomes`** - Display all available PlayOutcome values 2. **`resolve_with `** - Resolve play with a specific outcome ## Commands ### list_outcomes Displays a beautiful categorized table of all available PlayOutcome enum values. **Usage:** ```bash ⚾ > list_outcomes ``` **Output:** - Categorized table with: - **Outs**: strikeout, groundball variants, flyout variants, lineouts, popouts - **Hits**: single variants, double variants, triple, homerun - **Walks/HBP**: walk, hbp, intentional_walk - **Errors**: error - **Interrupts**: wild_pitch, passed_ball, stolen_base, caught_stealing, balk, pick_off - **Ballpark**: bp_homerun, bp_single, bp_flyout, bp_lineout ### resolve_with Resolves the current play with a specific outcome instead of rolling dice. **Usage:** ```bash ⚾ > resolve_with single_1 ⚾ > resolve_with homerun ⚾ > resolve_with groundball_a ⚾ > resolve_with double_uncapped ``` **Features:** - Validates outcome string against PlayOutcome enum - Provides clear error messages for invalid outcomes - TAB completion for all outcome names - Detailed help text with examples **Current Status:** ⚠️ **Experimental** - Currently shows warning and uses regular dice resolution. Full forced outcome integration will be added in Week 7 as part of the strategic decision system implementation. The command infrastructure is in place and ready for integration when the game engine supports forced outcomes. ## Testing Use Cases These commands will be useful for testing: 1. **Runner Advancement Rules** ```bash # Set up bases loaded # Then force specific outcomes to test advancement resolve_with single_1 # Test standard single advancement resolve_with single_2 # Test enhanced advancement resolve_with double_2 # Runners to 2nd and home resolve_with double_3 # Runners to 3rd and home ``` 2. **Double Play Mechanics** ```bash # Set up runner on first, <2 outs resolve_with groundball_a # Should check for DP opportunity resolve_with groundball_b # Standard groundout ``` 3. **Uncapped Hit Decision Trees** ```bash # Test uncapped outcomes resolve_with single_uncapped resolve_with double_uncapped # Should trigger advancement decision workflows ``` 4. **Scoring Scenarios** ```bash # Runner on third, test different outcomes resolve_with groundball_b # Does runner score? resolve_with flyout_b # Tag up from third? resolve_with single_1 # Should score easily ``` 5. **Game State Edge Cases** ```bash # Test bases loaded, 2 outs resolve_with strikeout # Inning over resolve_with homerun # Grand slam resolve_with walk # Force in run ``` ## Implementation Details ### Files Modified 1. **`terminal_client/commands.py`** - Added `PlayOutcome` import - Enhanced `resolve_play()` with `forced_outcome` parameter - Added `list_outcomes()` method with Rich table display 2. **`terminal_client/repl.py`** - Added `do_list_outcomes()` command - Added `do_resolve_with()` command with outcome parsing 3. **`terminal_client/completions.py`** - Added `VALID_OUTCOMES` constant with all PlayOutcome values - Added `complete_resolve_with()` method for TAB completion 4. **`terminal_client/help_text.py`** - Added commands to "Testing & Development" section - Added `list_outcomes` help entry - Added `resolve_with` help entry with examples ### TAB Completion The `resolve_with` command has full TAB completion support: ```bash ⚾ > resolve_with strikeout groundball_a groundball_b groundball_c flyout_a flyout_b flyout_c lineout single_1 single_2 single_uncapped double_2 double_3 double_uncapped triple homerun walk hbp ... ⚾ > resolve_with single_ single_1 single_2 single_uncapped ⚾ > resolve_with single_1 ``` ### Error Handling Clear error messages for invalid input: ```bash ⚾ > resolve_with ❌ Missing outcome argument ℹ Usage: resolve_with ℹ Use 'list_outcomes' to see available values ⚾ > resolve_with invalid_outcome ❌ Invalid outcome: invalid_outcome ℹ Use 'list_outcomes' to see valid values ``` ## Future Enhancements (Week 7) When implementing Week 7 strategic decisions, integrate forced outcomes: 1. **Add `resolve_play_with_outcome()` to GameEngine** ```python async def resolve_play_with_outcome( self, game_id: UUID, forced_outcome: PlayOutcome ) -> PlayResult: """ Resolve play with a specific outcome (testing only). Bypasses dice rolling and uses provided outcome directly. All other game logic (runner advancement, scoring, etc.) still applies. """ # Get current state state = state_manager.get_state(game_id) # Create PlayResult with forced outcome result = PlayResult( outcome=forced_outcome, description=f"Forced outcome: {forced_outcome.value}", outs_recorded=1 if forced_outcome.is_out() else 0, runs_scored=0, # Calculated by runner advancement hit_location=self._get_default_hit_location(forced_outcome), runner_movements=[] ) # Apply result using normal resolution logic await self._apply_play_result(state, result) return result ``` 2. **Update `commands.py` to use new method** ```python if forced_outcome: result = await game_engine.resolve_play_with_outcome(game_id, forced_outcome) else: result = await game_engine.resolve_play(game_id) ``` 3. **Add runner advancement for forced outcomes** - Use RunnerAdvancer class (from Week 7 plan) - Calculate movements based on outcome type - Apply scoring logic ## Testing Manual testing performed: - ✅ `list_outcomes` displays all outcomes correctly - ✅ TAB completion works for outcome names - ✅ Invalid outcomes show clear error messages - ✅ Help text displays correctly - ✅ Commands integrate with existing REPL flow --- ## Usage Examples ### Basic Workflow ```bash # Start terminal client python -m terminal_client # Create a game ⚾ > new_game # Submit decisions ⚾ > defensive ⚾ > offensive # See all available outcomes ⚾ > list_outcomes # Try forcing a specific outcome ⚾ > resolve_with single_1 ⚠️ Manual outcome selection is experimental Using regular resolution for now (forced outcome noted) # [Regular resolution happens] # This will be fully functional in Week 7 # Continue testing ⚾ > status ⚾ > resolve_with homerun ``` ### Testing Runner Advancement ```bash # Set up specific scenario ⚾ > quick_play 10 # Advance game state # Check current state ⚾ > status # Inning: 3 Top, Outs: 1, Runners: [1st, 3rd] # Force single to test advancement ⚾ > defensive ⚾ > offensive ⚾ > resolve_with single_2 # Verify runner advancement logic ⚾ > status # Runner from 3rd should score # Runner from 1st should advance to 3rd (enhanced) ``` --- **Next Steps**: Week 7 implementation will add full forced outcome support to the game engine. **Documentation**: See `terminal_client/CLAUDE.md` for full terminal client guide.