|
|
|
@ -2,10 +2,9 @@ use crate::goban::{Coordinate, Goban};
|
|
|
|
|
use config::define_config;
|
|
|
|
|
use config_derive::ConfigOption;
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
use sgf::GameNode;
|
|
|
|
|
use sgf::GameTree;
|
|
|
|
|
use std::{cell::RefCell, collections::VecDeque, fmt, path::PathBuf, time::Duration};
|
|
|
|
|
use thiserror::Error;
|
|
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
|
|
|
|
define_config! {
|
|
|
|
|
LibraryPath(LibraryPath),
|
|
|
|
@ -229,6 +228,7 @@ impl GameState {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
// To properly generate a tree, I need to know how deep to go. Then I can backtrace. Each node
|
|
|
|
|
// needs to have a depth. Given a tree, the depth of the node is just the distance from the root.
|
|
|
|
|
// This seems obvious, but I had to write it to discover how important that fact was.
|
|
|
|
@ -238,18 +238,22 @@ impl GameState {
|
|
|
|
|
pub struct Tree<T> {
|
|
|
|
|
nodes: Vec<Node<T>>,
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
struct DepthTree(slab_tree::Tree<SizeNode>);
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct Node<T> {
|
|
|
|
|
pub struct SizeNode {
|
|
|
|
|
pub id: usize,
|
|
|
|
|
node: T,
|
|
|
|
|
node_id: slab_tree::NodeId,
|
|
|
|
|
parent: Option<usize>,
|
|
|
|
|
depth: usize,
|
|
|
|
|
width: RefCell<Option<usize>>,
|
|
|
|
|
children: Vec<usize>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T> Tree<T> {
|
|
|
|
|
impl DepthTree {
|
|
|
|
|
/*
|
|
|
|
|
fn new(root: T) -> Self {
|
|
|
|
|
Tree {
|
|
|
|
|
nodes: vec![Node {
|
|
|
|
@ -286,12 +290,16 @@ impl<T> Tree<T> {
|
|
|
|
|
parent.children.push(next_idx);
|
|
|
|
|
next_idx
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
pub fn max_depth(&self) -> usize {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
/*
|
|
|
|
|
self.nodes.iter().fold(
|
|
|
|
|
0,
|
|
|
|
|
|max, node| if node.depth > max { node.depth } else { max },
|
|
|
|
|
)
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Since I know the width of a node, now I want to figure out its placement in the larger
|
|
|
|
@ -310,6 +318,8 @@ impl<T> Tree<T> {
|
|
|
|
|
//
|
|
|
|
|
// When drawing nodes, I don't know how to persist the level of indent.
|
|
|
|
|
pub fn position(&self, idx: usize) -> (usize, usize) {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
/*
|
|
|
|
|
let node = &self.nodes[idx];
|
|
|
|
|
match node.parent {
|
|
|
|
|
Some(parent_idx) => {
|
|
|
|
@ -326,8 +336,10 @@ impl<T> Tree<T> {
|
|
|
|
|
// Root nodes won't have a parent, so just put them in the first column
|
|
|
|
|
None => (0, 0),
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
// Given a node, do a postorder traversal to figure out the width of the node based on all of
|
|
|
|
|
// its children. This is equivalent to the widest of all of its children at all depths.
|
|
|
|
|
//
|
|
|
|
@ -359,8 +371,16 @@ impl<T> Tree<T> {
|
|
|
|
|
queue.push_back(&self.nodes[0]);
|
|
|
|
|
BFSIter { tree: self, queue }
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a> From<&'a GameTree> for DepthTree {
|
|
|
|
|
fn from(root: &'a GameTree) -> Self {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
impl<'a> From<&'a GameNode> for Tree<Uuid> {
|
|
|
|
|
fn from(root: &'a GameNode) -> Self {
|
|
|
|
|
fn add_subtree(tree: &mut Tree<Uuid>, parent_idx: usize, node: &GameNode) {
|
|
|
|
@ -390,7 +410,9 @@ impl<'a> From<&'a GameNode> for Tree<Uuid> {
|
|
|
|
|
tree
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
pub struct BFSIter<'a, T> {
|
|
|
|
|
tree: &'a Tree<T>,
|
|
|
|
|
queue: VecDeque<&'a Node<T>>,
|
|
|
|
@ -410,12 +432,13 @@ impl<'a, T> Iterator for BFSIter<'a, T> {
|
|
|
|
|
retval
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod test {
|
|
|
|
|
use super::*;
|
|
|
|
|
use cool_asserts::assert_matches;
|
|
|
|
|
use sgf::{Move, MoveNode};
|
|
|
|
|
// use sgf::{GameRecord, GameTree, GameType, Move, MoveNode};
|
|
|
|
|
use sgf::{GameNode, GameTree, Move, MoveNode};
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn current_player_changes_after_move() {
|
|
|
|
@ -474,69 +497,91 @@ mod test {
|
|
|
|
|
// B G H
|
|
|
|
|
// C I
|
|
|
|
|
// D E F
|
|
|
|
|
fn branching_tree() -> GameTree {
|
|
|
|
|
let mut game_tree = GameTree::default();
|
|
|
|
|
let node_a = game_tree.set_root(GameNode::MoveNode(MoveNode::new(
|
|
|
|
|
sgf::Color::Black,
|
|
|
|
|
Move::Move("dp".to_owned()),
|
|
|
|
|
)));
|
|
|
|
|
|
|
|
|
|
let node_b = game_tree
|
|
|
|
|
.get_mut(node_a)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.append(GameNode::MoveNode(MoveNode::new(
|
|
|
|
|
sgf::Color::Black,
|
|
|
|
|
Move::Move("dp".to_owned()),
|
|
|
|
|
))).node_id();
|
|
|
|
|
|
|
|
|
|
let node_c = game_tree
|
|
|
|
|
.get_mut(node_b)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.append(GameNode::MoveNode(MoveNode::new(
|
|
|
|
|
sgf::Color::Black,
|
|
|
|
|
Move::Move("dp".to_owned()),
|
|
|
|
|
))).node_id();
|
|
|
|
|
|
|
|
|
|
let node_d = game_tree
|
|
|
|
|
.get_mut(node_c)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.append(GameNode::MoveNode(MoveNode::new(
|
|
|
|
|
sgf::Color::Black,
|
|
|
|
|
Move::Move("dp".to_owned()),
|
|
|
|
|
))).node_id();
|
|
|
|
|
|
|
|
|
|
let node_e = game_tree
|
|
|
|
|
.get_mut(node_c)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.append(GameNode::MoveNode(MoveNode::new(
|
|
|
|
|
sgf::Color::Black,
|
|
|
|
|
Move::Move("dp".to_owned()),
|
|
|
|
|
))).node_id();
|
|
|
|
|
|
|
|
|
|
let node_f = game_tree
|
|
|
|
|
.get_mut(node_c)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.append(GameNode::MoveNode(MoveNode::new(
|
|
|
|
|
sgf::Color::Black,
|
|
|
|
|
Move::Move("dp".to_owned()),
|
|
|
|
|
))).node_id();
|
|
|
|
|
|
|
|
|
|
let node_g = game_tree
|
|
|
|
|
.get_mut(node_a)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.append(GameNode::MoveNode(MoveNode::new(
|
|
|
|
|
sgf::Color::Black,
|
|
|
|
|
Move::Move("dp".to_owned()),
|
|
|
|
|
))).node_id();
|
|
|
|
|
|
|
|
|
|
let node_h = game_tree
|
|
|
|
|
.get_mut(node_a)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.append(GameNode::MoveNode(MoveNode::new(
|
|
|
|
|
sgf::Color::Black,
|
|
|
|
|
Move::Move("dp".to_owned()),
|
|
|
|
|
))).node_id();
|
|
|
|
|
|
|
|
|
|
let _ = game_tree
|
|
|
|
|
.get_mut(node_h)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.append(GameNode::MoveNode(MoveNode::new(
|
|
|
|
|
sgf::Color::Black,
|
|
|
|
|
Move::Move("dp".to_owned()),
|
|
|
|
|
)));
|
|
|
|
|
|
|
|
|
|
game_tree
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn it_can_calculate_depth_from_game_tree() {
|
|
|
|
|
let mut node_a = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let mut node_b = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let mut node_c = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_d = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_e = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_f = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_g = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let mut node_h = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_i = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
|
|
|
|
|
node_c.children.push(GameNode::MoveNode(node_d));
|
|
|
|
|
node_c.children.push(GameNode::MoveNode(node_e));
|
|
|
|
|
node_c.children.push(GameNode::MoveNode(node_f));
|
|
|
|
|
|
|
|
|
|
node_b.children.push(GameNode::MoveNode(node_c));
|
|
|
|
|
|
|
|
|
|
node_h.children.push(GameNode::MoveNode(node_i));
|
|
|
|
|
|
|
|
|
|
node_a.children.push(GameNode::MoveNode(node_b));
|
|
|
|
|
node_a.children.push(GameNode::MoveNode(node_g));
|
|
|
|
|
node_a.children.push(GameNode::MoveNode(node_h));
|
|
|
|
|
|
|
|
|
|
let game_tree = GameNode::MoveNode(node_a);
|
|
|
|
|
|
|
|
|
|
let tree = Tree::from(&game_tree);
|
|
|
|
|
|
|
|
|
|
let game_tree = branching_tree();
|
|
|
|
|
let tree = DepthTree::from(&game_tree);
|
|
|
|
|
assert_eq!(tree.max_depth(), 3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A
|
|
|
|
|
// B G H
|
|
|
|
|
// C I
|
|
|
|
|
// D E F
|
|
|
|
|
#[test]
|
|
|
|
|
fn it_calculates_horizontal_position_of_nodes() {
|
|
|
|
|
let mut node_a = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let mut node_b = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let mut node_c = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_d = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_e = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_f = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_g = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let mut node_h = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_i = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
|
|
|
|
|
node_c.children.push(GameNode::MoveNode(node_d));
|
|
|
|
|
node_c.children.push(GameNode::MoveNode(node_e));
|
|
|
|
|
node_c.children.push(GameNode::MoveNode(node_f));
|
|
|
|
|
|
|
|
|
|
node_b.children.push(GameNode::MoveNode(node_c));
|
|
|
|
|
|
|
|
|
|
node_h.children.push(GameNode::MoveNode(node_i));
|
|
|
|
|
|
|
|
|
|
node_a.children.push(GameNode::MoveNode(node_b));
|
|
|
|
|
node_a.children.push(GameNode::MoveNode(node_g));
|
|
|
|
|
node_a.children.push(GameNode::MoveNode(node_h));
|
|
|
|
|
|
|
|
|
|
let game_tree = GameNode::MoveNode(node_a);
|
|
|
|
|
|
|
|
|
|
let tree = Tree::from(&game_tree);
|
|
|
|
|
|
|
|
|
|
let game_tree = branching_tree();
|
|
|
|
|
let tree = DepthTree::from(&game_tree);
|
|
|
|
|
assert_eq!(tree.position(2), (2, 0));
|
|
|
|
|
assert_eq!(tree.position(1), (1, 0));
|
|
|
|
|
assert_eq!(tree.position(0), (0, 0));
|
|
|
|
@ -546,44 +591,65 @@ mod test {
|
|
|
|
|
assert_eq!(tree.position(7), (1, 4));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[ignore]
|
|
|
|
|
#[test]
|
|
|
|
|
fn breadth_first_iter() {
|
|
|
|
|
let mut node_a = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let mut node_b = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let mut node_c = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_d = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_e = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_f = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_g = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let mut node_h = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_i = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
/*
|
|
|
|
|
let mut node_a = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let mut node_b = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let mut node_c = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_d = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_e = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_f = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_g = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let mut node_h = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
let node_i = MoveNode::new(sgf::Color::Black, Move::Move("dp".to_owned()));
|
|
|
|
|
|
|
|
|
|
node_c.children.push(GameNode::MoveNode(node_d.clone()));
|
|
|
|
|
node_c.children.push(GameNode::MoveNode(node_e.clone()));
|
|
|
|
|
node_c.children.push(GameNode::MoveNode(node_f.clone()));
|
|
|
|
|
let game = GameRecord::new(
|
|
|
|
|
GameType::Go,
|
|
|
|
|
Size {
|
|
|
|
|
width: 19,
|
|
|
|
|
height: 19,
|
|
|
|
|
},
|
|
|
|
|
Player {
|
|
|
|
|
name: Some("Black".to_owned()),
|
|
|
|
|
rank: None,
|
|
|
|
|
team: None,
|
|
|
|
|
},
|
|
|
|
|
Player {
|
|
|
|
|
name: Some("White".to_owned()),
|
|
|
|
|
rank: None,
|
|
|
|
|
team: None,
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
node_b.children.push(GameNode::MoveNode(node_c.clone()));
|
|
|
|
|
node_c.children.push(GameNode::MoveNode(node_d.clone()));
|
|
|
|
|
node_c.children.push(GameNode::MoveNode(node_e.clone()));
|
|
|
|
|
node_c.children.push(GameNode::MoveNode(node_f.clone()));
|
|
|
|
|
|
|
|
|
|
node_h.children.push(GameNode::MoveNode(node_i.clone()));
|
|
|
|
|
node_b.children.push(GameNode::MoveNode(node_c.clone()));
|
|
|
|
|
|
|
|
|
|
node_a.children.push(GameNode::MoveNode(node_b.clone()));
|
|
|
|
|
node_a.children.push(GameNode::MoveNode(node_g.clone()));
|
|
|
|
|
node_a.children.push(GameNode::MoveNode(node_h.clone()));
|
|
|
|
|
node_h.children.push(GameNode::MoveNode(node_i.clone()));
|
|
|
|
|
|
|
|
|
|
let game_tree = GameNode::MoveNode(node_a.clone());
|
|
|
|
|
node_a.children.push(GameNode::MoveNode(node_b.clone()));
|
|
|
|
|
node_a.children.push(GameNode::MoveNode(node_g.clone()));
|
|
|
|
|
node_a.children.push(GameNode::MoveNode(node_h.clone()));
|
|
|
|
|
|
|
|
|
|
let tree = Tree::from(&game_tree);
|
|
|
|
|
let game_tree = GameNode::MoveNode(node_a.clone());
|
|
|
|
|
|
|
|
|
|
let mut iter = tree.bfs_iter();
|
|
|
|
|
let tree = Tree::from(&game_tree);
|
|
|
|
|
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_a.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_b.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_g.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_h.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_c.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_i.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_d.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_e.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_f.id));
|
|
|
|
|
let mut iter = tree.bfs_iter();
|
|
|
|
|
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_a.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_b.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_g.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_h.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_c.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_i.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_d.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_e.id));
|
|
|
|
|
assert_matches!(iter.next(), Some(Node { node: uuid, .. }) => assert_eq!(*uuid, node_f.id));
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|