Implement the basic rules of Go #40
|
@ -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<Group> {
|
||||
let adjacent_spaces = self.group_halo(group).into_iter();
|
||||
println!("adjacent spaces: {:?}", adjacent_spaces);
|
||||
let mut grps: Vec<Group> = 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<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> {
|
||||
|
@ -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<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 {
|
||||
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)]
|
||||
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() {
|
||||
|
|
|
@ -2,4 +2,4 @@ release:
|
|||
cargo build --release
|
||||
|
||||
dev:
|
||||
cargo watch -x run
|
||||
cargo watch -x 'run --bin kifu-gtk'
|
||||
|
|
Loading…
Reference in New Issue