strat-gameplay-webapp/.claude/implementation/GROUNDBALL_CHART_REFERENCE.md
Cal Corum fb282a5e54 CLAUDE: Fix critical X-Check bugs and improve dice rolling
Fixed two critical bugs in Phase 3D X-Check implementation plus
improved dice audit trail for better tracking.

BUG #1: on_base_code Mapping Error (Sequential vs Bit Field)
============================================================
The implementation incorrectly treated on_base_code as a bit field
when it is actually a sequential lookup mapping.

WRONG (bit field):
  Code 3 (0b011) → R1 + R2
  Code 4 (0b100) → R3 only

CORRECT (sequential):
  Code 3 → R3 only
  Code 4 → R1 + R2

Fixed:
- build_advancement_from_code() decoder (sequential mapping)
- build_flyball_advancement_with_error() decoder (sequential mapping)
- 13 test on_base_code values (3↔4 corrections)
- Updated documentation to clarify NOT a bit field

BUG #2: Table Data Not Matching Official Charts
================================================
7 table entries in G1_ADVANCEMENT_TABLE and G2_ADVANCEMENT_TABLE
did not match the official rulebook charts provided by user.

Fixed table entries:
- G1 Code 1, Infield In: Changed Result 3 → 2
- G1 Code 3, Normal: Changed Result 13 → 3
- G1 Code 3, Infield In: Changed Result 3 → 1
- G1 Code 4, Normal: Changed Result 3 → 13
- G1 Code 4, Infield In: Changed Result 4 → 2
- G2 Code 3, Infield In: Changed Result 3 → 1
- G2 Code 4, Normal: Changed Result 5 → 4

Also fixed 7 test expectations to match corrected tables.

IMPROVEMENT: Better Dice Audit Trail
=====================================
Updated _resolve_x_check() in PlayResolver to use proper
dice_system.roll_fielding() instead of manual die rolling.

Benefits:
- All dice tracked in audit trail (roll_id, timestamp, position)
- Automatic error_total calculation (no manual 3d6 addition)
- Consistent with codebase patterns
- Position recorded for historical analysis

Testing:
- All 59 X-Check advancement tests passing (100%)
- All 9 PlayResolver tests passing (100%)
- All table entries validated against official charts
- Complete codebase scan: no bit field operations found

Files modified:
- backend/app/core/x_check_advancement_tables.py
- backend/tests/unit/core/test_x_check_advancement_tables.py
- backend/app/core/play_resolver.py
- .claude/implementation/PHASE_3D_CRITICAL_FIX.md (documentation)
- .claude/implementation/GROUNDBALL_CHART_REFERENCE.md (new)
- .claude/implementation/XCHECK_TEST_VALIDATION.md (new)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 23:09:16 -06:00

6.3 KiB

Groundball Chart Reference - Official Source of Truth

Source: User-provided images from official rulebook charts Date Created: 2025-11-02 Purpose: Comprehensive reference for validating all groundball test expectations


GroundballResultType Reference (1-13)

1.  BATTER_OUT_RUNNERS_HOLD
2.  DOUBLE_PLAY_AT_SECOND - Batter out, runner on 1st out - double play! Other runners advance 1 base
3.  BATTER_OUT_RUNNERS_ADVANCE
4.  BATTER_SAFE_FORCE_OUT_AT_SECOND - Batter safe, runner on 1st forced out at 2nd. Other runners advance 1 base
5.  HIT_TO_2B/SS - Batter out, runners advance 1 base. Hit anywhere else: batter out, runners hold
6.  HIT_TO_1B/2B - Batter out, runners advance 1 base. Hit anywhere else: batter out, runners hold
7.  BATTER_OUT_FORCED_ONLY - Batter out, runner holds (unless forced)
8.  BATTER_OUT_FORCED_ONLY_ALT - Batter out, runner holds (unless forced)
9.  LEAD_HOLDS_TRAIL_ADVANCES - Batter out, runner on 3rd holds, runner on 1st advances 1 base
10. DOUBLE_PLAY_HOME_TO_FIRST - Home to first double play, other runners advance
11. BATTER_SAFE_LEAD_OUT - Batter safe, lead runner is out, other runners advance 1 base
12. DECIDE - Hit to 1b/2b: batter is out, runners advance. Hit to 3b: batter is out, runners hold. Hit to ss/p/c: chance for DECIDE
13. CONDITIONAL_DOUBLE_PLAY - Hit to c/3b: double play at 3rd and 2nd base, batter safe. Otherwise: double play at 2nd and 1st base

G1 Chart (Groundball Type A - Fast Grounder)

Simplified View from Image #1

Bases Occupied Infield Normal Infield In
Empty 1 N/A
1st 2 2
2nd 12 12
3rd 3 1
1st & 2nd 13 2
1st & 3rd 2 1
2nd & 3rd 3 1
Loaded 2 10

Notes:

  • Image #1 appears to show a simplified chart with one result per (base situation, defensive position)
  • May represent GBA (Groundball A) specifically
  • Need clarification: Are GBB and GBC different for G1, or is G1 always the same result?

G2 Chart (Groundball Type B - Medium Grounder)

Simplified View from Image #2

Bases Occupied Infield Normal Infield In
Empty 1 N/A
1st 4 4
2nd 12 12
3rd 5 1
1st & 2nd 4 4
1st & 3rd 4 1
2nd & 3rd 5 1
Loaded 4 11

G3 Chart (Groundball Type C - Slow Grounder)

Simplified View from Image #3

Bases Occupied Infield Normal Infield In
Empty 1 N/A
1st 3 3
2nd 12 3
3rd 3 DECIDE
1st & 2nd 3 3
1st & 3rd 3 3
2nd & 3rd 3 DECIDE
Loaded 3 11

Note: "DECIDE" in chart may map to Result 12 (DECIDE_OPPORTUNITY)


Detailed Infield Back Chart (Image #4)

This appears to be a more detailed breakdown showing GBA, GBB, GBC variations:

Bases Occupied GBA GBB GBC Notes
Empty 1 1 1 Batter out, runners hold
1st 2 4 3 GBA: DP. GBB: Batter safe, force out at 2nd. GBC: Batter out, advance
2nd 6 6 3 GBA/B: Hit to right side conditional. GBC: Advance
3rd 5 5 3 GBA/B: Hit to middle infield conditional. GBC: Advance
1st & 2nd 2 4 3 GBA: DP. GBB: Batter safe, force. GBC: Advance
1st & 3rd 2 4 3 Same as 1st only
2nd & 3rd 5 5 3 GBA/B: Conditional middle IF. GBC: Advance
Loaded 2 4 3 GBA: DP. GBB: Batter safe, force. GBC: R3 holds, R1 advances

Detailed Infield In Chart (Image #5)

Bases Occupied GBA GBB GBC Notes
3rd 7 1 8 Hit to 1b/2b: runners advance. Hit to 3b: hold. ss/p/c: DECIDE
1st & 3rd 7 9 8 GBB: Lead holds, trail advances
2nd & 3rd 7 1 8 Hit to c/3b: double play at 3rd and 2nd
Loaded 10 11 11 GBA: DP home to 1st. GBB/C: Batter safe, lead out

Questions for Validation

  1. Chart Relationship:

    • Are Images #1, #2, #3 showing GBA results specifically?
    • Or are they showing a simplified "most common" result?
    • Do G1/G2/G3 have different results for GBA/GBB/GBC internally?
  2. Mapping GBA/GBB/GBC to G1/G2/G3:

    • Does G1 always use GBA column from detailed chart?
    • Does G2 always use GBB column?
    • Does G3 always use GBC column?
    • Or is the relationship different?
  3. Test Naming Convention:

    • Current tests use outcome names: GROUNDBALL_A, GROUNDBALL_B, GROUNDBALL_C
    • Do these map to: G1=GBA, G2=GBB, G3=GBC?
    • Or to: G1/G2/G3 (which then have internal GBA/GBB/GBC logic)?

Current Understanding (To Be Validated)

Based on the code in runner_advancement.py, it appears:

  • Tests use PlayOutcome.GROUNDBALL_A/B/C
  • Code maps these to gb_letter = 'A', 'B', or 'C'
  • Code has charts for "Infield Back" and "Infield In"
  • Code selects result based on (gb_letter, base_situation, defensive_position)

Hypothesis:

  • The detailed charts (Images #4 and #5) show the actual GBA/GBB/GBC breakdown
  • The G1/G2/G3 simplified charts (Images #1, #2, #3) might be showing a different categorization
  • OR they might be showing just one column from the detailed charts

Need clarification from user before proceeding with test fixes.


Next Steps

  1. Transcribe all charts (DONE)
  2. Get user clarification on chart relationship
  3. Map each current test to correct expected result
  4. Fix all test expectations
  5. Verify all 59 tests pass with correct expectations