From 0e1381c15fb829c9b4b6376875a7043d1945ff22 Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Fri, 20 May 2022 10:51:47 -0500 Subject: [PATCH] Update agent interface to accept the game state (probably a bad idea...) --- src/lib.rs | 44 +++++++++++++++++++++----------------------- src/test.rs | 10 +++++----- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ed44fce..6ff602b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -169,7 +169,7 @@ impl Player { !self.cards.is_empty() } fn wins_challenge(&self, action: Action) -> bool { - self.cards.iter().find(|&c| c.allows_action(action)).is_some() + self.cards.iter().any(|c| c.allows_action(action)) } fn lose(&mut self, card: Card, deck: &mut Vec) { @@ -178,7 +178,7 @@ impl Player { } fn holds(&self, card: Card) -> bool { - self.cards.iter().find(|&c| *c == card).is_some() + self.cards.iter().any(|c| *c == card) } } @@ -248,11 +248,10 @@ impl Game { } fn player_lose_influence(&mut self, id: usize, agents: &[&dyn Agent]) -> CoupResult<()>{ - let player = &mut self.players[id]; - let card = agents[id] - .choose_lost_influence(&player.cards); + let card = agents[id].choose_lost_influence(self); + let player = &self.players[id]; if player.holds(card) { - player.lose(card, &mut self.discard); + self.players[id].lose(card, &mut self.discard); Ok(()) } else { Err("Player discarded a card they don't hold") @@ -268,7 +267,7 @@ impl Game { ResMode::None => Ok(block), ResMode::Target => unreachable!(), ResMode::Anyone => { - let challenger = self.turn_iterator().find(|&id| agents[id].should_action_challenge(&action_challenge)); + let challenger = self.turn_iterator().find(|&id| agents[id].should_action_challenge(self, &action_challenge)); if let Some(challenger) = challenger{ let current_player_wins = self.players[self.turn].wins_challenge(action_challenge.action); if current_player_wins { @@ -294,7 +293,7 @@ impl Game { action: block.action, target: block.target, })), - ResMode::Target => match agents[block.target.unwrap()].choose_block_card(&block) { + ResMode::Target => match agents[block.target.unwrap()].choose_block_card(self, &block) { Some(card) => { if card.blocks_action(block.action) { Ok(Phase::BlockChallenge(phase::BlockChallenge { @@ -314,7 +313,7 @@ impl Game { } ResMode::Anyone => { for id in self.turn_iterator() { - if let Some(card) = agents[id].choose_block_card(&block) { + if let Some(card) = agents[id].choose_block_card(self, &block) { if card.blocks_action(block.action) { return Ok(Phase::BlockChallenge(phase::BlockChallenge { blocker: id, @@ -336,7 +335,7 @@ impl Game { } pub fn block_challenge(&mut self, block_challenge: phase::BlockChallenge, agents: &[&dyn Agent]) -> CoupResult { - if agents[self.turn].should_block_challenge(&block_challenge) { + if agents[self.turn].should_block_challenge(self, &block_challenge) { if self.players[block_challenge.blocker].holds(block_challenge.block_card) { // Player challenged incorrectly, loses influence and turn is forfeit self.player_lose_influence(self.turn, agents)?; @@ -358,11 +357,9 @@ impl Game { } pub fn resolution(&mut self, resolution: phase::Resolution, agents: &[&dyn Agent]) -> CoupResult { - let current_player = &mut self.players.get_mut(self.turn).unwrap(); - let current_agent = agents[self.turn]; match resolution.action { - Income => current_player.coins += 1, - ForeignAid => current_player.coins += 2, + Income => self.players[self.turn].coins += 1, + ForeignAid => self.players[self.turn].coins += 2, Coup | Assassinate => match resolution.target { Some(target) => { // Target may have died from challenge @@ -373,12 +370,12 @@ impl Game { } _ => return Err("Coup/Assassinate resolution has no target"), }, - Tax => current_player.coins += 3, + Tax => self.players[self.turn].coins += 3, Exchange => { let drawn = vec![self.deck.pop().unwrap(), self.deck.pop().unwrap()]; - let hand = current_player.cards.clone(); + let hand = self.players[self.turn].cards.clone(); let mut choices = [drawn, hand].concat(); - let discarded = current_agent.exchange(&choices); + let discarded = agents[self.turn].exchange(self, &choices); for card in discarded { if !choices.draw_first(card) { return Err("Exchanged a card that was not in choices"); @@ -386,7 +383,7 @@ impl Game { self.deck.push(card); } } - current_player.cards = choices; + self.players[self.turn].cards = choices; self.deck.shuffle(); } Steal => match resolution.target { @@ -453,18 +450,19 @@ use phase::Phase; /// An interface to a game to make strategic decisions. pub trait Agent : fmt::Debug { /// Should the agent challenge the action? - fn should_action_challenge(&self, action_challenge: &phase::ActionChallenge) -> bool; + fn should_action_challenge(&self, game: &Game, action_challenge: &phase::ActionChallenge) -> bool; /// Which [card](Card) the agent wishes to use to block the current action. /// If the agent does not wish to block, it should return [None] - fn choose_block_card(&self, block: &phase::Block) -> Option; + fn choose_block_card(&self, game: &Game, block: &phase::Block) -> Option; /// Should the agent challenge the block? - fn should_block_challenge(&self, block_challenge: &phase::BlockChallenge) -> bool; + fn should_block_challenge(&self, game: &Game, block_challenge: &phase::BlockChallenge) -> bool; /// The [Ambassador]'s exchange. /// Given 3 or 4 [Cards](Card) the agent must return two cards to the deck. - fn exchange(&self, cards: &[Card]) -> [Card; 2]; + fn exchange(&self, game: &Game, cards: &[Card]) -> [Card; 2]; /// The player has lost influence, and must choose a [Card] from their hand /// to discard. - fn choose_lost_influence(&self, cards: &[Card]) -> Card; + fn choose_lost_influence(&self, game: &Game) -> Card; } +#[cfg(test)] mod test; diff --git a/src/test.rs b/src/test.rs index 26a3603..3582cca 100644 --- a/src/test.rs +++ b/src/test.rs @@ -3,19 +3,19 @@ use super::*; #[derive(Debug)] struct DummyAgent(Card, Option, bool); impl Agent for DummyAgent { - fn should_action_challenge(&self, _action_challenge: &phase::ActionChallenge) -> bool { + fn should_action_challenge(&self, _game: &Game, _action_challenge: &phase::ActionChallenge) -> bool { self.2 } - fn choose_block_card(&self, _block: &phase::Block) -> Option { + fn choose_block_card(&self, _game: &Game, _block: &phase::Block) -> Option { self.1 } - fn should_block_challenge(&self, _block_challenge: &phase::BlockChallenge) -> bool { + fn should_block_challenge(&self, _game: &Game, _block_challenge: &phase::BlockChallenge) -> bool { self.2 } - fn exchange(&self, _cards: &[Card]) -> [Card; 2] { + fn exchange(&self, _game: &Game, _cards: &[Card]) -> [Card; 2] { [self.0, self.1.unwrap()] } - fn choose_lost_influence(&self, _cards: &[Card]) -> Card { + fn choose_lost_influence(&self, _game: &Game) -> Card { self.0 } }