From 7c56954cdac60fb3e159b6bf55b68a30eef08784 Mon Sep 17 00:00:00 2001 From: Richie Cahill Date: Sat, 29 Nov 2025 13:23:16 -0500 Subject: [PATCH] get splendor code ruff complient --- pyproject.toml | 5 +++-- python/splendor/base.py | 3 ++- python/splendor/bot.py | 37 ++++++++++++++++++++++++++++----- python/splendor/human.py | 10 ++++----- python/splendor/main.py | 2 ++ python/splendor/public_state.py | 8 +++++++ python/splendor/sim.py | 5 ++++- python/splendor/simulat.py | 3 ++- 8 files changed, 58 insertions(+), 15 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6bc8e6c..505490d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,8 +49,9 @@ lint.ignore = [ ] "python/splendor/**" = [ - "S311", # (perm) there is no security issue here - "T201", # (perm) I don't care about print statements dir + "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 ] [tool.ruff.lint.pydocstyle] diff --git a/python/splendor/base.py b/python/splendor/base.py index 5aa7d6d..dc3b16a 100644 --- a/python/splendor/base.py +++ b/python/splendor/base.py @@ -471,7 +471,8 @@ def apply_action(game: GameState, strategy: Strategy, action: Action) -> None: action_func(game, strategy, action) -def get_legal_actions( +# not sure how to simplify this yet +def get_legal_actions( # noqa: C901 game: GameState, player: PlayerState | None = None, ) -> list[Action]: diff --git a/python/splendor/bot.py b/python/splendor/bot.py index ef10a95..7c86190 100644 --- a/python/splendor/bot.py +++ b/python/splendor/bot.py @@ -38,9 +38,11 @@ class RandomBot(Strategy): """Dumb bot that follows rules but doesn't think.""" def __init__(self, name: str) -> None: + """Initialize the bot.""" super().__init__(name=name) def choose_action(self, game: GameState, player: PlayerState) -> Action | None: + """Choose an action for the current player.""" affordable: list[tuple[int, int]] = [] for tier, row in game.table_by_tier.items(): for idx, card in enumerate(row): @@ -68,17 +70,21 @@ class RandomBot(Strategy): def choose_discard( self, - game: GameState, + game: GameState, # noqa: ARG002 player: PlayerState, excess: int, ) -> dict[GemColor, int]: + """Choose how many tokens to discard.""" return auto_discard_tokens(player, excess) class PersonalizedBot(Strategy): + """PersonalizedBot.""" + """Dumb bot that follows rules but doesn't think.""" def __init__(self, name: str) -> None: + """Initialize the bot.""" super().__init__(name=name) def check_cards_in_tier(self, row: list[Card], player: PlayerState) -> bool: @@ -86,6 +92,7 @@ class PersonalizedBot(Strategy): return [index for index, card in enumerate(row) if can_bot_afford(player, card)] def choose_action(self, game: GameState, player: PlayerState) -> Action | None: + """Choose an action for the current player.""" for tier in (1, 2, 3): row = game.table_by_tier[tier] if affordable := check_cards_in_tier(row, player): @@ -98,10 +105,11 @@ class PersonalizedBot(Strategy): def choose_discard( self, - game: GameState, + game: GameState, # noqa: ARG002 player: PlayerState, excess: int, ) -> dict[GemColor, int]: + """Choose how many tokens to discard.""" return auto_discard_tokens(player, excess) @@ -111,12 +119,16 @@ def check_cards_in_tier(row: list[Card], player: PlayerState) -> bool: class PersonalizedBot2(Strategy): + """PersonalizedBot2.""" + """Dumb bot that follows rules but doesn't think.""" def __init__(self, name: str) -> None: + """Initialize the bot.""" super().__init__(name=name) def choose_action(self, game: GameState, player: PlayerState) -> Action | None: + """Choose an action for the current player.""" tiers = (1, 2, 3) for tier in tiers: row = game.table_by_tier[tier] @@ -142,14 +154,16 @@ class PersonalizedBot2(Strategy): def choose_discard( self, - game: GameState, + game: GameState, # noqa: ARG002 player: PlayerState, excess: int, ) -> dict[GemColor, int]: + """Choose how many tokens to discard.""" return auto_discard_tokens(player, excess) def buy_card_reserved(player: PlayerState) -> Action | None: + """Buy a card reserved.""" if affordable := check_cards_in_tier(player.reserved, player): index = random.choice(affordable) return BuyCardReserved(index=index) @@ -157,6 +171,7 @@ def buy_card_reserved(player: PlayerState) -> Action | None: def buy_card(game: GameState, player: PlayerState) -> Action | None: + """Buy a card.""" for tier in (1, 2, 3): row = game.table_by_tier[tier] if affordable := check_cards_in_tier(row, player): @@ -166,6 +181,7 @@ def buy_card(game: GameState, player: PlayerState) -> Action | None: def take_toekns(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: random.shuffle(colors_for_diff) @@ -174,12 +190,16 @@ def take_toekns(game: GameState) -> Action | None: class PersonalizedBot3(Strategy): + """PersonalizedBot3.""" + """Dumb bot that follows rules but doesn't think.""" def __init__(self, name: str) -> None: + """Initialize the bot.""" super().__init__(name=name) def choose_action(self, game: GameState, player: PlayerState) -> Action | None: + """Choose an action for the current player.""" print(len(get_legal_actions(game, player))) print(get_legal_actions(game, player)) if action := buy_card_reserved(player): @@ -201,10 +221,11 @@ class PersonalizedBot3(Strategy): def choose_discard( self, - game: GameState, + game: GameState, # noqa: ARG002 player: PlayerState, excess: int, ) -> dict[GemColor, int]: + """Choose how many tokens to discard.""" return auto_discard_tokens(player, excess) @@ -219,10 +240,14 @@ def estimate_value_of_token(game: GameState, player: PlayerState, color: GemColo class PersonalizedBot4(Strategy): + """PersonalizedBot4.""" + def __init__(self, name: str) -> None: + """Initialize the bot.""" super().__init__(name=name) def filter_actions(self, actions: list[Action]) -> list[Action]: + """Filter actions to only take different.""" return [ action for action in actions @@ -230,6 +255,7 @@ class PersonalizedBot4(Strategy): ] def choose_action(self, game: GameState, player: PlayerState) -> Action | None: + """Choose an action for the current player.""" legal_actions = get_legal_actions(game, player) print(len(legal_actions)) @@ -258,8 +284,9 @@ class PersonalizedBot4(Strategy): def choose_discard( self, - game: GameState, + game: GameState, # noqa: ARG002 player: PlayerState, excess: int, ) -> dict[GemColor, int]: + """Choose how many tokens to discard.""" return auto_discard_tokens(player, excess) diff --git a/python/splendor/human.py b/python/splendor/human.py index 88c8acb..e955a69 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: # noqa: PLR2004 + if len(parts) < 2: 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: # noqa: PLR2004 + if len(parts) < 3: 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: # noqa: PLR2004 + if len(parts) < 2: 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: # noqa: PLR2004 + if len(parts) < 3: 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: # noqa: PLR2004 + if len(parts) < 2: return "Usage: 6 " tier = int(parts[1]) self.result = ReserveCard(tier=tier, index=None, from_deck=True) diff --git a/python/splendor/main.py b/python/splendor/main.py index 5472378..462c582 100644 --- a/python/splendor/main.py +++ b/python/splendor/main.py @@ -1,3 +1,5 @@ +"""Main entry point for Splendor game.""" + from __future__ import annotations from .base import new_game, run_game diff --git a/python/splendor/public_state.py b/python/splendor/public_state.py index b1f8552..73904da 100644 --- a/python/splendor/public_state.py +++ b/python/splendor/public_state.py @@ -1,3 +1,5 @@ +"""Public state for RL/search.""" + from __future__ import annotations from dataclasses import dataclass @@ -25,12 +27,16 @@ class ObsCard: @dataclass(frozen=True) class ObsNoble: + """Numeric-ish noble view for RL/search.""" + points: int requirements: list[int] @dataclass(frozen=True) class ObsPlayer: + """Numeric-ish player view for RL/search.""" + tokens: list[int] discounts: list[int] score: int @@ -41,6 +47,8 @@ class ObsPlayer: @dataclass(frozen=True) class Observation: + """Full public state for RL/search.""" + current_player: int bank: list[int] players: list[ObsPlayer] diff --git a/python/splendor/sim.py b/python/splendor/sim.py index c96d704..33ce13f 100644 --- a/python/splendor/sim.py +++ b/python/splendor/sim.py @@ -1,3 +1,5 @@ +"""Simulate a step in the game.""" + from __future__ import annotations import copy @@ -13,7 +15,8 @@ class SimStrategy(RandomBot): but we reuse discard/noble-selection logic. """ - def choose_action(self, game: GameState, player: PlayerState) -> Action | None: + def choose_action(self, game: GameState, player: PlayerState) -> Action | None: # noqa: ARG002 + """Choose an action for the current player.""" msg = "SimStrategy.choose_action should not be used in simulate_step" raise RuntimeError(msg) diff --git a/python/splendor/simulat.py b/python/splendor/simulat.py index 0d3b0dc..27a8161 100644 --- a/python/splendor/simulat.py +++ b/python/splendor/simulat.py @@ -39,7 +39,8 @@ def main() -> None: winners[winner.strategy.name].append(turns) print( - f"out of {games} {turn_limit} turn games with {len(players)} random bots there where {good_games} games where a bot won" + f"out of {games} {turn_limit} turn games with {len(players)}" + f"random bots there where {good_games} games where a bot won" ) for name, turns in winners.items(): print(f"{name} won {len(turns)} games in {mean(turns):.2f} turns")