Skip to content

Commit c8b677a

Browse files
hankhsu1996claude
andcommitted
Add house edge calculation and CUDA Monte Carlo simulation
- Add composition-dependent EV calculation for player draws and dealer outcomes - Add HouseEdgeCalculator class for analytical house edge computation - Add CUDA Monte Carlo simulator (~290M hands/sec on RTX 3080) - Add blackjack payout option (3:2 vs 6:5) to web UI and strategy generation - Add house edge display with methodology tooltip on web UI - Remove legacy CLI (main.py) and renderers in favor of web app - Remove tabulate dependency (no longer needed) - Restructure .gitignore files to be local to each folder - Update documentation for new calculation methodology 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c4abc0b commit c8b677a

29 files changed

Lines changed: 4998 additions & 461 deletions

.gitignore

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,6 @@ ENV/
3636
.coverage
3737
htmlcov/
3838

39-
# Generated files
40-
strategy.html
41-
web/public/strategies/
42-
43-
# Web app
44-
web/node_modules/
45-
web/dist/
46-
4739
# Linting cache
4840
.ruff_cache/
4941

CLAUDE.md

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,6 @@ cd web && npm run dev
2020

2121
Open http://localhost:5173/blackjack-basic-strategy/
2222

23-
### CLI
24-
25-
```bash
26-
# Text output to terminal
27-
uv run main.py
28-
29-
# HTML output (color-coded)
30-
uv run main.py --format html
31-
```
32-
3323
## Project Structure
3424

3525
```
@@ -38,21 +28,24 @@ uv run main.py --format html
3828
│ ├── cards.py # Card values, probabilities
3929
│ ├── dealer.py # Dealer outcome distribution
4030
│ ├── evaluator.py # EV calculations
31+
│ ├── house_edge.py # House edge calculation
4132
│ ├── strategy.py # Optimal action selection
4233
│ ├── tables.py # Strategy data generation
43-
│ └── renderers.py # Text/HTML renderers
34+
│ └── renderers.py # Data structures
35+
├── cuda/ # GPU Monte Carlo simulation
36+
│ ├── monte_carlo.cu # CUDA implementation
37+
│ └── Makefile # Build configuration
4438
├── scripts/
4539
│ └── generate_strategies.py # Generate JSON for web app
46-
├── web/ # Svelte + Tailwind + DaisyUI
47-
│ ├── src/
48-
│ │ ├── App.svelte
49-
│ │ └── lib/
50-
│ │ ├── components/ # UI components
51-
│ │ ├── stores/ # Svelte stores
52-
│ │ ├── types/ # TypeScript types
53-
│ │ └── utils/ # Color utilities
54-
│ └── public/strategies/ # Pre-computed JSON (generated)
55-
└── main.py # CLI entry point
40+
└── web/ # Svelte + Tailwind + DaisyUI
41+
├── src/
42+
│ ├── App.svelte
43+
│ └── lib/
44+
│ ├── components/ # UI components
45+
│ ├── stores/ # Svelte stores
46+
│ ├── types/ # TypeScript types
47+
│ └── utils/ # Color utilities
48+
└── public/strategies/ # Pre-computed JSON (generated)
5649
```
5750

5851
## Development
@@ -61,7 +54,6 @@ uv run main.py --format html
6154

6255
```bash
6356
uv sync # Install dependencies
64-
uv run main.py # Run CLI
6557
uv run ruff check . # Lint
6658
uv run ruff format . # Format
6759
```
@@ -81,7 +73,21 @@ npm run build # Production build
8173
uv run python -m scripts.generate_strategies
8274
```
8375

84-
Generates 96 JSON files (6 deck options × 2⁴ boolean options) to `web/public/strategies/`.
76+
Generates strategy JSON files for all rule combinations to `web/public/strategies/`.
77+
78+
### CUDA Monte Carlo (Optional)
79+
80+
For verifying house edge calculations with high precision:
81+
82+
```bash
83+
cd cuda
84+
make # Build (requires NVIDIA GPU + CUDA toolkit)
85+
make test # Quick test: 1B hands
86+
make run # Standard: 10B hands (~±0.002%)
87+
make precision # High precision: 40B hands (~±0.001%)
88+
```
89+
90+
See `cuda/README.md` for setup instructions.
8591

8692
## Configuration Options
8793

@@ -115,17 +121,9 @@ GameConfig → EVCalculator → BasicStrategy → StrategyTables → JSON/Render
115121
- **GameConfig**: Immutable dataclass holding all rule parameters
116122
- **DealerProbabilities**: Calculates P(dealer final total | upcard)
117123
- **EVCalculator**: Core EV calculations using (total, soft_aces) state
124+
- **HouseEdgeCalculator**: Computes house edge for a given configuration
118125
- **BasicStrategy**: Determines optimal action by comparing EVs
119126
- **StrategyTables**: Generates strategy data (`StrategyData`)
120-
- **TextRenderer**: Renders tables as ASCII text (tabulate)
121-
- **HTMLRenderer**: Renders tables as color-coded HTML
122-
123-
### Renderer Pattern
124-
125-
The renderer architecture separates data from presentation:
126-
- `StrategyData` / `TableData`: Format-agnostic data structures
127-
- `Renderer` Protocol: Any class with `render(StrategyData) -> str`
128-
- Easy to add new formats (PDF, Image) by implementing the protocol
129127

130128
### State Representation
131129

cuda/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Compiled binary
2+
monte_carlo

cuda/Makefile

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# CUDA Monte Carlo Makefile
2+
3+
NVCC = /usr/local/cuda/bin/nvcc
4+
NVCC_FLAGS = -O3
5+
6+
# RTX 3080 = sm_86, RTX 3070 = sm_86, RTX 2080 = sm_75
7+
ARCH = -arch=sm_86
8+
9+
TARGET = monte_carlo
10+
SRC = monte_carlo.cu cJSON.c
11+
STRATEGY = ../web/public/strategies/6-h17-das-rsa-peek-32.json
12+
13+
.PHONY: all clean run test precision
14+
15+
all: $(TARGET)
16+
17+
$(TARGET): monte_carlo.cu cJSON.c cJSON.h
18+
$(NVCC) $(NVCC_FLAGS) $(ARCH) -o $@ monte_carlo.cu cJSON.c
19+
20+
clean:
21+
rm -f $(TARGET)
22+
23+
# Quick test: 1 billion hands
24+
test: $(TARGET)
25+
./$(TARGET) $(STRATEGY) 1
26+
27+
# Standard run: 10 billion hands
28+
run: $(TARGET)
29+
./$(TARGET) $(STRATEGY) 10
30+
31+
# High precision: 40 billion hands (~±0.001% accuracy)
32+
precision: $(TARGET)
33+
./$(TARGET) $(STRATEGY) 40

cuda/README.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# CUDA Monte Carlo Blackjack Simulator
2+
3+
High-performance GPU-accelerated Monte Carlo simulation for calculating blackjack house edge.
4+
5+
## Features
6+
7+
- Loads strategy and rules from JSON file
8+
- Finite deck simulation with proper shoe and reshuffling
9+
- ~290 million hands/second on RTX 3080
10+
11+
## Prerequisites (WSL2 Ubuntu)
12+
13+
### 1. Windows NVIDIA Driver
14+
15+
Your Windows NVIDIA driver must be version 470.76+ (you likely already have this with an RTX 3080).
16+
17+
Check in Windows:
18+
19+
```
20+
nvidia-smi
21+
```
22+
23+
### 2. Install CUDA Toolkit in WSL
24+
25+
```bash
26+
# Add NVIDIA package repository
27+
wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-keyring_1.1-1_all.deb
28+
sudo dpkg -i cuda-keyring_1.1-1_all.deb
29+
sudo apt-get update
30+
31+
# Install CUDA toolkit (compiler and libraries)
32+
sudo apt-get install -y cuda-toolkit-12-4
33+
34+
# Add to PATH (add to ~/.bashrc for persistence)
35+
export PATH=/usr/local/cuda/bin:$PATH
36+
```
37+
38+
### 3. Verify Installation
39+
40+
```bash
41+
nvcc --version
42+
nvidia-smi
43+
```
44+
45+
## Building
46+
47+
```bash
48+
cd cuda
49+
make
50+
```
51+
52+
## Usage
53+
54+
```bash
55+
# Quick test: 1 billion hands (~±0.005% precision)
56+
make test
57+
58+
# Standard run: 10 billion hands (~±0.002% precision)
59+
make run
60+
61+
# High precision: 40 billion hands (~±0.001% precision)
62+
make precision
63+
```
64+
65+
Or run directly with a strategy file:
66+
67+
```bash
68+
./monte_carlo ../web/public/strategies/6-h17-das-rsa-peek-32.json 10
69+
```
70+
71+
## Expected Output
72+
73+
```
74+
Loading strategy from: ../web/public/strategies/6-h17-das-rsa-peek-32.json
75+
Config: Decks=6, H17=Yes, Peek=Yes, BJ=1.50
76+
77+
=== CUDA Monte Carlo Blackjack Simulator ===
78+
Target: 10 billion hands
79+
Threads: 8704
80+
81+
Running simulation...
82+
83+
=== Results ===
84+
Hands: 10.00 billion
85+
House edge: 0.6971% +/- 0.0022%
86+
95% CI: [0.6949%, 0.6994%]
87+
Time: 34.69 seconds
88+
Speed: 288.28 million hands/sec
89+
```
90+
91+
## Precision vs Hands
92+
93+
Standard error scales as 1/√n:
94+
95+
| Hands | Standard Error | 95% CI | Time (RTX 3080) |
96+
| ----- | -------------- | ------- | --------------- |
97+
| 1B | ±0.006% | ±0.012% | ~4s |
98+
| 10B | ±0.002% | ±0.004% | ~35s |
99+
| 40B | ±0.001% | ±0.002% | ~140s |
100+
101+
## Troubleshooting
102+
103+
### "CUDA driver version is insufficient"
104+
105+
Update your Windows NVIDIA driver to the latest version.
106+
107+
### "no CUDA-capable device is detected"
108+
109+
1. Make sure you're on WSL2 (not WSL1): `wsl --status`
110+
2. Update WSL: `wsl --update`
111+
3. Restart WSL: `wsl --shutdown` then reopen
112+
113+
## Technical Details
114+
115+
- Each CUDA thread maintains its own shoe
116+
- Fisher-Yates shuffle for true random shoe
117+
- Reshuffles at 75% penetration
118+
- One split allowed, split aces get one card only
119+
- Dealer peeks for blackjack (configurable via JSON)

0 commit comments

Comments
 (0)