public GamePathNode[,] get_pathnode_map(int startX, int startY, int start_virus_level, bool my_tiles_are_blocked) { update_map(); var pathNodeMap = new GamePathNode[width(), height()]; for (int x = 0; x < width(); x++) { for (int y = 0; y < height(); y++) { Boolean isWall = false; var node = map[x, y]; // WALL: node that can't be moved through if (node.Type == NodeType.MyBase || node.Type == NodeType.EnemyBase || node.Type == NodeType.Wall || (node.Type == NodeType.EnemyVirus && node.VirusLevel >= start_virus_level) || (node.Type == NodeType.MyTile && my_tiles_are_blocked) ) { isWall = true; } // NOT WALL: starting location else if (x == startX && y == startY) { isWall = false; } // WALL: adjacent virus of mine else if ( node.Type == NodeType.MyVirus && ( (x == startX + 1 && y == startY) || (x == startX - 1 && y == startY) || (x == startX && y == startY + 1) || (x == startX && y == startY - 1) ) ) { isWall = true; } // NOT WALL: anything else (hopefully) else { isWall = false; } // WALL: Adjacent tile with adjecent >= level enemy virus if ( (x == startX + 1 && y == startY) || (x == startX - 1 && y == startY) || (x == startX && y == startY + 1) || (x == startX && y == startY - 1) ) { if (x + 1 < width()) { if (map[x + 1, y].Type == NodeType.EnemyVirus && start_virus_level <= map[x + 1, y].VirusLevel) { isWall = true; } } else if (x - 1 >= 0) { if (map[x - 1, y].Type == NodeType.EnemyVirus && start_virus_level <= map[x - 1, y].VirusLevel) { isWall = true; } } else if (y + 1 < height()) { if (map[x, y + 1].Type == NodeType.EnemyVirus && start_virus_level <= map[x, y + 1].VirusLevel) { isWall = true; } } else if (y - 1 >= 0) { if (map[x, y - 1].Type == NodeType.EnemyVirus && start_virus_level <= map[x, y - 1].VirusLevel) { isWall = true; } } } if (start_virus_level == -1 && startX == x && startY == y) { isWall = false; } pathNodeMap[x, y] = new GamePathNode() { IsWall = isWall, X = x, Y = y, }; } } return(pathNodeMap); }
public GamePoint find_point(int x, int y, int this_virus_level, int desired_virus_level) { if (x >= width() || y >= height() || y < 0 || x < 0) { return(null); } // BEGIN: First find a path to the desired position to influence our movement var grid = get_pathnode_map(x, y, this_virus_level, !goingAfterEnemy); var aStar = new SettlersEngine.SpatialAStar <GamePathNode, Object>(grid); var path = aStar.Search(new Point(x, y), new Point(desiredX, desiredY), null); //LinkedList<GamePathNode> path = null; // END: First find a path to the desired position to influence our movement var points = new List <GamePoint>(); var returnablePoints = new List <GamePoint>(); //var startingPoint = new GamePoint(x, y); points.Add(new GamePoint(x + 1, y)); points.Add(new GamePoint(x - 1, y)); points.Add(new GamePoint(x, y + 1)); points.Add(new GamePoint(x, y - 1)); int loopCount = 0; int returnDepth = 0; while (points.Count > 0 && loopCount < 1000) { //Console.WriteLine("FloodFill: " + loopCount); var pt = points[0]; loopCount++; // make sure the point is not out of range of the game board if (pt.X >= width() || pt.X < 0 || pt.Y >= height() || pt.Y < 0) { points.Remove(pt); continue; } // check to make sure this tile is not dangerous (eg >= enemy virus adjacent to it), if it is remove it if (pt.X + 1 < width()) { if (map[pt.X + 1, pt.Y].Type == NodeType.EnemyVirus && map[pt.X + 1, pt.Y].VirusLevel >= this_virus_level) { points.Remove(pt); continue; } } if (pt.X - 1 >= 0) { if (map[pt.X - 1, pt.Y].Type == NodeType.EnemyVirus && map[pt.X - 1, pt.Y].VirusLevel >= this_virus_level) { points.Remove(pt); continue; } } if (pt.Y + 1 < height()) { if (map[pt.X, pt.Y + 1].Type == NodeType.EnemyVirus && map[pt.X, pt.Y + 1].VirusLevel >= this_virus_level) { points.Remove(pt); continue; } } if (pt.Y - 1 >= 0) { if (map[pt.X, pt.Y - 1].Type == NodeType.EnemyVirus && map[pt.X, pt.Y - 1].VirusLevel >= this_virus_level) { points.Remove(pt); continue; } } // at this point we willa ctually look at this node var node = map[pt.X, pt.Y]; // if it is interesting let's go to it if (node.Type == NodeType.EnemyTile || node.Type == NodeType.NeutralTile || (node.Type == NodeType.EnemyVirus && node.VirusLevel < this_virus_level) || (node.Type == NodeType.MyVirus && node.VirusLevel == this_virus_level && this_virus_level < desired_virus_level && pt.Depth == 1)) { returnablePoints.Add(pt); points.Remove(pt); if (returnDepth == 0) { returnDepth = pt.Depth; } } // else if the pt is not interesting remove it else if (node.Type == NodeType.Wall || node.Type == NodeType.MyBase || node.Type == NodeType.EnemyBase || (node.Type == NodeType.MyVirus && node.VirusLevel != this_virus_level) || (node.Type == NodeType.EnemyVirus && node.VirusLevel >= this_virus_level) || (node.Type == NodeType.MyVirus && pt.Depth == 1)) { points.Remove(pt); } // else if it is my tile or my far away virus look for something else else if (node.Type == NodeType.MyTile || (node.Type == NodeType.MyVirus && pt.Depth > 1)) { // if we can add the point then do so if (returnDepth == 0 || pt.Depth < returnDepth) { // for each direction made a seed point in that direction and add it to the points if that point is not already in points foreach (Direction dir in Enum.GetValues(typeof(Direction))) { var seedPoint = new GamePoint(pt, dir); bool alreadyInPoints = false; foreach (var point in points) { if (point.X == seedPoint.X && point.Y == seedPoint.Y) { alreadyInPoints = true; break; } } if (!alreadyInPoints) { points.Add(seedPoint); } } } points.Remove(pt); } else { Console.WriteLine("PROBLEM: I don't know what to do for this node of type: " + node.Type); return(null); } } if (loopCount >= 999) { Console.WriteLine("ALERT: Preventing Infinite Loop at Flood Fill."); } if (returnablePoints.Count > 0) { // Check points for Priority in this order: // 1. Enemy Viruses // 2. Enemy Tiles // 3. Neutral Tiles // 4. My Viruses to join with var inOrder = new List <GamePoint>(); foreach (var returnablePoint in returnablePoints) { if (map[returnablePoint.X, returnablePoint.Y].Type == NodeType.EnemyVirus) { inOrder.Add(returnablePoint); } } foreach (var returnablePoint in returnablePoints) { if (map[returnablePoint.X, returnablePoint.Y].Type == NodeType.EnemyTile) { inOrder.Add(returnablePoint); } } foreach (var returnablePoint in returnablePoints) { if (map[returnablePoint.X, returnablePoint.Y].Type == NodeType.NeutralTile) { inOrder.Add(returnablePoint); } } foreach (var returnablePoint in returnablePoints) { if (map[returnablePoint.X, returnablePoint.Y].Type == NodeType.MyVirus) { inOrder.Add(returnablePoint); } } // go through the points we want in order and if there is a path return the point that is in that path // this basically says, "oh you have a many options? well take the one that mvoes you closer to the desired point". if (path != null && path.Count > 2) { path.RemoveFirst(); GamePathNode firstStep = null; //because path.First won't compile :( foreach (var node in path) { firstStep = node; break; } foreach (var returnablePoint in inOrder) { if (returnablePoint.X == firstStep.X && returnablePoint.Y == firstStep.Y) { return(returnablePoint); } } } //only should happen if there was no path return(inOrder[0]); } else { // just go where ever that path we found the the desired point is if (path != null && path.Count > 2) { path.RemoveFirst(); GamePathNode firstStep = null; //because path.First won't compile :( foreach (var node in path) { firstStep = node; break; } return(new GamePoint(firstStep.X, firstStep.Y)); } } Console.WriteLine("PROBLEM: No point was found to return...\n"); return(null); }