aboutsummaryrefslogtreecommitdiff
path: root/internal/game/render_cash_hunt.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/render_cash_hunt.go')
-rw-r--r--internal/game/render_cash_hunt.go110
1 files changed, 110 insertions, 0 deletions
diff --git a/internal/game/render_cash_hunt.go b/internal/game/render_cash_hunt.go
new file mode 100644
index 0000000..374d6c8
--- /dev/null
+++ b/internal/game/render_cash_hunt.go
@@ -0,0 +1,110 @@
+package game
+
+import (
+ "fmt"
+ "strings"
+
+ "thehouseoficarus/internal/casino"
+ "thehouseoficarus/internal/color"
+)
+
+func cashHuntPrizeColor(multiplier int) int {
+ switch {
+ case multiplier >= 10000:
+ return 225
+ case multiplier >= 500:
+ return 201
+ case multiplier >= 100:
+ return 220
+ case multiplier >= 20:
+ return 207
+ case multiplier >= 5:
+ return 141
+ case multiplier >= 2:
+ return 81
+ case multiplier == 1:
+ return 120
+ default:
+ return 240
+ }
+}
+
+const (
+ cashHuntColumns = 10
+ cashHuntTileWidth = 7
+)
+
+// cashHuntTileColors is a dark rainbow, one hue per column. The shades stay
+// dark enough for bright prize text while replacing the old black/blue checker.
+var cashHuntTileColors = [cashHuntColumns]int{88, 94, 100, 28, 29, 30, 24, 18, 90, 89}
+
+// cashHuntCenter pads text to a fixed tile width, keeping every column aligned
+// whether it holds a one- or three-digit square number.
+func cashHuntCenter(text string, width int) string {
+ if len(text) >= width {
+ return text
+ }
+ left := (width - len(text)) / 2
+ return strings.Repeat(" ", left) + text + strings.Repeat(" ", width-len(text)-left)
+}
+
+func renderCashHunt(s *casino.CashHuntSnapshot, mode string, unicode bool) string {
+ paint := func(text string, fg int) string { return color.Render(mode, color.ColorSpec{Fg: fg, Bg: -1}, text) }
+ title := paint("CASH HUNT / "+strings.ToUpper(s.Risk)+" / 98% RTP", 220)
+ switch s.Phase {
+ case "hidden":
+ side, topLeft, topRight, bottomLeft, bottomRight, bar := "|", "+", "+", "+", "+", "-"
+ if unicode {
+ side, topLeft, topRight, bottomLeft, bottomRight, bar = "│", "╭", "╮", "╰", "╯", "─"
+ }
+ lines := []string{topLeft + strings.Repeat(bar, 68) + topRight}
+ for _, text := range []string{"* THE VAULT WHIRLS ... THE PRIZES VANISH! *", "All 100 positions have been hidden and mixed.", "The prizes are sealed. Your choice unlocks one.", "Choose your square: type 1-100, or pick N."} {
+ padding := 68 - len(text)
+ lines = append(lines, side+strings.Repeat(" ", padding/2)+text+strings.Repeat(" ", padding-padding/2)+side)
+ }
+ lines = append(lines, bottomLeft+strings.Repeat(bar, 68)+bottomRight)
+ for i, line := range lines {
+ lines[i] = color.Render(mode, color.ColorSpec{Fg: -1, Bg: -1, Gradient: []int{196, 208, 220, 46, 51, 45, 39, 21, 201, 207}}, line)
+ }
+ return strings.Join(lines, "\n")
+ case "paytable":
+ lines := []string{title, "Prize Chance per square"}
+ for _, prize := range s.Odds {
+ lines = append(lines, paint(fmt.Sprintf("%6dx %10.6f%%", prize.Multiplier, float64(prize.Weight)/1_000_000), cashHuntPrizeColor(prize.Multiplier)))
+ }
+ return strings.Join(append(lines, "Returns include stake. Each board's mix varies; jackpots are not guaranteed."), "\n")
+ case "preview", "result":
+ // Ten columns, two lines per tile: all 100 labels and even 50000x fit
+ // into a 70-column canvas without relying on cursor controls.
+ lines := []string{title}
+ if s.Phase == "preview" {
+ highest := 0
+ for _, value := range s.Squares {
+ highest = max(highest, value)
+ }
+ lines = append(lines, paint(fmt.Sprintf("PRIZE PREVIEW / top prize %dx / positions will be mixed", highest), cashHuntPrizeColor(highest)))
+ } else {
+ lines = append(lines, paint(fmt.Sprintf("YOUR PICK: %d / %dx", s.Selected, s.Squares[s.Selected-1]), 220))
+ }
+ for start := 0; start < casino.CashHuntSquares; start += cashHuntColumns {
+ var numbers, prizes strings.Builder
+ for k := start; k < start+cashHuntColumns; k++ {
+ bg := cashHuntTileColors[k%cashHuntColumns]
+ number := cashHuntCenter(fmt.Sprintf("%d", k+1), cashHuntTileWidth)
+ value := cashHuntCenter(fmt.Sprintf("%dx", s.Squares[k]), cashHuntTileWidth)
+ nf, vf := 246, cashHuntPrizeColor(s.Squares[k])
+ selected := s.Selected == k+1
+ if selected {
+ number = cashHuntCenter(fmt.Sprintf(">%d<", k+1), cashHuntTileWidth)
+ nf, vf, bg = 16, 16, 226
+ }
+ numbers.WriteString(color.Render(mode, color.ColorSpec{Fg: nf, Bg: bg, Bold: selected}, number))
+ prizes.WriteString(color.Render(mode, color.ColorSpec{Fg: vf, Bg: bg, Bold: selected}, value))
+ }
+ lines = append(lines, numbers.String(), prizes.String())
+ }
+ return strings.Join(lines, "\n")
+ default:
+ return title + "\n" + paint("100 squares. One choice. Prizes from 0x to 50000x.", 81)
+ }
+}