package casino // Published optimal max-coin returns and royal frequencies. Source pages: // https://wizardofodds.com/games/video-poker/tables/{jacks-or-better, // bonus-poker,bonus-poker-deluxe,double-bonus,double-double-bonus, // deuces-wild,joker-poker-kings-or-better}/ // Below max coins we price the reduced royal using that schedule's strategy; // this is a reference estimate rather than a second optimal-strategy solver. type pokerReturn struct{ rtp, royal float64 } var pokerReturns = map[string]map[string]pokerReturn{ "jacks_or_better": {"9/6": {.99543904, .00002476}, "9/5": {.984498, .000025}, "8/6": {.983927, .000025}, "8/5": {.97298434, .00002489}, "7/5": {.961472, .000025}}, "bonus_poker": {"8/5": {.991660, .000025}, "7/5": {.980147, .000025}, "6/5": {.968687, .000025}}, "bonus_poker_deluxe": {"9/6": {.996417, .000024}, "9/5": {.985495, .000025}, "8/6": {.984928, .000024}, "8/5": {.974009, .000025}, "7/5": {.962526, .000025}}, "double_bonus": {"10/7": {1.001725, .000021}, "9/7": {.991065, .000021}, "9/6/5": {.978062, .000024}, "9/6/4": {.963754, .000024}, "9/5/4": {.952738, .000025}, "8/5": {.941897, .000025}}, "double_double_bonus": {"10/6": {1.000670, .000025}, "9/6": {.989808, .000025}, "8/6": {.978949, .000025}, "9/5": {.978729, .000025}, "8/5": {.967861, .000025}}, "deuces_wild": {"25/15/9/5/3/2": {1.007620, .000022}, "25/15/9/4/4/3": {.989131, .000023}, "20/12/10/4/4/3": {.975791, .000023}, "25/16/13/4/3/2": {.967651, .000023}}, "joker_poker": {"50/17/7/5/3": {.980854, .000025}, "50/16/7/5/3": {.972349, .000025}, "50/15/7/5/3": {.963848, .000025}}, } // Ultimate X is a continuing-game reference, not the value of cashing in a // particular banked multiplier. Entries are single / three / five / ten hands. // Sources: .../tables/ultimate-x-single-line/ and .../tables/ultimate-x/. var pokerUXReturns = map[string]map[string][4]float64{ "jacks_or_better": {"9/6": {.9972, 0, 0, 0}, "8/6": {.9857, .992978, .994008, .994220}, "8/5": {.9738, .978730, .979671, .979795}, "7/5": {.9623, .967211, .968142, .968267}}, "bonus_poker": {"8/5": {.9921, .992828, .993408, .994034}, "7/5": {.9809, .981242, .981817, .982439}, "6/5": {.9694, 0, 0, 0}}, "bonus_poker_deluxe": {"9/6": {.9996, 0, 0, 0}, "8/6": {.9882, .995712, .996777, .997022}, "8/5": {.9747, .981052, .982014, .982169}, "7/5": {.9632, .969549, .970502, .970658}}, "double_bonus": {"9/7": {.9921, .988866, .989590, .990359}, "9/6/5": {.9811, .984517, .985227, .985987}, "9/6/4": {.9662, .973059, .973764, .974517}, "9/5/4": {.9539, .959471, .960118, .960810}}, "double_double_bonus": {"9/6": {.9905, .997261, .997928, .998663}, "9/5": {.9793, .983633, .984253, .984940}, "8/5": {.9680, .972266, .972859, .973521}}, "deuces_wild": {"25/15/9/4/4/3": {.9905, .991282, .992657, .994362}, "20/12/10/4/4/3": {.9788, .979863, .981217, .982817}, "25/16/13/4/3/2": {.9681, .969387, .970777, .972477}}, "joker_poker": {"50/17/7/5/3": {.9824, .989856, .990144, .990445}, "50/16/7/5/3": {.9738, .981190, .981474, .981771}, "50/15/7/5/3": {.9652, .972528, .972808, .973102}}, } func videoPokerHouseEdge(c TableConfig, bet string) HouseEdge { r := c.VideoPoker.Normalize() return pokerHouseEdge(r, bet, 5, true, CabinetHandCounts(r.Cabinet, r.Variant)[0]) } func pokerHouseEdge(c VideoPokerConfig, bet string, coins int, feature bool, hands int) HouseEdge { if bet != "main" { return unknownEdge("unrecognized video poker wager") } c = c.Normalize() ref, ok := pokerReturns[c.Variant][c.PayTable] if !ok { return unknownEdge("unrecognized poker schedule") } rtp := ref.rtp if coins > 0 && coins < 5 { rtp -= 550 * ref.royal feature = false } if feature { switch c.Feature { case PokerUltimateX: ix := 0 if c.Cabinet == CabinetUXMulti { switch hands { case 3: ix = 1 case 5: ix = 2 case 10: ix = 3 default: return unknownEdge("unsupported hand count") } } rtp = pokerUXReturns[c.Variant][c.PayTable][ix] if rtp == 0 { return unknownEdge("unsupported Ultimate X schedule") } case PokerSuperTimesPay: // E[multiplier] = 14/15 + (2*.17+3*.33+4*.16+5*.24+8*.06+10*.04)/15. rtp *= (14.0/15 + 4.05/15) * 5 / 6 case PokerHotRoll: // Five extra coins buy 5/6 normal hands and 1/6 at mean 7x. rtp *= (5.0/6 + 7.0/6) / 2 } } return edge(1 - rtp) }