CLAUDE: Add X-Check testing to resolve_with command
Added ability to test X-Check defensive plays directly in the terminal client using the resolve_with command. This allows testing the complete X-Check resolution system (defense tables, error charts, runner advancement) with actual player ratings. Changes: - repl.py: Updated do_resolve_with() to parse "x-check <position>" syntax - Accepts "x-check", "xcheck", or "x_check" followed by position - Validates position (P, C, 1B, 2B, 3B, SS, LF, CF, RF) - Passes xcheck_position parameter through to commands - commands.py: Updated resolve_play() to accept xcheck_position parameter - Passes xcheck_position to game_engine.resolve_play() - Shows "🎯 Forcing X-Check to: <position>" message - game_engine.py: Updated resolve_play() to accept xcheck_position parameter - For X_CHECK outcomes, uses xcheck_position as hit_location - Enables full X-Check resolution with defense tables and error charts - help_text.py: Updated resolve_with help documentation - Added x-check usage syntax and examples - Documented position parameter requirement - Added note about using actual player ratings Usage: ⚾ > defensive ⚾ > offensive ⚾ > resolve_with x-check SS # Test X-Check to shortstop ⚾ > resolve_with x-check LF # Test X-Check to left field This integrates the existing play_resolver._resolve_x_check() logic, providing a way to test the complete X-Check system including defense range adjustments, table lookups, SPD tests, G2#/G3# conversion, error charts, and runner advancement. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
8fb740fe3e
commit
bb78de2b84
@ -400,7 +400,7 @@ class GameEngine:
|
||||
logger.warning(f"Offensive decision timeout for game {state.game_id}, using default")
|
||||
return OffensiveDecision() # All defaults
|
||||
|
||||
async def resolve_play(self, game_id: UUID, forced_outcome: Optional[PlayOutcome] = None) -> PlayResult:
|
||||
async def resolve_play(self, game_id: UUID, forced_outcome: Optional[PlayOutcome] = None, xcheck_position: Optional[str] = None) -> PlayResult:
|
||||
"""
|
||||
Resolve the current play with dice roll
|
||||
|
||||
@ -415,6 +415,7 @@ class GameEngine:
|
||||
Args:
|
||||
game_id: Game to resolve
|
||||
forced_outcome: If provided, use this outcome instead of rolling dice (for testing)
|
||||
xcheck_position: For X_CHECK outcomes, the position to check (SS, LF, etc.)
|
||||
|
||||
Returns:
|
||||
PlayResult with complete outcome
|
||||
@ -443,9 +444,12 @@ class GameEngine:
|
||||
"Use resolve_manual_play() for manual mode or resolve_auto_play() for auto mode."
|
||||
)
|
||||
|
||||
# For X_CHECK, use xcheck_position as the hit_location parameter
|
||||
hit_location = xcheck_position if forced_outcome == PlayOutcome.X_CHECK else None
|
||||
|
||||
result = resolver.resolve_outcome(
|
||||
outcome=forced_outcome,
|
||||
hit_location=None, # Testing doesn't specify location
|
||||
hit_location=hit_location, # For X_CHECK, this is the position being checked
|
||||
state=state,
|
||||
defensive_decision=defensive_decision,
|
||||
offensive_decision=offensive_decision,
|
||||
|
||||
@ -199,22 +199,26 @@ class GameCommands:
|
||||
logger.exception("Offensive decision error")
|
||||
return False
|
||||
|
||||
async def resolve_play(self, game_id: UUID, forced_outcome: Optional[PlayOutcome] = None) -> bool:
|
||||
async def resolve_play(self, game_id: UUID, forced_outcome: Optional[PlayOutcome] = None, xcheck_position: Optional[str] = None) -> bool:
|
||||
"""
|
||||
Resolve the current play.
|
||||
|
||||
Args:
|
||||
game_id: Game to resolve
|
||||
forced_outcome: If provided, use this outcome instead of rolling dice
|
||||
xcheck_position: For X_CHECK outcomes, the position to check (SS, LF, etc.)
|
||||
|
||||
Returns:
|
||||
True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
if forced_outcome:
|
||||
if xcheck_position:
|
||||
display.print_info(f"🎯 Forcing X-Check to: {xcheck_position}")
|
||||
else:
|
||||
display.print_info(f"🎯 Forcing outcome: {forced_outcome.value}")
|
||||
|
||||
result = await game_engine.resolve_play(game_id, forced_outcome)
|
||||
result = await game_engine.resolve_play(game_id, forced_outcome, xcheck_position)
|
||||
state = await game_engine.get_game_state(game_id)
|
||||
|
||||
if state:
|
||||
|
||||
@ -268,12 +268,17 @@ HELP_DATA = {
|
||||
|
||||
'resolve_with': {
|
||||
'summary': 'Resolve current play with a specific outcome (bypassing dice rolls)',
|
||||
'usage': 'resolve_with <OUTCOME>',
|
||||
'usage': 'resolve_with <OUTCOME>\n resolve_with x-check <POSITION>',
|
||||
'options': [
|
||||
{
|
||||
'name': 'OUTCOME',
|
||||
'type': 'STRING',
|
||||
'desc': 'PlayOutcome enum value. Use list_outcomes to see all available values.'
|
||||
},
|
||||
{
|
||||
'name': 'POSITION',
|
||||
'type': 'P|C|1B|2B|3B|SS|LF|CF|RF',
|
||||
'desc': 'For x-check: defensive position to test (required)'
|
||||
}
|
||||
],
|
||||
'examples': [
|
||||
@ -281,9 +286,11 @@ HELP_DATA = {
|
||||
'resolve_with homerun',
|
||||
'resolve_with groundball_a',
|
||||
'resolve_with double_uncapped',
|
||||
'resolve_with strikeout'
|
||||
'resolve_with strikeout',
|
||||
'resolve_with x-check SS # Test X-Check to shortstop',
|
||||
'resolve_with x-check LF # Test X-Check to left field'
|
||||
],
|
||||
'notes': 'Experimental feature for testing specific scenarios without random dice rolls. Useful for testing runner advancement, scoring, and game state changes with known outcomes.'
|
||||
'notes': 'Experimental feature for testing specific scenarios without random dice rolls. X-Check mode uses full defense tables and error charts with actual player ratings.'
|
||||
},
|
||||
|
||||
'quick_play': {
|
||||
|
||||
@ -289,9 +289,11 @@ Press Ctrl+D or type 'quit' to exit.
|
||||
Resolve the current play with a specific outcome (for testing).
|
||||
|
||||
Usage: resolve_with <outcome>
|
||||
resolve_with x-check <position>
|
||||
|
||||
Arguments:
|
||||
outcome PlayOutcome value (e.g., single_1, homerun, strikeout)
|
||||
position For x-check: P, C, 1B, 2B, 3B, SS, LF, CF, RF
|
||||
|
||||
This command allows you to force a specific outcome instead of
|
||||
rolling dice, useful for testing runner advancement, specific
|
||||
@ -304,31 +306,54 @@ Press Ctrl+D or type 'quit' to exit.
|
||||
resolve_with homerun
|
||||
resolve_with groundball_a
|
||||
resolve_with double_uncapped
|
||||
resolve_with x-check SS # Test X-Check to shortstop
|
||||
resolve_with x-check LF # Test X-Check to left field
|
||||
"""
|
||||
async def _resolve_with():
|
||||
try:
|
||||
gid = self._ensure_game()
|
||||
await self._ensure_game_loaded(gid)
|
||||
|
||||
# Parse outcome argument
|
||||
outcome_str = arg.strip().lower()
|
||||
if not outcome_str:
|
||||
# Parse arguments
|
||||
args = arg.strip().lower().split()
|
||||
if not args:
|
||||
display.print_error("Missing outcome argument")
|
||||
display.print_info("Usage: resolve_with <outcome>")
|
||||
display.print_info(" resolve_with x-check <position>")
|
||||
display.print_info("Use 'list_outcomes' to see available values")
|
||||
return
|
||||
|
||||
# Check for x-check with position
|
||||
outcome_str = args[0]
|
||||
xcheck_position = None
|
||||
|
||||
if outcome_str in ['x-check', 'xcheck', 'x_check']:
|
||||
if len(args) < 2:
|
||||
display.print_error("Missing position for x-check")
|
||||
display.print_info("Usage: resolve_with x-check <position>")
|
||||
display.print_info("Valid positions: P, C, 1B, 2B, 3B, SS, LF, CF, RF")
|
||||
return
|
||||
outcome_str = 'x_check'
|
||||
xcheck_position = args[1].upper()
|
||||
|
||||
# Validate position
|
||||
valid_positions = ['P', 'C', '1B', '2B', '3B', 'SS', 'LF', 'CF', 'RF']
|
||||
if xcheck_position not in valid_positions:
|
||||
display.print_error(f"Invalid position: {xcheck_position}")
|
||||
display.print_info(f"Valid positions: {', '.join(valid_positions)}")
|
||||
return
|
||||
|
||||
# Try to convert string to PlayOutcome enum
|
||||
from app.config import PlayOutcome
|
||||
try:
|
||||
outcome = PlayOutcome(outcome_str)
|
||||
except ValueError:
|
||||
display.print_error(f"Invalid outcome: {outcome_str}")
|
||||
display.print_info("Use 'list_outcomes' to see valid values")
|
||||
display.print_info("Use 'list_outcomes' to see available values")
|
||||
return
|
||||
|
||||
# Use shared command with forced outcome
|
||||
await game_commands.resolve_play(gid, forced_outcome=outcome)
|
||||
await game_commands.resolve_play(gid, forced_outcome=outcome, xcheck_position=xcheck_position)
|
||||
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
Loading…
Reference in New Issue
Block a user