diff --git a/pyproject.toml b/pyproject.toml index 295e147..c5d88a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,9 +48,8 @@ lint.ignore = [ "ERA001", # (perm) I don't care about print statements dir ] "python/splendor/**" = [ - "S311", # (perm) there is no security issue here - "T201", # (perm) I don't care about print statements dir - "PLR2004", # (temps) need to think about this + "S311", # (perm) there is no security issue here + "T201", # (perm) I don't care about print statements dir ] "python/orm/**" = [ "TC003", # (perm) this creates issues because sqlalchemy uses these at runtime diff --git a/python/splendor/bot.py b/python/splendor/bot.py index ee438be..07c9a09 100644 --- a/python/splendor/bot.py +++ b/python/splendor/bot.py @@ -34,6 +34,11 @@ def can_bot_afford(player: PlayerState, card: Card) -> bool: return True +_BUY_PROBABILITY = 0.5 +_RESERVE_PROBABILITY = 0.2 +_TAKE_DOUBLE_PROBABILITY = 0.5 + + class RandomBot(Strategy): """Dumb bot that follows rules but doesn't think.""" @@ -48,19 +53,19 @@ class RandomBot(Strategy): for idx, card in enumerate(row): if can_bot_afford(player, card): affordable.append((tier, idx)) - if affordable and random.random() < 0.5: + if affordable and random.random() < _BUY_PROBABILITY: tier, idx = random.choice(affordable) return BuyCard(tier=tier, index=idx) - if random.random() < 0.2: + if random.random() < _RESERVE_PROBABILITY: tier = random.choice([1, 2, 3]) row = game.table_by_tier.get(tier, []) if row: idx = random.randrange(len(row)) return ReserveCard(tier=tier, index=idx, from_deck=False) - if random.random() < 0.5: - colors_for_double = [c for c in BASE_COLORS if game.bank[c] >= 4] + if random.random() < _TAKE_DOUBLE_PROBABILITY: + colors_for_double = [c for c in BASE_COLORS if game.bank[c] >= game.config.minimum_tokens_to_buy_2] if colors_for_double: return TakeDouble(color=random.choice(colors_for_double)) @@ -137,16 +142,16 @@ class PersonalizedBot2(Strategy): return BuyCardReserved(index=index) colors_for_diff = [c for c in BASE_COLORS if game.bank[c] > 0] - if len(colors_for_diff) >= 3: + if len(colors_for_diff) >= game.config.max_token_take: random.shuffle(colors_for_diff) - return TakeDifferent(colors=colors_for_diff[:3]) + return TakeDifferent(colors=colors_for_diff[: game.config.max_token_take]) for tier in tiers: len_deck = len(game.decks_by_tier[tier]) if len_deck: return ReserveCard(tier=tier, index=None, from_deck=True) - return TakeDifferent(colors=colors_for_diff[:3]) + return TakeDifferent(colors=colors_for_diff[: game.config.max_token_take]) def choose_discard( self, @@ -179,7 +184,7 @@ def buy_card(game: GameState, player: PlayerState) -> Action | None: def take_tokens(game: GameState) -> Action | None: """Take tokens.""" colors_for_diff = [color for color in BASE_COLORS if game.bank[color] > 0] - if len(colors_for_diff) >= 3: + if len(colors_for_diff) >= game.config.max_token_take: random.shuffle(colors_for_diff) return TakeDifferent(colors=colors_for_diff[: game.config.max_token_take]) return None @@ -204,16 +209,16 @@ class PersonalizedBot3(Strategy): return action colors_for_diff = [color for color in BASE_COLORS if game.bank[color] > 0] - if len(colors_for_diff) >= 3: + if len(colors_for_diff) >= game.config.max_token_take: random.shuffle(colors_for_diff) - return TakeDifferent(colors=colors_for_diff[:3]) + return TakeDifferent(colors=colors_for_diff[: game.config.max_token_take]) for tier in (1, 2, 3): len_deck = len(game.decks_by_tier[tier]) if len_deck: return ReserveCard(tier=tier, index=None, from_deck=True) - return TakeDifferent(colors=colors_for_diff[:3]) + return TakeDifferent(colors=colors_for_diff[: game.config.max_token_take]) def choose_discard( self, @@ -242,12 +247,13 @@ class PersonalizedBot4(Strategy): """Initialize the bot.""" super().__init__(name=name) - def filter_actions(self, actions: list[Action]) -> list[Action]: + def filter_actions(self, actions: list[Action], max_token_take: int) -> list[Action]: """Filter actions to only take different.""" return [ action for action in actions - if (isinstance(action, TakeDifferent) and len(action.colors) == 3) or not isinstance(action, TakeDifferent) + if (isinstance(action, TakeDifferent) and len(action.colors) == max_token_take) + or not isinstance(action, TakeDifferent) ] def choose_action(self, game: GameState, player: PlayerState) -> Action | None: @@ -255,7 +261,7 @@ class PersonalizedBot4(Strategy): legal_actions = get_legal_actions(game, player) print(len(legal_actions)) - good_actions = self.filter_actions(legal_actions) + good_actions = self.filter_actions(legal_actions, game.config.max_token_take) print(len(good_actions)) print(good_actions) @@ -267,16 +273,16 @@ class PersonalizedBot4(Strategy): return action colors_for_diff = [color for color in BASE_COLORS if game.bank[color] > 0] - if len(colors_for_diff) >= 3: + if len(colors_for_diff) >= game.config.max_token_take: random.shuffle(colors_for_diff) - return TakeDifferent(colors=colors_for_diff[:3]) + return TakeDifferent(colors=colors_for_diff[: game.config.max_token_take]) for tier in (1, 2, 3): len_deck = len(game.decks_by_tier[tier]) if len_deck: return ReserveCard(tier=tier, index=None, from_deck=True) - return TakeDifferent(colors=colors_for_diff[:3]) + return TakeDifferent(colors=colors_for_diff[: game.config.max_token_take]) def choose_discard( self, diff --git a/python/splendor/human.py b/python/splendor/human.py index e955a69..88c8acb 100644 --- a/python/splendor/human.py +++ b/python/splendor/human.py @@ -407,7 +407,7 @@ class ActionApp(App[None]): def _cmd_2(self, parts: list[str]) -> str | None: """Take two of the same color.""" - if len(parts) < 2: + if len(parts) < 2: # noqa: PLR2004 return "Usage: 2 " color = parse_color_token(parts[1]) if self.game.bank[color] < self.game.config.minimum_tokens_to_buy_2: @@ -418,7 +418,7 @@ class ActionApp(App[None]): def _cmd_3(self, parts: list[str]) -> str | None: """Buy face-up card.""" - if len(parts) < 3: + if len(parts) < 3: # noqa: PLR2004 return "Usage: 3 " tier = int(parts[1]) idx = int(parts[2]) @@ -428,7 +428,7 @@ class ActionApp(App[None]): def _cmd_4(self, parts: list[str]) -> str | None: """Buy reserved card.""" - if len(parts) < 2: + if len(parts) < 2: # noqa: PLR2004 return "Usage: 4 " idx = int(parts[1]) if not (0 <= idx < len(self.player.reserved)): @@ -439,7 +439,7 @@ class ActionApp(App[None]): def _cmd_5(self, parts: list[str]) -> str | None: """Reserve face-up card.""" - if len(parts) < 3: + if len(parts) < 3: # noqa: PLR2004 return "Usage: 5 " tier = int(parts[1]) idx = int(parts[2]) @@ -449,7 +449,7 @@ class ActionApp(App[None]): def _cmd_6(self, parts: list[str]) -> str | None: """Reserve top of deck.""" - if len(parts) < 2: + if len(parts) < 2: # noqa: PLR2004 return "Usage: 6 " tier = int(parts[1]) self.result = ReserveCard(tier=tier, index=None, from_deck=True)