From d68e088500e5a4959f198c6d18d58b709257f505 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Wed, 3 May 2023 20:49:20 -0400 Subject: [PATCH] Implement the self-capture rule --- kifu/kifu-core/src/board.rs | 100 ++++++++---------------------------- kifu/kifu-gtk/Makefile | 2 +- 2 files changed, 23 insertions(+), 79 deletions(-) diff --git a/kifu/kifu-core/src/board.rs b/kifu/kifu-core/src/board.rs index bd89291..4390c53 100644 --- a/kifu/kifu-core/src/board.rs +++ b/kifu/kifu-core/src/board.rs @@ -2,9 +2,10 @@ use crate::{Color, Size}; use grid::Grid; use std::collections::HashSet; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub enum Error { InvalidPosition, + SelfCapture, } #[derive(Clone, Debug)] @@ -69,6 +70,8 @@ impl Board { return Err(Error::InvalidPosition); } + let old_groups = self.groups.clone(); + let mut friendly_group = self .adjacencies(&coordinate) .into_iter() @@ -95,6 +98,11 @@ impl Board { } } + if self.liberties(&friendly_group) == 0 { + self.groups = old_groups; + return Err(Error::SelfCapture); + } + Ok(()) } @@ -117,13 +125,11 @@ impl Board { pub fn adjacent_groups(&self, group: &Group) -> Vec { let adjacent_spaces = self.group_halo(group).into_iter(); - println!("adjacent spaces: {:?}", adjacent_spaces); let mut grps: Vec = Vec::new(); adjacent_spaces.for_each(|coord| match self.group(&coord) { None => return, Some(adj) => { - println!("group found: {:?}", adj.color); if group.color == adj.color { return; } @@ -151,32 +157,6 @@ impl Board { .into_iter() .filter(|c| self.stone(&c) == None) .count() - - // let adjacencies: HashSet = self.adjacencies(group.coordinates.iter()).collect(); - /* - println!("adjacencies: {:?}", adjacencies); - let opposing_spaces = adjacencies - .iter() - .filter(|coord| match self.grid.get(coord.row, coord.column) { - None => true, - Some(&None) => false, - Some(&Some(c)) => c != group.color, - }) - .cloned() - .collect::>(); - println!("opposition: {:?}", opposing_spaces); - - adjacencies.len() - opposing_spaces.len() - */ - - /* - group - .adjacencies(self.size.width as u8 - 1, self.size.height as u8 - 1) - .into_iter() - .filter(|coordinate| self.stone(*coordinate).is_none()) - .collect::>() - .len() - */ } pub fn adjacencies(&self, coordinate: &Coordinate) -> Vec { @@ -204,41 +184,6 @@ impl Board { v.into_iter().filter(|c| self.within_board(c)).collect() } - /* - pub fn adjacencies<'a>( - &'a self, - coordinates: impl Iterator + 'a, - ) -> impl Iterator + 'a { - coordinates - .map(|coordinate| { - let mut v = Vec::new(); - if coordinate.column > 0 { - v.push(Coordinate { - column: coordinate.column - 1, - row: coordinate.row, - }); - } - if coordinate.row > 0 { - v.push(Coordinate { - column: coordinate.column, - row: coordinate.row - 1, - }); - } - v.push(Coordinate { - column: coordinate.column + 1, - row: coordinate.row, - }); - v.push(Coordinate { - column: coordinate.column, - row: coordinate.row + 1, - }); - v - }) - .flatten() - .filter(|coordinate| self.within_board(coordinate)) - } - */ - pub fn within_board(&self, coordinate: &Coordinate) -> bool { coordinate.column < self.size.width && coordinate.row < self.size.height } @@ -256,18 +201,6 @@ impl Group { } } -/* -impl Group { - pub fn adjacencies(&self, max_column: usize, max_row: usize) -> HashSet { - self.coordinates - .iter() - .map(|stone| stone.adjacencies(max_column, max_row)) - .flatten() - .collect() - } -} -*/ - #[cfg(test)] mod test { use super::*; @@ -329,6 +262,10 @@ mod test { (Coordinate { column: 6, row: 16 }, Color::White), (Coordinate { column: 7, row: 17 }, Color::White), (Coordinate { column: 7, row: 18 }, Color::White), + /* */ + (Coordinate { column: 17, row: 0 }, Color::White), + (Coordinate { column: 17, row: 1 }, Color::White), + (Coordinate { column: 18, row: 1 }, Color::White), ] .into_iter(), ); @@ -594,8 +531,15 @@ mod test { }); } - fn suicide_is_forbidden() { - assert!(false); + #[test] + fn self_capture_is_forbidden() { + with_example_board(|mut board| { + let res = board.place_stone(Coordinate { column: 18, row: 0 }, Color::Black); + assert_eq!(res, Err(Error::SelfCapture)); + + let res = board.place_stone(Coordinate { column: 5, row: 18 }, Color::Black); + assert_eq!(res, Err(Error::SelfCapture)); + }); } fn captures_preceed_self_capture() { diff --git a/kifu/kifu-gtk/Makefile b/kifu/kifu-gtk/Makefile index 08b2bcb..2297add 100644 --- a/kifu/kifu-gtk/Makefile +++ b/kifu/kifu-gtk/Makefile @@ -2,4 +2,4 @@ release: cargo build --release dev: - cargo watch -x run + cargo watch -x 'run --bin kifu-gtk'