Skip to content

Commit 608d5fc

Browse files
committed
fix: incorrect logic implementation with advances with cards
1 parent 1fda697 commit 608d5fc

File tree

10 files changed

+181
-120
lines changed

10 files changed

+181
-120
lines changed

src/plugin/action/advance.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
use pyo3::{pyclass, pymethods, PyErr};
22

3-
use crate::plugin::{
4-
errors::{CannotPlayCardError, MustBuyOneCardError, MustPlayCardError},
5-
field::Field,
6-
game_state::GameState,
7-
};
3+
use crate::plugin::{errors::HUIError, field::Field, game_state::GameState};
84

95
use super::card::Card;
106

@@ -28,15 +24,13 @@ impl Advance {
2824
pub fn perform(&self, state: &mut GameState) -> Result<(), PyErr> {
2925
let mut player = state.clone_current_player();
3026

31-
player.advance_by(state, self.distance as isize, self.cards.clone())?;
27+
player.advance_by(state, self.distance, self.cards.clone())?;
3228

3329
let current_field = state.board.get_field(player.position).unwrap();
3430
if self.cards.is_empty() {
3531
match current_field {
3632
Field::Market | Field::Hare => {
37-
return Err(MustPlayCardError::new_err(
38-
"Cannot enter field without any cards",
39-
));
33+
return Err(HUIError::new_err("Cannot enter field without any cards"));
4034
}
4135
_ => {
4236
state.update_player(player);
@@ -51,7 +45,7 @@ impl Advance {
5145
for card in &self.cards {
5246
match current_field {
5347
Field::Market if card_bought => {
54-
return Err(MustBuyOneCardError::new_err("Only one card allowed to buy"));
48+
return Err(HUIError::new_err("Only one card allowed to buy"));
5549
}
5650
Field::Market => {
5751
player.consume_carrots(state, 10)?;
@@ -61,22 +55,22 @@ impl Advance {
6155
Field::Hare => {
6256
if let Some(last) = last_card {
6357
if !last.moves() {
64-
return Err(CannotPlayCardError::new_err("Card cannot be played"));
58+
return Err(HUIError::new_err("Card cannot be played"));
6559
}
6660
}
6761

6862
last_card = Some(card);
6963
let mut remaining_cards = self.cards.clone();
7064

71-
if let Some(position) = player.cards.iter().position(|c| c == card) {
65+
if let Some(position) = remaining_cards.iter().position(|c| c == card) {
7266
remaining_cards.remove(position);
7367
} else {
74-
return Err(CannotPlayCardError::new_err("Card not owned"));
68+
return Err(HUIError::new_err("Card not in list of cards"))?;
7569
}
7670

7771
card.perform(state, remaining_cards)?;
7872
}
79-
_ => {}
73+
_ => Err(HUIError::new_err("Card cannot be played on this field"))?,
8074
}
8175
}
8276

src/plugin/action/card.rs

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,7 @@ use std::mem::swap;
33
use pyo3::*;
44

55
use crate::plugin::{
6-
errors::{CannotEnterFieldError, CannotPlayCardError, CardNotOwnedError},
7-
field::Field,
8-
game_state::GameState,
9-
hare::Hare,
10-
rules_engine::RulesEngine,
6+
errors::HUIError, field::Field, game_state::GameState, hare::Hare, rules_engine::RulesEngine,
117
};
128

139
use super::Action;
@@ -37,10 +33,8 @@ impl Card {
3733
target_position: usize,
3834
cards: Vec<Card>,
3935
) -> Result<(), PyErr> {
40-
println!("target_position: {}", target_position);
41-
println!("player.position: {}", player.position);
4236
let distance = target_position as isize - player.position as isize;
43-
RulesEngine::can_advance_to(
37+
RulesEngine::can_move_to(
4438
&state.board,
4539
distance,
4640
player,
@@ -64,7 +58,7 @@ impl Card {
6458
match self {
6559
Card::FallBack => {
6660
if current.position < other.position {
67-
return Err(CannotPlayCardError::new_err(
61+
return Err(HUIError::new_err(
6862
"You can only play this card if you are ahead of the other player",
6963
));
7064
}
@@ -77,7 +71,7 @@ impl Card {
7771
}
7872
Card::HurryAhead => {
7973
if current.position > other.position {
80-
return Err(CannotPlayCardError::new_err(
74+
return Err(HUIError::new_err(
8175
"You can only play this card if you are behind the other player",
8276
));
8377
}
@@ -90,14 +84,14 @@ impl Card {
9084
.board
9185
.get_previous_field(Field::Salad, state.board.track.len() - 1)
9286
.ok_or_else(|| {
93-
CannotPlayCardError::new_err(
94-
"Unable to find the last lettuce field position",
95-
)
87+
HUIError::new_err("Unable to find the last lettuce field position")
9688
})?;
9789

98-
if current.position < last_lettuce_position {
99-
return Err(CannotPlayCardError::new_err(
100-
"You can only play this card if you are standing in front of the last lettuce field",
90+
if current.position > last_lettuce_position
91+
|| other.position > last_lettuce_position
92+
{
93+
return Err(HUIError::new_err(
94+
"You can only play this card if both players haven't passed the last lettuce field",
10195
));
10296
}
10397

@@ -108,9 +102,9 @@ impl Card {
108102
(&current_last_move.action, &other_last_move.action)
109103
{
110104
if current_advance.cards.contains(&Card::SwapCarrots)
111-
&& other_advance.cards.contains(&Card::SwapCarrots)
105+
|| other_advance.cards.contains(&Card::SwapCarrots)
112106
{
113-
return Err(CannotPlayCardError::new_err(
107+
return Err(HUIError::new_err(
114108
"You can only play this card if the last similar swap card was not used in one of the last two turns",
115109
));
116110
}
@@ -129,10 +123,10 @@ impl Card {
129123
let field = state
130124
.board
131125
.get_field(current.position)
132-
.ok_or_else(|| CannotEnterFieldError::new_err("Field not found"))?;
126+
.ok_or_else(|| HUIError::new_err("Field not found"))?;
133127

134128
if field != Field::Hare {
135-
return Err(CannotPlayCardError::new_err(
129+
return Err(HUIError::new_err(
136130
"You can only play cards on the hare field",
137131
));
138132
}
@@ -141,7 +135,7 @@ impl Card {
141135
.cards
142136
.iter()
143137
.position(|card| card == self)
144-
.ok_or_else(|| CardNotOwnedError::new_err("Card not owned"))?;
138+
.ok_or_else(|| HUIError::new_err("Card not owned"))?;
145139

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

src/plugin/board.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,16 @@ impl Board {
3030

3131
/// Finds the previous occurrence of the specified field before the given index.
3232
pub fn get_previous_field(&self, field: Field, index: usize) -> Option<usize> {
33-
if index == 0 {
34-
None
35-
} else {
36-
(0..index)
37-
.rev()
38-
.find(|&i| self.track.get(i) == Some(&field))
39-
}
33+
self.track.iter().take(index).rposition(|&f| f == field)
4034
}
4135

4236
/// Finds the next occurrence of the specified field after the given index.
4337
pub fn get_next_field(&self, field: Field, index: usize) -> Option<usize> {
44-
(index + 1..self.track.len()).find(|&i| self.track.get(i) == Some(&field))
38+
self.track
39+
.iter()
40+
.skip(index + 1)
41+
.position(|&f| f == field)
42+
.map(|i| i + index + 1)
4543
}
4644

4745
pub fn __repr__(&self) -> String {

src/plugin/errors.rs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,3 @@
1-
use pyo3::{ exceptions::PyException, * };
1+
use pyo3::{exceptions::PyException, *};
22

3-
create_exception!(_socha, GoalConditionsError, PyException);
4-
create_exception!(_socha, NoSaladError, PyException);
5-
create_exception!(_socha, MissingCarrotsError, PyException);
6-
create_exception!(_socha, MustEatSaladError, PyException);
7-
create_exception!(_socha, CannotEnterFieldError, PyException);
8-
create_exception!(_socha, FieldOccupiedError, PyException);
9-
create_exception!(_socha, FieldNonexistentError, PyException);
10-
create_exception!(_socha, HedgehogOnlyBackwardsError, PyException);
11-
create_exception!(_socha, CannotMoveForwardError, PyException);
12-
create_exception!(_socha, CannotFallBackError, PyException);
13-
create_exception!(_socha, CannotEatSaladError, PyException);
14-
create_exception!(_socha, CannotExchangeCarrotsError, PyException);
15-
create_exception!(_socha, MustBuyOneCardError, PyException);
16-
create_exception!(_socha, MustPlayCardError, PyException);
17-
create_exception!(_socha, CardNotOwnedError, PyException);
18-
create_exception!(_socha, CannotPlayCardError, PyException);
19-
create_exception!(_socha, CannotPlayFallBackError, PyException);
20-
create_exception!(_socha, CannotPlayHurryAheadError, PyException);
3+
create_exception!(_socha, HUIError, PyException);

src/plugin/hare.rs

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,8 @@ use std::fmt;
33
use pyo3::*;
44

55
use super::{
6-
action::card::Card,
7-
constants::PluginConstants,
8-
errors::{CannotEnterFieldError, MissingCarrotsError},
9-
field::Field,
10-
game_state::GameState,
11-
r#move::Move,
12-
rules_engine::RulesEngine,
6+
action::card::Card, constants::PluginConstants, errors::HUIError, field::Field,
7+
game_state::GameState, r#move::Move, rules_engine::RulesEngine,
138
};
149

1510
#[pyclass]
@@ -84,24 +79,24 @@ impl Hare {
8479
pub fn advance_by(
8580
&mut self,
8681
state: &mut GameState,
87-
distance: isize,
82+
distance: usize,
8883
cards: Vec<Card>,
8984
) -> Result<(), PyErr> {
90-
let needed_carrots = RulesEngine::calculates_carrots(distance.unsigned_abs());
85+
let needed_carrots = RulesEngine::calculates_carrots(distance);
9186

9287
if self.carrots - needed_carrots < 0 {
93-
return Err(MissingCarrotsError::new_err("Not enough carrots"));
88+
return Err(HUIError::new_err("Not enough carrots"));
9489
}
9590

96-
RulesEngine::can_advance_to(
91+
RulesEngine::can_move_to(
9792
&state.board,
98-
distance,
93+
distance as isize,
9994
self,
10095
&state.clone_other_player(),
10196
cards,
10297
)?;
10398

104-
let new_position = (self.position as isize + distance) as usize;
99+
let new_position = self.position + distance;
105100

106101
self.carrots -= needed_carrots;
107102
self.position = new_position;
@@ -126,7 +121,7 @@ impl Hare {
126121
state.update_player(self.clone());
127122
Ok(())
128123
} else {
129-
Err(MissingCarrotsError::new_err("Not enough carrots"))
124+
Err(HUIError::new_err("Not enough carrots"))
130125
}
131126
}
132127

@@ -160,7 +155,7 @@ impl Hare {
160155
state.update_player(self.clone());
161156
Ok(())
162157
}
163-
None => Err(CannotEnterFieldError::new_err("Field not found")),
158+
None => Err(HUIError::new_err("Field not found")),
164159
}
165160
}
166161

0 commit comments

Comments
 (0)