示例#1
0
        private bool Build(EnemyShip design)
        {
            // find sector to place ship in
            var places = new List <dynamic>();
            var sys    = StarSystem;
            var x      = X;
            var y      = Y;

            for (int dx = -1; dx <= 1; dx++)
            {
                for (int dy = -1; dy <= 1; dy++)
                {
                    if (sys.SpaceObjects.AreCoordsInBounds(x + dx, y + dy) && sys.SpaceObjects[x + dx, y + dy] == null)
                    {
                        places.Add(new { X = x + dx, Y = y + dy });
                    }
                }
            }
            if (!places.Any())
            {
                return(false);                // nowhere to put the ship
            }
            var coords = places.PickRandom();

            // create the ship and place it
            var ship = design.Clone();

            if (PlayerShip.Instance.StarSystem == StarSystem)
            {
                Log.Add("An enemy shipyard builds a " + ship.Name + "!", Color.Red);
            }
            Savings -= ship.Cost;
            StarSystem.PlaceSpaceObject(ship, coords.X, coords.Y, 0);
            Galaxy.Current.RefreshEnemyCounts();
            return(true);
        }
示例#2
0
        /// <summary>
        /// Dijkstra-style pathfinding algorithm.
        /// based on http://www.roguebasin.com/index.php?title=Pathfinding
        /// </summary>
        /// <param name="sys">The star system to navigate.</param>
        /// <param name="x">Starting X coordinate.</param>
        /// <param name="y">Starting Y coordinate.</param>
        /// <param name="priority">Priority function. Takes x and y coordinates; returns priority value (zero is optimal, higher numbers are worse).</param>
        /// <returns>Direction to travel.</returns>
        public static Direction Pathfind(StarSystem sys, int x, int y, Func <int, int, int> priority)
        {
            // create "check-it" queue and add start node to it
            var pQueue = new List <PathfindingNode>();

            pQueue.Add(new PathfindingNode(x, y, null, 0));

            // create list of previously visitied nodes
            var visited = new List <PathfindingNode>();

            // search for paths
            while (pQueue.Any())
            {
                // take out the lowest cost node and work on it
                var lowestCost = pQueue.Min(n => n.Cost);
                var node       = pQueue.Where(n => n.Cost == lowestCost).First();
                pQueue.Remove(node);

                // did we reach the goal?
                if (priority(node.X, node.Y) <= 0)
                {
                    var first = node.SecondAncestor;
                    return(Direction.Get(first.X - x, first.Y - y));
                }

                // find successor nodes
                foreach (var dir in Direction.All)
                {
                    var next = new PathfindingNode(node.X + dir.DeltaX, node.Y + dir.DeltaY, node, node.Cost + 1);
                    if (sys.SpaceObjects.AreCoordsInBounds(next.X, next.Y) && (sys.SpaceObjects[next.X, next.Y] == null || sys.SpaceObjects[next.X, next.Y] is WarpPoint))
                    {
                        var sameNodes   = visited.Where(n => n.X == next.X && n.Y == next.Y).ToArray();
                        var queuedNodes = pQueue.Where(n => n.X == next.X && n.Y == next.Y).ToArray();
                        if (!sameNodes.Any() ||
                            queuedNodes.Any(n => n.Cost > next.Cost) ||
                            sameNodes.Any(n => n.Cost > next.Cost))
                        {
                            // if node already exists, get rid of old node with higher cost
                            foreach (var n in sameNodes)
                            {
                                visited.Remove(n);
                            }
                            foreach (var n in queuedNodes)
                            {
                                pQueue.Remove(n);
                            }

                            // add to visited list and priority queue
                            pQueue.Add(next);
                            visited.Add(next);
                        }
                    }
                }
            }

            // get as close as possible
            var closest = visited.OrderBy(n => priority(n.X, n.Y)).FirstOrDefault();

            if (closest == null)
            {
                return(Direction.None);                // no path leads closer than where we are now
            }
            // find first node in path
            var resultFirst = closest.SecondAncestor;

            return(Direction.Get(resultFirst.X - x, resultFirst.Y - y));
        }
示例#3
0
        /// <summary>
        /// Creates a galaxy with the specified settings (radius 0 = 1x1, radius 1 = 3x3, etc.)
        /// </summary>
        /// <param name="radius"></param>
        public Galaxy(int radius, int numSystems, int systemRadius, int planetsPerSystem, int colonyChance, int mineralsChance, int maxMinerals, int enemyShipyards, int enemyShipyardBuildRate, int enemyShipyardScrapRate, int enemyShipScrapRate)
        {
            Current = this;

            ColonyChance           = colonyChance;
            MineralsChance         = mineralsChance;
            MaxMinerals            = maxMinerals;
            EnemyShipyardScrapRate = enemyShipyardScrapRate;
            EnemyShipScrapRate     = enemyShipScrapRate;

            StarSystems = new Grid <StarSystem>(radius);

            // place star systems on grid
            {
                for (int i = 0; i < numSystems && i < (radius + 1) * (radius + 1); i++)
                {
                    if (i == 0)
                    {
                        // place randomly
                        var x = Dice.Range(-StarSystems.Radius, StarSystems.Radius);
                        var y = Dice.Range(-StarSystems.Radius, StarSystems.Radius);
                        StarSystems[x, y] = new StarSystem(systemRadius, planetsPerSystem);
                    }
                    else
                    {
                        // place adjacent to some other system in an empty space
                        var places = new List <dynamic>();
                        for (var x = -StarSystems.Radius; x <= StarSystems.Radius; x++)
                        {
                            for (var y = -StarSystems.Radius; y <= StarSystems.Radius; y++)
                            {
                                if (!IsFilled(x, y) && HasFilledNeighbor(x, y))
                                {
                                    places.Add(new { X = x, Y = y });
                                }
                            }
                        }
                        var coords = places.PickRandom();
                        StarSystems[coords.X, coords.Y] = new StarSystem(systemRadius, planetsPerSystem);
                    }
                }
            }

            // place player ship
            {
                var sys    = StarSystems.Where(s => s != null).PickRandom();
                var places = new List <dynamic>();
                for (var x = -sys.SpaceObjects.Radius; x <= sys.SpaceObjects.Radius; x++)
                {
                    for (var y = -sys.SpaceObjects.Radius; y <= sys.SpaceObjects.Radius; y++)
                    {
                        if (sys.SpaceObjects[x, y] == null)
                        {
                            places.Add(new { X = x, Y = y });
                        }
                    }
                }
                var coords = places.PickRandom();
                sys.PlaceSpaceObject(PlayerShip.Instance, coords.X, coords.Y, 0);

                // perform initial sensor sweep
                for (var x = coords.X - PlayerShip.Instance.SensorRange; x <= coords.X + PlayerShip.Instance.SensorRange; x++)
                {
                    for (var y = coords.Y - PlayerShip.Instance.SensorRange; y <= coords.Y + PlayerShip.Instance.SensorRange; y++)
                    {
                        if (sys.SensorGrid.AreCoordsInBounds(x, y))
                        {
                            sys.SensorGrid[x, y] = true;
                        }
                    }
                }
            }

            // place enemy shipyards
            {
                for (int i = 0; i < enemyShipyards; i++)
                {
                    var sys    = StarSystems.Where(s => s != null).PickRandom();
                    var places = new List <dynamic>();
                    for (var x = -sys.SpaceObjects.Radius; x <= sys.SpaceObjects.Radius; x++)
                    {
                        for (var y = -sys.SpaceObjects.Radius; y <= sys.SpaceObjects.Radius; y++)
                        {
                            if (sys.SpaceObjects[x, y] == null)
                            {
                                places.Add(new { X = x, Y = y });
                            }
                        }
                    }
                    var coords = places.PickRandom();
                    sys.PlaceSpaceObject(new EnemyShipyard(enemyShipyardBuildRate), coords.X, coords.Y, 0);
                }
            }

            // delete warp points that lead nowhere
            for (int x = -StarSystems.Radius; x <= StarSystems.Radius; x++)
            {
                for (int y = -StarSystems.Radius; y <= StarSystems.Radius; y++)
                {
                    var wpsys = StarSystems[x, y];
                    if (wpsys != null)
                    {
                        for (int sx = -wpsys.SpaceObjects.Radius; sx <= wpsys.SpaceObjects.Radius; sx++)
                        {
                            for (int sy = -wpsys.SpaceObjects.Radius; sy <= wpsys.SpaceObjects.Radius; sy++)
                            {
                                if (wpsys.SpaceObjects[sx, sy] is WarpPoint)
                                {
                                    var wp = wpsys.SpaceObjects[sx, sy] as WarpPoint;
                                    if (wp.TargetSystem == null)
                                    {
                                        wpsys.SpaceObjects[sx, sy] = null;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            RefreshEnemyCounts();
        }
示例#4
0
        public override bool Move()
        {
            if (PlayerShip.Instance.StarSystem == StarSystem)
            {
                // player ship sighted!
                NeedsNewWaypoint = false;
                int desiredRange;
                var ourRanges   = Components.Select(c => c.WeaponInfo).Where(w => w != null).Select(w => w.Range).Distinct();
                var theirRanges = PlayerShip.Instance.Components.Select(c => c.WeaponInfo).Where(w => w != null).Select(w => w.Range).Distinct();
                if (!ourRanges.Any())
                {
                    // RUN AWAY!!!
                    // get new waypoint - random warp point to "patrol"
                    desiredRange     = int.MaxValue;
                    NeedsNewWaypoint = false;
                    var wp = StarSystem.FindSpaceObjects <WarpPoint>().PickRandom();
                    WaypointX = wp.X;
                    WaypointY = wp.Y;
                }
                else if (ourRanges.Any(r => r > theirRanges.Max()))
                {
                    // stay at max range of closest ranged weapon that is outside their max range
                    desiredRange = ourRanges.Where(r => r > theirRanges.Max()).Min();
                }
                else
                {
                    // stay at max range of closest ranged weapon
                    desiredRange = ourRanges.Min();
                }
                if (desiredRange < int.MaxValue)
                {
                    // stay at desired range
                    var dir = Utilities.Pathfind(StarSystem, X, Y, (nx, ny) =>
                    {
                        var dist   = Math.Abs(Utilities.Distance(nx, ny, PlayerShip.Instance.X, PlayerShip.Instance.Y));
                        var offset = dist - desiredRange;

                        // being too close is better than being too far away
                        if (offset > 0)
                        {
                            return(offset * 2);
                        }
                        else
                        {
                            return(-offset);
                        }
                    });
                    Go(dir);
                    return(true);
                }
            }
            else if (NeedsNewWaypoint)
            {
                // get new waypoint - random warp point to "patrol"
                NeedsNewWaypoint = false;
                var wp = StarSystem.FindSpaceObjects <WarpPoint>().PickRandom();
                WaypointX = wp.X;
                WaypointY = wp.Y;
            }
            else
            {
                // continue toward old waypoint, nothing to do here
            }

            // pursue warp point
            var wpDir = Utilities.Pathfind(StarSystem, X, Y, (nx, ny) => Utilities.Distance(nx, ny, WaypointX, WaypointY));

            Go(wpDir);

            // no need to wait for player input
            return(true);
        }