aboutsummaryrefslogtreecommitdiff
path: root/internal/game/casino.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/casino.go')
-rw-r--r--internal/game/casino.go143
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:]))