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