aboutsummaryrefslogtreecommitdiff
path: root/internal/casino/craps_rules.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-10-03 00:51:41 -0400
committerhistoria <[not public]>2026-10-03 00:51:41 -0400
commit82e571d227feeafd0af4011e701ce26b99c5e3d9 (patch)
treeab4d56ddf94c3bf3b42fff5dfc2ff9a339f09113 /internal/casino/craps_rules.go
parentcac16d1725c46c82a2e62b84c93f7090b2ce0746 (diff)
downloadthehouseoficarus-82e571d227feeafd0af4011e701ce26b99c5e3d9.tar.gz
fix: craps felt and wager description cleanup
Diffstat (limited to 'internal/casino/craps_rules.go')
-rw-r--r--internal/casino/craps_rules.go53
1 files changed, 46 insertions, 7 deletions
diff --git a/internal/casino/craps_rules.go b/internal/casino/craps_rules.go
index a9e52af..60a7c0f 100644
--- a/internal/casino/craps_rules.go
+++ b/internal/casino/craps_rules.go
@@ -47,6 +47,36 @@ func crapsTrueOdds(n int) (int, int) {
return 6, 5
}
}
+
+// crapsVigUnit is the smallest stake whose true-odds profit AND 5% commission
+// are both whole credits. Buy bets pay 5% of the stake, so 20 is the base;
+// lay bets pay 5% of the profit, so the unit scales with the lay odds.
+func crapsVigUnit(kind string, n int) int {
+ if kind == "buy" {
+ return 20
+ }
+ num, den := crapsTrueOdds(n)
+ // Lay profit is stake*den/num; commission is stake*den/(20*num).
+ d := 20 * num
+ return d / gcd(den, d)
+}
+
+func gcd(a, b int) int {
+ for b != 0 {
+ a, b = b, a%b
+ }
+ return a
+}
+
+// roundUpTo returns the smallest multiple of unit that is at least n. A stake
+// that misses the exact payout/commission unit is nudged up rather than
+// rejected, since single-credit differences are noise at table stakes.
+func roundUpTo(n, unit int) int {
+ if unit <= 1 {
+ return n
+ }
+ return ((n + unit - 1) / unit) * unit
+}
func (c CrapsConfig) oddsLimit(n int, against bool) int {
if c.Odds > 0 {
return c.Odds
@@ -66,6 +96,15 @@ func (c CrapsConfig) oddsLimit(n int, against bool) int {
return 5
}
}
+
+// oddsDisplay is the felt label for the free-odds cap: a uniform Nx cap, or
+// the classic 3-4-5x schedule when the config leaves Odds unset.
+func (c CrapsConfig) oddsDisplay() string {
+ if c.Odds > 0 {
+ return fmt.Sprintf("%dx", c.Odds)
+ }
+ return "3x-4x-5x"
+}
func (c TableConfig) CrapsRulesText() string {
r := c.Craps.Normalize()
if r.variant() != "bank" && r.variant() != "diceless" {
@@ -80,19 +119,19 @@ func (c TableConfig) CrapsRulesText() string {
odds = fmt.Sprintf("%dx", r.Odds)
}
return prefix + fmt.Sprintf("Bank Craps | Free odds %s | Field 12 pays %d:1\n"+
- "bet <amount> on pass / dontpass / come / dontcome / field\n"+
- "bet <amount> on place 6 / buy 4 / lay 10 / hard 8 / hop 2 3\n"+
- "bet <amount> on seven / craps / eleven / ace-deuce / aces / boxcars / horn\n"+
- "bet <amount> on odds pass / odds come 6 (also dontpass/dontcome)\n"+
- "bet <amount> on fire / small / tall / all (before shooter's first roll only)\n"+
+ "bet <n> on pass / dontpass / come / dontcome / field\n"+
+ "bet <n> on place 6 / buy 4 / lay 10 / hard 8 / hop 2 3\n"+
+ "bet <n> on seven / craps / eleven / ace-deuce / aces / boxcars / horn\n"+
+ "bet <n> on odds pass / odds come 6 (also dontpass/dontcome)\n"+
+ "bet <n> on fire / small / tall / all (before shooter's first roll only)\n"+
"Pass/come 1:1; don't bars 12. Place 4/10 9:5, 5/9 7:5, 6/8 7:6.\n"+
- "Buy/lay true odds; 5%% commission on buy STAKE / lay WIN, rounded up, wins only.\n"+
+ "Buy/lay true odds; 5%% commission on buy STAKE / lay WIN, rounded down, wins only.\n"+
"Field 2 pays 2:1; 3/4/9/10/11 pay 1:1. Hard 4/10 7:1; 6/8 9:1.\n"+
"Seven 4:1; craps 7:1; 11/3 15:1; 2/12 30:1; hop easy 15:1, hard 30:1.\n"+
"Horn splits equally across 2/3/11/12. Fire: 4/5/6 distinct made points pay 24/249/999:1.\n"+
"Small (2-6) / Tall (8-12) pay 34:1; All pays 175:1. Any 7 resets ATS.\n"+
"Place/buy/hard and come odds are OFF on come-out; lay and don't odds work.\n"+
- "Exact payout units required; no fractional-credit rounding except commission.\n"+
+ "Stakes round up to the next exact payout/vig unit; commission never rounds up.\n"+
"Solo: roll anytime. Multiplayer: 10 ticks to bet, then 60 ticks for the shooter.\n"+
"Bets remain open until the roll. Dice rotate on seven-out.\n"+
"autoroll: repeat every 3 ticks on your turn (multiplayer waits 10 ticks).\n"+