diff options
| author | tslil clingman <> | 2020-01-27 22:16:59 -0800 |
|---|---|---|
| committer | tslil clingman <> | 2020-01-27 22:16:59 -0800 |
| commit | 38200848953b1d8d7ba083752c2621603842b54e (patch) | |
| tree | 9e13f26df343d472c040ac6678a9836c5ba11eb7 /src | |
| parent | 87c2d3319effd4d6be83875bdb455be9077c0c1c (diff) | |
fix ptn issues
Diffstat (limited to 'src')
| -rw-r--r-- | src/consulter.rs | 2 | ||||
| -rw-r--r-- | src/game.rs | 139 | ||||
| -rw-r--r-- | src/gui.rs | 2 | ||||
| -rw-r--r-- | src/main.rs | 10 | ||||
| -rw-r--r-- | src/parser.rs | 44 |
5 files changed, 88 insertions, 109 deletions
diff --git a/src/consulter.rs b/src/consulter.rs index 1f27124..a8e666f 100644 --- a/src/consulter.rs +++ b/src/consulter.rs @@ -16,7 +16,7 @@ pub fn consult_next_action(game: &Game, proc: &str) -> Result<Action> { match String::from_utf8(output.stdout) { Err(e) => Err(Error::new(ErrorKind::InvalidData, e)), - Ok(string) => match parse_action(game, &string) { + Ok(string) => match parse_action(game.query_stone_owner(), &string.trim()) { Err(string) => Err(Error::new(ErrorKind::InvalidData, string)), Ok(action) => Ok(action), }, 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<u8>), + Move(Position, Direction, u8, Vec<u8>), } 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::<u32>(), - pos, - direction, - drops.into_iter().map(|q| q.to_string()).collect::<String>() - ), + 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::<String>(), + ), + (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<Position>, 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<u8>, ) -> 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::<usize>(); - 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<u8>, ) -> Result<(Vec<Position>, 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<Position> = 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.", @@ -204,7 +204,7 @@ impl BoardGUI { for i in 0..height { let piece = &stack[i]; self.draw_stone(win, i + 1 == height, &piece.player, &piece.stone); - if tall && i + 2 == carry_capacity { + if tall && i + 1 == height - carry_capacity { win.attrset(Attribute::Normal); win.addch(')'); } diff --git a/src/main.rs b/src/main.rs index 8335422..6a2f70a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -101,10 +101,12 @@ fn init_gui(size: u8) -> GUI { fn human_action(gui: &GUI, game: &Game) -> Result<Action, Error> { loop { let inp = gui.action_entry.read_action(); - match parse_action(&game, &inp) { - Err(err) => gui - .message_log - .log_error(format!("Input \"{}\": {}", inp, err)), + match parse_action(game.query_stone_owner(), &inp) { + Err(err) => { + gui.message_log + .log_error(format!("Input \"{}\": {}", inp, err)); + gui.action_entry.clear_entry_area(); + } Ok(action) => { gui.action_entry.clear_entry_area(); return Ok(action); diff --git a/src/parser.rs b/src/parser.rs index 9d50377..68e49a8 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,6 +1,6 @@ use crate::game::*; -fn parse_move(mv: &str, game: &Game) -> Result<Action, String> { +fn parse_move(mv: &str) -> Result<Action, String> { let mut chars = mv.chars(); let c = chars.next(); @@ -9,21 +9,19 @@ fn parse_move(mv: &str, game: &Game) -> Result<Action, String> { } let x; - let fill_in_number; + let picked_up; let dc = c.unwrap(); - let mut sum_drops: u8 = 1; if (dc >= 'a') && (dc <= 'h') { // Optional drop number omitted, assume everything - fill_in_number = true; x = dc; + picked_up = 1; } else { if (dc < '1') || ('9' < dc) { return Err(String::from( - "Moves must begin with a digit in 1-8 indicating the number of drops.", + "Moves must begin with a digit in 1-8 indicating the stones picked up.", )); } - fill_in_number = false; - sum_drops = dc.to_digit(10).unwrap() as u8; + picked_up = dc.to_digit(10).unwrap() as u8; let c = chars.next(); if c.is_none() { @@ -88,32 +86,22 @@ fn parse_move(mv: &str, game: &Game) -> Result<Action, String> { } let pos = Position { x: x, y: y }; - if fill_in_number { - if let Some(stack) = game.query_square(&pos) { - sum_drops = std::cmp::min(stack.len() as u8, game.get_size()); - } else { - return Err(String::from( - "Moves must specify a valid position on the game board.", - )); - } - } let sum = drops.iter().map(|&d| d as u32).sum::<u32>(); if sum == 0 { // Omitted all the drops, it's a total stack move - drops.push(0); - drops.push(sum_drops); - } else if sum != sum_drops as u32 { + drops.push(picked_up); + } else if sum != picked_up as u32 { return Err(format!( "The move called for {} stones, but {} were dropped.", - sum_drops, sum + picked_up, sum )); } - Ok(Action::Move(game.query_stone_owner(), pos, dir, drops)) + Ok(Action::Move(pos, dir, picked_up, drops)) } -fn parse_place(pl: &str, game: &Game) -> Result<Action, String> { +fn parse_place(pl: &str, stone_owner: Player) -> Result<Action, String> { let mut chars = pl.chars(); let c = chars.next(); @@ -167,20 +155,16 @@ fn parse_place(pl: &str, game: &Game) -> Result<Action, String> { } let y: u8 = (y.to_digit(10).unwrap() - 1) as u8; - Ok(Action::Place( - game.query_stone_owner(), - Position { x: x, y: y }, - stone, - )) + Ok(Action::Place(stone_owner, Position { x: x, y: y }, stone)) } -pub fn parse_action(game: &Game, act: &str) -> Result<Action, String> { +pub fn parse_action(stone_owner: Player, act: &str) -> Result<Action, String> { if act .chars() .any(|c| c == '+' || c == '-' || c == '>' || c == '<') { - parse_move(act, game) + parse_move(act) } else { - parse_place(act, game) + parse_place(act, stone_owner) } } |
