aboutsummaryrefslogtreecommitdiff
path: root/internal/game/render_cash_hunt.go
blob: 374d6c86f9f52a8340dadd4872bdbbc93cfb570d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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)
	}
}