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; } } }
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; } } } }