Skip to content

Commit 5aa870e

Browse files
committed
fix: hare movement logic and error handling
1 parent 13e71ec commit 5aa870e

File tree

3 files changed

+80
-33
lines changed

3 files changed

+80
-33
lines changed

src/plugin/hare.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use pyo3::*;
55
use super::{
66
action::card::Card,
77
constants::PluginConstants,
8-
errors::{CannotEnterFieldError, FieldNonexistentError, MissingCarrotsError, NoSaladError},
8+
errors::{CannotEnterFieldError, MissingCarrotsError},
99
field::Field,
1010
game_state::GameState,
1111
r#move::Move,
@@ -82,20 +82,22 @@ impl Hare {
8282
}
8383

8484
pub fn advance_by(&mut self, state: &mut GameState, distance: usize) -> Result<(), PyErr> {
85-
RulesEngine::can_advance_to(&state.board, distance, self, &state.clone_other_player())?;
85+
let new_position = self.position + distance;
86+
RulesEngine::can_advance_to(
87+
&state.board,
88+
new_position,
89+
self,
90+
&state.clone_other_player(),
91+
)?;
8692

87-
let carrots = RulesEngine::calculates_carrots(distance);
93+
let needed_carrots = RulesEngine::calculates_carrots(distance);
8894

89-
if self.carrots - carrots < 0 {
95+
if self.carrots - needed_carrots < 0 {
9096
return Err(MissingCarrotsError::new_err("Not enough carrots"));
9197
}
9298

93-
if self.position.checked_sub(distance).is_none() {
94-
return Err(FieldNonexistentError::new_err("Cannot go on this field"));
95-
}
96-
97-
self.carrots -= carrots;
98-
self.position += distance;
99+
self.carrots -= needed_carrots;
100+
self.position = new_position;
99101

100102
state.update_player(self.clone());
101103
Ok(())
@@ -121,9 +123,8 @@ impl Hare {
121123
}
122124

123125
pub fn eat_salad(&mut self, state: &mut GameState) -> Result<(), PyErr> {
124-
if self.salads < 1 {
125-
return Err(NoSaladError::new_err("Not enough salads"));
126-
}
126+
RulesEngine::can_eat_salad(&state.board, self)?;
127+
127128
self.salads -= 1;
128129
self.carrots += if self.is_ahead(state) { 10 } else { 30 };
129130

@@ -162,6 +163,8 @@ impl Hare {
162163
pub fn fall_back(&mut self, state: &mut GameState) -> Result<(), PyErr> {
163164
match self.get_fall_back(state) {
164165
Some(i) => {
166+
RulesEngine::has_to_eat_salad(&state.board, self)?;
167+
165168
self.carrots += 10 * ((self.position - i) as i32);
166169
self.position = i;
167170

src/plugin/rules_engine.rs

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ use crate::plugin::errors::{
66
};
77

88
use super::{
9-
action::Action, board::Board, errors::CannotEnterFieldError, field::Field, hare::Hare,
9+
action::{eat_salad::EatSalad, Action},
10+
board::Board,
11+
errors::{CannotEnterFieldError, NoSaladError},
12+
field::Field,
13+
hare::Hare,
1014
r#move::Move,
1115
};
1216

@@ -17,34 +21,77 @@ pub struct RulesEngine;
1721
impl RulesEngine {
1822
#[staticmethod]
1923
pub fn calculates_carrots(distance: usize) -> i32 {
20-
let distancce_i32: i32 = distance.try_into().unwrap();
21-
(distancce_i32 * (distancce_i32 + 1)) / 2
24+
let distance_i32: i32 = distance.try_into().unwrap();
25+
(distance_i32 * (distance_i32 + 1)) / 2
2226
}
2327

2428
#[staticmethod]
25-
pub fn can_exchange_carrots(board: &Board, player: &Hare, count: i32) -> Result<bool, PyErr> {
29+
pub fn can_exchange_carrots(board: &Board, player: &Hare, count: i32) -> Result<(), PyErr> {
2630
match board.get_field(player.position) {
27-
Some(f) => {
28-
Ok(f == Field::Carrots && (count == 10 || (count == -10 && player.carrots >= 10)))
31+
Some(Field::Carrots) => {
32+
if count != 10 && count != -10 {
33+
return Err(MissingCarrotsError::new_err(
34+
"You can only exchange 10 carrots",
35+
));
36+
}
37+
if count == -10 && player.carrots < 10 {
38+
return Err(MissingCarrotsError::new_err("Not enough carrots"));
39+
}
40+
Ok(())
2941
}
42+
Some(_) => Err(CannotEnterFieldError::new_err(
43+
"Field is not a carrot field",
44+
)),
3045
None => Err(CannotEnterFieldError::new_err("Field not found")),
3146
}
3247
}
3348

3449
#[staticmethod]
35-
pub fn can_eat_salad(board: &Board, player: &Hare) -> Result<bool, PyErr> {
50+
pub fn can_eat_salad(board: &Board, player: &Hare) -> Result<(), PyErr> {
51+
if player.salads < 1 {
52+
return Err(NoSaladError::new_err("No salad to eat"));
53+
}
54+
3655
match board.get_field(player.position) {
37-
Some(Field::Salad) => Ok(!matches!(
38-
player.last_move,
39-
Some(Move {
40-
action: Action::EatSalad(_)
41-
})
56+
Some(Field::Salad)
57+
if !matches!(
58+
player.last_move,
59+
Some(Move {
60+
action: Action::EatSalad(_)
61+
})
62+
) =>
63+
{
64+
Ok(())
65+
}
66+
Some(Field::Salad) => Err(CannotEnterFieldError::new_err(
67+
"Cannot eat salad twice in a row",
4268
)),
43-
Some(_) => Ok(false),
69+
Some(_) => Err(CannotEnterFieldError::new_err("Field is not a salad")),
4470
None => Err(CannotEnterFieldError::new_err("Field not found")),
4571
}
4672
}
4773

74+
#[staticmethod]
75+
pub fn has_to_eat_salad(board: &Board, player: &Hare) -> Result<(), PyErr> {
76+
match board.get_field(player.position) {
77+
Some(Field::Salad) => {
78+
if player.last_move
79+
!= Some(Move {
80+
action: Action::EatSalad(EatSalad::new()),
81+
})
82+
{
83+
Err(CannotEnterFieldError::new_err(
84+
"Cannot advance without eating salad",
85+
))
86+
} else {
87+
Ok(())
88+
}
89+
}
90+
Some(_) => Ok(()),
91+
None => Ok(()),
92+
}
93+
}
94+
4895
#[staticmethod]
4996
pub fn can_advance_to(
5097
board: &Board,
@@ -56,6 +103,8 @@ impl RulesEngine {
56103
return Err(CannotEnterFieldError::new_err("Cannot jump to position 0"));
57104
}
58105

106+
Self::has_to_eat_salad(board, player)?;
107+
59108
let field = match board.get_field(new_position) {
60109
Some(f) => f,
61110
None => {

src/plugin/test/rules_test.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,17 @@ mod tests {
4949

5050
let result = RulesEngine::can_exchange_carrots(&board, &player, 10);
5151
assert!(result.is_ok());
52-
assert!(result.unwrap());
5352

5453
player.carrots = 5;
5554
let result = RulesEngine::can_exchange_carrots(&board, &player, -10);
56-
assert!(result.is_ok());
57-
assert!(!result.unwrap());
55+
assert!(result.is_err());
5856

5957
player.carrots = 10;
6058
let result = RulesEngine::can_exchange_carrots(&board, &player, -10);
6159
assert!(result.is_ok());
62-
assert!(result.unwrap());
6360

6461
let result = RulesEngine::can_exchange_carrots(&board, &player, 5);
65-
assert!(result.is_ok());
66-
assert!(!result.unwrap());
62+
assert!(result.is_err());
6763
}
6864

6965
#[test]
@@ -73,7 +69,6 @@ mod tests {
7369

7470
let result = RulesEngine::can_eat_salad(&board, &player);
7571
assert!(result.is_ok());
76-
assert!(result.unwrap());
7772
}
7873

7974
#[test]

0 commit comments

Comments
 (0)