# 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 <outcome>`** - 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 <outcome>

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 <TAB>
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_<TAB>
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 <outcome>
ℹ 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.
