aboutsummaryrefslogtreecommitdiff
path: root/internal/casino/house_edge_fire.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-10-02 01:54:37 -0400
committerhistoria <[not public]>2026-10-02 01:54:37 -0400
commitd3a305d1d7962f82af2397760cf8008758bddd1d (patch)
treef91f0deb342c20f2993e5366f772c3432648f426 /internal/casino/house_edge_fire.go
parent8eea0e4e06a4aaa6a18edabd9897d3bea1ea2ca0 (diff)
downloadthehouseoficarus-d3a305d1d7962f82af2397760cf8008758bddd1d.tar.gz
feat: better 'list' bet table, multiple bets in baccarat
Diffstat (limited to 'internal/casino/house_edge_fire.go')
-rw-r--r--internal/casino/house_edge_fire.go61
1 files changed, 61 insertions, 0 deletions
diff --git a/internal/casino/house_edge_fire.go b/internal/casino/house_edge_fire.go
new file mode 100644
index 0000000..3bb1697
--- /dev/null
+++ b/internal/casino/house_edge_fire.go
@@ -0,0 +1,61 @@
+package casino
+
+import "math/bits"
+
+// crapsFireReturn is the fire bet's exact expected return (profit plus stake
+// where the bet wins; nothing where it loses) per unit staked. The bet
+// resolves only on a point-phase seven-out — a come-out seven keeps the
+// shooter's hand and the bet alive — paying 24/249/999:1 for 4/5/6 distinct
+// made points. The state is the six-bit mask of distinct points made in the
+// hand; come-out rolls and rerolls of an already-made point are self loops.
+// Solved by fixed-point iteration over the 64 masks (the chain is absorbing
+// and monotone, so iteration converges to the exact solution).
+func crapsFireReturn() float64 {
+ numbers := []int{4, 5, 6, 8, 9, 10}
+ ways := make([]int, len(numbers))
+ for i, n := range numbers {
+ ways[i] = diceWays(n)
+ }
+ pay := func(made int) float64 {
+ switch made {
+ case 4:
+ return 25 // 24:1 profit plus the returned stake
+ case 5:
+ return 250
+ case 6:
+ return 1000
+ }
+ return 0
+ }
+ vCome := make([]float64, 64)
+ for it := 0; it < 2000; it++ {
+ next := make([]float64, 64)
+ for mask := 0; mask < 64; mask++ {
+ sum := 0.0
+ for i := range numbers {
+ w := ways[i]
+ nm := mask | 1<<i
+ // Point-phase value of an established point n: making it
+ // moves to the come-out with the grown mask; a seven (6/36)
+ // resolves the bet at the CURRENT mask (not the grown one —
+ // the point has not been made).
+ made := bits.OnesCount(uint(mask))
+ pointValue := (float64(w)/36*vCome[nm] + 6.0/36*pay(made)) / (1 - float64(36-w-6)/36)
+ sum += float64(w) / 36 * pointValue
+ }
+ next[mask] = sum / (24.0 / 36.0)
+ }
+ done := true
+ for i := range next {
+ if diff := next[i] - vCome[i]; diff > 1e-12 || diff < -1e-12 {
+ done = false
+ break
+ }
+ }
+ vCome = next
+ if done {
+ break
+ }
+ }
+ return vCome[0]
+}