package casino import ( "fmt" "strings" ) // Craps wager tables are built from the live table state. Rows are grouped // where two bets share the same payout (pass/don't pass, the place numbers, // all free odds) so the list stays compact and the Win/action column rarely // wraps. Payouts are profit odds; winning stakes return alongside the profit. func (t *crapsTable) wagerRows(name string) []WagerRow { c := t.Config.Craps rows := []WagerRow{} passWin := "Come out: 7/11 wins, 2/3/12 loses / Point on: Roll the point to win." switch c.variant() { case "simplified": // One automatic roll of two dice; pass is the only target. rows = append(rows, WagerRow{"pass", "up to 5:1", "One roll: 2 pays 3:1; 3/4 1:1; 10/11 2:1; 12 5:1; 5-9 lose"}, ) case "high_point": rows = append(rows, WagerRow{"pass", "1:1", "2/3 roll again; 11/12 win; 4-10 must be beaten next roll"}, ) case "die_rich": rows = append(rows, WagerRow{"pass", "1:1", "6 wins; 1 loses; 2-5 must repeat before a 1"}, ) case "new_york": rows = append(rows, WagerRow{"pass", "1:1", passWin}, WagerRow{"dontpass", "1:1", "Opposite of Pass Line"}, ) if t.point != 0 { rows = append(rows, crapsOddsRows()...) rows = append(rows, crapsBuyLayRows()...) } case "crapless": rows = append(rows, WagerRow{"pass", "1:1", "Come-out 7 wins; every other total makes the point"}, ) if t.point != 0 { rows = append(rows, WagerRow{"come", "1:1", "A personal point with pass rules"}, ) rows = append(rows, crapsOddsRows()...) rows = append(rows, crapsPlaceRows(c)...) rows = append(rows, crapsBuyLayRows()...) rows = append(rows, WagerRow{"hard 4/10", "7:1", "Roll this pair before next 7"}, WagerRow{"hard 6/8", "9:1", "Roll this pair before next 7"}, ) } rows = append(rows, crapsPropRows(c, false)...) default: // bank and diceless rows = append(rows, WagerRow{"pass", "1:1", passWin}, WagerRow{"dontpass", "1:1", "Opposite of Pass Line"}, ) if t.point != 0 { rows = append(rows, WagerRow{"come", "1:1", passWin}, WagerRow{"dontcome", "1:1", "Opposite of Come"}, ) rows = append(rows, crapsOddsRows()...) rows = append(rows, crapsPlaceRows(c)...) rows = append(rows, crapsBuyLayRows()...) rows = append(rows, WagerRow{"hard 4/10", "7:1", "Roll this pair before next 7"}, WagerRow{"hard 6/8", "9:1", "Roll this pair before next 7"}, ) } rows = append(rows, crapsPropRows(c, !t.rolled)...) } return rows } // crapsBuyLayRows splits the commission bets so each side carries its own // win condition and the 5% vig applies only to the winning wager. func crapsBuyLayRows() []WagerRow { return []WagerRow{ {"buy N", "true", "This number rolled before 7; 5% commission on wins"}, {"lay N", "true", "7 rolled before this number; 5% commission on wins"}, } } // crapsPropRows is the one-roll section of the list: field, the proposition // bets and (when bonuses are allowed and still open) the Fire and ATS bets. func crapsPropRows(c CrapsConfig, bonuses bool) []WagerRow { rows := []WagerRow{ {"field", "1:1", "Next roll is 2-4 or 9-12"}, {"seven", "4:1", "Next roll totals 7"}, {"craps", "7:1", "Next roll is 2, 3 or 12"}, {"eleven / ace-deuce", "15:1", "Next roll totals 11 / 3"}, {"aces / boxcars", "30:1", "Next roll is 2 / 12"}, {"horn", "27:4", "Splits the stake over 2/3/11/12"}, {"hop A B", "15:1/30:1", "Next roll is a/b"}, } if bonuses { rows = append(rows, WagerRow{"fire", "24/249/999:1", "4/5/6 distinct points before a 7"}, WagerRow{"small / tall", "34:1", "All 2-6 or 8-12 before any 7"}, WagerRow{"all", "175:1", "All 2-6 and 8-12 before any 7"}, ) } return rows } // crapsPlaceRows lists one place row per distinct payout, so 4/10 share 9:5, // 5/9 share 7:5 and 6/8 share 7:6. Crapless tables also accept the // "impossible" numbers at extended odds. func crapsPlaceRows(c CrapsConfig) []WagerRow { numbers := []int{4, 5, 6, 8, 9, 10} if c.variant() == "crapless" { numbers = []int{2, 3, 4, 5, 6, 8, 9, 10, 11, 12} } type group struct { odds string nums []int } var order []*group byOdds := map[string]*group{} for _, n := range numbers { x, y := crapsPlaceOdds(n) key := fmt.Sprintf("%d:%d", x, y) g := byOdds[key] if g == nil { g = &group{odds: key} byOdds[key] = g order = append(order, g) } g.nums = append(g.nums, n) } var rows []WagerRow for _, g := range order { names := make([]string, len(g.nums)) for i, n := range g.nums { names[i] = fmt.Sprint(n) } rows = append(rows, WagerRow{"place " + strings.Join(names, "/"), g.odds, "This number rolled before 7"}) } return rows } // crapsOddsRows describes the free-odds wagers. Pass and come odds are one // group and don't odds another; the list column says simply "true" to keep // the payout column narrow. func crapsOddsRows() []WagerRow { return []WagerRow{ {"odds pass / come", "true", "Free odds behind the point"}, {"odds dont N", "true", "Laid against the point at inverse odds"}, } }