aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_registry.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/cmd_registry.go')
-rw-r--r--internal/game/cmd_registry.go99
1 files changed, 80 insertions, 19 deletions
diff --git a/internal/game/cmd_registry.go b/internal/game/cmd_registry.go
index 710dd92..5b60118 100644
--- a/internal/game/cmd_registry.go
+++ b/internal/game/cmd_registry.go
@@ -70,7 +70,7 @@ var commandRegistry = map[string]commandDef{
"dd": {func(g *Game, s *net.Session, _ []string, _ string) { g.executeTableAction(s, "double") }, ClassActive},
"sp": {func(g *Game, s *net.Session, _ []string, _ string) { g.executeTableAction(s, "split") }, ClassActive},
"bet": {(*Game).executeBet, ClassActive},
- "spin": {(*Game).executeBet, ClassActive},
+ "spin": {(*Game).executeSpin, ClassActive},
"autobet": {(*Game).executeAutoBet, ClassActive},
"autospin": {(*Game).executeAutoBet, ClassActive},
"hit": {func(g *Game, s *net.Session, _ []string, _ string) { g.executeTableAction(s, "hit") }, ClassActive},
@@ -240,35 +240,96 @@ func classifyCommand(cmd string) CommandClass {
return ClassUnknown
}
-// casinoShortVerbs are the casino verbs a seated player may abbreviate to an
-// unambiguous prefix. "stop" and "rules" are deliberately absent: their
-// prefixes (st, r, ru) would otherwise shadow stand and movement, so those two
-// commands must be typed in full.
-var casinoShortVerbs = []string{
- "bet", "deal", "draw", "hold", "paytable", "denom", "denomination",
- "hands", "feature", "game", "roll", "autoroll", "unbet", "table",
- "status", "list", "watch", "decline", "hit", "stand",
- "double", "split", "insurance", "surrender", "spin", "autobet",
- "autospin", "rebet",
+// casinoCommonVerbs are the generic controls a seated player may abbreviate
+// at any casino game; they are not tied to one game's rules.
+var casinoCommonVerbs = []string{"watch", "game", "table", "list", "stop", "rules"}
+
+// casinoVerbsByGame scopes the rest of the abbreviable verbs to the game the
+// player is actually in. A prefix can therefore never match another game's
+// command: "sp" is split at a blackjack table, but spin at a Big 6 wheel,
+// because "split" is not a Big 6 verb and "spin" is not a blackjack verb.
+var casinoVerbsByGame = map[casino.GameName][]string{
+ casino.GameBlackjack: {"bet", "rebet", "unbet", "hit", "stand", "double", "split", "insurance", "surrender", "decline"},
+ casino.GameBaccarat: {"bet", "rebet", "unbet"},
+ casino.GameRoulette: {"bet", "rebet", "unbet"},
+ casino.GameCraps: {"bet", "rebet", "unbet", "roll", "autoroll"},
+ casino.GamePaiGow: {"bet", "rebet", "unbet"},
+ casino.GameVideoPoker: {"bet", "deal", "draw", "hold", "paytable", "denom", "denomination", "hands", "feature"},
+ casino.GameSlots: {"bet", "spin", "autospin", "autobet"},
+ casino.GameBigSix: {"bet", "rebet", "unbet", "spin"},
+}
+
+// casinoShortAliases maps the registry's terse aliases onto the verb they
+// stand for. An alias only applies when its verb belongs to the current game;
+// otherwise the letters are re-read as a fresh prefix, so "sp" is split at a
+// blackjack table and spin at a Big 6 wheel.
+var casinoShortAliases = map[string]string{
+ "h": "hit", "st": "stand", "dd": "double", "sp": "split",
+}
+
+// casinoVerbsFor returns the game-scoped verb vocabulary for a seated player,
+// or nil when they are not in a casino game.
+func (g *Game) casinoVerbsFor(name string) []string {
+ if g.Casino == nil {
+ return nil
+ }
+ table, playing := g.Casino.Participation(name)
+ if !playing {
+ return nil
+ }
+ var game casino.GameName
+ switch {
+ case table != nil:
+ game = table.Config.Game
+ default:
+ machine, ok := g.Casino.MachineFor(name)
+ if !ok {
+ return nil
+ }
+ game = machine.Config.Game
+ }
+ verbs := append([]string(nil), casinoCommonVerbs...)
+ return append(verbs, casinoVerbsByGame[game]...)
}
-// casinoAbbreviation resolves a seated casino player's unambiguous command
-// prefix to its full verb. An exact command (including the h/st/dd/sp aliases
-// and video poker's d) always wins, so a prefix never shadows a real command;
-// an ambiguous prefix resolves to nothing and falls through unchanged.
+// casinoAbbreviation resolves a seated casino player's partial command to the
+// closest verb that is actually relevant to the game they are in. Exact
+// commands always win, so movement, look and the game's own real verbs are
+// never shadowed; a short alias applies only when its verb belongs to this
+// game; an ambiguous prefix resolves to nothing and falls through unchanged.
func (g *Game) casinoAbbreviation(sess *net.Session, cmd string) (string, bool) {
- if sess == nil || sess.Player == nil || cmd == "" || !g.inCasinoGame(sess.Player.Name) {
+ if sess == nil || sess.Player == nil || cmd == "" {
+ return "", false
+ }
+ verbs := g.casinoVerbsFor(sess.Player.Name)
+ if len(verbs) == 0 {
return "", false
}
- if _, ok := commandRegistry[cmd]; ok {
+ // A real casino verb needs no abbreviation: the registry dispatches it.
+ for _, verb := range verbs {
+ if verb == cmd {
+ return "", false
+ }
+ }
+ if target, ok := casinoShortAliases[cmd]; ok {
+ for _, verb := range verbs {
+ if verb == target {
+ return target, true
+ }
+ }
+ // The alias names another game's verb: fall through and read the
+ // letters as a prefix of this game's vocabulary instead.
+ } else if _, ok := commandRegistry[cmd]; ok {
+ // Any other real command (movement, look, inventory, ...) wins over a
+ // casino prefix.
return "", false
}
match := ""
- for _, verb := range casinoShortVerbs {
+ for _, verb := range verbs {
if !strings.HasPrefix(verb, cmd) {
continue
}
- if match != "" {
+ if match != "" && match != verb {
return "", false
}
match = verb