-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathnode_utils.go
140 lines (111 loc) · 3.26 KB
/
node_utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package sgf
import (
"fmt"
"sort"
)
// Parent returns the parent of a node. This will be nil if the node is the root
// of the tree.
func (self *Node) Parent() *Node {
return self.parent
}
// Children returns a new slice of pointers to all the node's children.
func (self *Node) Children() []*Node {
var ret []*Node
for _, child := range self.children {
ret = append(ret, child)
}
return ret
}
// MainChild returns the first child a node has. If the node has zero children,
// nil is returned.
func (self *Node) MainChild() *Node {
if len(self.children) == 0 {
return nil
}
return self.children[0]
}
// SetParent sets a node's parent. The node is also removed from the original
// parent's list of children, and added to the new parent's list. SetParent
// panics if a cyclic tree is created.
func (self *Node) SetParent(new_parent *Node) {
// Delete from parent's list of children...
if self.parent != nil {
for i := len(self.parent.children) - 1; i >= 0; i-- {
if self.parent.children[i] == self {
self.parent.children = append(self.parent.children[:i], self.parent.children[i + 1:]...)
}
}
}
// Attach to parent (at both ends)...
self.parent = new_parent
if self.parent != nil {
self.parent.children = append(self.parent.children, self)
}
// Check no cyclic structure was created...
node := self
for node.parent != nil {
if node.parent == self {
panic("Cyclic structure created.")
}
node = node.parent
}
// Clear the board cache (and that of all descendents) because it's invalid now.
self.clear_board_cache_recursive()
}
// Detach sets a node's parent to nil, turning the node into a root. The node is
// also removed from the parent's list of children.
func (self *Node) Detach() {
self.SetParent(nil)
}
// String returns some human-readable info about the node.
func (self *Node) String() string {
if self == nil {
return "<nil>"
}
noun := "children" ; if len(self.children) == 1 { noun = "child" }
keys := self.AllKeys()
sort.Strings(keys)
return fmt.Sprintf("Node %p: depth %d, %d %s, subtree size %d, keys %v",
self, len(self.GetLine()) - 1, len(self.children), noun, self.SubtreeSize(), keys)
}
// Validate checks a node for obvious problems; it returns the first problem
// found as an error, otherwise it returns nil.
func (self *Node) Validate() error {
all_b := self.AllValues("B")
all_w := self.AllValues("W")
all_ab := self.AllValues("AB")
all_aw := self.AllValues("AW")
all_ae := self.AllValues("AE")
if len(all_b) + len(all_w) > 1 {
return fmt.Errorf("Too many moves (B or W values)")
}
if len(all_b) + len(all_w) > 0 && len(all_ab) + len(all_aw) + len(all_ae) > 0 {
return fmt.Errorf("Mix of move and setup properties")
}
if self.parent != nil {
board := self.parent.Board()
if len(all_b) > 0 {
mv := all_b[0]
if ValidPoint(mv, board.Size) {
legal, err := board.LegalColour(mv, BLACK)
if legal == false {
return err
}
} else if mv != "" && mv != "tt" {
return fmt.Errorf("Got B value: %s", mv)
}
}
if len(all_w) > 0 {
mv := all_w[0]
if ValidPoint(mv, board.Size) {
legal, err := board.LegalColour(mv, WHITE)
if legal == false {
return err
}
} else if mv != "" && mv != "tt" {
return fmt.Errorf("Got W value: %s", mv)
}
}
}
return nil
}