aboutsummaryrefslogtreecommitdiff
path: root/internal/casino/house_edge_pai_gow.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/casino/house_edge_pai_gow.go')
-rw-r--r--internal/casino/house_edge_pai_gow.go55
1 files changed, 55 insertions, 0 deletions
diff --git a/internal/casino/house_edge_pai_gow.go b/internal/casino/house_edge_pai_gow.go
new file mode 100644
index 0000000..82cff09
--- /dev/null
+++ b/internal/casino/house_edge_pai_gow.go
@@ -0,0 +1,55 @@
+package casino
+
+// Main-game reference estimates: published house-way play, not a solver for
+// this implementation's house way or a player's chosen arrangement. Sources:
+// https://wizardofodds.com/games/pai-gow-poker/
+// https://wizardofodds.com/games/ez-pai-gow-poker/
+// https://wizardofodds.com/games/face-up-pai-gow-poker/
+// The wheel convention can change individual results; these rounded reference
+// estimates do not resolve its small effect on the full strategy distribution.
+func paiGowHouseEdge(c TableConfig, bet string) HouseEdge {
+ r := c.PaiGow.Normalize()
+ switch bet {
+ case "main":
+ switch r.Variant {
+ case PaiGowClassic:
+ return edge(.027212)
+ case PaiGowEZ:
+ return edge(.0254)
+ case PaiGowFaceUp:
+ return edge(.0181)
+ case PaiGowNoPush:
+ // No published table for our tiebreaker variant. Use published classic
+ // win/loss/push frequencies, remove commission, then price tied extra
+ // cards as dealer wins. Five ace-valued cards (including joker), 12x4
+ // other ranks. Card-removal correlation is ignored in this estimate.
+ return edge(.303847 - .291195 + .404958*(5.0*4+12*4*3)/(53*52))
+ }
+ case "fortune":
+ profit := -121694196.0
+ for i, row := range FortunePayTable(r.Envy) {
+ profit += float64(row.Odds * fortuneCombinations[i])
+ }
+ return edge(-profit / 154143080)
+ case "pushace":
+ if rates, ok := r.pushAceRates(); ok {
+ // Published event probabilities (both ace-high, joker, plain ace-high).
+ return edge(1 - (.008700*float64(rates[2]+1) + .004100*float64(rates[1]+1) + .080800*float64(rates[0]+1)))
+ }
+ }
+ return unknownEdge("unrecognized pai gow wager")
+}
+
+// Fortune table 8 category counts, also pinned by pai_gow_test.go.
+var fortuneCombinations = []int{32, 72, 196, 1128, 26020, 184644, 307472, 4188528, 6172088, 7672500, 11034204, 2862000}
+
+func fortuneEnvyReturn(others, stake int) float64 {
+ if stake < 5 {
+ return 0
+ }
+ total := 0.0
+ for i, row := range FortunePayTable(true) {
+ total += float64(row.Envy * fortuneCombinations[i])
+ }
+ return total / 154143080 * float64(others) / float64(stake)
+}