From 1082f3336085c15992ca83d5553c0ba52208d70a Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Thu, 1 Oct 2026 14:38:08 -0400 Subject: feat: pai gow poker added to the casino --- internal/game/render_pai_gow.go | 79 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 internal/game/render_pai_gow.go (limited to 'internal/game/render_pai_gow.go') diff --git a/internal/game/render_pai_gow.go b/internal/game/render_pai_gow.go new file mode 100644 index 0000000..2005daf --- /dev/null +++ b/internal/game/render_pai_gow.go @@ -0,0 +1,79 @@ +package game + +import ( + "fmt" + "strings" + + "thehouseoficarus/internal/cardart" + "thehouseoficarus/internal/casino" +) + +func renderPaiGowFelt(cfg casino.TableConfig, mode string, unicode bool) string { + c := newCrapsCanvas(25) + c.box(0, 0, 76, 24) + c.center(1, 75, 1, strings.ToUpper(cfg.PaiGow.Label()), crapsGold) + c.center(1, 75, 2, "FIVE HIGH / TWO LOW | COPIES LOSE | LIMITS "+betLimitsText(cfg.MinBet, cfg.MaxBet), crapsInk) + note := "MAIN WIN 0.95:1 | 5% COMMISSION" + switch cfg.PaiGow.Normalize().Variant { + case casino.PaiGowEZ: + note = "MAIN WIN 1:1 | DEALER QUEEN-HIGH PUSHES" + case casino.PaiGowNoPush: + note = "MAIN WIN 1:1 | SPLIT RESULT: EXTRA CARD HIGH WINS, TIES LOSE" + case casino.PaiGowFaceUp: + note = "DEALER FACE UP | ACE-HIGH PUSHES | PUSH ACE HIGH " + strings.ReplaceAll(cfg.PaiGow.PushAceHigh, "_", "/") + ":1" + } + c.center(1, 75, 3, note, crapsInk) + c.box(0, 4, 76, 19) + c.text(3, 5, "FORTUNE - BEST OF ALL SEVEN CARDS", crapsGold) + c.text(48, 5, "PROFIT ODDS", crapsGold) + envy := "ENVY OFF" + if cfg.PaiGow.Envy { + envy = "ENVY (FIXED)" + } + c.text(62, 5, envy, crapsGold) + for i, row := range casino.FortunePayTable(cfg.PaiGow.Envy) { + c.text(3, 6+i, row.Hand, crapsInk) + c.text(50, 6+i, fmt.Sprintf("%d:1", row.Odds), crapsInk) + if cfg.PaiGow.Envy { + c.text(65, 6+i, fmt.Sprintf("%d", row.Envy), crapsInk) + } + } + c.center(1, 75, 18, "Highest prize only. Winning Fortune wagers also return their stake.", crapsMuted) + note = "Envy disabled: quads improved from 25:1 to 30:1." + if cfg.PaiGow.Envy { + note = "Fortune 5+ earns Envy on other players, not yourself or dealer." + } + c.center(1, 75, 20, note, crapsInk) + c.center(1, 75, 21, "24 sets cards 2/4 LOW; 13456 sets five HIGH; house sets house way.", crapsInk) + c.center(1, 75, 22, "High must outrank low. Joker: ace or completes straight/flush.", crapsMuted) + c.center(1, 75, 23, "Bet main, optional bet fortune, then deal.", crapsMuted) + return c.render(mode, unicode) +} +func renderPaiGow(s *casino.PaiGowSnapshot, mode string, unicode bool, size int, style string, store *cardart.Store) string { + size = cardRenderSize(unicode, size) + lines := []string{renderPaiGowFelt(s.Config, mode, unicode)} + if len(s.Cards) > 0 { + lines = append(lines, "Your seven cards (positions 1-7):") + lines = append(lines, cardsLine(mode, s.Cards, size, unicode, style, store)...) + // Position labels use each card's actual rendered width; compact cards are + // variable-width, so print a separate unambiguous position-to-card key. + var positions []string + for i, c := range s.Cards { + positions = append(positions, fmt.Sprintf("%d=%s", i+1, cardSymbol(c))) + } + lines = append(lines, strings.Join(positions, " ")) + } + for _, h := range []struct { + label string + cards []casino.CardView + }{{"Your high", s.High}, {"Your low", s.Low}, {"Dealer high", s.DealerHigh}, {"Dealer low", s.DealerLow}, {"Tiebreaker: player / dealer", s.Tiebreaker}} { + if len(h.cards) > 0 { + lines = append(lines, h.label+":") + lines = append(lines, cardsLine(mode, h.cards, size, unicode, style, store)...) + } + } + if s.Result != "" { + lines = append(lines, s.Result) + } + return strings.Join(lines, "\n") +} -- cgit v1.2.3