import time from dataclasses import dataclass from bot_ai import BotAi from engine import EngineHandler, LiarsDiceEngine, Bid @dataclass class MyEngineHandler(EngineHandler): state: LiarsDiceEngine | None player_names: list[str] bot_ai: BotAi def is_current_player_numan(self): return self.state.active_player_index == 0 def on_game_started(self, game_state: LiarsDiceEngine): self.state = game_state print(f"Ahoy, challenger! You're playing against {', '.join(self.player_names[1:])}.") print() def on_bid_placed(self, bid: Bid): print( f"{self.player_names[self.state.active_player_index]} " f"bid{'s' if self.state.active_player_index != 0 else ''} " f"{bid.num_dice}x{bid.die_face}{'s' if bid.num_dice > 1 else ''}!" ) def on_challenge_bid(self): bid_owner = ( self.player_names[self.state.active_player_index - 1] + "'s" if self.is_current_player_numan() else "your" ) print( f"\n{self.player_names[self.state.active_player_index]} " f"challenge{'' if self.is_current_player_numan() else 's'} " f"{bid_owner} bid... " f"{'unsuccessfully' if self.state.is_current_bid_successful() else 'SUCCESSFULLY'}!" ) print(f"Your dice: {', '.join(str(d) for d in sorted(self.state.dice[0].elements()))}") for i in range(1, len(self.player_names)): print( f"{self.player_names[i]}'s dice: {', '.join(str(d) for d in sorted(self.state.dice[i].elements()))}" ) time.sleep(2) def on_new_round(self): print(f"\n--- Round {self.state.round_number} ---\n") print(f"Your dice: {', '.join(str(d) for d in sorted(self.state.dice[0].elements()))}") for i in range(1, len(self.player_names)): total = self.state.dice[i].total() print(f"{self.player_names[i]}'s has {total} {'die' if total == 1 else 'dice'} left.") print() def on_player_eliminated(self, player_index: int) -> None: human_player_eliminated = player_index == 0 print( f"*** {self.player_names[player_index]} {'have' if human_player_eliminated else 'has'} been eliminated!\n" ) self.player_names = [n for (i, n) in enumerate(self.player_names) if i != player_index] if len(self.player_names) == 1: print( f"+++ {self.player_names[0]} {'is' if human_player_eliminated else 'are'} the winner!\n" ) def get_players_turn(self) -> Bid | None: if self.is_current_player_numan(): return self.get_human_turn_input() else: return self.bot_ai.ai_turn(self.state) def get_human_turn_input(self): include_challenge_option = bool(self.state.current_bid) help_message = ( "Please use the input format of NX, whereby N is the number of dice and X is the die face of" "the bid. Example: '43' means a bid of 3 dice with the 'four' face." ) while True: bid_text = input( f"Your bid [{{NX}}{'/L' if include_challenge_option else ''}/?]: " ).lower() if bid_text == "?": print(f"\n{help_message}\n") if include_challenge_option and bid_text == "l": return None if len(bid_text) == 2 and bid_text.isdigit(): num_dice = int(bid_text[0]) die_face = int(bid_text[1]) if die_face < 1 or die_face > 6: print( "\nProper pirates only use d6'es, please chose a dice face appropriately! (1-6)" ) continue return Bid(die_face=die_face, num_dice=num_dice) print("\nInvalid bid!") print(help_message)