diff options
Diffstat (limited to 'internal/game/casino.go')
| -rw-r--r-- | internal/game/casino.go | 143 |
1 files changed, 94 insertions, 49 deletions
diff --git a/internal/game/casino.go b/internal/game/casino.go index 801c887..9666c41 100644 --- a/internal/game/casino.go +++ b/internal/game/casino.go @@ -137,44 +137,61 @@ func (g *Game) executeBet(sess *net.Session, args []string, rawInput string) { sess.WriteLine("Use bet, bet <amount>, or bet max.") return } - if len(args) == 0 { - if table, playing := g.Casino.Participation(p.Name); playing && table != nil && table.Config.Game == casino.GameBlackjack { - amount := g.Casino.RebetAmount(table.RoomID, table.Config.ID, p.Name) - g.emitCasinoEvents(g.Casino.Bet(table.RoomID, table.Config.ID, p.Name, amount, casinoWallet{g: g, p: p})) - return - } - sess.WriteLine("Bet how much?") + table, playing := g.Casino.Participation(p.Name) + if !playing || table == nil { + sess.WriteLine("You're not playing a game.") return } - if table, playing := g.Casino.Participation(p.Name); playing && table != nil && table.Config.Game == casino.GameBlackjack { - amount := 0 - switch args[0] { - case "min": - amount = table.Config.MinBet - case "max": - amount = table.Config.MaxBet - default: - var err error - amount, err = strconv.Atoi(args[0]) - if err != nil { - sess.WriteLine("Use bet, bet <amount>, bet min, or bet max.") + // Table bet syntax: bet | bet <amount> [on] [spot] | bet min|max [on] [spot]. + // Tokens that parse as an amount (or min/max) set the wager; any other + // token is the bet target and the table game validates it. + amount, spot, hasAmount := 0, "", false + for _, arg := range args { + if strings.EqualFold(arg, "on") { + continue + } + if strings.EqualFold(arg, "min") { + if hasAmount { + sess.WriteLine("Use bet, bet <amount> [on <target>], bet min, or bet max.") return } + amount, hasAmount = table.Config.MinBet, true + continue } - g.emitCasinoEvents(g.Casino.Bet(table.RoomID, table.Config.ID, p.Name, amount, casinoWallet{g: g, p: p})) - return - } - amount, err := strconv.Atoi(args[0]) - if err != nil || amount <= 0 { - sess.WriteLine("Your bet must be a positive whole number.") - return + if strings.EqualFold(arg, "max") { + if hasAmount { + sess.WriteLine("Use bet, bet <amount> [on <target>], bet min, or bet max.") + return + } + amount, hasAmount = table.Config.MaxBet, true + continue + } + if value, err := strconv.Atoi(arg); err == nil && value > 0 { + if hasAmount { + sess.WriteLine("Use bet, bet <amount> [on <target>], bet min, or bet max.") + return + } + amount, hasAmount = value, true + continue + } + if spot != "" { + sess.WriteLine("Use bet, bet <amount> [on <target>], bet min, or bet max.") + return + } + spot = strings.ToLower(arg) } - table, playing := g.Casino.Participation(p.Name) - if !playing { - sess.WriteLine("You're not playing a game.") - return + if !hasAmount { + var lastSpot string + lastSpot, amount = g.Casino.Rebet(table.RoomID, table.Config.ID, p.Name) + if spot == "" { + spot = lastSpot + } + if amount <= 0 { + sess.WriteLine("Bet how much?") + return + } } - g.emitCasinoEvents(g.Casino.Bet(table.RoomID, table.Config.ID, p.Name, amount, casinoWallet{g: g, p: p})) + g.emitCasinoEvents(g.Casino.Bet(table.RoomID, table.Config.ID, p.Name, spot, amount, casinoWallet{g: g, p: p})) } func (g *Game) executeAutoBet(sess *net.Session, args []string, rawInput string) { @@ -189,7 +206,7 @@ func (g *Game) executeAutoBet(sess *net.Session, args []string, rawInput string) sess.WriteLine("Autobet is only available at games without player choices.") } -func (g *Game) executeBlackjackAction(sess *net.Session, action string) { +func (g *Game) executeTableAction(sess *net.Session, action string) { p := sess.Player if p == nil { return @@ -229,6 +246,9 @@ func (g *Game) emitCasinoEvents(events []casino.Event) { if event.Blackjack != nil && sess.Player != nil { message += "\n" + renderBlackjackSnapshot(event.Blackjack, g.colorMode(sess), sess.Player.OptionBool("unicode"), sess.Player.OptionInt("card_size"), sess.Player.OptionString("card_style"), g.CardArt) } + if event.Baccarat != nil && sess.Player != nil { + message += "\n" + renderBaccaratSnapshot(event.Baccarat, g.colorMode(sess), sess.Player.OptionBool("unicode"), sess.Player.OptionInt("card_size"), sess.Player.OptionString("card_style"), g.CardArt) + } sess.WriteLine(g.colorize(sess, category, message)) } } @@ -252,6 +272,9 @@ func (g *Game) emitCasinoEvents(events []casino.Event) { if event.Blackjack != nil && sess.Player != nil { privateMessage += "\n" + renderBlackjackSnapshot(event.Blackjack, g.colorMode(sess), sess.Player.OptionBool("unicode"), sess.Player.OptionInt("card_size"), sess.Player.OptionString("card_style"), g.CardArt) } + if event.Baccarat != nil && sess.Player != nil { + privateMessage += "\n" + renderBaccaratSnapshot(event.Baccarat, g.colorMode(sess), sess.Player.OptionBool("unicode"), sess.Player.OptionInt("card_size"), sess.Player.OptionString("card_style"), g.CardArt) + } sess.WriteLine(g.renderCasinoMessage(sess, category, event.Menu, privateMessage)) if category == "casino_menu" { g.writePrompt(sess) @@ -293,6 +316,10 @@ func (g *Game) casinoPrivateMessage(sess *net.Session, category string, menu *ca commands[i] = g.colorize(sess, "casino_command", action) } return menu.Title + "\nActions: " + strings.Join(commands, ", ") + case casino.MenuBaccaratBet: + command := func(value string) string { return g.colorize(sess, "casino_command", value) } + return fmt.Sprintf("%s\n\nNew hand! You can %s, %s on player|banker|tie (inc. min/max), or %s.", + balance, command("bet"), command("bet <amount>"), command("stop")) case casino.MenuSlotCommands: if message == "" { return balance + "\n\n" + menu.Body @@ -306,7 +333,7 @@ func renderBlackjackSnapshot(snapshot *casino.BlackjackSnapshot, mode string, un if snapshot == nil { return "" } - size = blackjackCardSize(unicode, size) + size = cardRenderSize(unicode, size) var lines []string dealerTitle := "Dealer:" if snapshot.DealerRevealed { @@ -314,22 +341,40 @@ func renderBlackjackSnapshot(snapshot *casino.BlackjackSnapshot, mode string, un } else if snapshot.DealerShownScore != "" { dealerTitle = "Dealer (" + snapshot.DealerShownScore + "):" } - lines = append(lines, blackjackCardLine(mode, dealerTitle)) - lines = append(lines, blackjackCardsLine(mode, snapshot.Dealer, size, unicode, style, art)...) + lines = append(lines, cardLine(mode, dealerTitle)) + lines = append(lines, cardsLine(mode, snapshot.Dealer, size, unicode, style, art)...) for _, player := range snapshot.Players { - lines = append(lines, blackjackCardLine(mode, fmt.Sprintf("%s (%s):", player.Name, player.Score))) - lines = append(lines, blackjackCardsLine(mode, player.Cards, size, unicode, style, art)...) + lines = append(lines, cardLine(mode, fmt.Sprintf("%s (%s):", player.Name, player.Score))) + lines = append(lines, cardsLine(mode, player.Cards, size, unicode, style, art)...) + } + return strings.Join(lines, "\n") +} + +// renderBaccaratSnapshot draws the player and banker hands followed by the +// list of wagers riding on the round. +func renderBaccaratSnapshot(snapshot *casino.BaccaratSnapshot, mode string, unicode bool, size int, style string, art *cardart.Store) string { + if snapshot == nil { + return "" + } + size = cardRenderSize(unicode, size) + var lines []string + lines = append(lines, cardLine(mode, "Player ("+snapshot.PlayerScore+"):")) + lines = append(lines, cardsLine(mode, snapshot.Player, size, unicode, style, art)...) + lines = append(lines, cardLine(mode, "Banker ("+snapshot.BankerScore+"):")) + lines = append(lines, cardsLine(mode, snapshot.Banker, size, unicode, style, art)...) + for _, bet := range snapshot.Bets { + lines = append(lines, cardLine(mode, fmt.Sprintf("%s bets %d on %s.", bet.Name, bet.Amount, bet.Spot))) } return strings.Join(lines, "\n") } -func blackjackCardLine(mode, text string) string { +func cardLine(mode, text string) string { spec := color.NoColor() spec.Fg = 39 return color.Render(mode, spec, text) } -func blackjackCardsLine(mode string, cards []casino.BlackjackCardView, size int, unicode bool, style string, art *cardart.Store) []string { +func cardsLine(mode string, cards []casino.CardView, size int, unicode bool, style string, art *cardart.Store) []string { if len(cards) == 0 { return nil } @@ -342,7 +387,7 @@ func blackjackCardsLine(mode string, cards []casino.BlackjackCardView, size int, } artLines := make([][]string, len(cards)) for i, card := range cards { - artLines[i] = blackjackCardArt(card, size, unicode, style, art) + artLines[i] = cardArtLines(card, size, unicode, style, art) } lines := make([]string, size) for row := 0; row < size; row++ { @@ -355,7 +400,7 @@ func blackjackCardsLine(mode string, cards []casino.BlackjackCardView, size int, return lines } -func blackjackCardSize(unicode bool, size int) int { +func cardRenderSize(unicode bool, size int) int { if !unicode { return 5 } @@ -365,16 +410,16 @@ func blackjackCardSize(unicode bool, size int) int { return 7 } -var blackjackSuitSymbols = map[string]string{"hearts": "♥", "spades": "♠", "diamonds": "♦", "clubs": "♣"} +var suitSymbols = map[string]string{"hearts": "♥", "spades": "♠", "diamonds": "♦", "clubs": "♣"} -func blackjackSymbol(card casino.BlackjackCardView) string { +func cardSymbol(card casino.CardView) string { if card.Hidden { return "?" } - return card.Rank + blackjackSuitSymbols[card.Suit] + return card.Rank + suitSymbols[card.Suit] } -func blackjackCardArt(card casino.BlackjackCardView, size int, unicode bool, style string, art *cardart.Store) []string { +func cardArtLines(card casino.CardView, size int, unicode bool, style string, art *cardart.Store) []string { if card.Hidden { return generatedCardArt("?", "", size, unicode, style) } @@ -442,10 +487,10 @@ func suitLetter(suit string, unicode bool) string { if !unicode { return strings.ToUpper(suit[:1]) } - return blackjackSuitSymbols[suit] + return suitSymbols[suit] } -func colorizeCardLine(mode, line string, card casino.BlackjackCardView, row, size int, style string) string { +func colorizeCardLine(mode, line string, card casino.CardView, row, size int, style string) string { red := card.Suit == "hearts" || card.Suit == "diamonds" rankColor := 27 if red { @@ -487,7 +532,7 @@ func colorizeCardLine(mode, line string, card casino.BlackjackCardView, row, siz return builder.String() } -func colorizeCardSymbol(mode string, card casino.BlackjackCardView) string { +func colorizeCardSymbol(mode string, card casino.CardView) string { if card.Hidden { return color.Render(mode, color.ColorSpec{Fg: 15}, "?") } @@ -495,7 +540,7 @@ func colorizeCardSymbol(mode string, card casino.BlackjackCardView) string { if card.Suit == "hearts" || card.Suit == "diamonds" { rankColor, suitColor = 196, 196 } - runes := []rune(blackjackSymbol(card)) + runes := []rune(cardSymbol(card)) rankLength := len([]rune(card.Rank)) return color.Render(mode, color.ColorSpec{Fg: rankColor}, string(runes[:rankLength])) + color.Render(mode, color.ColorSpec{Fg: suitColor}, string(runes[rankLength:])) |
