Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/plugin/action/advance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl Advance {

last_card = Some(card);

card.perform(state, remaining_cards.clone())?;
card.perform(state, remaining_cards.clone(), self.distance)?;
player = state.clone_current_player();
}
_ => Err(HUIError::new_err("Card cannot be played on this field"))?,
Expand Down
52 changes: 41 additions & 11 deletions src/plugin/action/card.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ impl Card {
current: &mut Hare,
other: &mut Hare,
remaining_cards: Vec<Card>,
advance_distance: usize,
) -> Result<(), PyErr> {
match self {
Card::FallBack => {
Expand Down Expand Up @@ -97,28 +98,45 @@ impl Card {
));
}

if let (Some(current_last_move), Some(other_last_move)) =
(&current.last_move, &other.last_move)
let mut current_ok: bool = true;
if let Some(current_last_move) = &current.last_move
{
if let (Action::Advance(current_advance), Action::Advance(other_advance)) =
(&current_last_move.action, &other_last_move.action)
if let Action::Advance(current_advance) = &current_last_move.action
{
if current_advance.cards.contains(&Card::SwapCarrots)
&& state.board.track[current.position - advance_distance] == Field::Hare
{
current_ok = false;
}
}
}

let mut other_ok: bool = true;
if let Some(other_last_move) = &other.last_move
{
if let Action::Advance(other_advance) = &other_last_move.action
{
if current_advance.cards.contains(&Card::SwapCarrots)
|| other_advance.cards.contains(&Card::SwapCarrots)
if other_advance.cards.contains(&Card::SwapCarrots)
&& state.board.track[other.position] == Field::Hare
{
return Err(HUIError::new_err(
"You can only play this card if the last similar swap card was not used in one of the last two turns",
));
other_ok = false;
}
}
}

if !current_ok || !other_ok {
return Err(HUIError::new_err(
"You can only play this card if the last similar swap card was not used in one of the last two turns",
));
}

swap(&mut current.carrots, &mut other.carrots);
}
}
Ok(())
}

pub fn perform(&self, state: &mut GameState, remaining_cards: Vec<Card>) -> Result<(), PyErr> {
pub fn perform(&self, state: &mut GameState, remaining_cards: Vec<Card>, advance_distance: usize) -> Result<(), PyErr> {
let mut current = state.clone_current_player();
let mut other = state.clone_other_player();

Expand All @@ -139,7 +157,7 @@ impl Card {
.position(|card| card == self)
.ok_or_else(|| HUIError::new_err("Card not owned"))?;

self.play(state, &mut current, &mut other, remaining_cards)?;
self.play(state, &mut current, &mut other, remaining_cards, advance_distance)?;

current.cards.remove(index);

Expand All @@ -149,3 +167,15 @@ impl Card {
Ok(())
}
}

impl std::fmt::Display for Card {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {

match self {
Card::FallBack => write!(f, "Fallback Card"),
Card::HurryAhead => write!(f, "HurryAhead Card"),
Card::EatSalad => write!(f, "EatSalad Card"),
Card::SwapCarrots => write!(f, "SwapCarrot Card"),
}
}
}
117 changes: 90 additions & 27 deletions src/plugin/test/card_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,25 @@ mod tests {
fn create_test_game_state() -> GameState {
let board = Board::new(vec![
Field::Start,
Field::Position1,
Field::Carrots,
Field::Position2,
Field::Hare,
Field::Position1,
Field::Market,
Field::Carrots,
Field::Hare,
Field::Carrots,
Field::Hedgehog,
Field::Salad,
Field::Hare,
Field::Position1,
Field::Goal,
]);
let player_one = Hare::new(
TeamEnum::One,
Some(vec![Card::FallBack, Card::EatSalad, Card::SwapCarrots]),
Some(60),
Some(30),
Some(3),
None,
Some(6),
Some(7),
);
let player_two = Hare::new(
TeamEnum::Two,
Expand All @@ -45,7 +48,7 @@ mod tests {
let mut state = create_test_game_state();
let fallback_card = Card::FallBack;
assert!(fallback_card
.perform(&mut state, vec![Card::EatSalad, Card::SwapCarrots])
.perform(&mut state, vec![Card::EatSalad, Card::SwapCarrots], 0)
.is_ok());
let current_player = state.clone_current_player();
assert_eq!(current_player.position, 2);
Expand All @@ -56,75 +59,135 @@ mod tests {
let mut state = create_test_game_state();
state.turn = 1;
let hurry_ahead_card: Card = Card::HurryAhead;
assert!(hurry_ahead_card.perform(&mut state, vec![]).is_ok());
assert!(hurry_ahead_card.perform(&mut state, vec![], 0).is_ok());
let current_player = state.clone_current_player();
assert_eq!(current_player.position, 7);
assert_eq!(current_player.position, 8);
}

#[test]
fn test_eatsalad_card() {
let mut state = create_test_game_state();
let eat_salad_card = Card::EatSalad;
assert!(eat_salad_card
.perform(&mut state, vec![Card::FallBack, Card::SwapCarrots])
.perform(&mut state, vec![Card::FallBack, Card::SwapCarrots], 0)
.is_ok());
let current_player = state.clone_current_player();
assert_eq!(current_player.salads, 2);
}

#[test]
fn test_swapcarrots_card() {
fn test_swapcarrots_card_general() {
let mut state = create_test_game_state();

// modify player one
let mut player_one = state.clone_current_player();
let mut player_two = state.clone_other_player();
player_one.position = 3;
player_two.position = 2;
player_one.last_move = Some(Move {
action: Action::Advance(Advance {
distance: 2,
cards: vec![],
}),
});

state.update_player(player_one);

// modify player two
let mut player_two = state.clone_other_player();
player_two.last_move = Some(Move {
action: Action::Advance(Advance {
distance: 3,
cards: vec![],
}),
});

state.update_player(player_two);

// test card
let swap_carrots_card = Card::SwapCarrots;
assert!(swap_carrots_card
.perform(&mut state, vec![Card::FallBack, Card::EatSalad])
.perform(&mut state, vec![Card::FallBack, Card::EatSalad], 1)
.is_ok());
let current_player = state.clone_current_player();
let other_player = state.clone_other_player();
assert_eq!(current_player.carrots, 60);
assert_eq!(other_player.carrots, 60);
assert_eq!(other_player.carrots, 30);
}

#[test]
fn test_swapcarrots_card_already_occurred_last_two_rounds() {
fn test_swapcarrots_card_bought_last_two_rounds() {
let mut state = create_test_game_state();

// modify player one
let mut player_one = state.clone_current_player();
let mut player_two = state.clone_other_player();
player_one.position = 3;
player_two.position = 2;
player_one.last_move = Some(Move {
action: Action::Advance(Advance {
distance: 1,
cards: vec![Card::SwapCarrots],
}),
});

state.update_player(player_one);

// modify player two
let mut player_two = state.clone_other_player();
player_two.last_move = Some(Move {
action: Action::Advance(Advance {
distance: 1,
cards: vec![Card::SwapCarrots],
distance: 3,
cards: vec![],
}),
});

state.update_player(player_two);

// test card
let swap_carrots_card = Card::SwapCarrots;
assert!(swap_carrots_card
.perform(&mut state, vec![Card::FallBack, Card::EatSalad], 2)
.is_ok());
let current_player = state.clone_current_player();
let other_player = state.clone_other_player();
assert_eq!(current_player.carrots, 60);
assert_eq!(other_player.carrots, 30);
}

#[test]
fn test_swapcarrots_card_played_last_two_rounds() {
let mut state = create_test_game_state();

// modify player one
let mut player_one = state.clone_current_player();
player_one.last_move = Some(Move {
action: Action::Advance(Advance {
distance: 2,
cards: vec![],
}),
});

state.update_player(player_one);

// modify player two
let mut player_two = state.clone_other_player();
player_two.last_move = Some(Move {
action: Action::Advance(Advance {
distance: 3,
cards: vec![Card::SwapCarrots],
}),
});

state.update_player(player_two);

// test card
let swap_carrots_card = Card::SwapCarrots;
let result = swap_carrots_card.perform(&mut state, vec![Card::FallBack, Card::EatSalad]);
assert!(result.is_err());
assert!(swap_carrots_card
.perform(&mut state, vec![Card::FallBack, Card::EatSalad], 1)
.is_err());
}

#[test]
fn test_play_card_not_owned() {
let mut state = create_test_game_state();
state.turn = 1;
let card_not_owned = Card::FallBack;
let result = card_not_owned.perform(&mut state, vec![Card::HurryAhead]);
let result = card_not_owned.perform(&mut state, vec![Card::HurryAhead], 0);
assert!(result.is_err());
}

Expand All @@ -135,7 +198,7 @@ mod tests {
let mut current_player = state.clone_current_player();
current_player.position = 1;
state.update_player(current_player);
let result = card.perform(&mut state, vec![Card::EatSalad, Card::SwapCarrots]);
let result = card.perform(&mut state, vec![Card::EatSalad, Card::SwapCarrots], 0);
assert!(result.is_err());
}

Expand All @@ -144,7 +207,7 @@ mod tests {
let mut state = create_test_game_state();
let invalid_card = Card::FallBack;
state.board.track.clear();
let result = invalid_card.perform(&mut state, vec![Card::EatSalad, Card::SwapCarrots]);
let result = invalid_card.perform(&mut state, vec![Card::EatSalad, Card::SwapCarrots], 0);
assert!(result.is_err());
}

Expand All @@ -156,7 +219,7 @@ mod tests {
current_player.salads = 0;
current_player.cards = vec![card];
state.update_player(current_player);
let result = card.perform(&mut state, vec![]);
let result = card.perform(&mut state, vec![], 0);
assert!(result.is_err());
}
}