Start on a second-level representation for the game tree
This commit is contained in:
parent
d6c2a9519b
commit
0700f13429
|
@ -2309,6 +2309,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"typeshare",
|
"typeshare",
|
||||||
|
"uuid 1.4.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2726,6 +2727,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
|
checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -11,6 +11,7 @@ nom = { version = "7" }
|
||||||
serde = { version = "1", features = [ "derive" ] }
|
serde = { version = "1", features = [ "derive" ] }
|
||||||
thiserror = { version = "1"}
|
thiserror = { version = "1"}
|
||||||
typeshare = { version = "1" }
|
typeshare = { version = "1" }
|
||||||
|
uuid = { version = "1.4", features = ["v4", "serde"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
cool_asserts = { version = "2" }
|
cool_asserts = { version = "2" }
|
||||||
|
|
|
@ -0,0 +1,272 @@
|
||||||
|
use crate::{Color, Position};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub trait Node {
|
||||||
|
fn path_to_node<'a>(&'a self, id: Uuid) -> Vec<&'a GameNode>;
|
||||||
|
fn add_child<'a>(&'a mut self, node: GameNode) -> &'a GameNode;
|
||||||
|
fn add_annotation(&mut self, label: String, note: String);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum GameNode {
|
||||||
|
MoveNode(MoveNode),
|
||||||
|
SetupNode(SetupNode),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GameNode {
|
||||||
|
fn id(&self) -> Uuid {
|
||||||
|
match self {
|
||||||
|
GameNode::MoveNode(node) => node.id,
|
||||||
|
GameNode::SetupNode(node) => node.id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn children<'a>(&'a self) -> Vec<&'a GameNode> {
|
||||||
|
unimplemented!("GameNode::children")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Node for GameNode {
|
||||||
|
fn path_to_node<'a>(&'a self, id: Uuid) -> Vec<&'a GameNode> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_child<'a>(&'a mut self, node: GameNode) -> &'a GameNode {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_annotation(&mut self, label: String, note: String) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Root node
|
||||||
|
pub struct GameTree {
|
||||||
|
children: Vec<GameNode>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GameTree {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self { children: vec![] }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nodes<'a>(&'a self) -> impl Iterator<Item = &'a GameNode> {
|
||||||
|
vec![].into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_child<'a>(&'a mut self, node: GameNode) -> &'a GameNode {
|
||||||
|
// self.children.push(node);
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Node for GameTree {
|
||||||
|
fn path_to_node<'a>(&'a self, id: Uuid) -> Vec<&'a GameNode> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_child<'a>(&'a mut self, node: GameNode) -> &'a GameNode {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_annotation(&mut self, label: String, note: String) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MoveNode {
|
||||||
|
id: Uuid,
|
||||||
|
|
||||||
|
color: Color,
|
||||||
|
position: Position,
|
||||||
|
annotations: Vec<(String, String)>,
|
||||||
|
children: Vec<GameNode>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MoveNode {
|
||||||
|
pub fn new(color: Color, position: Position) -> Self {
|
||||||
|
Self {
|
||||||
|
id: Uuid::new_v4(),
|
||||||
|
|
||||||
|
color,
|
||||||
|
position,
|
||||||
|
annotations: Vec::new(),
|
||||||
|
children: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Node for MoveNode {
|
||||||
|
fn path_to_node<'a>(&'a self, id: Uuid) -> Vec<&'a GameNode> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_child<'a>(&'a mut self, node: GameNode) -> &'a GameNode {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_annotation(&mut self, label: String, note: String) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SetupNode {
|
||||||
|
id: Uuid,
|
||||||
|
|
||||||
|
positions: Vec<(Color, Position)>,
|
||||||
|
annotations: Vec<(String, String)>,
|
||||||
|
children: Vec<GameNode>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetupNode {
|
||||||
|
pub fn new(positions: Vec<(Color, Position)>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: Uuid::new_v4(),
|
||||||
|
positions,
|
||||||
|
annotations: Vec::new(),
|
||||||
|
children: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Node for SetupNode {
|
||||||
|
fn path_to_node<'a>(&'a self, id: Uuid) -> Vec<&'a GameNode> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_child<'a>(&'a mut self, node: GameNode) -> &'a GameNode {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_annotation(&mut self, label: String, note: String) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn path_to_node<'a>(node: &'a GameNode, id: Uuid) -> Vec<&'a GameNode> {
|
||||||
|
if node.id() == id {
|
||||||
|
return vec![node];
|
||||||
|
}
|
||||||
|
|
||||||
|
for child in node.children() {
|
||||||
|
let mut path = path_to_node(child, id);
|
||||||
|
if path.len() > 1 {
|
||||||
|
path.push(child);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_can_create_an_empty_game_tree() {
|
||||||
|
let tree = GameTree::new();
|
||||||
|
assert_eq!(tree.nodes().count(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_can_add_moves_to_a_game() {
|
||||||
|
let mut tree = GameTree::new();
|
||||||
|
|
||||||
|
let node = MoveNode::new(Color::Black, Position {});
|
||||||
|
let mut node = tree.add_child(GameNode::MoveNode(node));
|
||||||
|
let new_node = MoveNode::new(Color::White, Position {});
|
||||||
|
node.add_child(new_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_can_set_up_a_game() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_can_load_tree_from_sgf() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod root_node_tests {
|
||||||
|
#[test]
|
||||||
|
fn it_rejects_move_properties() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_rejects_setup_properties() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_can_parse_a_root_sgf() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod move_node_tests {
|
||||||
|
#[test]
|
||||||
|
fn it_rejects_setup_properties() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_rejects_root_properties() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_can_parse_an_sgf_move_node() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_rejects_an_sgf_setup_node() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod setup_node_tests {
|
||||||
|
#[test]
|
||||||
|
fn it_rejects_move_properties() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_rejects_root_properties() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_can_parse_an_sgf_setup_node() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_rejects_an_sgf_move_node() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod path_test {
|
||||||
|
#[test]
|
||||||
|
fn returns_empty_list_if_no_game_nodes() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn returns_empty_list_if_node_not_found() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn path_excludes_root_node() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,8 @@ pub mod go;
|
||||||
mod tree;
|
mod tree;
|
||||||
use tree::parse_collection;
|
use tree::parse_collection;
|
||||||
|
|
||||||
|
mod game;
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -16,6 +18,13 @@ pub enum Error {
|
||||||
InvalidSgf(VerboseNomError),
|
InvalidSgf(VerboseNomError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum Color {
|
||||||
|
Black,
|
||||||
|
White,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Position {}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct VerboseNomError(nom::error::VerboseError<String>);
|
pub struct VerboseNomError(nom::error::VerboseError<String>);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue