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
|
package casino
import (
"fmt"
"strings"
)
func (t *crapsTable) commands(name string) []MenuCommand {
commands := []MenuCommand{}
p := t.players.get(name)
if p != nil {
// Pass-only editions cannot accept another contract while a point or
// the player's existing pass bet is live.
if t.Config.Craps.allows("come") || t.Config.Craps.allows("buy") || (t.point == 0 && !p.HasBet) {
target := "<target>"
if !t.Config.Craps.allows("buy") {
target = "pass"
}
commands = append(commands, MenuCommand{Command: "bet <amount> on " + target, Desc: "Place a wager; targets: table rules"})
}
if p.HasBet {
if t.shooter() == p && (!t.multiplayer || t.roundElapsed >= crapsBetDelay) {
commands = append(commands, MenuCommand{Command: "roll", Desc: "Shoot now"})
}
if !p.autoRoll {
commands = append(commands, MenuCommand{Command: "autoroll", Desc: "Roll automatically on your turn"})
}
for _, b := range p.bets {
if !crapsContract(b.kind) || b.odds.Total > 0 {
commands = append(commands, MenuCommand{Command: "unbet <target> / unbet all", Desc: "Return optional bets or odds"})
break
}
}
}
stop := "Leave the table"
if p.HasBet {
stop = "Leave after your live bets settle"
}
if p.autoRoll {
stop = "Cancel autoroll; keep your bets"
}
commands = append(commands, MenuCommand{Command: "stop", Desc: stop})
}
return append(commands, MenuCommand{Command: "table", Desc: "View the felt"})
}
func crapsContract(kind string) bool {
switch kind {
case "pass", "come", "fire", "small", "tall", "all":
return true
default:
return false
}
}
func crapsBetLabel(b *crapsBet) string {
names := map[string]string{"pass": "Pass", "dontpass": "Don't pass", "come": "Come", "dontcome": "Don't come", "ace-deuce": "Ace-deuce", "small": "All Small", "tall": "All Tall", "all": "All", "fire": "Fire"}
label := names[b.kind]
if label == "" {
label = gameTitle(GameName(b.kind))
}
if b.kind == "hop" {
return fmt.Sprintf("Hop [%d + %d]", b.number/10, b.number%10)
}
if b.number != 0 {
label += fmt.Sprintf(" [%d]", b.number)
}
return label
}
// Numbers describe covered targets, not a promise that every listed roll wins
// (don't/lay bets oppose their number; bonus bets need complete sequences).
// betSummary lists each open wager, then the dice pairs that beat them. The
// roll table shares payout math with settlement (crapsNet), so the numbers
// never promise a win a real roll cannot pay.
func (t *crapsTable) betSummary(p *crapsPlayer) Event {
text := "{casino_emphasis}YOUR BETS{/}"
if len(p.bets) == 0 {
text += " No active bets."
} else {
for _, b := range p.bets {
label := crapsBetLabel(b)
if strings.HasPrefix(b.kind, "dont") || b.kind == "lay" {
label += " (against)"
}
if t.point == 0 && (b.kind == "place" || b.kind == "buy" || b.kind == "hard") {
label += " (off)"
}
text += fmt.Sprintf("\n {casino_action}%-24s{/} {casino_chips}%d{/}", label, b.stake.Total)
if b.odds.Total > 0 {
text += fmt.Sprintf(" + %d odds", b.odds.Total)
if t.point == 0 && b.kind == "come" {
text += " (odds off)"
}
}
}
}
e := t.private(p.Name, text+"\n"+t.rollTable(p))
e.ShowBalance = true
return e
}
func (t *crapsTable) reminder(name string) Event {
e := t.private(name, "Your move")
e.Color = "casino_menu"
e.Menu = &MenuView{Heading: "Your move", Commands: t.commands(name)}
return e
}
func (t *crapsTable) settlementEvent(p *crapsPlayer, lines []settlementLine, failed bool) Event {
text := ""
if len(lines) > 0 {
text = settlementText(lines)
}
if failed {
if text != "" {
text += "\n"
}
text += payoutFailedMessage()
}
e := t.private(p.Name, text)
if len(lines) > 0 {
e.Color = settlementTag(lines)
}
return e
}
|