From 38200848953b1d8d7ba083752c2621603842b54e Mon Sep 17 00:00:00 2001 From: tslil clingman <> Date: Mon, 27 Jan 2020 22:16:59 -0800 Subject: fix ptn issues --- src/game.rs | 139 +++++++++++++++++++++++++++++------------------------------- 1 file changed, 66 insertions(+), 73 deletions(-) (limited to 'src/game.rs') diff --git a/src/game.rs b/src/game.rs index a6c79a4..3c15796 100644 --- a/src/game.rs +++ b/src/game.rs @@ -78,21 +78,28 @@ impl fmt::Display for Direction { pub enum Action { Place(Player, Position, Stone), - Move(Player, Position, Direction, Vec), + Move(Position, Direction, u8, Vec), } impl fmt::Display for Action { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Action::Place(_, pos, stone) => write!(f, "{}{}", stone, pos), - Action::Move(_, pos, direction, drops) => write!( - f, - "{}{}{}", - // drops.iter().map(|&d| d as u32).sum::(), - pos, - direction, - drops.into_iter().map(|q| q.to_string()).collect::() - ), + Action::Move(pos, direction, picked_up, drops) => { + match (*picked_up > 1, drops.len() > 1) { + (true, true) => write!( + f, + "{}{}{}{}", + picked_up, + pos, + direction, + drops.into_iter().map(|q| q.to_string()).collect::(), + ), + (true, false) => write!(f, "{}{}{}", picked_up, pos, direction), + // (false, true) should be impossible + _ => write!(f, "{}{}", pos, direction), + } + } } } } @@ -254,9 +261,8 @@ impl GameState { pos: &Position, stone: Stone, ) -> Result<(Vec, GameState), String> { - if let Err(e) = self.is_legal_place(player, pos, stone) { - return Err(e); - } + self.is_legal_place(player, pos, stone)?; + // Place stone let mut copy = self.copy(); let idx = self.pos_to_idx(&pos); @@ -264,6 +270,7 @@ impl GameState { player: player, stone: stone, }); + // Decrease count match player { Player::Black => { @@ -289,6 +296,7 @@ impl GameState { player: Player, pos: &Position, direction: Direction, + picked_up: u8, drops: &Vec, ) -> Result<(), String> { if self.within_bounds(pos) { @@ -297,10 +305,8 @@ impl GameState { - Drops have been specified - Must actually move at least one stone - Top stone belongs to player - - Zero or more dropped on starting square - One or more on each subsequent square - - Total number of stones moved does not exceed the carry capacity - - Moved the entire stack (up to the carry capacity) + - Total number of stones picked up does not exceed the carry capacity - Direction does not contain a capstone - Wall may only appear on last spot if it's capstone alone that covers - All stones are used up before then end of the board is met @@ -319,7 +325,7 @@ impl GameState { )); }; - if drops_len == 1 && drops[0] == 1 { + if picked_up == 0 { return Err(String::from( "A valid move must change the position of at least a single stone.", )); @@ -335,34 +341,35 @@ impl GameState { }; for i in 0..drops_len { - if i > 0 && drops[i] == 0 { + if drops[i] == 0 { return Err(String::from( - "A move may not drop 0 stones past the first square.", + "A move may not drop 0 stones on subsequent squares.", )); } } + let picked_up = picked_up as usize; let sum_dropped = drops.iter().map(|&d| d as usize).sum::(); - let carry_capacity = self.size as usize; - if sum_dropped > carry_capacity { + if sum_dropped != picked_up { return Err(format!( - "A move may not exceed the carry capacity of {} stones.", - self.size + "Move intended to pick up {} stones but drop {}.", + picked_up, sum_dropped )); } - if sum_dropped != std::cmp::min(carry_capacity, stack_len) { - return Err(String::from( - "A move must effect the whole stack, up to the carry limit.", + let carry_capacity = self.size as usize; + if picked_up > carry_capacity { + return Err(format!( + "A move may not pick up more than the carry capacity of {} stones.", + self.size )); } - let mut steps: usize = drops.len() - 1; + let mut steps: usize = drops.len(); let cap: bool = stack[0].stone == Stone::Capstone; let mut pos_new = Position { x: pos.x, y: pos.y }; while steps > 0 { - steps -= 1; if { match direction { Direction::Up => pos_new.y + 1 >= self.size, @@ -404,6 +411,7 @@ impl GameState { )); } } + steps -= 1; } return Ok(()); } else { @@ -422,11 +430,10 @@ impl GameState { player: Player, pos: &Position, direction: Direction, + picked_up: u8, drops: &Vec, ) -> Result<(Vec, GameState), String> { - if let Err(e) = self.is_legal_move(player, pos, direction, drops) { - return Err(e); - } + self.is_legal_move(player, pos, direction, picked_up, drops)?; let mut copy = self.copy(); let mut pos_vec: Vec = vec![pos.clone()]; @@ -436,21 +443,35 @@ impl GameState { let stack_height = copy.board[idx].len(); - let mut offset = 0; - let carry_capacity = self.size as usize; - if stack_height > carry_capacity { - for _i in 0..carry_capacity { - copy.board[idx].pop(); - } - offset = stack_height - carry_capacity; - } else { - copy.board[idx].clear(); + let mut offset = stack_height - (picked_up as usize); + + for _i in offset..stack_height { + copy.board[idx].pop(); } - let num_drops = drops.len(); - for drop_idx in 0..num_drops { - let pos = pos_vec[pos_vec.len() - 1]; - let idx = copy.pos_to_idx(&pos); + for drop_idx in 0..drops.len() { + let new_pos = pos_vec[pos_vec.len() - 1]; + pos_vec.push(match direction { + Direction::Up => Position { + x: new_pos.x, + y: new_pos.y + 1, + }, + Direction::Down => Position { + x: new_pos.x, + y: new_pos.y - 1, + }, + Direction::Left => Position { + x: new_pos.x - 1, + y: new_pos.y, + }, + Direction::Right => Position { + x: new_pos.x + 1, + y: new_pos.y, + }, + }); + + let new_pos = pos_vec[pos_vec.len() - 1]; + let idx = copy.pos_to_idx(&new_pos); let num = drops[drop_idx] as usize; for i in 0..num { @@ -466,27 +487,6 @@ impl GameState { copy.board[idx].push(stack[offset + i]); } offset += num; - - if drop_idx + 1 < num_drops { - pos_vec.push(match direction { - Direction::Up => Position { - x: pos.x, - y: pos.y + 1, - }, - Direction::Down => Position { - x: pos.x, - y: pos.y - 1, - }, - Direction::Left => Position { - x: pos.x - 1, - y: pos.y, - }, - Direction::Right => Position { - x: pos.x + 1, - y: pos.y, - }, - }); - } } Ok((pos_vec, copy)) } @@ -787,16 +787,9 @@ impl Game { } TurnOrder::Normal => state.place_stone(*player, pos, *stone), }, - Action::Move(player, pos, direction, drops) => match self.turn_order { + Action::Move(pos, direction, picked_up, drops) => match self.turn_order { TurnOrder::Normal => { - if *player == self.current_player { - state.move_stack(*player, pos, *direction, drops) - } else { - Err(format!( - "{} may not take actions on {}'s turn.", - player, self.current_player - )) - } + state.move_stack(self.current_player, pos, *direction, *picked_up, drops) } _ => Err(String::from( "At the start of the game only placing flats is allowed.", -- cgit v1.3.1