void AddStairs() { var downStairs = Tower.StairsDownNextToGenerate(width, height); List <int> upPositions; if (downStairs >= 0) { SetTileType(downStairs, TileType.StairsDown); if (GetNeighbourIndices(downStairs, TileType.Walkable, tileTypeMap, width).Count == 0) { EatWallFromFirstFound(new List <int>(new int[] { downStairs }), TileType.Walkable); } upPositions = RoomSearch.GetPositionsAtDistance(tileTypeMap, downStairs, new Range(minDistanceBetweenStairs), TileType.Wall, true, width); } else { upPositions = RoomSearch.GetNonCornerPerimiterPositions(width, height); } if (upPositions.Count == 0) { Debug.LogError("No valid up stairs position"); } var upStairs = upPositions[Random.Range(0, upPositions.Count)]; SetTileType(upStairs, TileType.StairsUp); if (GetNeighbourIndices(upStairs, TileType.Walkable, tileTypeMap, width).Count == 0) { EatWallFromFirstFound(new List <int>(new int[] { upStairs }), TileType.Walkable); } }
int CountPathsToTargets(Coordinate origin, out Coordinate lastDeadEnd, params Coordinate[] targets) { int paths = 0; lastDeadEnd = origin; foreach (var neighbour in origin.Neighbours()) { if (!PassableTile(neighbour, false, TileType.Walkable, TileType.SpikeTrap)) { continue; } for (int i = 0; i < targets.Length; i++) { var pathsBefore = paths; if (RoomSearch.FindShortestPath(this, neighbour, targets[i], false, TileType.SpikeTrap, TileType.Walkable).Length > 1) { paths++; break; } if (pathsBefore == paths) { lastDeadEnd = neighbour; } } } return(paths); }
void RigDoorAndTreasure() { var candidates = RoomSearch.GetTileIndicesWithType(TileType.Walkable, tileTypeMap).ToArray(); if (candidates.Length > 1) { candidates = ShuffleArray <int> .Shuffle(candidates); } var upStairs = Coordinate.FromPosition(RoomSearch.GetFirstOccurance(tileTypeMap, TileType.StairsUp), width); var downStairs = Coordinate.FromPosition(RoomSearch.GetFirstOccurance(tileTypeMap, TileType.StairsDown), width); for (int i = 0; i < candidates.Length; i++) { var coord = Coordinate.FromPosition(candidates[i], width); if (PermissableDoorPosition(coord)) { var path = RoomSearch.FindShortestPath(this, upStairs, downStairs, false, TileType.Walkable, TileType.SpikeTrap, TileType.StairsUp, TileType.StairsDown); if (path.Length > 0 && !System.Array.Exists <Coordinate>(path, e => e == coord)) { SetTileType(coord, TileType.Door); Coordinate deadEnd; if (CountPathsToTargets(coord, out deadEnd, upStairs, downStairs) == 1) { if (deadEnd != coord) { PlaceCoins(deadEnd); } return; } } } } }
void JoinWalkableAreas() { var undecided = RoomSearch.GetTileIndicesWithType(TileType.None, tileTypeMap); bool firstIteration = true; int iterations = 0; while (RoomSearch.HasAnyOfType(TileType.None, tileTypeMap)) { if (firstIteration) { var floodOrigin = undecided[Random.Range(0, undecided.Count)]; FloodFillAs(floodOrigin, TileType.None, TileType.Walkable); firstIteration = false; } if (!RoomSearch.HasAnyOfType(TileType.None, tileTypeMap)) { break; } //Mapping the through wall distance EatWallFromFirstFound(GetTilesBorderingWalls(), TileType.None); iterations++; if (iterations > width * height) { return; } } }
void FindPath() { var newPath = RoomSearch.FindShortestPath(Tower.ActiveRoom, Tower.Player.position, lastTile.position, true, TileType.Door, TileType.Walkable, TileType.StairsUp, TileType.SpikeTrap); SmartJoinPaths(newPath); GrowTrailWhileNeeded(path); UpdateTrail(path); }
void FloodFillAs(int floodOrigin, TileType selector, TileType fillType) { var filling = RoomSearch.FloodSearch(tileTypeMap, width, floodOrigin, selector); for (int i = 0, l = filling.Count; i < l; i++) { SetTileType(filling[i], fillType); } }
public static int GetCorrespondingPosition(RoomData data, TileType tileType, int roomWidth, int roomHeight, bool stayOnEdge) { var pos = RoomSearch.GetFirstOccurance(data.tileTypeMap, tileType); if (pos < 0) { return(pos); } return(GetCorrespondingPosition(data, pos, roomWidth, roomHeight, stayOnEdge)); }
public static void LaySpikeTraps(Room room, RoomData data, int parts) { var selectedCoordinates = new List <Coordinate>(); var potentialSources = RoomSearch.GetTileIndicesWithType(TileType.Walkable, data.tileTypeMap); var position = potentialSources[Random.Range(0, potentialSources.Count)]; selectedCoordinates.Add(Coordinate.FromPosition(position, data.width)); parts--; room.SetTileType(position, TileType.SpikeTrap); data.tileTypeMap[position] = (int)TileType.SpikeTrap; while (parts > 0) { var prevCoordIndex = selectedCoordinates.Count - 1; var nextCandidates = RoomSearch.GetPositionsAtDistance( data.tileTypeMap, selectedCoordinates[prevCoordIndex].ToPosition(data.width, data.height), new Range(1, 2), TileType.Walkable, false, data.width); if (nextCandidates.Count == 0) { return; } else if (selectedCoordinates.Count == 1) { position = nextCandidates[Random.Range(0, nextCandidates.Count)]; } else { var offset = selectedCoordinates[prevCoordIndex] - selectedCoordinates[prevCoordIndex - 1]; position = (offset + selectedCoordinates[prevCoordIndex]).ToPosition(data.width, data.height); if (!nextCandidates.Contains(position)) { position = (offset.Rotated90CCW() + selectedCoordinates[prevCoordIndex]).ToPosition(data.width, data.height); if (!nextCandidates.Contains(position)) { position = (offset.Rotated90CW() + selectedCoordinates[prevCoordIndex]).ToPosition(data.width, data.height); if (!nextCandidates.Contains(position)) { return; } } } } selectedCoordinates.Add(Coordinate.FromPosition(position, data.width)); parts--; room.SetTileType(position, TileType.SpikeTrap); data.tileTypeMap[position] = (int)TileType.SpikeTrap; } }
void EatWallFromFirstFound(List <int> edge, TileType searchType) { var distanceToEdge = new int[tileTypeMap.Length]; int distance = 0; int wall = -1; //Find nearest connectable area while (true) { distance++; edge = GetNonPerimeterNeighbourIndices(edge, TileType.Wall, distanceToEdge, 0); for (int i = 0, l = edge.Count; i < l; i++) { distanceToEdge[edge[i]] = distance; } var bordersToUndecieded = RoomSearch.GetNonPerimeterTilesThatBorderToType(tileTypeMap, edge, searchType, width); if (bordersToUndecieded.Count > 0) { wall = bordersToUndecieded[Random.Range(0, bordersToUndecieded.Count)]; break; } if (distance > width + height) { break; } } //Digging a connection between walkable areas while (wall >= 0) { SetTileType(wall, TileType.None); distance--; if (distance <= 0) { break; } var neighbours = GetNeighbourIndices(wall, TileType.Wall, distanceToEdge, distance); if (neighbours.Count > 0) { wall = neighbours[Random.Range(0, neighbours.Count)]; } } if (wall > 0) { FloodFillAs(wall, TileType.None, TileType.Walkable); } }
List <int> GetNeighbourIndices(int index, TileType neighbourType, int[] selector, int selectionValue) { var neighbours = new List <int>(); var tileNeighbours = RoomSearch.GetNeighbourIndices(tileTypeMap, width, index, neighbourType); for (int i = 0, l = tileNeighbours.Count; i < l; i++) { if (selector[tileNeighbours[i]] == selectionValue) { neighbours.Add(tileNeighbours[i]); } } return(neighbours); }
List <int> GetNeighbourIndices(List <int> indices, TileType neighbourType) { var neighbours = new HashSet <int>(); for (int i = 0, j = indices.Count; i < j; i++) { var tileNeighbours = RoomSearch.GetNeighbourIndices(tileTypeMap, width, indices[i], neighbourType); for (int k = 0, l = tileNeighbours.Count; k < l; k++) { neighbours.Add(tileNeighbours[k]); } } return(new List <int>(neighbours)); }
List <int> GetTilesBorderingWalls() { var matchingByType = RoomSearch.GetTileIndicesWithType(TileType.Walkable, tileTypeMap); var edge = new List <int>(); for (int i = 0, l = matchingByType.Count; i < l; i++) { var tileNeighbours = RoomSearch.GetNeighbourIndices(tileTypeMap, width, matchingByType[i], TileType.Wall); if (tileNeighbours.Count > 0) { edge.Add(matchingByType[i]); } } return(edge); }
int PlayerSpawnPosition(RoomData data) { if (RoomSearch.HasAnyOfType(TileType.StairsDown, data.tileTypeMap)) { return(RoomSearch.GetFirstOccurance(data.tileTypeMap, TileType.StairsDown)); } else { var candidates = RoomSearch.GetPositionsAtDistance(data.tileTypeMap, RoomSearch.GetFirstOccurance(data.tileTypeMap, TileType.StairsUp), new Range(minDistanceSpawnInFirstLevel), TileType.Walkable, false, data.width); return(candidates[Random.Range(0, candidates.Count)]); } }
public Coordinate GetRandomFreeTileCoordinate(Coordinate referencePosition, int minDistance) { var distances = RoomSearch.GetDistanceMap(this, referencePosition); //Count all valid positions and set them to value 1 var validPositions = 0; var invalidDistance = Height + Width; for (int x = 0, lX = distances.GetLength(0); x < lX; x++) { for (int y = 0, lY = distances.GetLength(1); y < lY; y++) { if (distances[x, y] >= minDistance && distances[x, y] < invalidDistance) { distances[x, y] = 1; validPositions++; } else { distances[x, y] = 0; } } } //Select position based on count and iterate until found it int selectedPosition = Random.Range(0, validPositions); for (int x = 0, lX = distances.GetLength(0); x < lX; x++) { for (int y = 0, lY = distances.GetLength(1); y < lY; y++) { if (distances[x, y] == 1) { if (selectedPosition < 1) { return(new Coordinate(x, y)); } else { selectedPosition--; } } } } Debug.LogWarning("No valid position found"); return(Coordinate.InvalidPlacement); }
int[] GenerateWallIsands() { var undecidedTiles = RoomSearch.GetTileIndicesWithType(TileType.None, tileTypeMap); var islandsToCreate = Random.Range(minWallIslands, maxWallIslands); var islands = new int[Mathf.Max(islandsToCreate, 0)]; while (islandsToCreate > 0) { var tileIndex = undecidedTiles[Random.Range(0, undecidedTiles.Count)]; undecidedTiles.Remove(tileIndex); SetTileType(tileIndex, TileType.Wall); islands[islandsToCreate - 1] = tileIndex; islandsToCreate--; } return(islands); }
List <int> GetNonPerimeterNeighbourIndices(List <int> indices, TileType neighbourType, int[] selector, int selectionValue) { var neighbours = new HashSet <int>(); for (int i = 0, j = indices.Count; i < j; i++) { var tileNeighbours = RoomSearch.GetNeighbourIndices(tileTypeMap, width, indices[i], neighbourType); for (int k = 0, l = tileNeighbours.Count; k < l; k++) { if (selector[tileNeighbours[k]] == selectionValue && !RoomMath.IndexOnPerimeter(tileNeighbours[k], width, height)) { neighbours.Add(tileNeighbours[k]); } } } return(new List <int>(neighbours)); }
public static List <int> FloodSearch(int[] tileTypeMap, int width, int source, params TileType[] selectors) { var fillingIndex = 0; var filling = new List <int>(); filling.Add(source); while (fillingIndex < filling.Count) { var neighbourUndecided = RoomSearch.GetNeighbourIndices(tileTypeMap, width, filling[fillingIndex], selectors); for (int i = 0, l = neighbourUndecided.Count; i < l; i++) { if (!filling.Contains(neighbourUndecided[i])) { filling.AddRange(neighbourUndecided); } } fillingIndex++; } return(filling); }
void PlaceCoins(Coordinate deadEnd) { var treasurePositions = RoomSearch.FloodSearch(tileTypeMap, width, deadEnd.ToPosition(width, height), TileType.Walkable, TileType.SpikeTrap); TreasureChest.Spawn(treasurePositions, width); }
void GrowWalls(int iterations) { var walls = RoomSearch.GetTileIndicesWithType(TileType.Wall, tileTypeMap); GrowWallIslands(walls.ToArray(), iterations); }
void NewWaveSource() { waveSource = waveSource == TileType.StairsUp ? (RoomSearch.HasAnyOfType(TileType.StairsDown, tileTypeMap) ? TileType.StairsDown : TileType.StairsUp) : TileType.StairsUp; SetDistanceMap(RoomSearch.GetFirstOccurance(tileTypeMap, waveSource)); wavePeak = 0; }