Implement the self-capture rule
This commit is contained in:
parent
27d87fcd02
commit
d68e088500
|
@ -2,9 +2,10 @@ use crate::{Color, Size};
|
||||||
use grid::Grid;
|
use grid::Grid;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
InvalidPosition,
|
InvalidPosition,
|
||||||
|
SelfCapture,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -69,6 +70,8 @@ impl Board {
|
||||||
return Err(Error::InvalidPosition);
|
return Err(Error::InvalidPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let old_groups = self.groups.clone();
|
||||||
|
|
||||||
let mut friendly_group = self
|
let mut friendly_group = self
|
||||||
.adjacencies(&coordinate)
|
.adjacencies(&coordinate)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -95,6 +98,11 @@ impl Board {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.liberties(&friendly_group) == 0 {
|
||||||
|
self.groups = old_groups;
|
||||||
|
return Err(Error::SelfCapture);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,13 +125,11 @@ impl Board {
|
||||||
|
|
||||||
pub fn adjacent_groups(&self, group: &Group) -> Vec<Group> {
|
pub fn adjacent_groups(&self, group: &Group) -> Vec<Group> {
|
||||||
let adjacent_spaces = self.group_halo(group).into_iter();
|
let adjacent_spaces = self.group_halo(group).into_iter();
|
||||||
println!("adjacent spaces: {:?}", adjacent_spaces);
|
|
||||||
let mut grps: Vec<Group> = Vec::new();
|
let mut grps: Vec<Group> = Vec::new();
|
||||||
|
|
||||||
adjacent_spaces.for_each(|coord| match self.group(&coord) {
|
adjacent_spaces.for_each(|coord| match self.group(&coord) {
|
||||||
None => return,
|
None => return,
|
||||||
Some(adj) => {
|
Some(adj) => {
|
||||||
println!("group found: {:?}", adj.color);
|
|
||||||
if group.color == adj.color {
|
if group.color == adj.color {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -151,32 +157,6 @@ impl Board {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|c| self.stone(&c) == None)
|
.filter(|c| self.stone(&c) == None)
|
||||||
.count()
|
.count()
|
||||||
|
|
||||||
// let adjacencies: HashSet<Coordinate> = 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::<HashSet<Coordinate>>();
|
|
||||||
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::<Vec<Coordinate>>()
|
|
||||||
.len()
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn adjacencies(&self, coordinate: &Coordinate) -> Vec<Coordinate> {
|
pub fn adjacencies(&self, coordinate: &Coordinate) -> Vec<Coordinate> {
|
||||||
|
@ -204,41 +184,6 @@ impl Board {
|
||||||
v.into_iter().filter(|c| self.within_board(c)).collect()
|
v.into_iter().filter(|c| self.within_board(c)).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
pub fn adjacencies<'a>(
|
|
||||||
&'a self,
|
|
||||||
coordinates: impl Iterator<Item = &'a Coordinate> + 'a,
|
|
||||||
) -> impl Iterator<Item = Coordinate> + '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 {
|
pub fn within_board(&self, coordinate: &Coordinate) -> bool {
|
||||||
coordinate.column < self.size.width && coordinate.row < self.size.height
|
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<Coordinate> {
|
|
||||||
self.coordinates
|
|
||||||
.iter()
|
|
||||||
.map(|stone| stone.adjacencies(max_column, max_row))
|
|
||||||
.flatten()
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -329,6 +262,10 @@ mod test {
|
||||||
(Coordinate { column: 6, row: 16 }, Color::White),
|
(Coordinate { column: 6, row: 16 }, Color::White),
|
||||||
(Coordinate { column: 7, row: 17 }, Color::White),
|
(Coordinate { column: 7, row: 17 }, Color::White),
|
||||||
(Coordinate { column: 7, row: 18 }, 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(),
|
.into_iter(),
|
||||||
);
|
);
|
||||||
|
@ -594,8 +531,15 @@ mod test {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suicide_is_forbidden() {
|
#[test]
|
||||||
assert!(false);
|
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() {
|
fn captures_preceed_self_capture() {
|
||||||
|
|
|
@ -2,4 +2,4 @@ release:
|
||||||
cargo build --release
|
cargo build --release
|
||||||
|
|
||||||
dev:
|
dev:
|
||||||
cargo watch -x run
|
cargo watch -x 'run --bin kifu-gtk'
|
||||||
|
|
Loading…
Reference in New Issue