aboutsummaryrefslogtreecommitdiff
path: root/internal/game/prediction_interface.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-10-05 06:03:49 -0400
committerhistoria <[not public]>2026-10-05 06:03:49 -0400
commitc84a9944356f590d90d819d652bdf1349ebacd40 (patch)
treeaf1ee15992e141fb3eb6f26cac02cf06306d4982 /internal/game/prediction_interface.go
parent8b78aa4cd930fde145959704ba7bdc0e57465b9b (diff)
downloadthehouseoficarus-c84a9944356f590d90d819d652bdf1349ebacd40.tar.gz
feat: prediction exchange with live polymarket data
Diffstat (limited to 'internal/game/prediction_interface.go')
-rw-r--r--internal/game/prediction_interface.go155
1 files changed, 155 insertions, 0 deletions
diff --git a/internal/game/prediction_interface.go b/internal/game/prediction_interface.go
new file mode 100644
index 0000000..2e37145
--- /dev/null
+++ b/internal/game/prediction_interface.go
@@ -0,0 +1,155 @@
+package game
+
+import (
+ "strings"
+
+ "thehouseoficarus/internal/net"
+)
+
+func predictionUseTarget(input string) bool {
+ switch strings.ToLower(strings.TrimSpace(input)) {
+ case "predictions", "prediction", "market", "counter", "exchange", "prediction market", "prediction counter", "prediction exchange", "prediction market counter":
+ return true
+ }
+ return false
+}
+
+var predictionVerbs = []string{"markets", "view", "find", "next", "prev", "back", "active", "closed", "holding", "buy", "sell", "collect", "refresh", "rules", "stop"}
+
+func (g *Game) openPredictionCounter(s *net.Session) {
+ if !g.atPredictionCounter(s.Player) {
+ s.WriteLine("There is no Prediction Exchange here.")
+ return
+ }
+ if !g.leaveCasinoGames(s.Player) {
+ s.WriteLine("Finish your current casino round before using the counter.")
+ return
+ }
+ if s.PredictionActive {
+ g.executePredictions(s, []string{"refresh"}, "")
+ return
+ }
+ s.PredictionActive = true
+ s.PredictionEpoch++
+ s.PredictionBusy = false
+ s.PredictionSelected = ""
+ s.PredictionScreen = "list"
+ s.PredictionPage = 1
+ s.PredictionBoardPage = 1
+ s.PredictionSearch = ""
+ s.PredictionUnavailable = false
+ g.executePredictions(s, nil, "open")
+}
+
+func (g *Game) closePredictionCounter(s *net.Session) {
+ if s.PredictionCancel != nil {
+ s.PredictionCancel()
+ s.PredictionCancel = nil
+ }
+ s.PredictionActive = false
+ s.PredictionEpoch++ // Invalidate any download, including an in-flight trade.
+ s.PredictionBusy = false
+ s.PredictionSelected = ""
+}
+
+// Exact world commands keep their meaning unless explicitly part of this UI.
+// Abbreviations are scoped to the counter; no new global command is registered.
+func predictionVerb(cmd string) (string, bool) {
+ switch cmd {
+ case "list":
+ return "markets", true
+ case "table", "game":
+ return "refresh", true
+ case "status", "portfolio", "board":
+ return "active", true
+ case "help":
+ return "help", true
+ case "leave", "exit":
+ return "stop", true
+ }
+ for _, v := range predictionVerbs {
+ if cmd == v {
+ return v, true
+ }
+ }
+ if _, exists := commandRegistry[cmd]; exists {
+ return "", false
+ }
+ found := ""
+ for _, v := range predictionVerbs {
+ if strings.HasPrefix(v, cmd) {
+ if found != "" {
+ return "", true
+ }
+ found = v
+ }
+ }
+ return found, found != ""
+}
+func (g *Game) predictionInputOwned(s *net.Session, cmd string) bool {
+ if !s.PredictionActive || !g.atPredictionCounter(s.Player) {
+ return false
+ }
+ if isAllDigits(cmd) {
+ return true
+ }
+ _, ok := predictionVerb(cmd)
+ return ok
+}
+func (g *Game) handlePredictionInput(s *net.Session, cmd string, args []string) bool {
+ if !s.PredictionActive {
+ return false
+ }
+ if !g.atPredictionCounter(s.Player) {
+ g.closePredictionCounter(s)
+ return false
+ }
+ if cmd == "help" && len(args) > 0 {
+ return false
+ }
+ if isAllDigits(cmd) {
+ action := "view"
+ if s.PredictionScreen == "active" || s.PredictionScreen == "closed" {
+ action = "holding"
+ }
+ g.executePredictions(s, []string{action, cmd}, "")
+ return true
+ }
+ verb, owned := predictionVerb(cmd)
+ if !owned {
+ if cmd == "use" && predictionUseTarget(strings.Join(args, " ")) {
+ return false
+ }
+ switch cmd {
+ case "play", "use", "bank", "quit", "logout":
+ g.closePredictionCounter(s)
+ }
+ return false
+ }
+ if verb == "" {
+ s.WriteLine("That shortcut is ambiguous. Choose a command below.")
+ g.predictionHints(s)
+ return true
+ }
+ if verb == "stop" {
+ g.closePredictionCounter(s)
+ s.WriteLine(g.colorize(s, "casino_action", "You step away from the Prediction Exchange. Your contracts stay with the house."))
+ return true
+ }
+ switch verb {
+ case "markets":
+ verb = "list"
+ case "back":
+ args = nil
+ case "help":
+ g.predictionHelp(s)
+ return true
+ case "rules":
+ if s.PredictionScreen != "view" || s.PredictionSelected == "" {
+ g.predictionHelp(s)
+ return true
+ }
+ }
+ g.executePredictions(s, append([]string{verb}, args...), "")
+ return true
+}