namespace Models { const RootNodeId = 0 ; export class GameTree { public size : number ; public root : GameTreeNode ; public nodes : GameTreeNode [ ] ; private _activeNode : GameTreeNode ; private _facade : { [ type ] : ( ( tree : GameTree , event : KGS . SGF . NodeEvent ) => void ) ; } ; constructor ( size ? ) { this . size = size ; this . root = new GameTreeNode ( this , RootNodeId ) ; this . nodes = [ this . root ] ; this . _activeNode = null ; } public get ( nodeId ) { if ( nodeId < this . nodes . length ) { let node = this . nodes [ nodeId ] ; if ( node != null ) return node ; } throw "Game Tree Node [" + nodeId . toString ( ) + "] not found" ; } public create ( nodeId ) { let node ; if ( nodeId < this . nodes . length ) { node = this . nodes [ nodeId ] ; if ( node != null ) return node ; } node = new GameTreeNode ( this , nodeId ) ; this . nodes [ nodeId ] = node ; return node ; } public get activeNode ( ) : Models . GameTreeNode { return this . _activeNode ; } public get position ( ) : Models . GamePosition { return ( null != this . _activeNode ) ? this . _activeNode . position : null ; } public activate ( changedNodes , activateNodeId ) { let activate = [ ] ; if ( null == activateNodeId ) { if ( null != this . _activeNode ) { activateNodeId = this . _activeNode . nodeId ; } else return ; } let changedCount = Object . keys ( changedNodes ) . length ; let currentNode = this . nodes [ activateNodeId ] ; while ( ( null != currentNode ) && ( null == currentNode . position ) ) { let currentNodeId = currentNode . nodeId ; activate . push ( currentNodeId ) ; if ( changedNodes [ currentNodeId ] ) -- changedCount ; currentNode = currentNode . parent ; } let deactivateNode = this . _activeNode ; while ( ( null != deactivateNode ) && ( currentNode !== deactivateNode ) ) { deactivateNode . position = null ; if ( changedNodes [ deactivateNode . nodeId ] ) -- changedCount ; deactivateNode = deactivateNode . parent ; } while ( ( null != currentNode ) && ( changedCount > 0 ) ) { let currentNodeId = currentNode . nodeId ; currentNode . position = null ; activate . push ( currentNodeId ) ; if ( changedNodes [ currentNodeId ] ) -- changedCount ; currentNode = currentNode . parent ; } for ( let j = ( activate . length - 1 ) ; j >= 0 ; -- j ) { let activateNode = this . nodes [ activate [ j ] ] ; if ( ( null != currentNode ) && ( currentNode . nodeId != activateNode . parentId ) ) throw new Error ( "Attempted to activate off a path" ) ; if ( null != activateNode . position ) throw new Error ( "Attempted to activate an activenode" ) ; let previousPosition = ( null != currentNode ) ? currentNode . position : null ; if ( previousPosition ) { activateNode . position = new Models . GamePosition ( previousPosition ) ; } else if ( this . size ) { activateNode . position = new Models . GamePosition ( this . size ) ; } else { let rules = activateNode . getProperty ( KGS . SGF . _RULES ) as KGS . SGF . RULES ; let size = 19 ; if ( ( rules ) && ( rules . size ) ) size = rules . size ; activateNode . position = new Models . GamePosition ( size ) ; } activateNode . position . effectEvent ( activateNode . properties ) ; currentNode = activateNode ; } this . _activeNode = currentNode ; } public testMove ( x , y , colour ) { if ( null == this . _activeNode ) { Utils . log ( Utils . LogSeverity . Warning , "The game tree does not have an active path" ) ; return null ; } else if ( null == this . _activeNode . position ) { Utils . log ( Utils . LogSeverity . Warning , "The game tree does not have an active position" ) ; return null ; } let position = this . _activeNode . position ; let clone = new Models . GamePosition ( position ) ; return clone . play ( x , y , colour ) ; } } }