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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
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"},
}
}
|