Update agent interface to accept the game state (probably a bad idea...)
This commit is contained in:
parent
b25bd326ae
commit
0e1381c15f
44
src/lib.rs
44
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<Card>) {
|
||||
@ -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<Phase> {
|
||||
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<Phase> {
|
||||
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<Card>;
|
||||
fn choose_block_card(&self, game: &Game, block: &phase::Block) -> Option<Card>;
|
||||
/// 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;
|
||||
|
10
src/test.rs
10
src/test.rs
@ -3,19 +3,19 @@ use super::*;
|
||||
#[derive(Debug)]
|
||||
struct DummyAgent(Card, Option<Card>, 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<Card> {
|
||||
fn choose_block_card(&self, _game: &Game, _block: &phase::Block) -> Option<Card> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user