aboutsummaryrefslogtreecommitdiff
path: root/internal/game/video_poker_render_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/video_poker_render_test.go')
-rw-r--r--internal/game/video_poker_render_test.go112
1 files changed, 112 insertions, 0 deletions
diff --git a/internal/game/video_poker_render_test.go b/internal/game/video_poker_render_test.go
new file mode 100644
index 0000000..d618c36
--- /dev/null
+++ b/internal/game/video_poker_render_test.go
@@ -0,0 +1,112 @@
+package game
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+
+ "thehouseoficarus/internal/casino"
+ "thehouseoficarus/internal/color"
+)
+
+func TestPokerPayTableBordersPaletteAndColumns(t *testing.T) {
+ for _, cabinet := range []string{casino.CabinetClassic, casino.CabinetUXSingle, casino.CabinetUXMulti} {
+ cfg := (casino.VideoPokerConfig{Cabinet: cabinet, Variant: "double_double_bonus"}).Normalize()
+ snap := &casino.VideoPokerSnapshot{Config: cfg, Coins: 3, Hands: 3, Denomination: 10}
+ panel := renderPokerPayTable(snap, "xterm256")
+ for _, want := range []string{"┌", "┬", "┐", "│", "└", "┴", "┘", "....", "4000", "COINS PER HAND"} {
+ if !strings.Contains(panel, want) {
+ t.Fatalf("panel missing %q: %s", want, panel)
+ }
+ }
+ for _, seq := range []string{fmt.Sprintf("38;5;%d", pokerYellow), fmt.Sprintf("48;5;%d", pokerBlue), fmt.Sprintf("48;5;%d", pokerRed)} {
+ if !strings.Contains(panel, seq) {
+ t.Fatalf("missing palette %s", seq)
+ }
+ }
+ width := -1
+ for _, line := range strings.Split(stripANSI(panel), "\n") {
+ if !strings.HasPrefix(line, "│") && !strings.HasPrefix(line, "┌") && !strings.HasPrefix(line, "├") && !strings.HasPrefix(line, "└") {
+ continue
+ }
+ if width < 0 {
+ width = color.VisibleLen(line)
+ }
+ if color.VisibleLen(line) != width {
+ t.Fatalf("unaligned pay table: %q (%d != %d)", line, color.VisibleLen(line), width)
+ }
+ if strings.HasPrefix(line, "│") {
+ cells := strings.Split(line, "│")
+ want := 8
+ if cabinet != casino.CabinetClassic {
+ want = 9
+ }
+ if len(cells) != want {
+ t.Fatalf("bad column count %d: %s", len(cells), line)
+ }
+ }
+ }
+ if cabinet != casino.CabinetClassic && strings.Count(stripANSI(panel), "NEXT X") != 1 {
+ t.Fatal("missing/duplicate next award heading")
+ }
+ plain := renderPokerPayTable(snap, "none")
+ if strings.Contains(plain, "\x1b") {
+ t.Fatal("plain display contains escapes")
+ }
+ }
+}
+
+func TestPokerResultsBelowCardsAndHoldStyle(t *testing.T) {
+ cards := []casino.CardView{{Rank: "A", Suit: "hearts"}, {Rank: "K", Suit: "hearts"}, {Rank: "Q", Suit: "hearts"}, {Rank: "J", Suit: "hearts"}, {Rank: "10", Suit: "hearts"}}
+ cfg := (casino.VideoPokerConfig{Cabinet: casino.CabinetClassic}).Normalize()
+ for _, hands := range []int{1, 3, 100} {
+ for _, win := range []bool{false, true} {
+ line := casino.PokerLine{Cards: cards, Category: "No win", Multiplier: 1}
+ fg, text := 15, "No win"
+ if win {
+ line.Category = "Royal flush"
+ line.Coins = 4000
+ fg = pokerYellow
+ text = "WIN: Royal flush — 4000 coins"
+ }
+ snap := &casino.VideoPokerSnapshot{Config: cfg, Hands: hands, Lines: []casino.PokerLine{line}, Multiplier: 1}
+ out := renderVideoPoker(snap, "xterm256", true, 7, "", nil)
+ styled := color.Render("xterm256", color.ColorSpec{Fg: fg, Bg: -1, Bold: true}, text)
+ if !strings.Contains(out, styled) {
+ t.Fatalf("missing result styling: %q", out)
+ }
+ plain := stripANSI(out)
+ result := strings.Index(plain, text)
+ // The result starts its own line and follows the card/badge line.
+ if result < 0 || result == 0 || plain[result-1] != '\n' || strings.Index(plain, "CLASSIC") > result {
+ t.Fatalf("result not below cards: %s", plain)
+ }
+ if hands == 100 && !strings.Contains(plain, "♥") {
+ t.Fatal("hundred-play missing compact Unicode suits")
+ }
+ }
+ }
+ held := [5]bool{true, false, true, false, true}
+ art := strings.Join(renderPokerCards(cards, &held, "xterm256", true, 5, "", nil), "\n")
+ for _, n := range []int{1, 3, 5} {
+ if !strings.Contains(art, color.Render("xterm256", color.ColorSpec{Fg: pokerYellow, Bg: -1, Bold: true}, fmt.Sprintf("%d HELD", n))) {
+ t.Fatal("HELD not bold yellow")
+ }
+ }
+}
+
+func TestPokerDrawShortcutLeavesDownAlone(t *testing.T) {
+ g, sess, conn := casinoCrapsGame(t, "name: Poker\ncasino_tables:\n - id: vp\n game: video_poker\n")
+ g.executeCommand(sess, "d", nil, "d")
+ if !strings.Contains(string(conn.data), "You can't go that way.") {
+ t.Fatalf("d did not route down outside poker: %s", conn.data)
+ }
+ g.executePlay(sess, []string{"vp"}, "play vp")
+ g.executeBet(sess, nil, "bet")
+ g.executeTableAction(sess, "deal")
+ conn.data = nil
+ g.executeCommand(sess, "d", nil, "d")
+ if len(sess.Player.PendingWagers) != 0 || strings.Contains(string(conn.data), "You can't go that way.") {
+ t.Fatal("seated d did not settle the hand")
+ }
+}