示例#1
0
        private void GenerateTrees(ArrayGrid <MapElement> map)
        {
            var openGroundSpaces = map.GetPositionsOfType(defaultFillElement);
            int spacesToFill     = (int)(openGroundSpaces.Count * percentageOfGroundToFillWithTrees);
            //Debug.Log("trees = " + spacesToFill);
            int abort = 0;

            for (int i = 0; i < spacesToFill; ++i)
            {
                Vector2Int spotToFill = openGroundSpaces.GetRandomElementFromList();
                //Debug.Log("trying to put tree at " + spotToFill);
                var nearby = map.GetAdjacentElementsOfType(spotToFill, true, defaultBuildingWallElement);

                //TODO: fix this
                if (nearby.Count <= 0)
                {
                    //Debug.Log("Planting tree at " + spotToFill);
                    map[spotToFill] = defaultTreeElement;
                    openGroundSpaces.Remove(spotToFill);
                }
                else
                {
                    --i;
                    abort++;
                }

                if (abort >= 10000)
                {
                    break;
                }
            }
        }
示例#2
0
        protected void ConnectClosestRooms(ArrayGrid <MapElement> map, ArrayGrid <int> valueMap, bool withDoors, bool straightConnections = false)
        {
            int roomCount = 0;

            FillDisconnectedRoomsWithDifferentValues(map, valueMap, ref roomCount);

            List <List <Vector2Int> > rooms = (new List <Vector2Int> [roomCount]).ToList();

            for (int i = 0; i < rooms.Count; ++i)
            {
                rooms[i] = new List <Vector2Int>();
            }

            IEnumerator <Vector2Int> mapIter = IterateOverMap(map);

            while (mapIter.MoveNext())
            {
                Vector2Int current = mapIter.Current;
                if (valueMap[current] != valueWall)
                {
                    if (valueMap.GetAdjacentElementsOfType(current, false, valueWall).Count > 0)
                    {
                        int roomIndex = valueMap[current] - 1;
                        rooms[roomIndex].Add(current);
                    }
                }
            }

            if (rooms.Count < 2)
            {
                return;
            }

            // for warshall algorithm
            // set the connection matrix

            GameRNG.RandomShuffle(rooms);

            List <List <bool> > roomConnections   = (new List <bool> [rooms.Count]).ToList();
            List <List <bool> > transitiveClosure = (new List <bool> [rooms.Count]).ToList();;
            List <List <int> >  distanceMatrix    = (new List <int> [rooms.Count]).ToList();
            List <List <KeyValuePair <Vector2Int, Vector2Int> > > closestCellsMatrix = (new List <KeyValuePair <Vector2Int, Vector2Int> > [rooms.Count]).ToList();

            for (int a = 0; a < rooms.Count; ++a)
            {
                roomConnections[a]    = (new bool[rooms.Count]).ToList();
                transitiveClosure[a]  = (new bool[rooms.Count]).ToList();
                distanceMatrix[a]     = (new int[rooms.Count]).ToList();
                closestCellsMatrix[a] = (new KeyValuePair <Vector2Int, Vector2Int> [rooms.Count]).ToList();

                for (int b = 0; b < rooms.Count; ++b)
                {
                    roomConnections[a][b] = false;
                    distanceMatrix[a][b]  = int.MaxValue;
                }
            }

            IEnumerator <Vector2Int> roomAreas = IterateOverArea(rooms.Count, rooms.Count);

            // find the closest cells for each room - Random closest cell
            while (roomAreas.MoveNext())
            {
                Vector2Int ci = roomAreas.Current;
                if (ci.x == ci.y)
                {
                    continue;
                }

                KeyValuePair <Vector2Int, Vector2Int> closestCells = new KeyValuePair <Vector2Int, Vector2Int>();

                foreach (Vector2Int cellA in rooms[ci.y])
                {
                    foreach (Vector2Int cellB in rooms[ci.x])
                    {
                        int distAB = Mathf.CeilToInt((cellA - cellB).magnitude);

                        if ((distAB < distanceMatrix[ci.y][ci.x]) || (distAB == distanceMatrix[ci.y][ci.x] && GameRNG.CoinToss()))
                        {
                            closestCells = new KeyValuePair <Vector2Int, Vector2Int>(cellA, cellB);
                            distanceMatrix[ci.y][ci.x] = distAB;
                        }
                    }
                }

                closestCellsMatrix[ci.y][ci.x] = closestCells;
            }


            // Now connect the rooms to the closest ones

            for (int roomA = 0; roomA < rooms.Count; ++roomA)
            {
                int minDist     = int.MaxValue;
                int closestRoom = 0;

                for (int roomB = 0; roomB < rooms.Count; ++roomB)
                {
                    if (roomA == roomB)
                    {
                        continue;
                    }

                    int distance = distanceMatrix[roomA][roomB];
                    if (distance < minDist)
                    {
                        minDist     = distance;
                        closestRoom = roomB;
                    }
                }

                // connect roomA to closest one

                KeyValuePair <Vector2Int, Vector2Int> closestCells = closestCellsMatrix[roomA][closestRoom];

                if (!roomConnections[roomA][closestRoom] && AddCorridor(map, valueMap, closestCells, straightConnections))
                {
                    roomConnections[roomA][closestRoom] = true;
                    roomConnections[closestRoom][roomA] = true;
                }
            }

            // The closest rooms connected. Connect the rest until all areas are connected

            for (int toConnectA = 0; toConnectA != -1;)
            {
                roomAreas = IterateOverArea(rooms.Count, rooms.Count);

                while (roomAreas.MoveNext())
                {
                    Vector2Int ci = roomAreas.Current;
                    transitiveClosure[ci.y][ci.x] = roomConnections[ci.y][ci.x];
                }

                roomAreas = IterateOverArea(rooms.Count, rooms.Count);

                while (roomAreas.MoveNext())
                {
                    Vector2Int ci = roomAreas.Current;
                    if (transitiveClosure[ci.y][ci.x] == true && ci.y != ci.x)
                    {
                        for (int ciZ = 0; ciZ < rooms.Count; ++ciZ)
                        {
                            if (transitiveClosure[ci.x][ciZ] == true)
                            {
                                transitiveClosure[ci.y][ciZ] = true;
                                transitiveClosure[ciZ][ci.y] = true;
                            }
                        }
                    }
                }

                toConnectA = -1;

                roomAreas = IterateOverArea(rooms.Count, rooms.Count);

                while (roomAreas.MoveNext() && toConnectA == -1)
                {
                    Vector2Int ci = roomAreas.Current;
                    if (transitiveClosure[ci.y][ci.x] == false && ci.x != ci.y)
                    {
                        toConnectA = ci.y;
                        break;
                    }
                }

                if (toConnectA != -1)
                {
                    int toConnectB = toConnectA;
                    while (toConnectB == toConnectA)
                    {
                        toConnectB = GameRNG.Rand(rooms.Count);
                    }

                    KeyValuePair <Vector2Int, Vector2Int> closestCells = closestCellsMatrix[toConnectA][toConnectB];

                    AddCorridor(map, valueMap, closestCells, straightConnections);
                    {
                        roomConnections[toConnectA][toConnectB] = true;
                        roomConnections[toConnectB][toConnectA] = true;
                    }
                }
            }
        }