Skip to content

Commit 78e54b9

Browse files
authored
Merge pull request #83 from skent259/add-bet-string
Add `__str__` method for bets Replace `__repr__` with `__str__` in most places
2 parents 301e5c9 + 7542646 commit 78e54b9

10 files changed

Lines changed: 151 additions & 42 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
### Added
1313

14-
* New bets: `Horn`, `World` (Whirl), `Big6`/`Big8`, `Buy`, `Lay`, and `Put` (with or without odds)
14+
* New bets: `Horn`, `World` (Whirl), `Big6`/`Big8`, `Buy`, `Lay`, and `Put` (with or without odds) from [@nova-rey](https://github.com/nova-rey)
1515
* Corresponding single bet strategies
1616
* Corresponding odds strategies: `PutOddsAmount`, `PutOddsMultiplier`
1717
* Corresponding examples strategies: `QuickProps`, `BuySampler`, `LaySampler`, `PutWithOdds`
@@ -22,11 +22,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2222
* `ThreePointMolly` and `ThreePointDolly` strategies with variable odds/win mutipliers
2323
* Stress tests, expanded examples, tools as part of the Vanilla Expansion Project
2424

25+
### Changed
26+
27+
* The default printout for bets is now more compact and easy to read (the `__str__` method is defined; instead of only `__repr__`)
28+
2529
### Fixed
2630

2731
* `DontPass` and `DontCome` bets will now "push" on a come-out 12, bringing the bet down and returing the bet amount to the player. `_WinningLosingNumbersBet` gains `get_push_numbers()` method to accomodate.
2832
* The `Risk12` strategy will now take down place bets after hitting point (i.e. place bets not working), which is aligned to table conventions
29-
* `OddsMultiplier `__repr__` logic so that floats, ints, and incomplete dictionaries all work for odds/win multiplier
33+
* `OddsMultiplier` `__repr__` logic so that floats, ints, and incomplete dictionaries all work for odds/win multiplier
3034

3135
## [0.3.2] - 2025-10-11
3236

crapssim/bet.py

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,13 @@ class _MetaBetABC(ABCMeta):
116116
def __repr__(cls):
117117
return f"crapssim.bet.{cls.__name__}"
118118

119+
def __str__(cls):
120+
return f"{cls.__name__}"
121+
122+
123+
def _compact_float(x) -> str:
124+
return str(int(x)) if isinstance(x, float) and x.is_integer() else format(x, ".15g")
125+
119126

120127
class Bet(ABC, metaclass=_MetaBetABC):
121128
"""
@@ -227,6 +234,9 @@ def __sub__(self, other: "Bet") -> "Bet":
227234
def __rsub__(self, other):
228235
return self.__sub__(other)
229236

237+
def __str__(self) -> str:
238+
return f"${_compact_float(self.amount)} {self.__class__.__name__}"
239+
230240

231241
class _WinningLosingNumbersBet(Bet, ABC):
232242
"""
@@ -438,6 +448,10 @@ def _placed_key(self) -> Hashable:
438448
def __repr__(self) -> str:
439449
return f"{self.__class__.__name__}(amount={self.amount}, number={self.number})"
440450

451+
def __str__(self) -> str:
452+
number_str = f"({self.number})" if self.number is not None else ""
453+
return f"{super().__str__()}{number_str}"
454+
441455

442456
class DontPass(_WinningLosingNumbersBet):
443457
"""
@@ -547,6 +561,10 @@ def _placed_key(self) -> Hashable:
547561
def __repr__(self) -> str:
548562
return f"{self.__class__.__name__}(amount={self.amount}, number={self.number})"
549563

564+
def __str__(self) -> str:
565+
number_str = f"({self.number})" if self.number is not None else ""
566+
return f"{super().__str__()}{number_str}"
567+
550568

551569
# Odds bets -------------------------------------------------------------------
552570

@@ -663,10 +681,19 @@ def _placed_key(self) -> Hashable:
663681

664682
def __repr__(self):
665683
return (
666-
f"Odds(base_type={self.base_type}, number={self.number}, amount={self.amount}"
684+
f"Odds(base_type={self.base_type!r}, "
685+
f"number={self.number}, amount={self.amount}"
667686
f"{self._get_always_working_repr()}"
668687
)
669688

689+
def __str__(self) -> str:
690+
number_str = f", {self.number}" if self.number is not None else ""
691+
692+
if issubclass(self.base_type, (PassLine, DontPass)):
693+
return f"{super().__str__()}({self.base_type})"
694+
elif issubclass(self.base_type, (Come, Put, DontCome)):
695+
return f"{super().__str__()}({self.base_type}{number_str})"
696+
670697

671698
class Put(_SimpleBet):
672699
"""Flat line bet on a box number; point must be ON and odds obey table policy."""
@@ -692,6 +719,9 @@ def _placed_key(self) -> Hashable:
692719
def __repr__(self) -> str:
693720
return f"Put({self.number}, amount={self.amount})"
694721

722+
def __str__(self) -> str:
723+
return f"{super().__str__()}({self.number})"
724+
695725

696726
# Place bets ------------------------------------------------------------------
697727

@@ -728,6 +758,9 @@ def _placed_key(self) -> Hashable:
728758
def __repr__(self) -> str:
729759
return f"Place({self.winning_numbers[0]}, amount={self.amount})"
730760

761+
def __str__(self) -> str:
762+
return f"{super().__str__()}({self.number})"
763+
731764

732765
def _compute_vig(
733766
bet_amount: float,
@@ -815,6 +848,9 @@ def _placed_key(self) -> Hashable:
815848
def __repr__(self) -> str:
816849
return f"Buy({self.number}, amount={self.amount})"
817850

851+
def __str__(self) -> str:
852+
return f"{super().__str__()}({self.number})"
853+
818854

819855
class Lay(_SimpleBet):
820856
"""True-odds bet against 4/5/6/8/9/10, paying if 7 arrives first.
@@ -872,6 +908,9 @@ def _placed_key(self) -> Hashable:
872908
def __repr__(self) -> str:
873909
return f"Lay({self.number}, amount={self.amount})"
874910

911+
def __str__(self) -> str:
912+
return f"{super().__str__()}({self.number})"
913+
875914

876915
# _WinningLosingNumbersBets with variable payouts -----------------------------------------------------------------
877916

@@ -1178,6 +1217,9 @@ def _placed_key(self) -> Hashable:
11781217
def __repr__(self) -> str:
11791218
return f"{self.__class__.__name__}({self.number}, amount={self.amount})"
11801219

1220+
def __str__(self) -> str:
1221+
return f"{super().__str__()}({self.number})"
1222+
11811223

11821224
# Hop bets -------------------------------------------------------------------
11831225

@@ -1237,6 +1279,10 @@ def _placed_key(self) -> Hashable:
12371279
def __repr__(self) -> str:
12381280
return f"{self.__class__.__name__}({self.result}, amount={self.amount})"
12391281

1282+
def __str__(self) -> str:
1283+
result_str = f"({self.result[0]},{self.result[1]})"
1284+
return f"{super().__str__()}{result_str}"
1285+
12401286

12411287
# Fire bet -------------------------------------------------------------------
12421288

crapssim/strategy/odds.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def _get_always_working_repr(self) -> str:
8888

8989
def __repr__(self):
9090
return (
91-
f"{self.__class__.__name__}(base_type={self.base_type}, "
91+
f"{self.__class__.__name__}(base_type={self.base_type!r}, "
9292
f"odds_amounts={self.odds_amounts}"
9393
f"{self._get_always_working_repr()}"
9494
)
@@ -227,7 +227,7 @@ def _get_always_working_repr(self) -> str:
227227

228228
def __repr__(self) -> str:
229229
return (
230-
f"{self.__class__.__name__}(base_type={self.base_type}, "
230+
f"{self.__class__.__name__}(base_type={self.base_type!r}, "
231231
f"odds_multiplier={_condense_multiplier_dict(self.odds_multiplier)}"
232232
f"{self._get_always_working_repr()}"
233233
)
@@ -354,7 +354,7 @@ def _convert_win_to_odds_mult(
354354

355355
def __repr__(self) -> str:
356356
return (
357-
f"{self.__class__.__name__}(base_type={self.base_type}, "
357+
f"{self.__class__.__name__}(base_type={self.base_type!r}, "
358358
f"win_multiplier={_condense_multiplier_dict(self.win_multiplier)}"
359359
f"{self._get_always_working_repr()}"
360360
)

crapssim/strategy/tools.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,9 @@ def key(self, player: Player) -> bool:
420420

421421
def __repr__(self) -> str:
422422
return (
423-
f"{self.__class__.__name__}(bet_type={self.bet_type}, count={self.count}, "
424-
f"bet={self.bet})"
423+
f"{self.__class__.__name__}"
424+
f"(bet_type={self.bet_type!r}, count={self.count}, "
425+
f"bet={self.bet!r})"
425426
)
426427

427428

examples/run_examples.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def run_example(name, strategy_factory):
1818
print(f"Final bankroll: {player.bankroll:.2f}")
1919
# Show remaining open bets (should be few or none in these demos)
2020
if player.bets:
21-
print("Open bets:", [repr(bet) for bet in player.bets])
21+
print("Open bets:", [str(bet) for bet in player.bets])
2222

2323

2424
def main():
@@ -43,3 +43,4 @@ def main():
4343

4444
if __name__ == "__main__":
4545
main()
46+
main()

examples/run_strategy_testing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def run_scenario(rolls):
2929
# Show remaining open bets (should be few or none in these demos)
3030
# Note this does not run strategy to add/clear bets for next roll
3131
if player.bets:
32-
print("Open bets:", [repr(bet) for bet in player.bets])
32+
print("Open bets:", [str(bet) for bet in player.bets])
3333

3434

3535
def main():

tests/integration/verified_table_output.txt

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Player 1: Bankroll=1000.0, Bet amount=0, Bets=[]
88

99
Dice out! (roll 1, shooter 1)
1010
Shooter rolled 7 (5, 2)
11-
Player 0 won $5.0 on PassLine(amount=5.0)!
11+
Player 0 won $5.0 on $5 PassLine!
1212
Point is Off (None)
1313
Player 0: Bankroll=100.0, Bet amount=5.0, Bets=[PassLine(amount=5.0)]
1414
Player 1: Bankroll=1000.0, Bet amount=0, Bets=[]
@@ -21,7 +21,7 @@ Player 1: Bankroll=968.0, Bet amount=32.0, Bets=[Place(5, amount=10.0), Place(6,
2121

2222
Dice out! (roll 3, shooter 1)
2323
Shooter rolled 4 (2, 2)
24-
Player 1 won $18.0 on Place(4, amount=10.0)!
24+
Player 1 won $18.0 on $10 Place(4)!
2525
Point is On (8)
2626
Player 0: Bankroll=90.0, Bet amount=15.0, Bets=[PassLine(amount=5.0), Odds(base_type=crapssim.bet.PassLine, number=8, amount=10.0)]
2727
Player 1: Bankroll=986.0, Bet amount=32.0, Bets=[Place(5, amount=10.0), Place(6, amount=12.0), Place(4, amount=10.0)]
@@ -40,18 +40,18 @@ Player 1: Bankroll=986.0, Bet amount=32.0, Bets=[Place(5, amount=10.0), Place(6,
4040

4141
Dice out! (roll 6, shooter 1)
4242
Shooter rolled 4 (1, 3)
43-
Player 1 won $18.0 on Place(4, amount=10.0)!
43+
Player 1 won $18.0 on $10 Place(4)!
4444
Point is On (8)
4545
Player 0: Bankroll=90.0, Bet amount=15.0, Bets=[PassLine(amount=5.0), Odds(base_type=crapssim.bet.PassLine, number=8, amount=10.0)]
4646
Player 1: Bankroll=1004.0, Bet amount=32.0, Bets=[Place(5, amount=10.0), Place(6, amount=12.0), Place(4, amount=10.0)]
4747

4848
Dice out! (roll 7, shooter 1)
4949
Shooter rolled 7 (4, 3)
50-
Player 0 lost $5.0 on PassLine(amount=5.0).
51-
Player 0 lost $10.0 on Odds(base_type=crapssim.bet.PassLine, number=8, amount=10.0).
52-
Player 1 lost $10.0 on Place(5, amount=10.0).
53-
Player 1 lost $12.0 on Place(6, amount=12.0).
54-
Player 1 lost $10.0 on Place(4, amount=10.0).
50+
Player 0 lost $5.0 on $5 PassLine.
51+
Player 0 lost $10.0 on $10 Odds(PassLine).
52+
Player 1 lost $10.0 on $10 Place(5).
53+
Player 1 lost $12.0 on $12 Place(6).
54+
Player 1 lost $10.0 on $10 Place(4).
5555
Point is Off (None)
5656
Player 0: Bankroll=85.0, Bet amount=5.0, Bets=[PassLine(amount=5.0)]
5757
Player 1: Bankroll=1004.0, Bet amount=0, Bets=[]
@@ -70,11 +70,11 @@ Player 1: Bankroll=972.0, Bet amount=32.0, Bets=[Place(5, amount=10.0), Place(8,
7070

7171
Dice out! (roll 10, shooter 2)
7272
Shooter rolled 7 (4, 3)
73-
Player 0 lost $5.0 on PassLine(amount=5.0).
74-
Player 0 lost $10.0 on Odds(base_type=crapssim.bet.PassLine, number=6, amount=10.0).
75-
Player 1 lost $10.0 on Place(5, amount=10.0).
76-
Player 1 lost $12.0 on Place(8, amount=12.0).
77-
Player 1 lost $10.0 on Place(4, amount=10.0).
73+
Player 0 lost $5.0 on $5 PassLine.
74+
Player 0 lost $10.0 on $10 Odds(PassLine).
75+
Player 1 lost $10.0 on $10 Place(5).
76+
Player 1 lost $12.0 on $12 Place(8).
77+
Player 1 lost $10.0 on $10 Place(4).
7878
Point is Off (None)
7979
Player 0: Bankroll=70.0, Bet amount=5.0, Bets=[PassLine(amount=5.0)]
8080
Player 1: Bankroll=972.0, Bet amount=0, Bets=[]
@@ -87,15 +87,15 @@ Player 1: Bankroll=940.0, Bet amount=32.0, Bets=[Place(5, amount=10.0), Place(6,
8787

8888
Dice out! (roll 12, shooter 3)
8989
Shooter rolled 8 (6, 2)
90-
Player 0 won $5.0 on PassLine(amount=5.0)!
91-
Player 0 won $12.0 on Odds(base_type=crapssim.bet.PassLine, number=8, amount=10.0)!
90+
Player 0 won $5.0 on $5 PassLine!
91+
Player 0 won $12.0 on $10 Odds(PassLine)!
9292
Point is Off (None)
9393
Player 0: Bankroll=87.0, Bet amount=5.0, Bets=[PassLine(amount=5.0)]
9494
Player 1: Bankroll=972.0, Bet amount=0, Bets=[]
9595

9696
Dice out! (roll 13, shooter 3)
9797
Shooter rolled 3 (1, 2)
98-
Player 0 lost $5.0 on PassLine(amount=5.0).
98+
Player 0 lost $5.0 on $5 PassLine.
9999
Point is Off (None)
100100
Player 0: Bankroll=82.0, Bet amount=5.0, Bets=[PassLine(amount=5.0)]
101101
Player 1: Bankroll=972.0, Bet amount=0, Bets=[]
@@ -114,7 +114,7 @@ Player 1: Bankroll=938.0, Bet amount=34.0, Bets=[Place(6, amount=12.0), Place(8,
114114

115115
Dice out! (roll 16, shooter 3)
116116
Shooter rolled 8 (5, 3)
117-
Player 1 won $14.0 on Place(8, amount=12.0)!
117+
Player 1 won $14.0 on $12 Place(8)!
118118
Point is On (5)
119119
Player 0: Bankroll=72.0, Bet amount=15.0, Bets=[PassLine(amount=5.0), Odds(base_type=crapssim.bet.PassLine, number=5, amount=10.0)]
120120
Player 1: Bankroll=952.0, Bet amount=34.0, Bets=[Place(6, amount=12.0), Place(4, amount=10.0), Place(8, amount=12.0)]
@@ -127,25 +127,25 @@ Player 1: Bankroll=952.0, Bet amount=34.0, Bets=[Place(6, amount=12.0), Place(4,
127127

128128
Dice out! (roll 18, shooter 3)
129129
Shooter rolled 7 (3, 4)
130-
Player 0 lost $5.0 on PassLine(amount=5.0).
131-
Player 0 lost $10.0 on Odds(base_type=crapssim.bet.PassLine, number=5, amount=10.0).
132-
Player 1 lost $12.0 on Place(6, amount=12.0).
133-
Player 1 lost $10.0 on Place(4, amount=10.0).
134-
Player 1 lost $12.0 on Place(8, amount=12.0).
130+
Player 0 lost $5.0 on $5 PassLine.
131+
Player 0 lost $10.0 on $10 Odds(PassLine).
132+
Player 1 lost $12.0 on $12 Place(6).
133+
Player 1 lost $10.0 on $10 Place(4).
134+
Player 1 lost $12.0 on $12 Place(8).
135135
Point is Off (None)
136136
Player 0: Bankroll=67.0, Bet amount=5.0, Bets=[PassLine(amount=5.0)]
137137
Player 1: Bankroll=952.0, Bet amount=0, Bets=[]
138138

139139
Dice out! (roll 19, shooter 4)
140140
Shooter rolled 7 (3, 4)
141-
Player 0 won $5.0 on PassLine(amount=5.0)!
141+
Player 0 won $5.0 on $5 PassLine!
142142
Point is Off (None)
143143
Player 0: Bankroll=72.0, Bet amount=5.0, Bets=[PassLine(amount=5.0)]
144144
Player 1: Bankroll=952.0, Bet amount=0, Bets=[]
145145

146146
Dice out! (roll 20, shooter 4)
147147
Shooter rolled 7 (3, 4)
148-
Player 0 won $5.0 on PassLine(amount=5.0)!
148+
Player 0 won $5.0 on $5 PassLine!
149149
Point is Off (None)
150150
Player 0: Bankroll=82.0, Bet amount=0, Bets=[]
151151
Player 1: Bankroll=952.0, Bet amount=0, Bets=[]

0 commit comments

Comments
 (0)