/// <summary>
        /// Gets a list of player int identifiers from the galaxy
        /// </summary>
        /// <param name="galaxy">The galaxy to get the player list for</param>
        /// <returns>A List of ints, representing the player identifiers</returns>
        public List <int> GetPlayers()
        {
            List <int> players = new List <int>();

            foreach (Tuple <int, int> start in HSLocations)
            {
                SystemTile startTile = tiles[start.Item1][start.Item2];
                int        playerNum = startTile.playerNum;
                players.Add(playerNum);
            }
            return(players);
        }
        /// <summary>
        /// Initializes a new galaxy. This adds placeholder tiles and initializes data structures.
        /// </summary>
        /// <param name="maxRad">The maximum 'radius' of the galaxy.</param>
        /// <param name="playerCount">The number of players to initialize the galaxy for</param>
        public void init(int maxRad, int playerCount = 6)
        {
            players = playerCount;
            int width = 2 * maxRad + 1;

            tiles = new SystemTile[width][];
            for (int i = 0; i <= 2 * maxRad; i++)
            {
                SystemTile[] row = new SystemTile[width];
                for (int j = 0; j <= 2 * maxRad; j++)
                {
                    row[j] = TilesetGenerator.GetBlankTile();
                }
                tiles[i] = row;
            }
            MaxRadius = maxRad;
        }
Esempio n. 3
0
        public void RenderSystemTile(Form form, PaintEventArgs e, SystemTile tile, int x, int y, int w, int h, bool small = false)
        {
            if (e == null || form == null)
            {
                Debug.WriteLine("Render Tile missing needed field");
                return;
            }
            string pathString = $"..\\..\\Resources\\" +
                                $"{(small ? "small\\small-" : "full\\")}";

            if (tile.sysNum == 0 && tile.playerNum != -1)
            {
                pathString += "tilehome.png";
            }
            else
            {
                pathString += $"tile{(tile.sysNum < 10 ? "0" : "")}{tile.sysNum}.png";
            }
            Bitmap tileImage;

            if (images.ContainsKey(pathString))
            {
                tileImage = images[pathString];
            }
            else
            {
                try
                {
                    tileImage = new Bitmap(pathString);
                }
                catch (Exception ex)
                {
                    pathString = $"..\\..\\Resources\\" +
                                 $"{(small ? "small\\small-" : "full\\")}" +
                                 $"tilebw.png";
                    tileImage = new Bitmap(pathString);
                }
                images.Add(pathString, tileImage);
            }
            e.Graphics.DrawImage(tileImage, x, y, w, h);
        }
Esempio n. 4
0
        public void renderGalaxy(Form form, PaintEventArgs e, Galaxy galaxy)
        {
            if (galaxy == null)
            {
                return;
            }
            bool  small    = false;
            Point tileSize = new Point((int)((small ? 200 : 900) * scale), (int)((small ? 172 : 774) * scale));

            for (int y = 0; y < galaxy.tiles.Length; y++)
            {
                for (int x = 0; x < galaxy.tiles[y].Length; x++)
                {
                    SystemTile tile = galaxy.tiles[y][x];
                    bool       isHS = galaxy.HSLocations.Contains(new Tuple <int, int>(x, y));
                    if (tile.sysNum == 0 && !isHS)
                    {
                        continue;
                    }
                    Point tilePos = new Point((int)(0.75 * tileSize.X) * x, (int)(tileSize.Y * (y + 0.5 * (x - 3))));
                    RenderSystemTile(form, e, tile, tilePos.X, tilePos.Y, tileSize.X, tileSize.Y, small);
                }
            }
        }
        /// <summary>
        /// Sets Strength of claims on systems. Based on selected contest method and exponent of claim strength to distance ratio
        /// </summary>
        /// <param name="contestMethod">The method used to determine how to get STR claims from DIST claims</param>
        /// <param name="claimExponent">The exponent used to determing STR of claims from DIST of claims</param>
        public void StakeStrClaims(
            StrContestMethod contestMethod = StrContestMethod.TopAndClose,
            double claimExponent           = -2.0)
        {
            ResetStrengthClaims();
            for (int x = 0; x <= 2 * MaxRadius; x++)
            {
                for (int y = 0; y <= 2 * MaxRadius; y++)
                {
                    SystemTile tile = tiles[x][y];
                    if (tile.sysNum > 0 && tile.planets.Count() > 0)
                    {
                        Dictionary <int, double> claims = new Dictionary <int, double>();
                        foreach (int pnum in tile.distClaims.Keys)
                        {
                            switch (contestMethod)
                            {
                            case StrContestMethod.Slices:
                                if (claims[pnum] == tile.distClaims.Values.Max())
                                {
                                    // full claim on resources for best claim (or tied)
                                    claims.Add(pnum, 1.0);
                                }
                                break;

                            case StrContestMethod.ClaimSize:
                                if (tile.distClaims.Values.Min() == 0 && tile.distClaims.Values.Min() == claims[pnum])
                                {
                                    // home systems (distance = 0) are only claimed by owner
                                    // TODO: might be a way to refactor a bit so this check isn't needed
                                    claims.Add(pnum, 1.0);
                                }
                                else
                                {
                                    // all claims scaled by distance, inverted to a power
                                    // e.g. distances 10 and 20 might become claims of 1/10 and 1/20
                                    claims.Add(pnum, Math.Pow(tile.distClaims[pnum], claimExponent));
                                }
                                break;

                            case StrContestMethod.TopAndClose:
                                if (tile.distClaims.Values.Min() == 0 && tile.distClaims.Values.Min() == claims[pnum])
                                {
                                    // home systems (distance = 0) are only claimed by owner
                                    // TODO: might be a way to refactor a bit so this check isn't needed
                                    claims.Add(pnum, 1.0);
                                }
                                else if (claims[pnum] < 1.1 * tile.distClaims.Values.Min())
                                {
                                    // TODO: Refactor to make 'close' a configurable setting somehow
                                    // all claims scaled by distance, inverted to a power
                                    // e.g. distances 10 and 20 might become claims of 1/10 and 1/20
                                    claims.Add(pnum, Math.Pow(tile.distClaims[pnum], claimExponent));
                                }
                                break;
                            }
                        }
                        if (claims.Count() == 0)
                        {
                            throw new Exception("Every system should have at least one claim, right?");
                        }
                        double claimScale = claims.Sum(claim => claim.Value);
                        foreach (KeyValuePair <int, double> claim in claims)
                        {
                            tile.strClaims.Add(claim.Key, claim.Value / claimScale);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// For the galaxy, fills the 'claims' for each tile for each players, where the claim is the 'distance'
        /// from their home system to the tile in question. Used for scoring 'slices'
        /// </summary>
        /// <param name="galaxy">The Galaxy to stake claims in</param>
        /// <param name="walk">'distance' for default walk</param>
        /// <param name="emptyWalk">'distance' for walk through empty space</param>
        /// <param name="asteroidWalk">'distance' for walk through asteroids</param>
        /// <param name="novaWalk">'distance' for walk through nova</param>
        /// <param name="nebulaWalk">'distance' for walk through nebula</param>
        /// <param name="riftWalk">'distance' for walk through gravity rift</param>
        /// <param name="wormWalk">'distance' for walk through wormhole</param>
        public void StakeDistClaims(
            int walk         = 10,
            int emptyWalk    = 11,
            int asteroidWalk = 13,
            int novaWalk     = 100,
            int nebulaWalk   = 20,
            int riftWalk     = 08,
            int wormWalk     = 12)
        {
            ResetDistanceClaims();

            // for each home system (and therefore each player) determine how 'far' they are from each tile.
            // 'distances' are weighted by tile type, e.g. a system two tiles away with a planet in between is
            // 'closer' than the same setup where the middle tile is a nebula
            foreach (Tuple <int, int> start in HSLocations)
            {
                SystemTile startTile = tiles[start.Item1][start.Item2];
                int        playerNum = startTile.playerNum;
                // smaller number claims are better, a player's own home system has claim value 0 for themselves
                startTile.distClaims[playerNum] = 0;
                SortedList <int, List <SystemTile> > adjacent = new SortedList <int, List <SystemTile> >();
                // start by getting sorted list of all adjacent tiles to HS, sorted by lowest 'distance' first
                foreach (SystemTile tile in startTile.adjacent)
                {
                    int walkDist = walk;
                    if (tile.anomaly == Anomaly.Nova)
                    {
                        walkDist = novaWalk;
                    }
                    else if (tile.anomaly == Anomaly.Nebula)
                    {
                        walkDist = nebulaWalk;
                    }
                    else if (tile.anomaly == Anomaly.Asteroids)
                    {
                        walkDist = asteroidWalk;
                    }
                    else if (tile.anomaly == Anomaly.Rift)
                    {
                        walkDist = riftWalk;
                    }
                    else if (tile.planets.Count() == 0)
                    {
                        walkDist = emptyWalk;
                    }
                    if (!adjacent.ContainsKey(walkDist))
                    {
                        adjacent.Add(walkDist, new List <SystemTile>());
                    }
                    adjacent[walkDist].Add(tile);
                }

                //dijkstra's (?) to find 'shortest path' from HS to all tiles on the board
                while (adjacent.Count() > 0)
                {
                    IList <int>       keys        = adjacent.Keys;
                    int               firstKey    = keys.First();
                    List <SystemTile> firstList   = adjacent[firstKey];
                    SystemTile        closestTile = firstList.First();
                    firstList.Remove(closestTile);
                    if (firstList.Count() == 0)
                    {
                        adjacent.Remove(firstKey);
                    }
                    if (!closestTile.distClaims.ContainsKey(playerNum))
                    {
                        closestTile.distClaims.Add(playerNum, firstKey);
                        foreach (SystemTile next in closestTile.adjacent)
                        {
                            if (!next.distClaims.ContainsKey(playerNum))
                            {
                                int walkDist = firstKey;
                                if (next.anomaly == Anomaly.Nova)
                                {
                                    walkDist += novaWalk;
                                }
                                else if (next.anomaly == Anomaly.Nebula)
                                {
                                    walkDist += nebulaWalk;
                                }
                                else if (next.anomaly == Anomaly.Asteroids)
                                {
                                    walkDist += asteroidWalk;
                                }
                                else if (next.anomaly.HasFlag(Anomaly.Rift))
                                {
                                    walkDist += riftWalk;
                                }
                                else if ((closestTile.wormholes & next.wormholes) != Wormhole.None)
                                {
                                    walkDist += wormWalk;
                                }
                                else if (next.planets.Count() == 0)
                                {
                                    walkDist += emptyWalk;
                                }
                                else
                                {
                                    walkDist += walk;
                                }
                                if (!adjacent.ContainsKey(walkDist))
                                {
                                    adjacent.Add(walkDist, new List <SystemTile>());
                                }
                                adjacent[walkDist].Add(next);
                            }
                        }
                    }
                }
            }
        }