00001 //---------------------------------------------------------------------------- 00002 /** @file SgNode.h 00003 Trees of nodes with properties. 00004 00005 Module SgNode defines trees and operations on those trees. The abstract 00006 data type 'Node' represents a node in a tree; each node has a list of 00007 properties associated with it. Typical properties are moves, territory, 00008 values, and comments. 00009 00010 Each node in the tree corresponds to a board position. The move leading 00011 to a position is stored in that node. The root node is the position where 00012 no move has as yet been played. Root nodes cannot have any brothers. 00013 There is no concept of "current position", as each node encodes both the 00014 tree it is in and its relation to other nodes in that tree. (The current 00015 position in the game is handled by GoGame.) 00016 00017 The special node pointer 0 has no father, no sons, no brother, 00018 and no properties. 00019 It is usually returned from procedures to indicate failure. 00020 Because the tree is usually traversed depth-first, it is safe to assume 00021 that it is faster to go to the leftmost than to the rightmost son, and 00022 faster to go to the right brother than to the left brother. */ 00023 //---------------------------------------------------------------------------- 00024 00025 #ifndef SG_NODE_H 00026 #define SG_NODE_H 00027 00028 #include <string> 00029 #include "SgProp.h" 00030 #include "SgPointSet.h" 00031 #include "SgVector.h" 00032 00033 //---------------------------------------------------------------------------- 00034 00035 /** Node in tree. 00036 Procedures for moving around in the tree return 0 if the desti- 00037 nation doesn't exist. 00038 References to "left" and "right" picture the tree with the root at the 00039 top and the main line of play going down the left side. */ 00040 class SgNode 00041 { 00042 public: 00043 enum Direction { 00044 PREVIOUS, 00045 NEXT, 00046 NEXT_RIGHTMOST, 00047 PREV_DEPTHFIRST, 00048 NEXT_DEPTHFIRST, 00049 PREV_TERMINAL, 00050 NEXT_TERMINAL, 00051 PREV_BRANCH, 00052 NEXT_BRANCH, 00053 LEFT_BROTHER, 00054 RIGHT_BROTHER, 00055 MAIN_BRANCH, 00056 START_OF_GAME, 00057 END_OF_GAME 00058 }; 00059 00060 SgNode(); 00061 00062 ~SgNode(); 00063 00064 /** Return a newly allocated copy of this node and its subtree. */ 00065 SgNode* CopyTree() const; 00066 00067 /** @todo: distinguish SgVector<SgPoint>, SgVector<int> etc. */ 00068 // @todo add const& version when conversion is done. 00069 // const SgVector<SgPoint>& VectorProp(SgPropID prop) const; 00070 SgVector<SgPoint> VectorProp(SgPropID prop) const; 00071 00072 bool HasFather() const 00073 { 00074 return (m_father != 0); 00075 } 00076 00077 bool IsRoot() const 00078 { 00079 return (m_father == 0); 00080 } 00081 00082 bool HasLeftBrother() const; 00083 00084 bool HasRightBrother() const 00085 { 00086 return (m_brother != 0); 00087 } 00088 00089 bool HasSon() const 00090 { 00091 return (m_son != 0); 00092 } 00093 00094 /** HasLeftBrother(node) OR HasRightBrother(node) */ 00095 bool HasBrother() const 00096 { 00097 return HasLeftBrother() || HasRightBrother(); 00098 } 00099 00100 /** True of the node is on the main branch of the tree, that is 00101 none of its ancestors has a left brother. */ 00102 bool IsOnMain() const; 00103 00104 /** NOT HasSon(node) */ 00105 bool IsTerminal() const 00106 { 00107 return (m_son == 0); 00108 } 00109 00110 /** NumSons(node) >= 2 */ 00111 bool IsBranchPoint() const 00112 { 00113 return (m_son && m_son->m_brother); 00114 } 00115 00116 int NumSons() const; 00117 00118 int NumLeftBrothers() const; 00119 00120 SgNode* Root() const; 00121 00122 SgNode* Father() const 00123 { 00124 return m_father; 00125 } 00126 00127 SgNode* LeftBrother() const; 00128 00129 SgNode* RightBrother() const 00130 { 00131 return m_brother; 00132 } 00133 00134 SgNode* LeftMostSon() const 00135 { 00136 return m_son; 00137 } 00138 00139 SgNode* RightMostSon() const; 00140 00141 /** Depth-first traversal of the tree. */ 00142 SgNode* NextDepthFirst() const; 00143 00144 /** Inverse operation of NextDepthFirst. */ 00145 SgNode* PrevDepthFirst() const; 00146 00147 /** Return the next node in the given direction. 00148 Returns 0 if there is no such node. */ 00149 SgNode* NodeInDirection(Direction dir) const; 00150 00151 /** Return whether this node contains a property that matches the given 00152 text. 00153 Doesn't handle text representing special properties. */ 00154 bool ContainsText(const std::string& findText); 00155 00156 /** Returns all nodes on path from this node up to the root. */ 00157 void PathToRoot(SgVectorOf<SgNode>* path) const; 00158 00159 /** Find the closest common ancestor of the two nodes. 00160 Returns the path from this node to 'node': how many times 00161 to go one node back, and a vector of the nodes to execute from 00162 there (excluding the common ancestor). */ 00163 void ShortestPathTo(SgNode* node, int* numBack, 00164 SgVectorOf<SgNode>* path) const; 00165 00166 /** Promote this node to first son. 00167 Moves all its left brothers one position to the right. */ 00168 void PromoteNode(); 00169 00170 /** The tree above this node is changed such that this node is on 00171 the main path. 00172 (first in depth-first search). */ 00173 void PromotePath(); 00174 00175 /** Deletes all nodes below this node, but not this node itself. */ 00176 void DeleteSubtree(); 00177 00178 /** Deletes everything below the current node except the main branch. */ 00179 void DeleteBranches(); 00180 00181 /** Deletes the tree that this node is part of. 00182 Same as: 00183 @verbatim 00184 SgNode* root = Root(); 00185 root->DeleteSubtree(); 00186 delete root; 00187 @endverbatim */ 00188 void DeleteTree(); 00189 00190 SgNode* NewFather(); 00191 00192 SgNode* NewRightBrother(); 00193 00194 SgNode* NewLeftMostSon(); 00195 00196 /** Insert a node at the appropriate place in the tree. */ 00197 SgNode* NewRightMostSon(); 00198 00199 /** Append this tree to '*n'. */ 00200 void AppendTo(SgNode* n); 00201 00202 /** Add a new node and add all trees in 'roots' as subtrees of that 00203 node. */ 00204 static SgNode* LinkTrees(const SgVectorOf<SgNode>& roots); 00205 00206 SgPropList& Props() 00207 { 00208 return m_props; 00209 } 00210 00211 const SgPropList& Props() const 00212 { 00213 return m_props; 00214 } 00215 00216 void Add(const SgProp* prop) 00217 { 00218 // Check for root properties in root or one below root (linked nodes 00219 // in game collection). 00220 SG_ASSERT(! prop->Flag(SG_PROPCLASS_ROOT) || ! HasFather() 00221 || ! Father()->HasFather()); 00222 m_props.Add(prop); 00223 } 00224 00225 SgProp* Get(SgPropID id) const 00226 { 00227 return m_props.Get(id); 00228 } 00229 00230 /** HasProp also handles abstract node properties like SG_PROP_TERMINAL 00231 and SG_PROP_BRANCH, while Get only returns real properties. */ 00232 bool HasProp(SgPropID id) const; 00233 00234 /** has SG_PROP_MOVE_BLACK or SG_PROP_MOVE_WHITE */ 00235 bool HasNodeMove() const; 00236 00237 /** Player of move. 00238 REQUIRES: HasNodeMove() */ 00239 SgBlackWhite NodePlayer() const; 00240 00241 SgPoint NodeMove() const; 00242 00243 /** Return the most recent node that has the given property, starting 00244 backwards from this node. 00245 Return this node if it has the wanted property; return the root of the 00246 tree if no node with that property was found. */ 00247 SgNode* TopProp(SgPropID id) const; 00248 00249 /** Return the value of the given property at this node. 00250 Or 0 if there is no such property. The property must be of class 00251 SgPropInt (or a derived class). */ 00252 int GetIntProp(SgPropID id) const; 00253 00254 /** return if property exists. If true, return its value in *value */ 00255 bool GetIntProp(SgPropID id, int* value) const; 00256 00257 /** Value of the given property at this node. 00258 Returns 0 if there is no such property. 00259 The property must be of class SgPropReal. */ 00260 double GetRealProp(SgPropID id) const; 00261 00262 /** Set the value of the given property at this node to 'value'. 00263 Create such a property if it doesn't exist yet. The property must be 00264 of class SgPropInt (or a derived class). */ 00265 void SetIntProp(SgPropID id, int value); 00266 00267 /** Set the value of the given property at this node. 00268 Create such a property if it doesn't exist yet. 00269 The property must be of class SgPropReal. 00270 @param id 00271 @param value 00272 @param precision Precision; 0 means default precision (6) */ 00273 void SetRealProp(SgPropID id, double value, int precision = 0); 00274 00275 /** Set the value of the given property at this node to 'value'. 00276 Create such a property if it doesn't exist yet. The property must be 00277 of class SgPropText (or a derived class). */ 00278 void SetStringProp(SgPropID id, const std::string& value); 00279 00280 /** Return the value of the given property at this node. 00281 Or 0 if there is no such property. The property must be of class 00282 SgPropText (or a derived class). */ 00283 bool GetStringProp(SgPropID id, std::string* value) const; 00284 00285 /** Set the value of the given property at this node to 'value'. 00286 Create such a property if it doesn't exist yet. The property must be 00287 of class SgPropPointList (or a derived class). */ 00288 void SetListProp(SgPropID id, const SgVector<SgPoint>& value); 00289 00290 void SetListProp(SgPropID id, const SgPointSet& value); 00291 00292 /** Add comment to existing SG_PROP_COMMENT of this node, or create a new 00293 SG_PROP_COMMENT with this text. */ 00294 void AddComment(const std::string& comment); 00295 00296 /** If it exists, copy the property with the given 'id' from 'sourceNode' 00297 to this node, and return it. 00298 If the property doesn't exist, return 0. */ 00299 SgProp* CopyPropFrom(const SgNode& sourceNode, SgPropID id); 00300 00301 /** Copy all properties from 'sourceNode' to this node. */ 00302 void CopyAllPropsFrom(const SgNode& sourceNode); 00303 00304 /** Add a move property to this node with 'move' played by 'player'. 00305 @return the property added. 00306 @warning Only for games which use SgMoveProp 00307 @todo Too game dependent for a member of SgNode, move somewhere else */ 00308 SgProp* AddMoveProp(SgMove move, SgBlackWhite player); 00309 00310 /** Return the player, if explicitely set. 00311 REQUIRES: Get(SG_PROP_PLAYER) */ 00312 SgBlackWhite Player() const; 00313 00314 /** Count the nodes in this subtree and sets SG_PROP_NUM_NODES for each 00315 interior node in the subtree that has at least two sons, plus for this 00316 node if 'fSetPropOnThisNode' is set. 00317 Return the number of nodes in the subtree, including this node. */ 00318 int CountNodes(bool fSetPropOnThisNode); 00319 00320 static void CopySubtree(const SgNode* node, SgNode* copy); 00321 00322 #ifndef NDEBUG 00323 /** Total number of nodes allocated, still in use. */ 00324 static void GetStatistics(int* numAlloc, int* numUsed); 00325 #endif 00326 00327 static void MemCheck(); 00328 00329 /** Location of node in tree. 00330 This function builds a unique string from the location of a node 00331 in the tree. It is a list of integers separated by dots, each integer 00332 represents the child index (counting from 1) for each node in 00333 the path from the root to the given node. 00334 For example 00335 @verbatim 00336 root -- node1 -- node2 00337 | 00338 +- node3 00339 00340 root "1" 00341 node1 "1.1" 00342 node2 "1.1.1" 00343 node3 "1.2" 00344 @endverbatim 00345 A null node pointer has the TreeIndex "NIL". */ 00346 static std::string TreeIndex(const SgNode* node); 00347 00348 private: 00349 SgNode* m_son; 00350 00351 SgNode* m_father; 00352 00353 SgNode* m_brother; 00354 00355 SgPropList m_props; 00356 00357 bool m_marked; 00358 00359 void LinkWithBrother(SgNode* node); 00360 00361 void Mark() 00362 { 00363 m_marked = true; 00364 } 00365 00366 void Unmark() 00367 { 00368 m_marked = false; 00369 } 00370 00371 bool IsMarked() const 00372 { 00373 return m_marked; 00374 } 00375 00376 /** Not implemented. */ 00377 SgNode(const SgNode&); 00378 00379 /** Not implemented. */ 00380 SgNode& operator=(const SgNode&); 00381 00382 #ifndef NDEBUG 00383 static int s_alloc; 00384 00385 static int s_free; 00386 #endif 00387 }; 00388 00389 //---------------------------------------------------------------------------- 00390 00391 /** Iterator for iterating through all the sons of a SgNode */ 00392 class SgSonNodeIterator 00393 { 00394 public: 00395 SgSonNodeIterator(SgNode* node) 00396 : m_nextNode(node->LeftMostSon()) 00397 { } 00398 00399 void operator++() 00400 { 00401 m_nextNode = m_nextNode->RightBrother(); 00402 } 00403 00404 SgNode* operator*() const 00405 { 00406 SG_ASSERT(m_nextNode); 00407 return m_nextNode; 00408 } 00409 00410 operator bool() const 00411 { 00412 return m_nextNode != 0; 00413 } 00414 00415 private: 00416 SgNode* m_nextNode; 00417 00418 /** Not implemented. */ 00419 SgSonNodeIterator(const SgSonNodeIterator&); 00420 00421 /** Not implemented. */ 00422 SgSonNodeIterator& operator=(const SgSonNodeIterator&); 00423 }; 00424 00425 //---------------------------------------------------------------------------- 00426 00427 /** Iterator for iterating through all the sons of a Node */ 00428 class SgSonNodeConstIterator 00429 { 00430 public: 00431 SgSonNodeConstIterator(const SgNode* node) 00432 : m_nextNode(node->LeftMostSon()) 00433 { } 00434 00435 void operator++() 00436 { 00437 m_nextNode = m_nextNode->RightBrother(); 00438 } 00439 00440 const SgNode* operator*() const 00441 { 00442 SG_ASSERT(m_nextNode); 00443 return m_nextNode; 00444 } 00445 00446 operator bool() const 00447 { 00448 return m_nextNode != 0; 00449 } 00450 00451 private: 00452 SgNode* m_nextNode; 00453 00454 /** Not implemented. */ 00455 SgSonNodeConstIterator(const SgSonNodeConstIterator&); 00456 00457 /** Not implemented. */ 00458 SgSonNodeConstIterator& operator=(const SgSonNodeConstIterator&); 00459 }; 00460 00461 //---------------------------------------------------------------------------- 00462 00463 /** Iterator for iterating through all nodes in subtree. */ 00464 class SgNodeIterator 00465 { 00466 public: 00467 /** Create an iterator for iterating through all nodes in the subtree 00468 of 'rootOfSubtree', including the node itself. 00469 If 'preOrder' (default), return internal nodes before their sons; if 00470 'postOrder', then return the leaves before the internal nodes. */ 00471 SgNodeIterator(SgNode* rootOfSubtree, bool postOrder = false); 00472 00473 /** Abort the iteration. 00474 The next call to operator bool will return false. */ 00475 void Abort() 00476 { 00477 m_nextNode = 0; 00478 } 00479 00480 void operator++() 00481 { 00482 SG_ASSERT(m_nextNode); 00483 Next(); 00484 } 00485 00486 SgNode* operator*() const 00487 { 00488 SG_ASSERT(m_nextNode); 00489 return m_nextNode; 00490 }; 00491 00492 operator bool() const 00493 { 00494 return m_nextNode != 0; 00495 } 00496 00497 private: 00498 /** Find next node in the tree. Return false when done with all nodes. */ 00499 bool Next(); 00500 00501 bool m_postOrder; 00502 00503 SgNode* const m_rootOfSubtree; 00504 00505 SgNode* m_nextNode; 00506 00507 /** Not implemented. */ 00508 SgNodeIterator(const SgNodeIterator&); 00509 00510 /** Not implemented. */ 00511 SgNodeIterator& operator=(const SgNodeIterator&); 00512 }; 00513 00514 //---------------------------------------------------------------------------- 00515 00516 /** Iterator for iterating through all nodes in subtree. */ 00517 class SgNodeConstIterator 00518 { 00519 public: 00520 /** Create an iterator for iterating through all nodes in the subtree 00521 of 'rootOfSubtree', including the node itself. 00522 If 'preOrder' (default), return internal nodes before their sons; if 00523 'postOrder', then return the leaves before the internal nodes. */ 00524 SgNodeConstIterator(const SgNode* rootOfSubtree, bool postOrder = false); 00525 00526 /** Find next node in the tree. Return false when done with all nodes. */ 00527 bool Next(); 00528 00529 /** Abort the iteration. 00530 The next call to operator bool will return false. */ 00531 void Abort() 00532 { 00533 m_nextNode = 0; 00534 } 00535 00536 void operator++() 00537 { 00538 SG_ASSERT(m_nextNode); 00539 Next(); 00540 } 00541 00542 const SgNode* operator*() const 00543 { 00544 SG_ASSERT(m_nextNode); 00545 return m_nextNode; 00546 }; 00547 00548 operator bool() const 00549 { 00550 return m_nextNode != 0; 00551 } 00552 00553 private: 00554 bool m_postOrder; 00555 00556 const SgNode* const m_rootOfSubtree; 00557 00558 const SgNode* m_nextNode; 00559 00560 /** Not implemented. */ 00561 SgNodeConstIterator(const SgNodeConstIterator&); 00562 00563 /** Not implemented. */ 00564 SgNodeConstIterator& operator=(const SgNodeConstIterator&); 00565 }; 00566 00567 //---------------------------------------------------------------------------- 00568 00569 #endif // SG_NODE_H