def hand(self, state: State) -> List[Card]: """ Get the agent's hand for this state. """ return state.get_player_hand(self.player_index)
def get_hint_rating(state: State, hint: CommandHint) -> HintStat: """ For the given hint, give it a score based on what it can accomplish. """ # Get the prior information. hand = state.get_player_hand(hint.target_index) observed_matrix = generate_observed_matrix(state, hint.target_index, hint.player_index) # HintStat is how we store this hint's effectiveness. hint_stat = HintStat() for card in hand: # Get the probability matrix for the known state, before and after. original_matrix = get_card_matrix(state, hint.target_index, card.observed_color, card.observed_number, observed_matrix=observed_matrix) post_matrix = original_matrix # Simulate a color hint. if hint.color is not None and hint.color == card.color: if not card.hint_received_color: _set_hint_success(card, hint_stat, state) post_matrix = get_card_matrix(state, hint.target_index, hint.color, card.observed_number, observed_matrix=observed_matrix) # Simulate a number hint. if hint.number is not None and hint.number == card.number: if not card.hint_received_number: _set_hint_success(card, hint_stat, state) post_matrix = get_card_matrix(state, hint.target_index, card.observed_color, hint.number, observed_matrix=observed_matrix) if not card.hint_received_number and hint.number == 5: hint_stat.vital_reveal += 1 gain = post_matrix.rating_play - original_matrix.rating_play discard_gain = post_matrix.rating_discard - original_matrix.rating_discard if post_matrix.rating_play > 0.99 and gain > 0: hint_stat.enables_play += 1 if post_matrix.rating_discard > 0.99 and discard_gain > 0: hint_stat.enables_discard += 1 hint_stat.total_play_gain += gain hint_stat.total_discard_gain += discard_gain hint_stat.max_play_gain = max(gain, hint_stat.max_play_gain) hint_stat.max_discard_gain = max(gain, hint_stat.max_discard_gain) return hint_stat
def get_rating_play(state: State, c: Color, n: int) -> float: """ Get a rating for this card to be played. """ if state.is_card_playable(Card(n, c)): return 1.0 return 0.0
def get_rating_discard(state: State, c: Color, n: int) -> float: """ Get the discard rating for this card. """ return state.get_discard_score(Card(n, c))
class Engine: def __init__(self): # Create the agents. self.agents: List[Agent] = [] for i in range(N_PLAYERS): self.agents.append(Agent(i)) self.command_index: int = 0 self.state: State = State() self.history: List[Command] = [] self.reset() def reset(self): """ Reset the entire state of this controller for a new game. """ self.state = State() self.history = [] self.history.append( Command("Initialize Board", "Set up the game board.")) self.state.reset(len(self.agents), Card.generate_deck(), N_HINT_TOKENS_MAX, N_FUSE_TOKENS_MAX) self.command_index: int = 0 @property def latest_command_index(self) -> int: """ Get the index of the latest command. """ return len(self.history) - 1 def add_command(self, command: Command): """ Add a command to the history list.""" self.history.append(command) self.set_command_index(self.latest_command_index) def play(self) -> bool: """ Execute a turn in the game. """ # First, step to the latest command. self.set_command_index(self.latest_command_index) if self.state.game_ended: return True # Play out the command. agent = self.agents[self.state.player_index] commands = agent.play_command(self.state) for c in commands: self.add_command(c) # Switch the player. self.add_command(CommandNextPlayer()) # Check for game ending. if self.state.game_ended: self.history.append(Command("Game Over", "The game is over.")) print(f"Game Ended. Score: {self.state.score}") return True return False def set_command_index(self, index: int) -> None: """ Scrub the state of this game to the specified command index. """ while self.command_index != index: if self.command_index < index: self.command_index += 1 self.history[self.command_index].forward(self.state) else: self.history[self.command_index].back(self.state) self.command_index -= 1