/// <summary> /// Given an empty position in the grid, find all of the viable room prefabs /// for that position that meets the following requirements: /// - PrefabHasRequiredDirections: Neighbouring rooms may have /// doors that need to lead into a room at the given position, and the /// random prefab must have associated doors so that the doors in /// the neighbouring rooms are not blocked off. /// - PrefabIsEnclosedIfRequired: At the end of level generation, /// the final chosen room prefabs must be fully enclosed so that the level /// does not contain doors that lead to nowhere. /// - PrefabHasSpaceInFrontOfDoors: Similar to PrefabHasRequiredDirections, /// neighbouring rooms may NOT have a door that leads into a room at /// the given position, so the chosen prefab must not have a door /// in that direction as it would be blocked off by the existing /// neighbouring room. /// - GuaranteedPrefabHasNotBeenSpawned: Prefabs marked as /// guaranteed spawn for a given depth should only be spawned once /// for that depth. If the prefab was already spawned, it is no /// longer viable. /// </summary> /// <param name="position"> /// The position in the grid of rooms. The units used are relative /// to the starting room. So 0,0 is the starting room. 1,0 is the /// room east of that, etc. /// </param> /// <param name="enclosedPrefabRequired"> /// Whether or not the random prefab needs to be enclosed, meaning /// all of its doors will connect to already existing rooms and the /// room will contain no unconnected doors. /// </param> /// <returns> /// An array of room prefabs that meets the requirements for the given position. /// </returns> private GameObject[] FindViablePrefabsFor(Vector2Int position, bool enclosedPrefabRequired, float depthPercentage) { HashSet <Direction> requiredDirections = FindRequiredDirectionsFor(position); bool PrefabHasRequiredDirections(GameObject prefab) { RoomConnectionBehaviour prefabRoom = prefab.GetComponent <RoomConnectionBehaviour>(); return(requiredDirections.All(direction => prefabRoom.Directions.Contains(direction))); } bool PrefabIsEnclosedIfRequired(GameObject prefab) { if (!enclosedPrefabRequired) { return(true); } RoomConnectionBehaviour prefabRoom = prefab.GetComponent <RoomConnectionBehaviour>(); return(requiredDirections.SetEquals(prefabRoom.Directions)); } bool PrefabHasSpaceInFrontOfDoors(GameObject prefab) { RoomConnectionBehaviour prefabRoom = prefab.GetComponent <RoomConnectionBehaviour>(); bool DoorNotRequired(DoorConnectionBehaviour door) => !requiredDirections.Contains(door.Direction); IEnumerable <DoorConnectionBehaviour> nonRequiredDoors = prefabRoom.Doors.Where(DoorNotRequired); return(nonRequiredDoors.All(door => PositionInDirectionIsEmpty(position, door.Direction))); } bool OnlyOnceGuaranteePrefabHasNotBeenSpawned(GameObject prefab) { RoomGenerationBehaviour roomGenerationBehaviour = prefab.GetComponent <RoomGenerationBehaviour>(); SpawnProbability? spawnProbability = roomGenerationBehaviour.GetSpawnProbability(depthPercentage); if (spawnProbability.HasValue && spawnProbability.Value.Guarantee == SpawnProbability.SpawnGuarantee.SpawnOnlyOnce) { return(!HasSpawnedGuaranteedRoomPrefab(prefab, spawnProbability.Value.DepthPercentage)); } return(true); } IEnumerable <GameObject> viablePrefabs = _roomPrefabs .Where(PrefabHasRequiredDirections) .Where(PrefabIsEnclosedIfRequired) .Where(PrefabHasSpaceInFrontOfDoors) .Where(OnlyOnceGuaranteePrefabHasNotBeenSpawned); return(viablePrefabs.ToArray()); }
/// <summary> /// Verifies that the RoomGrid has placed all guaranteed rooms, /// this is used as a fail-safe to ensure the level is not missing /// vital rooms. /// </summary> /// <returns> /// true if the RoomGrid contains all of the guaranteed rooms level /// otherwise false. /// </returns> public bool Verify() { foreach (GameObject roomPrefab in _roomPrefabs) { RoomGenerationBehaviour roomGenerationBehaviour = roomPrefab.GetComponent <RoomGenerationBehaviour>(); List <SpawnProbability> spawnProbabilities = roomGenerationBehaviour.SpawnProbabilities; foreach (SpawnProbability spawnProbability in spawnProbabilities) { if (spawnProbability.Guarantee == SpawnProbability.SpawnGuarantee.None) { continue; } bool verified = HasSpawnedGuaranteedRoomPrefab(roomPrefab, spawnProbability.DepthPercentage); if (!verified) { return(false); } } } return(true); }