Repository: skent259/crapssim

Issue:
PlaceInside strategy is slightly off from table conventions
Place bets are not automatically turned "off" when the shooter is on the come-out (after making the point). This goes against the typical casino style. It won't add bets but we need to remove them when point is off. 

Source of the problem is that the default strategy mode is "ADD_IF_POINT_ON" but that does not subsequently "REMOVE" them when the point is off. 

Issue likely needs a different strategy mode name, noting the subtle difference between "add if point on" and "bet if point on" which could both be useful (i.e. if some players do keep their place bets working but don't add them while the point is off). 

Affects all strategies that use BetPlace underneath (including IronCross)

Hints from issue comments:

Solution patch:
diff --git a/crapssim/strategy/__init__.py b/crapssim/strategy/__init__.py
index 54b48f8..af40017 100644
--- a/crapssim/strategy/__init__.py
+++ b/crapssim/strategy/__init__.py
@@ -14,13 +14,14 @@ from crapssim.strategy.odds import (
 )
 from crapssim.strategy.single_bet import BetDontPass, BetPassLine, BetPlace
 from crapssim.strategy.tools import (
+    AddIfNewShooter,
+    AddIfNotBet,
+    AddIfPointOff,
+    AddIfPointOn,
+    AddIfTrue,
     AggregateStrategy,
-    BetIfTrue,
-    BetNewShooter,
-    BetPointOff,
-    BetPointOn,
     CountStrategy,
-    IfBetNotExist,
+    RemoveIfPointOff,
     RemoveIfTrue,
     Strategy,
 )
diff --git a/crapssim/strategy/examples.py b/crapssim/strategy/examples.py
index dd16d6a..d6ce800 100644
--- a/crapssim/strategy/examples.py
+++ b/crapssim/strategy/examples.py
@@ -18,12 +18,12 @@ from crapssim.strategy.single_bet import (
     StrategyMode,
 )
 from crapssim.strategy.tools import (
+    AddIfNotBet,
+    AddIfPointOff,
+    AddIfPointOn,
+    AddIfTrue,
     AggregateStrategy,
-    BetIfTrue,
-    BetPointOff,
-    BetPointOn,
     CountStrategy,
-    IfBetNotExist,
     Player,
     RemoveByType,
     RemoveIfTrue,
@@ -234,7 +234,7 @@ class Place68Move59(Strategy):
                 continue
 
             if len([x for x in player.bets if isinstance(x, Place)]) < 2:
-                IfBetNotExist(bet).update_bets(player)
+                AddIfNotBet(bet).update_bets(player)
 
     def __repr__(self) -> str:
         return (
@@ -349,7 +349,7 @@ class Place682Come(AggregateStrategy):
 class IronCross(AggregateStrategy):
     """Strategy that bets the PassLine, bets the PassLine Odds, and bets Place on the 5, 6, and 8.
     If the point is on and there is no bet on the field, place a bet on the field. Equivalent to:
-    BetPassLine(...) + PassLineOddsMultiplier(2), + BetPlace({...}) + BetPointOn(Field(...))
+    BetPassLine(...) + PassLineOddsMultiplier(2), + BetPlace({...}) + AddIfPointOn(Field(...))
     """
 
     def __init__(self, base_amount: float):
@@ -374,7 +374,7 @@ class IronCross(AggregateStrategy):
             BetPassLine(base_amount),
             PassLineOddsMultiplier(2),
             BetPlace(place_amounts, skip_point=True),
-            BetPointOn(Field(base_amount)),
+            AddIfPointOn(Field(base_amount)),
         )
 
     def __repr__(self) -> str:
@@ -459,12 +459,8 @@ class HammerLock(Strategy):
     def pass_and_dontpass(self, player: Player) -> None:
         """Update bets when point is Off: add a PassLine and a DontPass bet if they don't already exist."""
         RemoveByType(Place).update_bets(player)
-        BetPassLine(self.base_amount, StrategyMode.ADD_IF_NON_EXISTENT).update_bets(
-            player
-        )
-        BetDontPass(self.base_amount, StrategyMode.ADD_IF_NON_EXISTENT).update_bets(
-            player
-        )
+        BetPassLine(self.base_amount, StrategyMode.ADD_IF_NOT_BET).update_bets(player)
+        BetDontPass(self.base_amount, StrategyMode.ADD_IF_NOT_BET).update_bets(player)
 
     def place68(self, player: Player) -> None:
         """Update bets to Place the 6 and 8 (regardless of the point) and then lay odds on DontPass bets."""
@@ -540,8 +536,8 @@ class Risk12(Strategy):
         player
             The player to check the bets for.
         """
-        IfBetNotExist(PassLine(5)).update_bets(player)
-        IfBetNotExist(Field(5)).update_bets(player)
+        AddIfNotBet(PassLine(5)).update_bets(player)
+        AddIfNotBet(Field(5)).update_bets(player)
 
     def point_on(self, player: Player) -> None:
         """If your winnings were enough to cover the place bets (throwing in another dollar for
@@ -554,9 +550,9 @@ class Risk12(Strategy):
         """
         if self.pre_point_winnings >= 6 - 1:
             if player.table.point.number != 6:
-                IfBetNotExist(Place(6, 6)).update_bets(player)
+                AddIfNotBet(Place(6, 6)).update_bets(player)
             else:
-                IfBetNotExist(Place(8, 6)).update_bets(player)
+                AddIfNotBet(Place(8, 6)).update_bets(player)
         if self.pre_point_winnings >= 12 - 2:
             BetPlace({6: 6, 8: 6}).update_bets(player)
 
@@ -579,7 +575,7 @@ class Knockout(AggregateStrategy):
     """PassLine and Don't bet prior to point, 345x PassLine Odds after point.
 
     Equivalent to:
-    BetPassLine(amount) + BetPointOff(DontPass(amount)) +
+    BetPassLine(amount) + AddIfPointOff(DontPass(amount)) +
     PassLineOddsMultiplier({4: 3, 5: 4, 6: 5, 8: 5, 9: 4, 10: 3})
     """
 
@@ -587,7 +583,7 @@ class Knockout(AggregateStrategy):
         self.base_amount = float(base_amount)
         super().__init__(
             BetPassLine(base_amount),
-            BetPointOff(DontPass(base_amount)),
+            AddIfPointOff(DontPass(base_amount)),
             PassLineOddsMultiplier({4: 3, 5: 4, 6: 5, 8: 5, 9: 4, 10: 3}),
         )
 
@@ -741,7 +737,7 @@ class Place68DontCome2Odds(AggregateStrategy):
         self.dont_come_amount = float(dont_come_amount)
         super().__init__(
             BetPlace({6: six_eight_amount, 8: six_eight_amount}, skip_point=False),
-            BetIfTrue(
+            AddIfTrue(
                 DontCome(dont_come_amount),
                 lambda p: len(p.get_bets_by_type((DontCome,))) == 0,
             ),
diff --git a/crapssim/strategy/single_bet.py b/crapssim/strategy/single_bet.py
index 096d9dd..b8632f0 100644
--- a/crapssim/strategy/single_bet.py
+++ b/crapssim/strategy/single_bet.py
@@ -21,23 +21,25 @@ from crapssim.bet import (
     Yo,
 )
 from crapssim.strategy.tools import (
-    BetIfTrue,
-    BetNewShooter,
-    BetPointOff,
-    BetPointOn,
-    IfBetNotExist,
+    AddIfNewShooter,
+    AddIfNotBet,
+    AddIfPointOff,
+    AddIfPointOn,
+    AddIfTrue,
     Player,
+    RemoveIfPointOff,
     RemoveIfTrue,
     Strategy,
 )
 
 
 class StrategyMode(enum.Enum):
-    ADD_IF_NON_EXISTENT = enum.auto()
+    ADD_IF_NOT_BET = enum.auto()
     ADD_IF_POINT_OFF = enum.auto()
     ADD_IF_POINT_ON = enum.auto()
     ADD_IF_NEW_SHOOTER = enum.auto()
     ADD_OR_INCREASE = enum.auto()
+    BET_IF_POINT_ON = enum.auto()
     REPLACE = enum.auto()
 
 
@@ -45,7 +47,7 @@ class _BaseSingleBet(Strategy):
     def __init__(
         self,
         bet: Bet,
-        mode: StrategyMode = StrategyMode.ADD_IF_NON_EXISTENT,
+        mode: StrategyMode = StrategyMode.ADD_IF_NOT_BET,
     ):
         super().__init__()
         self.bet = bet
@@ -58,21 +60,26 @@ class _BaseSingleBet(Strategy):
         if not self.bet.is_allowed(player):
             return
 
-        if self.mode == StrategyMode.ADD_IF_NON_EXISTENT:
-            BetIfTrue(self.bet, lambda p: self.bet not in p.bets).update_bets(player)
-        elif self.mode == StrategyMode.ADD_IF_POINT_ON:
-            BetPointOn(self.bet).update_bets(player)
-        elif self.mode == StrategyMode.ADD_IF_POINT_OFF:
-            BetPointOff(self.bet).update_bets(player)
-        elif self.mode == StrategyMode.ADD_IF_NEW_SHOOTER:
-            BetNewShooter(self.bet).update_bets(player)
-        elif self.mode == StrategyMode.ADD_OR_INCREASE:
-            player.add_bet(self.bet)
-        elif self.mode == StrategyMode.REPLACE:
-            existing_bets = player.already_placed_bets(self.bet)
-            for bet in existing_bets:
-                player.remove_bet(bet)
-            player.add_bet(self.bet)
+        match self.mode:
+            case StrategyMode.ADD_IF_NOT_BET:
+                AddIfNotBet(self.bet).update_bets(player)
+            case StrategyMode.ADD_IF_POINT_ON:
+                AddIfPointOn(self.bet).update_bets(player)
+            case StrategyMode.ADD_IF_POINT_OFF:
+                AddIfPointOff(self.bet).update_bets(player)
+            case StrategyMode.ADD_IF_NEW_SHOOTER:
+                AddIfNewShooter(self.bet).update_bets(player)
+            case StrategyMode.ADD_OR_INCREASE:
+                player.add_bet(self.bet)
+            case StrategyMode.BET_IF_POINT_ON:
+                AddIfPointOn(self.bet).update_bets(player)
+                # If only betting when point on, also need to turn off when point off
+                RemoveIfPointOff(self.bet).update_bets(player)
+            case StrategyMode.REPLACE:
+                existing_bets = player.already_placed_bets(self.bet)
+                for bet in existing_bets:
+                    player.remove_bet(bet)
+                player.add_bet(self.bet)
 
     def __repr__(self) -> str:
         return (
@@ -88,7 +95,7 @@ class BetPlace(Strategy):
     def __init__(
         self,
         place_bet_amounts: dict[int, float],
-        mode: StrategyMode = StrategyMode.ADD_IF_POINT_ON,
+        mode: StrategyMode = StrategyMode.BET_IF_POINT_ON,
         skip_point: bool = True,
         skip_come: bool = False,
     ):
@@ -217,7 +224,7 @@ class BetHardWay(_BaseSingleBet):
         self,
         number: tuple[int],
         bet_amount: typing.SupportsFloat,
-        mode=StrategyMode.ADD_IF_NON_EXISTENT,
+        mode=StrategyMode.ADD_IF_NOT_BET,
     ):
         if number not in [4, 6, 8, 10]:
             raise NotImplementedError
@@ -235,7 +242,7 @@ class BetField(_BaseSingleBet):
     def __init__(
         self,
         bet_amount: typing.SupportsFloat,
-        mode=StrategyMode.ADD_IF_NON_EXISTENT,
+        mode=StrategyMode.ADD_IF_NOT_BET,
     ):
         super().__init__(Field(bet_amount), mode=mode)
 
@@ -244,7 +251,7 @@ class BetAny7(_BaseSingleBet):
     def __init__(
         self,
         bet_amount: typing.SupportsFloat,
-        mode=StrategyMode.ADD_IF_NON_EXISTENT,
+        mode=StrategyMode.ADD_IF_NOT_BET,
     ):
         super().__init__(Any7(bet_amount), mode=mode)
 
@@ -253,7 +260,7 @@ class BetTwo(_BaseSingleBet):
     def __init__(
         self,
         bet_amount: typing.SupportsFloat,
-        mode=StrategyMode.ADD_IF_NON_EXISTENT,
+        mode=StrategyMode.ADD_IF_NOT_BET,
     ):
         super().__init__(Two(bet_amount), mode=mode)
 
@@ -262,7 +269,7 @@ class BetThree(_BaseSingleBet):
     def __init__(
         self,
         bet_amount: typing.SupportsFloat,
-        mode=StrategyMode.ADD_IF_NON_EXISTENT,
+        mode=StrategyMode.ADD_IF_NOT_BET,
     ):
         super().__init__(Three(bet_amount), mode=mode)
 
@@ -271,7 +278,7 @@ class BetYo(_BaseSingleBet):
     def __init__(
         self,
         bet_amount: typing.SupportsFloat,
-        mode=StrategyMode.ADD_IF_NON_EXISTENT,
+        mode=StrategyMode.ADD_IF_NOT_BET,
     ):
         super().__init__(Yo(bet_amount), mode=mode)
 
@@ -280,11 +287,11 @@ class BetBoxcars(_BaseSingleBet):
     def __init__(
         self,
         bet_amount: typing.SupportsFloat,
-        mode=StrategyMode.ADD_IF_NON_EXISTENT,
+        mode=StrategyMode.ADD_IF_NOT_BET,
     ):
         super().__init__(Boxcars(bet_amount), mode=mode)
 
 
 class BetFire(_BaseSingleBet):
-    def __init__(self, bet_amount: float, mode=StrategyMode.ADD_IF_NON_EXISTENT):
+    def __init__(self, bet_amount: float, mode=StrategyMode.ADD_IF_NOT_BET):
         super().__init__(Fire(bet_amount), mode=mode)
diff --git a/crapssim/strategy/tools.py b/crapssim/strategy/tools.py
index bcefe02..78277e2 100644
--- a/crapssim/strategy/tools.py
+++ b/crapssim/strategy/tools.py
@@ -7,7 +7,7 @@ import typing
 from abc import ABC, abstractmethod
 from typing import Protocol
 
-from crapssim.bet import Bet
+from crapssim.bet import Bet, HardWay, Place
 from crapssim.dice import Dice
 from crapssim.point import Point
 
@@ -141,7 +141,7 @@ class NullStrategy(Strategy):
         return f"{self.__class__.__name__}()"
 
 
-class BetIfTrue(Strategy):
+class AddIfTrue(Strategy):
     """Strategy that places a bet if a given key taking Player as a parameter is True."""
 
     def __init__(self, bet: Bet, key: typing.Callable[[Player], bool]):
@@ -288,9 +288,9 @@ class ReplaceIfTrue(Strategy):
         )
 
 
-class IfBetNotExist(BetIfTrue):
+class AddIfNotBet(AddIfTrue):
     """Strategy that adds a bet if it isn't on the table for that player. Equivalent of
-    BetIfTrue(bet, lambda p: bet not in p.bets)"""
+    AddIfTrue(bet, lambda p: bet not in p.bets)"""
 
     def __init__(self, bet: Bet):
         """The strategy adds the given bet object to the table if it is not already on the table.
@@ -306,9 +306,9 @@ class IfBetNotExist(BetIfTrue):
         return f"{self.__class__.__name__}(bet={self.bet})"
 
 
-class BetPointOff(BetIfTrue):
+class AddIfPointOff(AddIfTrue):
     """Strategy that adds a bet if the table point is Off, and the Player doesn't have a bet on the
-    table. Equivalent to BetIfTrue(bet, lambda p: p.table.point.status == "Off"
+    table. Equivalent to AddIfTrue(bet, lambda p: p.table.point.status == "Off"
                                         and bet not in p.bets)"""
 
     def __init__(self, bet: Bet):
@@ -328,9 +328,9 @@ class BetPointOff(BetIfTrue):
         return f"{self.__class__.__name__}(bet={self.bet})"
 
 
-class BetPointOn(BetIfTrue):
+class AddIfPointOn(AddIfTrue):
     """Strategy that adds a bet if the table point is On, and the Player doesn't have a bet on the
-    table. Equivalent to BetIfTrue(bet, lambda p: p.table.point.status == "On"
+    table. Equivalent to AddIfTrue(bet, lambda p: p.table.point.status == "On"
                                         and bet not in p.bets)"""
 
     def __init__(self, bet: Bet):
@@ -349,9 +349,9 @@ class BetPointOn(BetIfTrue):
         return f"{self.__class__.__name__}(bet={self.bet})"
 
 
-class BetNewShooter(BetIfTrue):
+class AddIfNewShooter(AddIfTrue):
     """Strategy that adds a bet if there is a new shooter at the table, and the Player doesn't have a bet on the
-    table. Equivalent to BetIfTrue(bet, lambda p: p.table.new_shooter and bet not in p.bets)
+    table. Equivalent to AddIfTrue(bet, lambda p: p.table.new_shooter and bet not in p.bets)
     """
 
     def __init__(self, bet: Bet):
@@ -368,7 +368,7 @@ class BetNewShooter(BetIfTrue):
         return f"{self.__class__.__name__}(bet={self.bet})"
 
 
-class CountStrategy(BetIfTrue):
+class CountStrategy(AddIfTrue):
     """Strategy that checks how many bets exist of a certain type. If the number of bets of that
     type is less than the given count, it places the bet (if the bet isn't already on the table.)
     """
@@ -422,6 +422,37 @@ class CountStrategy(BetIfTrue):
         )
 
 
+class RemoveIfPointOff(RemoveIfTrue):
+    """Strategy that removes a bet if the table point is Off
+
+    This will match bets based on type, and number for Place and Hardway bets.
+    It will not consider bet amounts when matching."""
+
+    def __init__(self, bet: Bet):
+        if isinstance(bet, Place):
+            key = (
+                lambda b, p: isinstance(b, Place)
+                and b.number == self.bet.number
+                and p.table.point.status == "Off"
+            )
+        elif isinstance(bet, HardWay):
+            key = (
+                lambda b, p: isinstance(b, HardWay)
+                and b.number == self.bet.number
+                and p.table.point.status == "Off"
+            )
+        else:
+            key = (
+                lambda b, p: isinstance(b, type(self.bet))
+                and p.table.point.status == "Off"
+            )
+        super().__init__(key)
+        self.bet = bet
+
+    def __repr__(self) -> str:
+        return f"{self.__class__.__name__}(bet={self.bet})"
+
+
 class RemoveByType(RemoveIfTrue):
     """Remove any bets that are of the given type(s)."""
 
@@ -497,7 +528,7 @@ class WinProgression(Strategy):
             new_bet.amount = (
                 self.bet.amount * self.multipliers[self.current_progression]
             )
-        IfBetNotExist(new_bet).update_bets(player)
+        AddIfNotBet(new_bet).update_bets(player)
 
     def __repr__(self) -> str:
         return f"{self.__class__.__name__}(first_bet={self.bet}, multipliers={self.multipliers})"
diff --git a/docs/tutorial-strategy-01.ipynb b/docs/tutorial-strategy-01.ipynb
index 67d7c6d..a281136 100644
--- a/docs/tutorial-strategy-01.ipynb
+++ b/docs/tutorial-strategy-01.ipynb
@@ -79,7 +79,7 @@
     "| `BetDontPass()` | crapssim.strategy            | ADD_IF_POINT_OFF    |                                                |\n",
     "| `BetCome()`     | crapssim.strategy.single_bet | ADD_IF_POINT_ON     |                                                |\n",
     "| `BetDontCome()` | crapssim.strategy.single_bet | ADD_IF_POINT_ON     |                                                |\n",
-    "| `BetPlace()`    | crapssim.strategy            | ADD_IF_POINT_ON     | `place_bet_amounts`; `skip_point`; `skip_come` |\n",
+    "| `BetPlace()`    | crapssim.strategy            | BET_IF_POINT_ON   | `place_bet_amounts`; `skip_point`; `skip_come` |\n",
     "| `BetHardWay()`  | crapssim.strategy.single_bet | ADD_IF_NON_EXISTENT | `number`                                       |\n",
     "| `BetField()`    | crapssim.strategy.single_bet | ADD_IF_NON_EXISTENT |                                                |\n",
     "| `BetAny7()`     | crapssim.strategy.single_bet | ADD_IF_NON_EXISTENT |                                                |\n",
@@ -136,6 +136,7 @@
     "- `ADD_IF_POINT_ON`: Adds a bet only if the point is on\n",
     "- `ADD_IF_NEW_SHOOTER`: Adds a bet only if there is a new shooter (i.e. the previous player has just seven-ed out)\n",
     "- `ADD_OR_INCREASE`: After each roll of the dice, the bet will be added (if it doesn't exist) or the bet amount will be increased by one unit (if it already exists)\n",
+    "- `BET_IF_POINT_ON`: Player bets only if the point is on (i.e. also removes the bets when point is off, in contrast to `ADD_IF_POINT_ON`). Useful for place bets which typically are not working when the point is off. \n",
     "- `REPLACE`: Will remove all bets of this type (when possible) before adding a new one. This mode is less useful, so don't worry if it's confusing now\n",
     "\n",
     "The following example shows how to change the strategy mode, by showing two different players at the table that both bet the Yo, but at different times. "
@@ -192,7 +193,7 @@
     "For place bets, there are four arguments: \n",
     "\n",
     "- `place_bet_amounts`: Dictionary of the point to make the Place bet on and the amount of the place bet to make. Replaces `bet_amount` argument.\n",
-    "- `mode`: same as before. Defaults to `StrategyMode.ADD_IF_POINT_ON`\n",
+    "- `mode`: same as before. Defaults to `StrategyMode.BET_IF_POINT_ON`\n",
     "- `skip_point`: If True don't make the bet on the given Place if that's the number the tables Point is on. Default is True.\n",
     "- `skip_come`: If True don't make the bet on the given Place if there is a Come bet with that Point already on that number. Default is False.\n",
     "\n",
@@ -225,7 +226,7 @@
     "strategies = [\n",
     "    BetPlace({6: 12, 8: 12}, skip_point=False),\n",
     "    BetPlace({5: 10, 6: 12, 8: 12, 9: 10}, skip_point=True),\n",
-    "    BetPlace({4: 10, 5: 10, 6: 12, 8: 24, 9: 20, 10: 20}, mode=StrategyMode.ADD_IF_NON_EXISTENT, skip_point=False)\n",
+    "    BetPlace({4: 10, 5: 10, 6: 12, 8: 24, 9: 20, 10: 20}, mode=StrategyMode.ADD_IF_NOT_BET, skip_point=False)\n",
     "]\n",
     "\n",
     "for i, s in enumerate(strategies):\n",


Test patch:
diff --git a/tests/integration/test_ironcross_integration.py b/tests/integration/test_ironcross_integration.py
index e77c248..42fd6de 100644
--- a/tests/integration/test_ironcross_integration.py
+++ b/tests/integration/test_ironcross_integration.py
@@ -65,7 +65,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(8, amount=12.0)],
             (1, 5),
-            [Place(5, amount=10.0), Place(8, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             9,
@@ -209,12 +209,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(6, amount=12.0), Place(5, amount=10.0), Place(8, amount=12.0)],
             (5, 4),
-            [
-                Place(6, amount=12.0),
-                Place(5, amount=10.0),
-                Place(8, amount=12.0),
-                PassLine(amount=5.0),
-            ],
+            [PassLine(amount=5.0)],
         ),
         (
             4,
@@ -351,7 +346,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(8, amount=12.0)],
             (5, 1),
-            [Place(5, amount=10.0), Place(8, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             None,
@@ -359,7 +354,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(8, amount=12.0)],
             (5, 6),
-            [Place(5, amount=10.0), Place(8, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             6,
@@ -400,7 +395,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(8, amount=12.0)],
             (3, 3),
-            [Place(5, amount=10.0), Place(8, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             9,
@@ -457,7 +452,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(6, amount=12.0)],
             (3, 5),
-            [Place(5, amount=10.0), Place(6, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             6,
@@ -479,7 +474,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(8, amount=12.0)],
             (2, 4),
-            [Place(5, amount=10.0), Place(8, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             8,
@@ -554,7 +549,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(6, amount=12.0)],
             (2, 6),
-            [Place(5, amount=10.0), Place(6, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             9,
@@ -1722,7 +1717,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(6, amount=12.0), Place(8, amount=12.0)],
             (4, 1),
-            [Place(6, amount=12.0), Place(8, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             6,
@@ -1778,7 +1773,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(8, amount=12.0)],
             (2, 4),
-            [Place(5, amount=10.0), Place(8, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             6,
@@ -2119,12 +2114,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(6, amount=12.0), Place(8, amount=12.0)],
             (5, 4),
-            [
-                Place(5, amount=10.0),
-                Place(6, amount=12.0),
-                Place(8, amount=12.0),
-                PassLine(amount=5.0),
-            ],
+            [PassLine(amount=5.0)],
         ),
         (
             9,
@@ -2332,7 +2322,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(8, amount=12.0)],
             (2, 4),
-            [Place(5, amount=10.0), Place(8, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             6,
@@ -2428,7 +2418,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(8, amount=12.0), Place(5, amount=10.0)],
             (3, 3),
-            [Place(8, amount=12.0), Place(5, amount=10.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             None,
@@ -2436,7 +2426,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(8, amount=12.0), Place(5, amount=10.0)],
             (6, 5),
-            [Place(8, amount=12.0), Place(5, amount=10.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             9,
@@ -2459,12 +2449,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(8, amount=12.0), Place(5, amount=10.0), Place(6, amount=12.0)],
             (4, 5),
-            [
-                Place(8, amount=12.0),
-                Place(5, amount=10.0),
-                Place(6, amount=12.0),
-                PassLine(amount=5.0),
-            ],
+            [PassLine(amount=5.0)],
         ),
         (
             4,
@@ -2560,7 +2545,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(8, amount=12.0)],
             (1, 5),
-            [Place(5, amount=10.0), Place(8, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             9,
@@ -2583,12 +2568,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(8, amount=12.0), Place(6, amount=12.0)],
             (3, 6),
-            [
-                Place(5, amount=10.0),
-                Place(8, amount=12.0),
-                Place(6, amount=12.0),
-                PassLine(amount=5.0),
-            ],
+            [PassLine(amount=5.0)],
         ),
         (
             8,
@@ -3042,7 +3022,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(8, amount=12.0), Place(6, amount=12.0)],
             (2, 3),
-            [Place(8, amount=12.0), Place(6, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             None,
@@ -3050,7 +3030,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(8, amount=12.0), Place(6, amount=12.0)],
             (6, 5),
-            [Place(8, amount=12.0), Place(6, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             9,
@@ -3381,12 +3361,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(8, amount=12.0), Place(6, amount=12.0)],
             (4, 5),
-            [
-                Place(5, amount=10.0),
-                Place(8, amount=12.0),
-                Place(6, amount=12.0),
-                PassLine(amount=5.0),
-            ],
+            [PassLine(amount=5.0)],
         ),
         (
             4,
@@ -3542,7 +3517,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(6, amount=12.0), Place(8, amount=12.0)],
             (4, 1),
-            [Place(6, amount=12.0), Place(8, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             None,
@@ -3550,7 +3525,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(6, amount=12.0), Place(8, amount=12.0)],
             (2, 1),
-            [Place(6, amount=12.0), Place(8, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             10,
@@ -3666,7 +3641,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(8, amount=12.0)],
             (4, 2),
-            [Place(5, amount=10.0), Place(8, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             6,
@@ -3743,12 +3718,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(6, amount=12.0), Place(8, amount=12.0)],
             (4, 5),
-            [
-                Place(5, amount=10.0),
-                Place(6, amount=12.0),
-                Place(8, amount=12.0),
-                PassLine(amount=5.0),
-            ],
+            [PassLine(amount=5.0)],
         ),
         (
             5,
@@ -3846,7 +3816,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(6, amount=12.0)],
             (5, 3),
-            [Place(5, amount=10.0), Place(6, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             4,
@@ -4095,12 +4065,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(8, amount=12.0), Place(6, amount=12.0)],
             (1, 3),
-            [
-                Place(5, amount=10.0),
-                Place(8, amount=12.0),
-                Place(6, amount=12.0),
-                PassLine(amount=5.0),
-            ],
+            [PassLine(amount=5.0)],
         ),
         (
             None,
@@ -4108,12 +4073,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(8, amount=12.0), Place(6, amount=12.0)],
             (2, 1),
-            [
-                Place(5, amount=10.0),
-                Place(8, amount=12.0),
-                Place(6, amount=12.0),
-                PassLine(amount=5.0),
-            ],
+            [PassLine(amount=5.0)],
         ),
         (
             6,
@@ -4323,7 +4283,7 @@ from crapssim.table import Table, TableUpdate
             None,
             [Place(5, amount=10.0), Place(8, amount=12.0)],
             (4, 2),
-            [Place(5, amount=10.0), Place(8, amount=12.0), PassLine(amount=5.0)],
+            [PassLine(amount=5.0)],
         ),
         (
             6,
diff --git a/tests/integration/test_strategy.py b/tests/integration/test_strategy.py
index d529cec..2825272 100644
--- a/tests/integration/test_strategy.py
+++ b/tests/integration/test_strategy.py
@@ -3,8 +3,8 @@ import pytest
 from crapssim import Table
 from crapssim.bet import Come, DontCome, DontPass, Field, Fire, Odds, PassLine, Place
 from crapssim.strategy import (
+    AddIfTrue,
     BetDontPass,
-    BetIfTrue,
     BetPassLine,
     BetPlace,
     DontPassOddsMultiplier,
@@ -21,10 +21,11 @@ from crapssim.strategy.examples import (
     Place68DontCome2Odds,
     Place68PR,
     Place682Come,
+    PlaceInside,
     Risk12,
 )
 from crapssim.strategy.single_bet import BetFire
-from crapssim.strategy.tools import BetIfTrue, BetNewShooter, WinProgression
+from crapssim.strategy.tools import AddIfNewShooter, AddIfTrue, WinProgression
 from crapssim.table import TableUpdate
 
 
@@ -236,7 +237,7 @@ from crapssim.table import TableUpdate
             ],
         ),
         (
-            BetIfTrue(
+            AddIfTrue(
                 bet=PassLine(amount=5.0), key=lambda p: p.table.point.status == "Off"
             ),
             [],
@@ -350,9 +351,8 @@ def test_strategies_compare_bets(
 
 def test_strategies_in_simulation_persistent_features():
 
-    n_sim = 100
     bankroll = 100
-    strategies = {"Fire 1": BetNewShooter(Fire(1)), "Fire 2": BetFire(1)}
+    strategies = {"Fire 1": AddIfNewShooter(Fire(1)), "Fire 2": BetFire(1)}
 
     # Simulation 1, five fire points hit
     outcomes = [
@@ -391,3 +391,44 @@ def test_strategies_in_simulation_persistent_features():
         print(f"{p.name}, {p.bankroll}, {bankroll}, {table.dice.n_rolls}")
 
     assert p.bankroll == bankroll - 1
+
+
+def test_placeinside_with_betpointon():
+
+    bankroll = 100
+    strategy = PlaceInside(10)
+
+    # Simulation 1, point hit, then come-out seven, nothing should happen
+    outcomes = [
+        (2, 2),
+        (2, 2),
+        (1, 6),  # come-out seven, should not lose
+    ]
+    table = Table()
+    table.add_player(bankroll, strategy)
+
+    table.fixed_run(outcomes, verbose=False)
+    for p in table.players:
+        print(f"{p.name}, {p.bankroll}, {bankroll}, {table.dice.n_rolls}")
+
+    assert p.total_player_cash == bankroll
+    assert p.bets == []
+
+    # Simulation 2, point hit, then come-out seven, reset point and win one
+    outcomes = [
+        (2, 2),
+        (2, 2),
+        (1, 6),  # come-out seven, should not lose
+        (3, 3),
+        (4, 4),  # 8 wins
+        (1, 2),
+    ]
+    table = Table()
+    table.add_player(bankroll, strategy)
+
+    table.fixed_run(outcomes, verbose=True)
+    for p in table.players:
+        print(f"{p.name}, {p.bankroll}, {bankroll}, {table.dice.n_rolls}")
+
+    assert p.total_player_cash == bankroll + 14
+    assert len(p.bets) == 4
diff --git a/tests/integration/verified_table_output.txt b/tests/integration/verified_table_output.txt
index 0d3f024..de66aa7 100644
--- a/tests/integration/verified_table_output.txt
+++ b/tests/integration/verified_table_output.txt
@@ -1,6 +1,6 @@
 Welcome to the Craps Table!
 Player 0: Strategy=BetPassLine(bet_amount=5.0, mode=StrategyMode.ADD_IF_POINT_OFF) + PassLineOddsMultiplier(odds_multiplier=2), Bankroll=100.0
-Player 1: Strategy=BetPlace(place_bet_amounts={5: 10, 6: 12, 8: 12, 4: 10}, mode=StrategyMode.ADD_IF_POINT_ON, skip_point=True, skip_come=False), Bankroll=1000.0
+Player 1: Strategy=BetPlace(place_bet_amounts={5: 10, 6: 12, 8: 12, 4: 10}, mode=StrategyMode.BET_IF_POINT_ON, skip_point=True, skip_come=False), Bankroll=1000.0
 
 
 Player 0: Bankroll=95.0, Bet amount=5.0, Bets=[PassLine(amount=5.0)]
@@ -91,40 +91,39 @@ Player 0 won $5.0 on PassLine(amount=5.0)!
 Player 0 won $12.0 on Odds(base_type=crapssim.bet.PassLine, number=8, amount=10.0)!
 Point is Off (None)
 Player 0: Bankroll=87.0, Bet amount=5.0, Bets=[PassLine(amount=5.0)]
-Player 1: Bankroll=940.0, Bet amount=32.0, Bets=[Place(5, amount=10.0), Place(6, amount=12.0), Place(4, amount=10.0)]
+Player 1: Bankroll=972.0, Bet amount=0, Bets=[]
 
 Dice out!
 Shooter rolled 3 (1, 2)
 Player 0 lost $5.0 on PassLine(amount=5.0).
 Point is Off (None)
 Player 0: Bankroll=82.0, Bet amount=5.0, Bets=[PassLine(amount=5.0)]
-Player 1: Bankroll=940.0, Bet amount=32.0, Bets=[Place(5, amount=10.0), Place(6, amount=12.0), Place(4, amount=10.0)]
+Player 1: Bankroll=972.0, Bet amount=0, Bets=[]
 
 Dice out!
 Shooter rolled 5 (3, 2)
-Player 1 won $14.0 on Place(5, amount=10.0)!
 Point is On (5)
 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)]
-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)]
+Player 1: Bankroll=938.0, Bet amount=34.0, Bets=[Place(6, amount=12.0), Place(8, amount=12.0), Place(4, amount=10.0)]
 
 Dice out!
 Shooter rolled 11 (6, 5)
 Point is On (5)
 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)]
-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)]
+Player 1: Bankroll=938.0, Bet amount=34.0, Bets=[Place(6, amount=12.0), Place(8, amount=12.0), Place(4, amount=10.0)]
 
 Dice out!
 Shooter rolled 8 (5, 3)
 Player 1 won $14.0 on Place(8, amount=12.0)!
 Point is On (5)
 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)]
-Player 1: Bankroll=966.0, Bet amount=34.0, Bets=[Place(6, amount=12.0), Place(4, amount=10.0), Place(8, amount=12.0)]
+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)]
 
 Dice out!
 Shooter rolled 3 (1, 2)
 Point is On (5)
 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)]
-Player 1: Bankroll=966.0, Bet amount=34.0, Bets=[Place(6, amount=12.0), Place(4, amount=10.0), Place(8, amount=12.0)]
+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)]
 
 Dice out!
 Shooter rolled 7 (3, 4)
@@ -135,18 +134,18 @@ Player 1 lost $10.0 on Place(4, amount=10.0).
 Player 1 lost $12.0 on Place(8, amount=12.0).
 Point is Off (None)
 Player 0: Bankroll=67.0, Bet amount=5.0, Bets=[PassLine(amount=5.0)]
-Player 1: Bankroll=966.0, Bet amount=0, Bets=[]
+Player 1: Bankroll=952.0, Bet amount=0, Bets=[]
 
 Dice out!
 Shooter rolled 7 (3, 4)
 Player 0 won $5.0 on PassLine(amount=5.0)!
 Point is Off (None)
 Player 0: Bankroll=72.0, Bet amount=5.0, Bets=[PassLine(amount=5.0)]
-Player 1: Bankroll=966.0, Bet amount=0, Bets=[]
+Player 1: Bankroll=952.0, Bet amount=0, Bets=[]
 
 Dice out!
 Shooter rolled 7 (3, 4)
 Player 0 won $5.0 on PassLine(amount=5.0)!
 Point is Off (None)
 Player 0: Bankroll=82.0, Bet amount=0, Bets=[]
-Player 1: Bankroll=966.0, Bet amount=0, Bets=[]
+Player 1: Bankroll=952.0, Bet amount=0, Bets=[]
diff --git a/tests/unit/test_strategy.py b/tests/unit/test_strategy.py
index 0db309a..25d39a0 100644
--- a/tests/unit/test_strategy.py
+++ b/tests/unit/test_strategy.py
@@ -19,14 +19,14 @@ from crapssim.bet import (
     Place,
 )
 from crapssim.strategy import (
+    AddIfNewShooter,
+    AddIfNotBet,
+    AddIfPointOff,
+    AddIfPointOn,
+    AddIfTrue,
     AggregateStrategy,
-    BetIfTrue,
-    BetNewShooter,
     BetPlace,
-    BetPointOff,
-    BetPointOn,
     CountStrategy,
-    IfBetNotExist,
     RemoveIfTrue,
     Strategy,
 )
@@ -43,7 +43,7 @@ from crapssim.strategy.examples import (
 )
 from crapssim.strategy.odds import OddsAmount, OddsMultiplier
 from crapssim.strategy.single_bet import StrategyMode, _BaseSingleBet
-from crapssim.strategy.tools import RemoveByType, ReplaceIfTrue
+from crapssim.strategy.tools import RemoveByType, RemoveIfPointOff, ReplaceIfTrue
 
 
 @pytest.fixture
@@ -186,7 +186,7 @@ def example_bet():
 @pytest.fixture
 def bet_if_true(example_bet):
     key = MagicMock(return_value=True)
-    return BetIfTrue(example_bet, key)
+    return AddIfTrue(example_bet, key)
 
 
 def test_bet_if_true_key_is_called(bet_if_true, player):
@@ -209,7 +209,7 @@ def test_player_add_bet_is_not_called_if_key_is_true(bet_if_true, player):
 
 def test_bet_if_true_repr(bet_if_true):
     assert (
-        repr(bet_if_true) == f"BetIfTrue(bet={bet_if_true.bet}, key={bet_if_true.key})"
+        repr(bet_if_true) == f"AddIfTrue(bet={bet_if_true.bet}, key={bet_if_true.key})"
     )
 
 
@@ -324,7 +324,7 @@ def test_if_bet_not_exists_bet_doesnt_exist_add_bet(player):
     bet2 = MagicMock()
     player.bets = [bet1]
     player.add_bet = MagicMock()
-    strategy = IfBetNotExist(bet2)
+    strategy = AddIfNotBet(bet2)
     strategy.update_bets(player)
     player.add_bet.assert_called_once_with(bet2)
 
@@ -334,22 +334,22 @@ def test_if_bet_exists_dont_add_bet(player):
     bet2 = MagicMock()
     player.bets = [bet1, bet2]
     player.add_bet = MagicMock()
-    strategy = IfBetNotExist(bet2)
+    strategy = AddIfNotBet(bet2)
     strategy.update_bets(player)
     player.add_bet.assert_not_called()
 
 
 def test_if_bet_not_exist_repr(player):
     bet = MagicMock()
-    strategy = IfBetNotExist(bet)
-    assert repr(strategy) == f"IfBetNotExist(bet={bet})"
+    strategy = AddIfNotBet(bet)
+    assert repr(strategy) == f"AddIfNotBet(bet={bet})"
 
 
 def test_bet_point_off_add_bet(player):
     player.table.point.number = None
     player.add_bet = MagicMock()
     bet = MagicMock()
-    strategy = BetPointOff(bet)
+    strategy = AddIfPointOff(bet)
     strategy.update_bets(player)
     player.add_bet.assert_called_with(bet)
 
@@ -358,7 +358,7 @@ def test_bet_point_off_dont_add_bet(player):
     player.table.point.number = 6
     player.add_bet = MagicMock()
     bet = MagicMock()
-    strategy = BetPointOff(bet)
+    strategy = AddIfPointOff(bet)
     strategy.update_bets(player)
     player.add_bet.assert_not_called()
 
@@ -367,7 +367,7 @@ def test_bet_point_on_add_bet(player):
     player.table.point.number = 9
     player.add_bet = MagicMock()
     bet = MagicMock()
-    strategy = BetPointOn(bet)
+    strategy = AddIfPointOn(bet)
     strategy.update_bets(player)
     player.add_bet.assert_called_with(bet)
 
@@ -376,7 +376,7 @@ def test_bet_point_on_dont_add_bet(player):
     player.table.point.number = None
     player.add_bet = MagicMock()
     bet = MagicMock()
-    strategy = BetPointOn(bet)
+    strategy = AddIfPointOn(bet)
     strategy.update_bets(player)
     player.add_bet.assert_not_called()
 
@@ -385,7 +385,7 @@ def test_bet_new_shooter_add_bet(player):
     player.table.new_shooter = True
     player.add_bet = MagicMock()
     bet = MagicMock()
-    strategy = BetNewShooter(bet)
+    strategy = AddIfNewShooter(bet)
     strategy.update_bets(player)
     player.add_bet.assert_called_with(bet)
 
@@ -394,7 +394,7 @@ def test_bet_new_shooter_dont_add_bet(player):
     player.table.new_shooter = False
     player.add_bet = MagicMock()
     bet = MagicMock()
-    strategy = BetNewShooter(bet)
+    strategy = AddIfNewShooter(bet)
     strategy.update_bets(player)
     player.add_bet.assert_not_called()
 
@@ -450,6 +450,30 @@ def test_count_strategy_key_fails_too_many_bets(player):
     assert not strategy.key(player)
 
 
+def test_remove_if_point_off_repr(player):
+    bet = MagicMock()
+    strategy = RemoveIfPointOff(bet)
+    assert repr(strategy) == f"RemoveIfPointOff(bet={bet})"
+
+
+def test_remove_if_point_off_remove_bet(player):
+    player.table.point.number = None
+    player.remove_bet = MagicMock()
+    bet = MagicMock()
+    strategy = RemoveIfPointOff(bet)
+    strategy.update_bets(player)
+    player.add_bet.assert_called_with(bet)
+
+
+def test_remove_if_point_off_remove_bet(player):
+    player.table.point.number = 6
+    player.remove_bet = MagicMock()
+    bet = MagicMock()
+    strategy = RemoveIfPointOff(bet)
+    strategy.update_bets(player)
+    player.remove_bet.assert_not_called()
+
+
 def test_remove_by_type_remove_bet_called(player):
     strategy = RemoveByType(PassLine)
     player.remove_bet = MagicMock()
@@ -590,6 +614,24 @@ def test_base_single_bet_replace(player):
     player.add_bet.assert_called_once_with(PassLine(5))
 
 
+def test_base_single_bet_bet_point_on_when_point_on(player):
+    strategy = _BaseSingleBet(Place(4, 5), StrategyMode.BET_IF_POINT_ON)
+    player.table.point.number = 6
+    player.add_bet = MagicMock()
+    strategy.update_bets(player)
+    player.add_bet.assert_called_once_with(Place(4, 5))
+
+
+def test_base_single_bet_bet_point_on_when_point_off(player):
+    strategy = _BaseSingleBet(Place(4, 5), StrategyMode.BET_IF_POINT_ON)
+    player.table.point.number = None
+    player.bets = [Place(4, 5)]
+    player.add_bet = MagicMock()
+    player.remove_bet = MagicMock()
+    strategy.update_bets(player)
+    player.remove_bet.assert_called_once_with(Place(4, 5))
+
+
 def test_bet_place_remove_point_bet(player):
     strategy = BetPlace({5: 5})
     player.bets = [Place(5, 5)]
@@ -1183,7 +1225,7 @@ def test_place_68_cpr_update_bets_initial_bets_placed_no_update(player):
         # Single bet strategies
         (
             crapssim.strategy.BetPlace({6: 6, 8: 6}),
-            "BetPlace(place_bet_amounts={6: 6, 8: 6}, mode=StrategyMode.ADD_IF_POINT_ON, skip_point=True, skip_come=False)",
+            "BetPlace(place_bet_amounts={6: 6, 8: 6}, mode=StrategyMode.BET_IF_POINT_ON, skip_point=True, skip_come=False)",
         ),
         (
             crapssim.strategy.BetPassLine(1),
@@ -1203,47 +1245,47 @@ def test_place_68_cpr_update_bets_initial_bets_placed_no_update(player):
         ),
         (
             crapssim.strategy.single_bet.BetHardWay(4, 1),
-            "BetHardWay(4, bet_amount=1.0, mode=StrategyMode.ADD_IF_NON_EXISTENT)",
+            "BetHardWay(4, bet_amount=1.0, mode=StrategyMode.ADD_IF_NOT_BET)",
         ),
         (
             crapssim.strategy.single_bet.BetHardWay(6, 1),
-            "BetHardWay(6, bet_amount=1.0, mode=StrategyMode.ADD_IF_NON_EXISTENT)",
+            "BetHardWay(6, bet_amount=1.0, mode=StrategyMode.ADD_IF_NOT_BET)",
         ),
         (
             crapssim.strategy.single_bet.BetHardWay(8, 1),
-            "BetHardWay(8, bet_amount=1.0, mode=StrategyMode.ADD_IF_NON_EXISTENT)",
+            "BetHardWay(8, bet_amount=1.0, mode=StrategyMode.ADD_IF_NOT_BET)",
         ),
         (
             crapssim.strategy.single_bet.BetHardWay(10, 1),
-            "BetHardWay(10, bet_amount=1.0, mode=StrategyMode.ADD_IF_NON_EXISTENT)",
+            "BetHardWay(10, bet_amount=1.0, mode=StrategyMode.ADD_IF_NOT_BET)",
         ),
         (
             crapssim.strategy.single_bet.BetField(1),
-            "BetField(bet_amount=1.0, mode=StrategyMode.ADD_IF_NON_EXISTENT)",
+            "BetField(bet_amount=1.0, mode=StrategyMode.ADD_IF_NOT_BET)",
         ),
         (
             crapssim.strategy.single_bet.BetAny7(1),
-            "BetAny7(bet_amount=1.0, mode=StrategyMode.ADD_IF_NON_EXISTENT)",
+            "BetAny7(bet_amount=1.0, mode=StrategyMode.ADD_IF_NOT_BET)",
         ),
         (
             crapssim.strategy.single_bet.BetTwo(1),
-            "BetTwo(bet_amount=1.0, mode=StrategyMode.ADD_IF_NON_EXISTENT)",
+            "BetTwo(bet_amount=1.0, mode=StrategyMode.ADD_IF_NOT_BET)",
         ),
         (
             crapssim.strategy.single_bet.BetThree(1),
-            "BetThree(bet_amount=1.0, mode=StrategyMode.ADD_IF_NON_EXISTENT)",
+            "BetThree(bet_amount=1.0, mode=StrategyMode.ADD_IF_NOT_BET)",
         ),
         (
             crapssim.strategy.single_bet.BetYo(1),
-            "BetYo(bet_amount=1.0, mode=StrategyMode.ADD_IF_NON_EXISTENT)",
+            "BetYo(bet_amount=1.0, mode=StrategyMode.ADD_IF_NOT_BET)",
         ),
         (
             crapssim.strategy.single_bet.BetBoxcars(1),
-            "BetBoxcars(bet_amount=1.0, mode=StrategyMode.ADD_IF_NON_EXISTENT)",
+            "BetBoxcars(bet_amount=1.0, mode=StrategyMode.ADD_IF_NOT_BET)",
         ),
         (
             crapssim.strategy.single_bet.BetFire(1),
-            "BetFire(bet_amount=1.0, mode=StrategyMode.ADD_IF_NON_EXISTENT)",
+            "BetFire(bet_amount=1.0, mode=StrategyMode.ADD_IF_NOT_BET)",
         ),
         # Example strategies
         (crapssim.strategy.examples.Pass2Come(1), "Pass2Come(amount=1.0)"),