aboutsummaryrefslogtreecommitdiff
path: root/internal/game/casino.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-10-03 02:16:00 -0400
committerhistoria <[not public]>2026-10-03 02:16:00 -0400
commit6232d41e5639f9c38e47b2bb65266e343ca26e8f (patch)
treead0c1676838a6c7e162d3a5c055f914016dac803 /internal/game/casino.go
parentefccf58741ae43d9e891c6b743b146982b344ccf (diff)
downloadthehouseoficarus-6232d41e5639f9c38e47b2bb65266e343ca26e8f.tar.gz
feat: add casino_hints option and standardize casino command syntax
Diffstat (limited to 'internal/game/casino.go')
-rw-r--r--internal/game/casino.go48
1 files changed, 30 insertions, 18 deletions
diff --git a/internal/game/casino.go b/internal/game/casino.go
index 0b16114..8f18614 100644
--- a/internal/game/casino.go
+++ b/internal/game/casino.go
@@ -342,7 +342,7 @@ func (g *Game) executePlay(sess *net.Session, args []string, rawInput string) {
if len(args) > 1 {
amount, err := strconv.Atoi(args[1])
if !choice.table || len(args) > 3 || (args[1] != "min" && args[1] != "max" && (err != nil || amount <= 0)) {
- sess.WriteLine("Use play <game> [amount|min|max] [target]. No wager was placed.")
+ sess.WriteLine("Use play GAME [N|min|max] [on BET]. No wager was placed.")
return
}
}
@@ -406,7 +406,7 @@ func (g *Game) executeBet(sess *net.Session, args []string, rawInput string) {
return
}
}
- sess.WriteLine("Use bet, bet <amount>, or bet max.")
+ sess.WriteLine("Use bet, bet N, or bet max.")
return
}
table, playing := g.Casino.Participation(p.Name)
@@ -424,7 +424,7 @@ func (g *Game) executeBet(sess *net.Session, args []string, rawInput string) {
g.emitCasinoEvents(g.Casino.RebetAll(table.RoomID, table.Config.ID, p.Name, casinoWallet{g: g, p: p}))
return
}
- // Table bet syntax: bet | bet <amount> [on] <target> | bet min|max [on] <target>.
+ // Table bet syntax: bet | bet N [on BET] | bet min|max [on BET].
// BEFORE an "on" keyword, a token that parses as an amount (or min/max)
// sets the wager and any other token is the bet target; AFTER "on", the
// next token is always the target. That makes numeric targets reachable
@@ -438,26 +438,21 @@ func (g *Game) executeBet(sess *net.Session, args []string, rawInput string) {
for i, arg := range args {
if strings.EqualFold(arg, "on") {
if sawOn || spot != "" || i == len(args)-1 {
- sess.WriteLine("Use bet <n> on <bet>. No wager was placed.")
+ sess.WriteLine("Use bet N on BET. No wager was placed.")
return
}
sawOn = true
continue
}
- if !sawOn && !(joinTarget && hasAmount && spot != "") {
+ // Once an amount is set, every remaining token belongs to the target
+ // ("bet 2 2" and "bet 2 on 2" are identical). Before that, a numeric
+ // token sets the amount and anything else starts the target.
+ if !sawOn && !hasAmount {
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
}
if strings.EqualFold(arg, "max") {
- if hasAmount {
- sess.WriteLine("Use bet, bet <amount> [on <target>], bet min, or bet max.")
- return
- }
amount = min(table.Config.MaxBet, casinoAffordable(p))
if amount < 1 {
sess.WriteLine("You don't have any chips or credits to bet.")
@@ -467,10 +462,6 @@ func (g *Game) executeBet(sess *net.Session, args []string, rawInput string) {
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
}
@@ -483,7 +474,7 @@ func (g *Game) executeBet(sess *net.Session, args []string, rawInput string) {
spot += " " + strings.ToLower(arg)
continue
}
- sess.WriteLine("Use bet, bet <amount> [on <target>], bet min, or bet max.")
+ sess.WriteLine("Use bet, bet N [on BET], bet min, or bet max.")
return
}
if table.Config.Game == casino.GameBaccarat {
@@ -657,6 +648,9 @@ func (g *Game) casinoMenuParts(sess *net.Session, menu *casino.MenuView, message
heading = message
}
commands = append([]casino.MenuCommand(nil), menu.Commands...)
+ if !g.casinoHintsVisible(sess, menu) {
+ commands = nil
+ }
for i := range commands {
if commands[i].Cost > casinoAffordable(sess.Player) {
commands[i].Desc += " [unavailable: insufficient funds]"
@@ -665,6 +659,24 @@ func (g *Game) casinoMenuParts(sess *net.Session, menu *casino.MenuView, message
return balance, heading, commands
}
+// casinoHintsVisible decides whether a menu's command list prints. "on"
+// always shows hints (the historical behavior); "off" never does; the default
+// "once" shows them only on the menu a player gets when sitting down. Players
+// can always ask for the live list with "what" or "verbs".
+func (g *Game) casinoHintsVisible(sess *net.Session, menu *casino.MenuView) bool {
+ if sess == nil || sess.Player == nil || menu == nil {
+ return true
+ }
+ switch sess.Player.OptionString("casino_hints") {
+ case "off":
+ return false
+ case "once":
+ return menu.ShowHints
+ default:
+ return true
+ }
+}
+
// casinoBoardReminder splits a persistent-board menu (craps, roulette, video
// poker, Pai Gow) so its instructions print under the board they describe.
// Every other game, and compact displays, keep their menu in one block.