aboutsummaryrefslogtreecommitdiff
path: root/internal/casino/house_edge_pai_gow.go
blob: 82cff09e0c2e2f6937ea9dc829da1b24bb468848 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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)
}