package casino import ( "fmt" ) func (t *crapsTable) commands(name string) []MenuCommand { commands := []MenuCommand{} p := t.players.get(name) simplified := t.Config.Craps.variant() == "simplified" 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) { if simplified { // Pass is the only target, so the bare bet is a rebet. if p.lastBet > 0 { commands = append(commands, MenuCommand{Command: "bet", Desc: fmt.Sprintf("Rebet %d on pass (also: rebet)", p.lastBet)}, MenuCommand{Command: "bet ", Desc: "New amount on pass; the dice roll 3 ticks after a bet"}) } else { commands = append(commands, MenuCommand{Command: "bet ", Desc: "Wager on pass; the dice roll 3 ticks after a bet"}) } } else { target := "" if !t.Config.Craps.allows("buy") { target = "pass" } commands = append(commands, MenuCommand{Command: "bet on " + target, Desc: "Place a wager; targets: list"}) } } if p.HasBet { if !simplified { if t.shooter() == p && (!t.multiplayer || t.roundTicks >= crapsBetTicks) && t.pendingRollTicks == 0 { 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", Desc: "Return every optional bet and free 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}) // "rules" stays available to a seated player at every phase of every // variant; "list" rides along whenever the wager table names more // than one bet. commands = withTableHints(commands, t.wagerRows(name)) } 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 the dice pairs that settle the player's open wagers. The // roll table shares payout math with settlement (crapsNet), so the numbers // never promise a win a real roll cannot pay. The open-bet list itself is no // longer shown: the settlement wager table already names every stake. func (t *crapsTable) betSummary(p *crapsPlayer) Event { return t.private(p.Name, t.rollTable(p)) } // shooterHeading names the current shooter for the join, status and reminder // menus. The board no longer carries its own Shooter line. func (t *crapsTable) shooterHeading() string { if shooter := t.shooter(); shooter != nil { return "Shooter " + shooter.Name } return "Shooter" } func (t *crapsTable) reminder(name string) Event { heading := t.shooterHeading() e := t.private(name, heading) e.Color = "casino_menu" e.Menu = &MenuView{ShowBalance: true, Heading: heading, 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) e.Settlement = lines if len(lines) > 0 { if failed { e.SettlementNote = payoutFailedMessage() } e.Color = settlementTag(lines) } return e }