Пример #1
0
    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);
    }
Пример #2
0
    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);
    }