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) }