예제 #1
0
    private IntIntPair SelectProvinceCenter(int provinceId, int radius)
    {
        IntIntPair quadrant = null;
        int        midX     = (int)(0.5 * _provinceMap.GetLength(0));
        int        midY     = (int)(0.5 * _provinceMap.GetLength(1));

        if (provinceId == 1)
        {
            quadrant = new IntIntPair(midX, midY);
            MarkProvinceCell(quadrant.first, quadrant.second, provinceId, _provinceMap, _quadrants, false);
        }
        else
        {
            quadrant = AddRandomNeighbor(provinceId, _provinceMap, _quadrants, false);
        }

        if (quadrant == null)
        {
            return(null);
        }
        _quadrants.Add(quadrant);

        return(new IntIntPair(2 * radius * (quadrant.first - midX) + (int)(0.5 * _cellMap.GetLength(0)) + UnityEngine.Random.Range(-2, 2),
                              2 * radius * (quadrant.second - midY) + (int)(0.5 * _cellMap.GetLength(1)) + UnityEngine.Random.Range(-2, 2)));
    }
예제 #2
0
        private void ResizeShapesToExtrude(SceneSelectedEntity selectedNode, int nodeIndex, int subFace)
        {
            SortedDictionary <int, IntIntPair> subCollection;
            Node extrudeNode;

            if (_extrudesList.TryGetValue(nodeIndex, out extrudeNode))
            {
                var extrudeBuilder      = new NodeBuilder(extrudeNode);
                var sourceFaceNodeIndex = extrudeBuilder[0].Reference.Index;
                _shapesToExtrude.Remove(sourceFaceNodeIndex);
                return;
            }
            if (!_shapesToExtrude.TryGetValue(nodeIndex, out subCollection))
            {
                subCollection = new SortedDictionary <int, IntIntPair>();
                _shapesToExtrude[nodeIndex] = subCollection;
            }
            if (subCollection.ContainsKey(subFace))
            {
                //subCollection.Remove(subFace);
                //if (subCollection.Count == 0)
                //    _shapesToExtrude.Remove(nodeIndex);
            }
            else
            {
                subCollection[subFace] = new IntIntPair(selectedNode);
            }
        }
예제 #3
0
    /// <summary>
    /// Bribe a province garrison to change sides
    /// </summary>
    /// <param name="province">The garrisoned province</param>
    /// <returns>Whether the opration was successful</returns>
    public bool BribeProvince(Province province)
    {
        IntIntPair costs = CalculateBriberyCosts(province);

        if (GetCurrentFaction().SubtractCost(costs.second))
        {
            ChangeProvinceOwnership(province, GetCurrentFaction());
            return(true);
        }
        return(false);
    }
예제 #4
0
    /// <summary>
    /// Bribe a province garrison to disband
    /// </summary>
    /// <param name="province">The garrisoned province</param>
    /// <returns>Whether the opration was successful</returns>
    public bool DisbandGarrison(Province province)
    {
        IntIntPair costs = CalculateBriberyCosts(province);

        if (GetCurrentFaction().SubtractCost(costs.first))
        {
            province.RemoveAllUnits();
            return(true);
        }
        return(false);
    }
예제 #5
0
    private bool MarkProvinceCell(int x, int y, int provinceId, int[,] tileMap, List <IntIntPair> neighbors, bool useStricterRules)
    {
        if (tileMap[x, y] > 0 || tileMap[x, y] == provinceId)
        {
            return(false);
        }
        tileMap[x, y] = provinceId;
        HexBorder[] borders = HexBorder.GetBorderDirections(x % 2 == 1);
        for (int i = 0; i < borders.Length; i++)
        {
            int        neighborX = x + borders[i].GetDeltaX();
            int        neighborY = y + borders[i].GetDeltaY();
            IntIntPair neighbor  = new IntIntPair(neighborX, neighborY);

            bool passesBasicRules = IsInnerCell(neighborX, neighborY, tileMap) &&
                                    tileMap[neighborX, neighborY] <= 0;

            // stricter rules means having at least two neighboring cells
            // belonging to the same province
            // it's used to avoid serpentine forms
            bool passesStricterRules = false;
            if (useStricterRules)
            {
                int         sameProvinceNeighbors = 0;
                HexBorder[] newBorders            = HexBorder.GetBorderDirections(neighborX % 2 == 1);
                for (int j = 0; j < newBorders.Length; j++)
                {
                    int xx = neighborX + newBorders[j].GetDeltaX();
                    int yy = neighborY + newBorders[j].GetDeltaY();
                    if (IsInnerCell(xx, yy, tileMap) && tileMap[xx, yy] == provinceId)
                    {
                        sameProvinceNeighbors++;
                        if (sameProvinceNeighbors >= 2)
                        {
                            passesStricterRules = true;
                            break;
                        }
                    }
                }
            }

            // is within the map area, is a water cell, and either doesn't care
            // about stricter rules or satisfies them
            if (passesBasicRules && (!useStricterRules || passesStricterRules))
            {
                neighbors.Add(neighbor);
            }
        }
        return(true);
    }
예제 #6
0
    /// <summary>
    /// Class constructor
    /// </summary>
    /// <param name="data">Serialized race data</param>
    /// <param name="unitTypes">Hash of unit type id => unit type of racial units</param>
    public Race(RaceData data, Dictionary <int, UnitType> unitTypes)
    {
        _data          = data;
        _lowercaseName = _data.name.ToLower();

        _racialUnits = new List <UnitType>();
        for (int i = 0; i < _data.units.Length; i++)
        {
            UnitType unitType = unitTypes[_data.units[i]];
            if (unitType != null)
            {
                _racialUnits.Add(unitType);
            }
        }
        _magicUpgrades = new Dictionary <UnitType, UnitType>();
        if (_data.magicUpgrades != null)
        {
            for (int i = 0; i < _data.magicUpgrades.Length; i++)
            {
                IntIntPair upgrade = _data.magicUpgrades[i];
                _magicUpgrades[unitTypes[upgrade.first]] = unitTypes[upgrade.second];
            }
        }

        _divineAdditions = new List <UnitType>();
        if (_data.divineAdditions != null)
        {
            for (int i = 0; i < _data.divineAdditions.Length; i++)
            {
                int newUnit = _data.divineAdditions[i];
                _divineAdditions.Add(unitTypes[newUnit]);
            }
        }

        _divineUpgrades = new Dictionary <UnitType, UnitType>();
        if (_data.divineUpgrades != null)
        {
            for (int i = 0; i < _data.divineUpgrades.Length; i++)
            {
                IntIntPair upgrade = _data.divineUpgrades[i];
                _divineUpgrades[unitTypes[upgrade.first]] = unitTypes[upgrade.second];
            }
        }
    }
예제 #7
0
    private void ConnectIsland(int index)
    {
        FileLogger.Trace("MAP", "Connecting province #" + (index + 1).ToString() + " to the mainland");
        int targetCellsWithNeighbors = 3;
        int addedCells = 0;

        while (addedCells < targetCellsWithNeighbors)
        {
            IntIntPair addition = AddRandomNeighbor(index + 1, _cellMap, _neighbors[index], false, true);
            if (addition == null)
            {
                // nothing can be done - the list of potential neighbors exhausted
                return;
            }
            if (SearchForNeighbors(addition.first, addition.second, true))
            {
                addedCells++;
            }
        }
    }
예제 #8
0
    private IntIntPair AddRandomNeighbor(int provinceId, int[,] tileMap, List <IntIntPair> neighbors, bool useStricterRules, bool towardCenterOnly = false)
    {
        IntIntPair newProvinceCell = null;

        // more accurately, the center of the province #1
        IntIntPair mapCenter = _centers[0];

        bool found = false;

        while (!found)
        {
            // a safety valve - should not happen
            if (neighbors.Count == 0)
            {
                return(null);
            }

            int randomIndex = UnityEngine.Random.Range(0, neighbors.Count - 1);
            newProvinceCell = neighbors[randomIndex];

            neighbors.RemoveAt(randomIndex);

            // when deepening the ocean (provinceId = -1), only 0 satisfies the criteria
            // otherwise, both -1 and 0 work
            if (tileMap[newProvinceCell.first, newProvinceCell.second] <= 0 && tileMap[newProvinceCell.first, newProvinceCell.second] != provinceId)
            {
                found = !towardCenterOnly || CalculateDistance(mapCenter, newProvinceCell) <= CalculateDistance(mapCenter, _centers[provinceId - 1]);
            }
        }

        if (MarkProvinceCell(newProvinceCell.first, newProvinceCell.second, provinceId, tileMap, neighbors, useStricterRules))
        {
            return(newProvinceCell);
        }
        return(null);
    }
예제 #9
0
 private int CalculateDistance(IntIntPair one, IntIntPair two)
 {
     // http://www.redblobgames.com/grids/hexagons/
     return(Math.Max(Math.Abs(one.first - two.first), Math.Abs(one.second - two.second)));
 }
예제 #10
0
    public Game CreateScenario(GameData data)
    {
        data.turn = 1;

        int height = 42;
        int width  = 48;
        // all cells within this radius should ideally belong to the same province
        int radius = 3;

        int cellsPerProvince = radius * (radius + 1) * 3 + 1;

        // the number of provinces is calculated with +/- 5% variance
        int numberOfProvinces = (int)(height * width * LAND_FRACTION / cellsPerProvince * (UnityEngine.Random.Range(0, 10) * 0.01 + 0.95));

        _cellMap = new int[width, height];
        _centers = new List <IntIntPair>();

        int provinceMapXSize = (int)(width * 0.5 / radius);
        int provinceMapYSize = (int)(height * 0.5 / radius);

        _provinceMap = new int[provinceMapXSize, provinceMapYSize];
        _quadrants   = new List <IntIntPair>();

        // list of (current number of cells, total number of cells) per province
        List <IntIntPair> cellQtys = new List <IntIntPair>();
        // the number of cells the largest province will have
        int maxCellQty = 0;

        // can't really have more than this number of provinces - the map would be too cluttered
        numberOfProvinces = Math.Min(numberOfProvinces, provinceMapXSize * provinceMapYSize);
        FileLogger.Trace("MAP", "The world will have " + numberOfProvinces + " provinces ");

        _neighbors = new List <List <IntIntPair> >();
        for (int i = 0; i < numberOfProvinces; i++)
        {
            // each province get its own list of neighboring cells coordinates
            _neighbors.Add(new List <IntIntPair>());
        }

        int provinceId  = 1;
        int failedTries = 0;

        // placing province centers
        while (_centers.Count < numberOfProvinces && failedTries < 10)
        {
            IntIntPair provinceCenter = SelectProvinceCenter(provinceId, radius);
            if (provinceCenter != null)
            {
                _centers.Add(provinceCenter);
                MarkProvinceCell(provinceCenter.first, provinceCenter.second, provinceId, _cellMap, _neighbors[provinceId - 1], false);
                //FileLogger.Trace("MAP", "The center of province #" + provinceId + " is [" + provinceCenter.first + ", " + provinceCenter.second + "]");

                // reset failures count
                failedTries = 0;
                // move to the next province
                provinceId++;
            }
            else
            {
                failedTries++;
            }
        }

        FileLogger.Trace("MAP", "The number of provinces changes from " + numberOfProvinces + " to " + _centers.Count);
        numberOfProvinces = _centers.Count;

        // calculating the number of cells to create per province
        for (int i = 0; i < numberOfProvinces; i++)
        {
            IntIntPair provinceCenter = _centers[i];

            //int markedCells = MakeProvince(provinceCenter.first, provinceCenter.second, i + 1, radius, cellMap, neighbors[i]);
            //FileLogger.Trace("MAP", "The bulk of province #" + (i + 1).ToString() + " conists of " + markedCells + " cells");

            int cellQty = cellsPerProvince + UnityEngine.Random.Range(-4, 6);
            if (provinceCenter.first > 3 * radius && provinceCenter.first < width - 3 * radius &&
                provinceCenter.second > 3 * radius && provinceCenter.second < height - 3 * radius)
            {
                cellQty += UnityEngine.Random.Range(4, 10);
            }

            // can't be fewer than we already marked
            //cellQty = Math.Max(cellQty, markedCells);

            cellQtys.Add(new IntIntPair(1, cellQty));
            maxCellQty = Math.Max(maxCellQty, cellQty);

            //FileLogger.Trace("MAP", "Province #" + (i + 1).ToString() + " will have " + cellQty + " cells with the center at [" + provinceCenter.first + ", " + provinceCenter.second + "]");
        }

        //FileLogger.Trace("MAP", "The largest province should have " + maxCellQty + " cells");

        // try to reach the desired number of cells per province
        for (int i = 1; i < maxCellQty; i++)
        {
            //FileLogger.Trace("MAP", "Adding cells: pass #" + i);
            for (int p = 0; p < numberOfProvinces; p++)
            {
                if (cellQtys[p].first < cellQtys[p].second && _neighbors[p].Count > 0)
                {
                    if (AddRandomNeighbor(p + 1, _cellMap, _neighbors[p], true) != null)
                    {
                        cellQtys[p].first++;
                    }
                }
            }
        }

        _distancesInProvinces = new int[numberOfProvinces, numberOfProvinces];

        // init distances in provinces
        for (int i = 0; i < numberOfProvinces; i++)
        {
            for (int j = 0; j < numberOfProvinces; j++)
            {
                _distancesInProvinces[i, j] = int.MaxValue;
            }
            _distancesInProvinces[i, i] = 0;
        }

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                if (_cellMap[x, y] > 0)
                {
                    SearchForNeighbors(x, y, false);
                }
            }
        }

        // we only need distances from province #1
        UpdateDistancesForProvince(0);

        /*
         * for (int i = 0; i < numberOfProvinces - 1; i++)
         * {
         *  for (int j = i + 1; j < numberOfProvinces; j++)
         *  {
         *      FileLogger.Trace("MAP", "Distance between provinces #" + (i + 1).ToString() + " and #" + (j + 1).ToString() + " is " + distancesInProvinces[i, j]);
         *  }
         * }
         */

        for (int i = 1; i < numberOfProvinces; i++)
        {
            if (_distancesInProvinces[0, i] == int.MaxValue)
            {
                ConnectIsland(i);
            }
        }

        // for connected water tiles, set province id to -1
        // so that lakes and inner seas can be identified
        // and eliminated
        for (int x = 1; x < width - 1; x++)
        {
            DeepenTheOcean(x, 1);
            DeepenTheOcean(x, height - 1);
        }

        for (int y = 1; y < height - 1; y++)
        {
            DeepenTheOcean(1, y);
            DeepenTheOcean(width - 1, y);
        }

        // dry lakes and inner seas - water tiles that are not
        // connected to the ocean
        for (int x = 1; x < _cellMap.GetLength(0) - 1; x++)
        {
            for (int y = 1; y < _cellMap.GetLength(1) - 1; y++)
            {
                if (_cellMap[x, y] == 0)
                {
                    DryLake(x, y);
                }
            }
        }

        _distancesInCells = new int[numberOfProvinces, numberOfProvinces];
        // calculate distances in cells
        for (int i = 0; i < numberOfProvinces; i++)
        {
            _distancesInCells[i, i] = 0;
            for (int j = i + 1; j < numberOfProvinces; j++)
            {
                int distance = CalculateDistance(_quadrants[i], _quadrants[j]);
                _distancesInCells[i, j] = distance;
                _distancesInCells[j, i] = distance;
            }
        }

        // converting the cells list into an array
        List <MapCellData> cells = new List <MapCellData>();

        for (int x = 1; x < width - 1; x++)
        {
            for (int y = 1; y < height - 1; y++)
            {
                if (_cellMap[x, y] > 0)
                {
                    cells.Add(new MapCellData(x, y, _cellMap[x, y]));
                }
            }
        }
        data.cells = cells.ToArray();

        // setting up province data
        ProvinceData[] templates = data.provinces;
        data.provinces = new ProvinceData[numberOfProvinces];

        // set up Utopia in the center of the map
        data.provinces[0] = templates[0].CloneAs(1);

        // calculate max distance to potential faction capitals
        List <int> orcishCapitalCandidates  = new List <int>();
        List <int> elvenCapitalCandidates   = new List <int>();
        List <int> dwarvenCapitalCandidates = new List <int>();

        int maxOrcishDistance  = 0;
        int maxElvenDistance   = 0;
        int maxDwarvenDistance = 0;

        IntIntPair mapCenter = _centers[0];

        for (int i = 1; i < numberOfProvinces; i++)
        {
            if (_distancesInProvinces[0, i] > 1)
            {
                IntIntPair provinceCenter = _centers[i];
                if (provinceCenter.first > mapCenter.first)
                {
                    // orcs: lower-right corner
                    if (provinceCenter.second < mapCenter.second)
                    {
                        orcishCapitalCandidates.Add(i);
                        maxOrcishDistance = Math.Max(maxOrcishDistance, _distancesInProvinces[0, i]);
                    }
                    else
                    {
                        // dwarves: upper-right corner
                        dwarvenCapitalCandidates.Add(i);
                        maxDwarvenDistance = Math.Max(maxDwarvenDistance, _distancesInProvinces[0, i]);
                    }
                }
                else
                {
                    // elves: a 90 degrees sector in the left half of the map
                    if (Math.Abs(provinceCenter.first - mapCenter.first) > Math.Abs(provinceCenter.second - mapCenter.second))
                    {
                        elvenCapitalCandidates.Add(i);
                        maxElvenDistance = Math.Max(maxElvenDistance, _distancesInProvinces[0, i]);
                    }
                }
            }
        }

        // we should be able to find a province for each faction at this distance from the center
        int targetDistance = Math.Min(maxOrcishDistance, Math.Min(maxElvenDistance, maxDwarvenDistance));

        // select candidates for the orcish capital
        List <int> provinceCandidates = new List <int>();

        for (int i = 0; i < orcishCapitalCandidates.Count; i++)
        {
            if (_distancesInProvinces[0, orcishCapitalCandidates[i]] == targetDistance)
            {
                provinceCandidates.Add(orcishCapitalCandidates[i]);
            }
        }

        // if for some reason there is no suitable province at the target distance, search farther
        if (provinceCandidates.Count == 0)
        {
            for (int i = 0; i < orcishCapitalCandidates.Count; i++)
            {
                if (_distancesInProvinces[0, orcishCapitalCandidates[i]] > targetDistance)
                {
                    provinceCandidates.Add(orcishCapitalCandidates[i]);
                }
            }
        }

        // start with the first candidate, search for the one
        // with the largest x and smallest y
        int orcishCapitalIndex = provinceCandidates[0];
        int distance1          = Math.Abs(_centers[orcishCapitalIndex].first - _centers[orcishCapitalIndex].second);

        for (int i = 1; i < provinceCandidates.Count; i++)
        {
            int distance2 = Math.Abs(_centers[provinceCandidates[i]].first - _centers[provinceCandidates[i]].second);
            if (distance2 > distance1)
            {
                orcishCapitalIndex = provinceCandidates[i];
            }
        }
        data.provinces[orcishCapitalIndex] = templates[1].CloneAs(orcishCapitalIndex + 1);

        // select candidates for the elven capital
        provinceCandidates = new List <int>();
        for (int i = 0; i < elvenCapitalCandidates.Count; i++)
        {
            if (_distancesInProvinces[0, elvenCapitalCandidates[i]] == targetDistance)
            {
                provinceCandidates.Add(elvenCapitalCandidates[i]);
            }
        }

        // if for some reason there is no suitable province at the target distance, search farther
        if (provinceCandidates.Count == 0)
        {
            for (int i = 0; i < elvenCapitalCandidates.Count; i++)
            {
                if (_distancesInProvinces[0, elvenCapitalCandidates[i]] > targetDistance)
                {
                    provinceCandidates.Add(elvenCapitalCandidates[i]);
                }
            }
        }

        // start with the first candidate, search for the one with the smallest x
        int elvenCapitalIndex = provinceCandidates[0];

        for (int i = 1; i < provinceCandidates.Count; i++)
        {
            if (_centers[provinceCandidates[i]].first < _centers[elvenCapitalIndex].first)
            {
                elvenCapitalIndex = provinceCandidates[i];
            }
        }
        data.provinces[elvenCapitalIndex] = templates[2].CloneAs(elvenCapitalIndex + 1);

        // select candidates for the dwarven capital
        provinceCandidates = new List <int>();
        for (int i = 0; i < dwarvenCapitalCandidates.Count; i++)
        {
            if (_distancesInProvinces[0, dwarvenCapitalCandidates[i]] == targetDistance)
            {
                provinceCandidates.Add(dwarvenCapitalCandidates[i]);
            }
        }

        // if for some reason there is no suitable province at the target distance, search farther
        if (provinceCandidates.Count == 0)
        {
            for (int i = 0; i < dwarvenCapitalCandidates.Count; i++)
            {
                if (_distancesInProvinces[0, dwarvenCapitalCandidates[i]] > targetDistance)
                {
                    provinceCandidates.Add(dwarvenCapitalCandidates[i]);
                }
            }
        }

        // start with the first candidate, search for the one with the largest x
        int dwarvenCapitalIndex = provinceCandidates[0];

        for (int i = 1; i < provinceCandidates.Count; i++)
        {
            if (_centers[provinceCandidates[i]].first + _centers[provinceCandidates[i]].second >
                _centers[dwarvenCapitalIndex].first + _centers[dwarvenCapitalIndex].second)
            {
                dwarvenCapitalIndex = provinceCandidates[i];
            }
        }
        data.provinces[dwarvenCapitalIndex] = templates[3].CloneAs(dwarvenCapitalIndex + 1);


        // select provinces that can be a secondary orcish province
        provinceCandidates = new List <int>();
        for (int i = 0; i < orcishCapitalCandidates.Count; i++)
        {
            if (_distancesInProvinces[0, orcishCapitalCandidates[i]] == 2 &&
                _distancesInProvinces[orcishCapitalIndex, orcishCapitalCandidates[i]] == 2)
            {
                provinceCandidates.Add(orcishCapitalCandidates[i]);
            }
        }

        // if there is no suitable province at distance of 2 from Utopia, search at distance of 1
        if (provinceCandidates.Count == 0)
        {
            for (int i = 0; i < orcishCapitalCandidates.Count; i++)
            {
                if (_distancesInProvinces[0, orcishCapitalCandidates[i]] >= 1 &&
                    _distancesInProvinces[orcishCapitalIndex, orcishCapitalCandidates[i]] >= 2)
                {
                    provinceCandidates.Add(orcishCapitalCandidates[i]);
                }
            }
        }

        int randomIndex;
        int provinceIndex;

        // pick one at random
        if (provinceCandidates.Count > 0)
        {
            randomIndex   = UnityEngine.Random.Range(0, provinceCandidates.Count - 1);
            provinceIndex = provinceCandidates[randomIndex];
            data.provinces[provinceIndex] = templates[4].CloneAs(provinceIndex + 1);
        }


        // select provinces that can be a secondary elven province
        provinceCandidates = new List <int>();
        for (int i = 0; i < elvenCapitalCandidates.Count; i++)
        {
            if (_distancesInProvinces[0, elvenCapitalCandidates[i]] == 2 &&
                _distancesInProvinces[elvenCapitalIndex, elvenCapitalCandidates[i]] == 2)
            {
                provinceCandidates.Add(elvenCapitalCandidates[i]);
            }
        }

        if (provinceCandidates.Count == 0)
        {
            for (int i = 0; i < elvenCapitalCandidates.Count; i++)
            {
                if (_distancesInProvinces[0, elvenCapitalCandidates[i]] >= 1 &&
                    _distancesInProvinces[elvenCapitalIndex, elvenCapitalCandidates[i]] >= 2)
                {
                    provinceCandidates.Add(elvenCapitalCandidates[i]);
                }
            }
        }

        // pick one at random
        if (provinceCandidates.Count > 0)
        {
            randomIndex   = UnityEngine.Random.Range(0, provinceCandidates.Count - 1);
            provinceIndex = provinceCandidates[randomIndex];
            data.provinces[provinceIndex] = templates[5].CloneAs(provinceIndex + 1);
        }

        // select provinces that can be a secondary dwarven province
        provinceCandidates = new List <int>();
        for (int i = 0; i < dwarvenCapitalCandidates.Count; i++)
        {
            if (_distancesInProvinces[0, dwarvenCapitalCandidates[i]] == 2 &&
                _distancesInProvinces[dwarvenCapitalIndex, dwarvenCapitalCandidates[i]] == 2)
            {
                provinceCandidates.Add(dwarvenCapitalCandidates[i]);
            }
        }

        if (provinceCandidates.Count == 0)
        {
            for (int i = 0; i < dwarvenCapitalCandidates.Count; i++)
            {
                if (_distancesInProvinces[0, dwarvenCapitalCandidates[i]] >= 1 &&
                    _distancesInProvinces[dwarvenCapitalIndex, dwarvenCapitalCandidates[i]] >= 2)
                {
                    provinceCandidates.Add(dwarvenCapitalCandidates[i]);
                }
            }
        }

        // pick one at random
        if (provinceCandidates.Count > 0)
        {
            randomIndex   = UnityEngine.Random.Range(0, provinceCandidates.Count - 1);
            provinceIndex = provinceCandidates[randomIndex];
            data.provinces[provinceIndex] = templates[6].CloneAs(provinceIndex + 1);
        }

        _humanProvinceNames = new List <string>();
        TextAsset    resourceFile = Resources.Load("HumanNames") as TextAsset;
        StringReader reader       = new StringReader(resourceFile.text);

        if (reader == null)
        {
            FileLogger.Error("MAP", "Can't load human province names");
        }
        else
        {
            string currentLine;
            while ((currentLine = reader.ReadLine()) != null)
            {
                _humanProvinceNames.Add(currentLine);
            }
        }

        // select provinces neighboring to Utopia and not used for another purpose yet
        provinceCandidates = new List <int>();
        for (int i = 1; i < numberOfProvinces; i++)
        {
            if (_distancesInProvinces[0, i] == 1 && data.provinces[i] == null)
            {
                provinceCandidates.Add(i);
            }
        }

        // put fighter-producing provinces in the select spots
        int counter = 1;

        while (provinceCandidates.Count > 0)
        {
            provinceIndex = provinceCandidates[0];
            data.provinces[provinceIndex]      = templates[7].CloneAs(provinceIndex + 1);
            data.provinces[provinceIndex].name = CreateProvinceName(provinceIndex + 1);
            counter++;
            provinceCandidates.RemoveAll(province => _distancesInProvinces[province, provinceIndex] < 2);
        }

        for (int i = 1; i < numberOfProvinces; i++)
        {
            if (data.provinces[i] == null)
            {
                randomIndex            = UnityEngine.Random.Range(8, templates.Length - 1);
                data.provinces[i]      = templates[randomIndex].CloneAs(i + 1);
                data.provinces[i].name = CreateProvinceName(i + 1);
            }
        }

        return(new Game(data));
    }