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); }
public override bool run() { update_map(); int desired_virus_level = 0; int enemy_virus_count = 0; // see if we need to find a new // find the desired level for our viruses foreach (var virus in viruses) { if (virus.getOwner() == enemyID()) { desired_virus_level += virus.getLevel(); enemy_virus_count++; } } if (enemy_virus_count > 0) { desired_virus_level = (int)Math.Ceiling((double)desired_virus_level / (double)enemy_virus_count) + 1; } // for each of my bases try to spawn a virus var my_bases = new Dictionary <Base, int>(); foreach (var my_base in bases) { if ( my_base.getOwner() == playerID() && map[my_base.getX(), my_base.getY()].VirusLevel == -1 && players[playerID()].getCycles() >= 10 ) { var grid = get_pathnode_map(my_base.getX(), my_base.getY(), -1, false); var aStar = new SettlersEngine.SpatialAStar <GamePathNode, Object>(grid); var path = aStar.Search(new Point(my_base.getX(), my_base.getY()), new Point(desiredX, desiredY), null); //Console.WriteLine("Base at: " + my_base.getX() + "," + my_base.getY() + " has a path of length " + (path != null ? Convert.ToString(path.Count) : "NULL") ); my_bases.Add(my_base, path != null ? path.Count : int.MaxValue); } } var sortedBases = from key in my_bases.Keys orderby my_bases[key] ascending select key; foreach (var my_base in sortedBases) { my_base.spawn(0); } // check to see if we will loose soon if (players[enemyID()].getByteDollars() >= 118) { players[playerID()].talk("I curse Wooly Willy on you, " + players[enemyID()].getPlayerName()); } // for each of my viruses find a point to go to, then go there! foreach (var virus in viruses) { if (virus.getOwner() == playerID()) { update_map(); var pt = find_point(virus.getX(), virus.getY(), virus.getLevel(), desired_virus_level); var points = new List <GamePoint>(); int loopCount = 0; while (pt != null && loopCount < 1000) { loopCount++; points.Insert(0, pt); pt = pt.Parent; } if (loopCount >= 999) { Console.WriteLine("ALERT: Preventing Infinite Loop at UNPACKING POINTS."); } loopCount = 0; while (virus.getMovesLeft() > 0 && points.Count > 0 && loopCount < 1000) { //switch(rand.Next(5)) { case 0: virus.move(virus.getX() + 1, virus.getY()); break; case 1: virus.move(virus.getX(), virus.getY() + 1); break; case 2: virus.move(virus.getX(), virus.getY() - 1); break; case 3: virus.move(virus.getX() - 1, virus.getY()); break; } loopCount++; virus.move(points[0].X, points[0].Y); //if we just move to the desired point if (goingAfterEnemy && points[0].X == desiredX && points[0].Y == desiredY) { find_new_desired_point(points[0].X, points[0].Y); } points.RemoveAt(0); } if (loopCount >= 999) { Console.WriteLine("ALERT: Preventing Infinite Loop at DOING MOVE."); } } } return(true); }