carina_libgo/
sgf.rs

1pub use sgf_parse::*;
2
3//transform sgf_parse::Color to crate::Color
4impl From<crate::Color> for Color {
5    fn from(c: crate::Color) -> Self {
6        match c {
7            crate::Color::Black => Color::Black,
8            crate::Color::White => Color::White,
9        }
10    }
11}
12
13// transform crate::Color to sgf_parse::Color
14impl From<Color> for crate::Color {
15    fn from(c: Color) -> Self {
16        match c {
17            Color::Black => crate::Color::Black,
18            Color::White => crate::Color::White,
19        }
20    }
21}
22
23// impl crate::Move function to_sgf;
24impl crate::Move {
25    pub fn to_sgf(self) -> go::Move {
26        match self {
27            crate::Move::Pass => go::Move::Pass,
28            crate::Move::Coordinate { x, y } => go::Move::Move(go::Point { x, y }),
29        }
30    }
31
32    pub fn from_sgf(m: go::Move) -> Self {
33        match m {
34            go::Move::Pass => crate::Move::Pass,
35            go::Move::Move(p) => crate::Move::Coordinate { x: p.x, y: p.y },
36        }
37    }
38}
39
40pub struct BranchesIterator<'a> {
41    /// Stack of parent nodes to keep track of the current branch
42    stack: Vec<(&'a SgfNode<go::Prop>, usize)>,
43}
44
45impl<'a> BranchesIterator<'a> {
46    pub fn new(root: &'a SgfNode<go::Prop>) -> Self {
47        let mut stack = Vec::new();
48        stack.push((root, 0));
49        BranchesIterator { stack }
50    }
51}
52
53impl<'a> Iterator for BranchesIterator<'a> {
54    type Item = Vec<&'a SgfNode<go::Prop>>;
55
56    fn next(&mut self) -> Option<Self::Item> {
57        loop {
58            let (current_node, child_idx) = match self.stack.pop() {
59                Some(data) => data,
60                None => return None, // stack is empty, return None. iteration is done
61            };
62            // if current node children is empty, return current node
63            if current_node.children.is_empty() {
64                let mut current_path = self.stack.iter().map(|(node, _)| *node).collect::<Vec<_>>();
65                // Push current node to path
66                current_path.push(current_node);
67                // backtrack to the last unvisited node
68                loop {
69                    let (current_node, child_idx) = match self.stack.pop() {
70                        Some(data) => data,
71                        None => break, // stack is empty, break out of the loop
72                    };
73                    if current_node.children.len() > child_idx {
74                        // Push back
75                        self.stack.push((current_node, child_idx));
76                        break;
77                    }
78                }
79                return Some(current_path);
80            } else {
81                self.stack.push((current_node, child_idx + 1));
82                let child_node = &current_node.children[child_idx];
83                self.stack.push((child_node, 0)); // 
84            }
85        }
86    }
87}
88
89pub trait IntoMoves {
90    fn into_moves(self) -> Vec<(Color, go::Move)>;
91}
92
93impl<'a, T> IntoMoves for T
94where
95    T: Iterator<Item = &'a SgfNode<go::Prop>>,
96{
97    fn into_moves(self) -> Vec<(Color, go::Move)> {
98        let mut moves = Vec::new();
99        self.for_each(|node| {
100            if let Some(prop) = node.get_move() {
101                match prop {
102                    go::Prop::B(m) => {
103                        moves.push((Color::Black, m.clone()));
104                    }
105                    go::Prop::W(m) => {
106                        moves.push((Color::White, m.clone()));
107                    }
108                    _ => {}
109                }
110            }
111        });
112        moves
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use super::*;
119    use crate::Move;
120
121    #[test]
122    fn test_move_to_sgf() {
123        assert_eq!(
124            Move::new(0, 1).to_sgf(),
125            go::Move::Move(go::Point { x: 0, y: 1 })
126        );
127        assert_eq!(
128            Move::new(18, 18).to_sgf(),
129            go::Move::Move(go::Point { x: 18, y: 18 })
130        );
131    }
132
133    #[test]
134    fn test_move_from_sgf() {
135        assert_eq!(
136            Move::from_sgf(go::Move::Move(go::Point { x: 0, y: 1 })),
137            Move::new(0, 1)
138        );
139        assert_eq!(Move::from_sgf(go::Move::Pass), Move::Pass);
140    }
141}