/// <summary> /// Crawls this instance. /// </summary> /// <returns>The solution if found</returns> /// <remarks>We have to override this so we can synchonize the forward and reverse crawlers</remarks> public override BaseNode Crawl() { if (!this.reversed) { BaseNode solution = null; while ((!this.IsQueueEmpty() || !reverseCrawler.IsQueueEmpty()) && solution == null) { this.EvaluateAndExpandNode(this.PopQueue()); reverseCrawler.Crawl(); // If there exists a node that both crawlers have found where, combined, a solution is found; that is our winner. List <BaseNode> similarNodes = this.ExploredSet.Where(en => reverseCrawler.ExploredSet.Any(rcEn => rcEn.Key == en.Key)).ToList(); foreach (BaseNode similarNode in similarNodes) { foreach (BaseNode possibleSolution in this.reverseCrawler.ExploredSet.Where(en => en.Key == similarNode.Key)) { List <Move> movesToGoal = TreeHelpers.ActionTracker(possibleSolution); movesToGoal.Reverse(); movesToGoal = TreeHelpers.ReflectMoves(movesToGoal); int x = similarNode.X; int y = similarNode.Y; List <int[]> newChildState = new List <int[]>(); similarNode.CrateLocations.ForEach(state => newChildState.Add(new int[] { state[0], state[1] })); this.MoveToCurrentNode(movesToGoal, ref x, ref y, ref newChildState); if (IsWinningState(newChildState)) { return(InvertNodeHeritage(similarNode, possibleSolution.Parent)); } } } } return(solution); } else { // If we are the reversed solution, we just need to take the normal steps and return if we found a solution. // all the Bi-Directional stuff is done in the non-reversed loop. BaseNode reverseSolution; reverseSolution = this.EvaluateAndExpandNode(this.PopQueue()); return(reverseSolution); } }