diff options
| author | historia <[not public]> | 2026-10-03 00:51:41 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-10-03 00:51:41 -0400 |
| commit | 82e571d227feeafd0af4011e701ce26b99c5e3d9 (patch) | |
| tree | ab4d56ddf94c3bf3b42fff5dfc2ff9a339f09113 /internal/game | |
| parent | cac16d1725c46c82a2e62b84c93f7090b2ce0746 (diff) | |
| download | thehouseoficarus-82e571d227feeafd0af4011e701ce26b99c5e3d9.tar.gz | |
fix: craps felt and wager description cleanup
Diffstat (limited to 'internal/game')
| -rw-r--r-- | internal/game/casino.go | 2 | ||||
| -rw-r--r-- | internal/game/casino_edge_list_test.go | 20 | ||||
| -rw-r--r-- | internal/game/casino_house_edge.go | 6 | ||||
| -rw-r--r-- | internal/game/casino_ux.go | 2 | ||||
| -rw-r--r-- | internal/game/craps_test.go | 4 | ||||
| -rw-r--r-- | internal/game/game.go | 2 | ||||
| -rw-r--r-- | internal/game/render_casino_settlement.go | 6 | ||||
| -rw-r--r-- | internal/game/render_casino_settlement_test.go | 11 | ||||
| -rw-r--r-- | internal/game/render_craps.go | 113 | ||||
| -rw-r--r-- | internal/game/render_craps_test.go | 45 | ||||
| -rw-r--r-- | internal/game/render_roulette_test.go | 2 |
11 files changed, 162 insertions, 51 deletions
diff --git a/internal/game/casino.go b/internal/game/casino.go index dc9f8f0..5e09d48 100644 --- a/internal/game/casino.go +++ b/internal/game/casino.go @@ -438,7 +438,7 @@ func (g *Game) executeBet(sess *net.Session, args []string, rawInput string) { for i, arg := range args { if strings.EqualFold(arg, "on") { if sawOn || spot != "" || i == len(args)-1 { - sess.WriteLine("Use bet <amount> on <target>. No wager was placed.") + sess.WriteLine("Use bet <n> on <bet>. No wager was placed.") return } sawOn = true diff --git a/internal/game/casino_edge_list_test.go b/internal/game/casino_edge_list_test.go index ff0b965..902d178 100644 --- a/internal/game/casino_edge_list_test.go +++ b/internal/game/casino_edge_list_test.go @@ -34,6 +34,26 @@ func TestEdgeListAllTableGames(t *testing.T) { } } +// TestCrapsListEveryBetHasRTP: once a reference item is carried, every +// craps wager the list can name must resolve to a real percentage. An +// unknown target would render the dash, which is the bug this guards. +func TestCrapsListEveryBetHasRTP(t *testing.T) { + for _, variant := range []string{"bank", "crapless", "new_york"} { + t.Run(variant, func(t *testing.T) { + room := "name: CR\ncasino_tables:\n - id: cr\n game: craps\n craps:\n variant: " + variant + "\n" + g, sess, conn := houseEdgeGame(t, room) + writeHouseEdgeManual(t, g, sess, 2) + g.executePlay(sess, []string{"craps"}, "play craps") + g.executeBet(sess, []string{"10", "pass"}, "bet 10 pass") + conn.data = nil + g.executeList(sess, nil, "list") + if text := stripANSI(string(conn.data)); strings.Contains(text, "—") { + t.Fatalf("%s come-out list left a bet without RTP:\n%s", variant, text) + } + }) + } +} + func TestEdgeListBlackjackActionsOmitRTP(t *testing.T) { g, sess, conn := houseEdgeGame(t, "name: BJ\ncasino_tables:\n - id: bj\n game: blackjack\n") writeHouseEdgeManual(t, g, sess, 2) diff --git a/internal/game/casino_house_edge.go b/internal/game/casino_house_edge.go index 19d8cc2..1abbcac 100644 --- a/internal/game/casino_house_edge.go +++ b/internal/game/casino_house_edge.go @@ -78,8 +78,10 @@ func (g *Game) casinoListRows(sess *net.Session, t *casino.Table, wagers []casin entry := row if strings.Contains(wager.Bet, "<n>") { entry.bet = strings.ReplaceAll(wager.Bet, "<n>", part.Label) - } else { - entry.win = part.Label + "; " + entry.win + } else if part.Label != "" { + // The label refines the shared win text (hop's doubles), so append + // it: the base phrase stays "Next roll is a/b (doubles)". + entry.win = entry.win + " " + part.Label } entry.edge = casino.HouseEdge{Parts: []casino.EdgePart{part}} rows = append(rows, entry) diff --git a/internal/game/casino_ux.go b/internal/game/casino_ux.go index 2650d47..4c9accb 100644 --- a/internal/game/casino_ux.go +++ b/internal/game/casino_ux.go @@ -410,7 +410,7 @@ func (g *Game) showCasinoWagerList(sess *net.Session, t *casino.Table) { g.showCasinoListTable(sess, "Bet", list) return } - g.showCasinoListTable(sess, "bet <amount> on", g.casinoListRows(sess, t, rows)) + g.showCasinoListTable(sess, "bet <n> on", g.casinoListRows(sess, t, rows)) } // showCasinoGameLook appends the live game state and hint menu for the diff --git a/internal/game/craps_test.go b/internal/game/craps_test.go index 6712455..1e9ff6b 100644 --- a/internal/game/craps_test.go +++ b/internal/game/craps_test.go @@ -18,7 +18,7 @@ func TestCrapsCommandsAndRendering(t *testing.T) { conn := &casinoTestConn{} sess := &net.Session{Player: player.New("alice"), Conn: conn} g.loggedInChars = map[string]*net.Session{"alice": sess} - for _, args := range [][]string{{"12", "on", "place", "6"}, {"10", "on", "hop", "2", "3"}, {"10", "buy", "4"}, {"10", "on", "fire"}} { + for _, args := range [][]string{{"12", "on", "place", "6"}, {"10", "on", "hop", "2", "3"}, {"20", "buy", "4"}, {"10", "on", "fire"}} { conn.data = nil g.executeBet(sess, args, "bet "+strings.Join(args, " ")) if !strings.Contains(string(conn.data), "You don't have enough chips and credits") { @@ -43,7 +43,7 @@ func TestCrapsCommandsAndRendering(t *testing.T) { for _, unicode := range []bool{false, true} { art := renderCrapsSnapshot(snap, mode, unicode) plain := plainRoulette(art) - for _, word := range []string{"PASS LINE", "DON'T COME", "FIELD", "FIRE", "SMALL", "Total: 7", "POINT 6"} { + for _, word := range []string{"PASS LINE", "DON'T COME", "F I E L D", "FIRE", "SMALL", "Total: 7", "POINT 6"} { if !strings.Contains(plain, word) { t.Fatal("missing", word) } diff --git a/internal/game/game.go b/internal/game/game.go index f1855dc..3357077 100644 --- a/internal/game/game.go +++ b/internal/game/game.go @@ -750,7 +750,7 @@ func (g *Game) ProcessQueuedCommands() { ss, _ := g.safespot.Get(p.Name) isHiding := ss.Active isBusy := p.Action != nil || len(p.WalkSequence) > 0 || g.Combat.Get(p.Name) != nil || p.MoveTicks > 0 || isHiding - isCasinoSpin := g.Casino != nil && g.Casino.MachineBusy(p.Name) + isCasinoSpin := g.Casino != nil && (g.Casino.MachineBusy(p.Name) || g.Casino.TableBusy(p.Name)) _, isResting := g.restTimers[p.Name] if !isResting && !isBusy && !isCasinoSpin && qc.Session.State() == net.StateGame { g.writePrompt(qc.Session) diff --git a/internal/game/render_casino_settlement.go b/internal/game/render_casino_settlement.go index bfe101c..2b5acc9 100644 --- a/internal/game/render_casino_settlement.go +++ b/internal/game/render_casino_settlement.go @@ -149,6 +149,12 @@ func renderCasinoSettlement(lines []casino.SettlementLine, unicode bool, paint f } } } + if settled == 0 { + // Nothing settled yet: the whole totals footer is noise, so end the + // receipt at the wager rows with the flat bottom border. + out = append(out, paint("dim", bl+strings.Repeat(h, inner)+br)) + return strings.Join(out, "\n") + } out = append(out, border(lj, bj, rj)) footer := func(text, tag string) { out = append(out, paint("dim", v)+" "+paint(tag, pad(text, inner-2, false))+" "+paint("dim", v)) diff --git a/internal/game/render_casino_settlement_test.go b/internal/game/render_casino_settlement_test.go index f26a174..15441ac 100644 --- a/internal/game/render_casino_settlement_test.go +++ b/internal/game/render_casino_settlement_test.go @@ -129,10 +129,15 @@ func TestCasinoReceiptIsPrivateEvenOnPublicResult(t *testing.T) { } } -func TestCasinoReceiptUnresolvedIsNotPush(t *testing.T) { +// TestCasinoReceiptUnresolvedOmitsTotals: while every wager is still live, +// the receipt shows only the rows; the settled/active totals and NET PENDING +// footer are omitted entirely. +func TestCasinoReceiptUnresolvedOmitsTotals(t *testing.T) { got := renderCasinoSettlement([]casino.SettlementLine{{Label: "Pass line", Stake: 100, Unresolved: true}}, false, plainReceipt) - if !strings.Contains(got, "NET PENDING") || strings.Contains(got, "NET EVEN") || strings.Contains(got, "PUSH") { - t.Fatal(got) + for _, gone := range []string{"NET PENDING", "NET EVEN", "PUSH", "Settled:", "Active:", "Staked:"} { + if strings.Contains(got, gone) { + t.Fatalf("unresolved receipt still shows %q:\n%s", gone, got) + } } } diff --git a/internal/game/render_craps.go b/internal/game/render_craps.go index ce9825f..e4e6618 100644 --- a/internal/game/render_craps.go +++ b/internal/game/render_craps.go @@ -21,17 +21,23 @@ const ( crapsPuckOn crapsPuckOff crapsBonus + crapsGoldInk + crapsBonusInk + crapsBonusDim ) var crapsPaint = []color.ColorSpec{ {Fg: 15, Bg: crapsFelt}, {Fg: 229, Bg: crapsFelt, Bold: true}, - {Fg: 217, Bg: crapsFelt, Bold: true}, + {Fg: 160, Bg: crapsFelt, Bold: true}, // deep red for come/pass/props {Fg: 108, Bg: crapsFelt}, {Fg: 0, Bg: 220, Bold: true}, {Fg: 0, Bg: 15, Bold: true}, {Fg: 15, Bg: 0, Bold: true}, {Fg: 229, Bg: 24, Bold: true}, // Fire/ATS tracker: yellow on blue + {Fg: 229, Bg: crapsFelt}, // regular-weight gold, used for field notes + {Fg: 229, Bg: 24}, // regular-weight tracker text and brackets + {Fg: 108, Bg: 24}, // dim tracker odds, matching the place/lay payouts } type crapsCell struct { @@ -93,6 +99,26 @@ func (c *crapsCanvas) center(x1, x2, y int, s string, ink int) { c.text(x1+(x2-x1+1-color.VisibleLen(s))/2, y, s, ink) } +// crapsSpan is one color run inside a centered line. centerSpans lays the runs +// end to end and centers their combined width, so a label can stay regular +// weight while its payout is dim, or a heading can pair two inks on one row. +type crapsSpan struct { + text string + ink int +} + +func (c *crapsCanvas) centerSpans(x1, x2, y int, spans ...crapsSpan) { + total := 0 + for _, s := range spans { + total += color.VisibleLen(s.text) + } + x := x1 + (x2-x1+1-total)/2 + for _, s := range spans { + c.text(x, y, s.text, s.ink) + x += color.VisibleLen(s.text) + } +} + // crapsJoints maps a union of box edges (N=1, E=2, S=4, W=8) to its glyph. var crapsJoints = map[uint8]rune{3: '└', 6: '┌', 9: '┘', 12: '┐', 7: '├', 11: '┴', 13: '┤', 14: '┬', 15: '┼'} @@ -191,17 +217,15 @@ func renderCrapsTrackers(s *casino.CrapsSnapshot, mode string, unicode bool) str c.box(38, 4, 76, 6) c.text(3, 1, "FIRE", crapsBonus) for i, n := range []int{4, 5, 6, 8, 9, 10} { - ink := crapsBonus - if crapsHas(s.Made, n) { - ink = crapsMarked - } - c.text(15+i*9, 1, fmt.Sprintf("[%2d]", n), ink) + crapsTrackerPoint(c, 15+i*9, 1, n, crapsHas(s.Made, n)) } bounds := []int{0, 25, 50, 76} for i, payout := range []string{"24:1", "249:1", "999:1"} { lo, hi := bounds[i], bounds[i+1] c.box(lo, 2, hi, 4) - c.center(lo+1, hi-1, 3, fmt.Sprintf("%d POINTS %s", i+4, payout), crapsBonus) + c.centerSpans(lo+1, hi-1, 3, + crapsSpan{fmt.Sprintf("%d POINTS", i+4), crapsBonusInk}, + crapsSpan{" " + payout, crapsBonusDim}) } c.text(2, 5, "SMALL", crapsBonus) c.text(40, 5, "TALL", crapsBonus) @@ -210,16 +234,27 @@ func renderCrapsTrackers(s *casino.CrapsSnapshot, mode string, unicode bool) str if i >= 5 { x = 48 + (i-5)*5 } - ink := crapsBonus - if crapsHas(s.Seen, n) { - ink = crapsMarked - } - c.text(x, 5, fmt.Sprintf("[%2d]", n), ink) + crapsTrackerPoint(c, x, 5, n, crapsHas(s.Seen, n)) } return c.render(mode, unicode) } + +// crapsTrackerPoint draws one bracketed total for the Fire/ATS tracker. The +// brackets stay regular weight while the number itself is bold; a made or +// seen point keeps its solid highlight across the whole token. +func crapsTrackerPoint(c *crapsCanvas, x, y, n int, marked bool) { + if marked { + c.text(x, y, fmt.Sprintf("[%2d]", n), crapsMarked) + return + } + c.text(x, y, "[", crapsBonusInk) + c.text(x+1, y, fmt.Sprintf("%2d", n), crapsBonus) + c.text(x+3, y, "]", crapsBonusInk) +} func renderCrapsFelt(s *casino.CrapsSnapshot, mode string, unicode bool) string { - c := newCrapsCanvas(26) + // Compact half-table: every rail keeps its label and value on adjacent + // rows, so the felt is five rows shorter than the spaced-out layout. + c := newCrapsCanvas(21) c.box(0, 0, 14, 6) c.center(1, 13, 4, "DON'T COME", crapsInk) c.center(1, 13, 5, "BAR 12", crapsMuted) @@ -241,9 +276,9 @@ func renderCrapsFelt(s *casino.CrapsSnapshot, mode string, unicode bool) string c.box(0, 6, 50, 10) c.center(1, 49, 7, "PLACE / BUY / LAY ON THE NUMBERS ABOVE", crapsMuted) c.center(1, 49, 9, "C O M E", crapsRed) - c.box(0, 10, 50, 16) - c.center(1, 49, 11, "FIELD", crapsGold) - c.center(1, 49, 13, "( 2 ) 3 4 9 10 11 ( 12 )", crapsInk) + c.box(0, 10, 50, 14) + c.center(1, 49, 11, "F I E L D", crapsGold) + c.center(1, 49, 12, "( 2 ) 3 4 9 10 11 ( 12 )", crapsInk) twelve := s.Field12 if twelve == 0 { twelve = 2 @@ -252,13 +287,17 @@ func renderCrapsFelt(s *casino.CrapsSnapshot, mode string, unicode bool) string if twelve == 3 { twelvePay = "TRIPLE" } - c.center(1, 49, 15, fmt.Sprintf("2 PAYS DOUBLE 12 PAYS %s", twelvePay), crapsGold) - c.box(0, 16, 50, 19) - c.center(1, 49, 18, "DON'T PASS / BAR 12", crapsInk) - c.box(0, 19, 50, 22) - c.center(1, 49, 21, "PASS LINE", crapsGold) - c.box(0, 22, 50, 25) - c.center(1, 49, 24, "FREE ODDS / BEHIND THE LINE", crapsInk) + c.center(1, 49, 13, fmt.Sprintf("2 PAYS DOUBLE 12 PAYS %s", twelvePay), crapsGoldInk) + c.box(0, 14, 50, 16) + c.centerSpans(1, 49, 15, crapsSpan{"DON'T PASS", crapsInk}, crapsSpan{" BAR 12", crapsMuted}) + c.box(0, 16, 50, 18) + c.center(1, 49, 17, "PASS LINE", crapsRed) + c.box(0, 18, 50, 20) + odds := s.Odds + if odds == "" { + odds = "3x-4x-5x" + } + c.centerSpans(1, 49, 19, crapsSpan{"FREE ODDS", crapsInk}, crapsSpan{" (" + odds + ")", crapsMuted}) // Centre action: four bonus spots, four hardways, six propositions, horn/hop. // The Fire and ATS spots share one blue field. bonus := []struct{ label, pays string }{{"FIRE", "24x"}, {"SMALL", "34:1"}, {"ALL", "175:1"}, {"TALL", "34:1"}} @@ -269,11 +308,11 @@ func renderCrapsFelt(s *casino.CrapsSnapshot, mode string, unicode bool) string c.fill(50, 0, 76, 5, crapsBonus) for i, spot := range bonus { c.center(xs[i]+1, xs[i+1]-1, 2, spot.label, crapsBonus) - c.center(xs[i]+1, xs[i+1]-1, 4, spot.pays, crapsBonus) + c.center(xs[i]+1, xs[i+1]-1, 4, spot.pays, crapsBonusDim) } for i, n := range []int{4, 6, 8, 10} { - x, y := 50+(i%2)*13, 5+(i/2)*4 - c.box(x, y, x+13, y+4) + x, y := 50+(i%2)*13, 5+(i/2)*3 + c.box(x, y, x+13, y+3) c.center(x+1, x+12, y+1, fmt.Sprintf("HARD %d", n), crapsInk) pay := 7 if n == 6 || n == 8 { @@ -283,29 +322,29 @@ func renderCrapsFelt(s *casino.CrapsSnapshot, mode string, unicode bool) string if unicode { pair = crapsDie(n/2) + "+" + crapsDie(n/2) } - c.center(x+1, x+12, y+3, fmt.Sprintf("%s %d:1", pair, pay), crapsGold) + c.centerSpans(x+1, x+12, y+2, crapsSpan{pair + " ", crapsGold}, crapsSpan{fmt.Sprintf("%d:1", pay), crapsMuted}) } props := []string{"SEVEN", "CRAPS", "ELEVEN", "ACES", "ACE 3", "BOXCARS"} - odds := []string{"4:1", "7:1", "15:1", "30:1", "15:1", "30:1"} + oddsRows := []string{"4:1", "7:1", "15:1", "30:1", "15:1", "30:1"} px := []int{50, 59, 67, 76} for i, label := range props { - col, y := i%3, 13+(i/3)*4 + col, y := i%3, 11+(i/3)*3 x, x2 := px[col], px[col+1] - c.box(x, y, x2, y+4) + c.box(x, y, x2, y+3) c.center(x+1, x2-1, y+1, label, crapsRed) - c.center(x+1, x2-1, y+3, odds[i], crapsInk) + c.center(x+1, x2-1, y+2, oddsRows[i], crapsMuted) } - c.box(50, 21, 63, 25) - c.center(51, 62, 22, "HORN", crapsGold) + c.box(50, 17, 63, 20) + c.center(51, 62, 18, "HORN", crapsGold) horn := "2 3 11 12" if unicode { // Horn combinations as painted dice pairs: 2, 3, 11, 12. horn = strings.Join([]string{crapsDie(1) + crapsDie(1), crapsDie(1) + crapsDie(2), crapsDie(5) + crapsDie(6), crapsDie(6) + crapsDie(6)}, " ") } - c.center(51, 62, 24, horn, crapsMuted) - c.box(63, 21, 76, 25) - c.center(64, 75, 22, "HOP", crapsGold) - c.center(64, 75, 24, "15:1 / 30:1", crapsMuted) + c.center(51, 62, 19, horn, crapsMuted) + c.box(63, 17, 76, 20) + c.center(64, 75, 18, "HOP", crapsGold) + c.center(64, 75, 19, "15:1 / 30:1", crapsMuted) return c.render(mode, unicode) } diff --git a/internal/game/render_craps_test.go b/internal/game/render_craps_test.go index 49bda4a..b6a70be 100644 --- a/internal/game/render_craps_test.go +++ b/internal/game/render_craps_test.go @@ -18,7 +18,7 @@ func TestCrapsHalfTableGeometryAndPuck(t *testing.T) { s := &casino.CrapsSnapshot{Point: point, Field12: 3} art := renderCrapsFelt(s, "none", unicode) rows := strings.Split(strings.TrimSuffix(art, "\n"), "\n") - if len(rows) != 26 { + if len(rows) != 21 { t.Fatal(len(rows)) } for _, row := range rows { @@ -48,7 +48,7 @@ func TestCrapsHalfTableGeometryAndPuck(t *testing.T) { if !strings.Contains(art, "12 PAYS TRIPLE") { t.Fatal("field variant invisible") } - for _, bet := range []string{"DON'T COME", "C O M E", "FIELD", "DON'T PASS", "PASS LINE", "HARD 4", "HARD 6", "HARD 8", "HARD 10", "SEVEN", "CRAPS", "ELEVEN", "ACES", "ACE 3", "BOXCARS", "HORN", "HOP"} { + for _, bet := range []string{"DON'T COME", "C O M E", "F I E L D", "DON'T PASS", "PASS LINE", "HARD 4", "HARD 6", "HARD 8", "HARD 10", "SEVEN", "CRAPS", "ELEVEN", "ACES", "ACE 3", "BOXCARS", "HORN", "HOP"} { if strings.Count(art, bet) != 1 { t.Fatalf("missing or duplicate %q", bet) } @@ -58,6 +58,45 @@ func TestCrapsHalfTableGeometryAndPuck(t *testing.T) { t.Log("\n" + renderCrapsSnapshot(&casino.CrapsSnapshot{Point: 6, Field12: 3, Dice: [2]int{3, 3}, Queue: []string{"Alice", "Bob"}, Made: []int{4, 5}, Seen: []int{2, 4, 5, 6, 9}, Phase: "betting", ShootIn: 10, DealerIn: 70}, "none", true)) } +// TestCrapsFeltOddsLabelAndCompaction pins the compacted felt copy: the +// free-odds cap is printed in parentheses, the old behind-the-line suffix is +// gone, and FIELD is letter-spaced. +func TestCrapsFeltOddsLabelAndCompaction(t *testing.T) { + base := &casino.CrapsSnapshot{Point: 6, Field12: 3} + art := plainRoulette(renderCrapsFelt(base, "none", true)) + for _, want := range []string{"F I E L D", "FREE ODDS (3x-4x-5x)", "DON'T PASS", "BAR 12"} { + if !strings.Contains(art, want) { + t.Fatalf("felt missing %q", want) + } + } + if strings.Count(art, "BAR 12") != 2 { + t.Fatalf("expected BAR 12 on both don't rails: %q", art) + } + for _, gone := range []string{"BEHIND THE LINE", "DON'T PASS /", "FREE ODDS /"} { + if strings.Contains(art, gone) { + t.Fatalf("felt still shows %q", gone) + } + } + custom := &casino.CrapsSnapshot{Point: 6, Field12: 3, Odds: "100x"} + if !strings.Contains(plainRoulette(renderCrapsFelt(custom, "none", true)), "FREE ODDS (100x)") { + t.Fatal("custom odds cap not shown") + } +} + +// TestCrapsTrackerBracketsRegularNumbersBold pins the mixed tracker weights: +// the bracket glyphs are regular while the total itself stays bold. +func TestCrapsTrackerBracketsRegularNumbersBold(t *testing.T) { + art := renderCrapsTrackers(&casino.CrapsSnapshot{}, "xterm256", true) + regular := color.Render("xterm256", color.ColorSpec{Fg: 229, Bg: 24}, "[") + bold := color.Render("xterm256", color.ColorSpec{Fg: 229, Bg: 24, Bold: true}, " 4") + if !strings.Contains(art, regular) { + t.Fatal("tracker brackets are not regular weight") + } + if !strings.Contains(art, bold) { + t.Fatal("tracker numbers are not bold") + } +} + // TestCrapsFireTrackerHighlightsMadePoints pins the Fire half of the tracker: // made points highlight, un-made points do not, and no asterisk is involved. func TestCrapsFireTrackerHighlightsMadePoints(t *testing.T) { @@ -168,7 +207,7 @@ func TestCrapsRemindersFollowArt(t *testing.T) { conn.data = nil g.emitCasinoEvents(g.Casino.Table(1, "c").Status("alice")) text := plainRoulette(string(conn.data)) - felt, commands := strings.Index(text, "PASS LINE"), strings.Index(text, "bet <amount> on <target>") + felt, commands := strings.Index(text, "PASS LINE"), strings.Index(text, "bet <n> on <bet>") if felt < 0 || commands < felt { t.Fatal("reminder above graphic", text) } diff --git a/internal/game/render_roulette_test.go b/internal/game/render_roulette_test.go index 72da225..90cee0c 100644 --- a/internal/game/render_roulette_test.go +++ b/internal/game/render_roulette_test.go @@ -606,7 +606,7 @@ func TestRouletteMenuPutsReminderAfterBoard(t *testing.T) { out := strings.ReplaceAll(string(conn.data), "\r\n", "\n") tracker := strings.Index(out, "History: last 0 spins") board := strings.Index(out, "R = red, B = black, G = green") - reminder := strings.Index(out, "bet <amount> on <target>") + reminder := strings.Index(out, "bet <n> on <bet>") if tracker < 0 || board < 0 || reminder < 0 { t.Fatalf("missing tracker, board, or reminder:\n%s", out) } |
