public void AppendOutput(LevelGenOutput output) { foreach (string key in output.MapInfo.Keys) { this.AddMapInfo(output.MapInfo[key]); } }
public virtual LevelGenOutput GetOutput() { LevelGenOutput output = new LevelGenOutput(); output.Grid = this.Map.Grid; output.MapInfo = new Dictionary<string, LevelGenMapInfo>(); output.OpenTiles = this.Map.ListOfCoordinatesOfType(this.Bounds, this.OpenTileType); return output; }
void LevelGenUpdate() { if (_levelGenManager.Finished) { LevelGenOutput output = _levelGenManager.GetOutput(); _targets = new List <Transform>(); _enemySpawns = new List <EnemySpawnGroup>(); _playerSpawns = new List <IntegerVector>(); bool generationOk = false; switch (output.Input.Type) { default: case LevelGenInput.GenerationType.CA: generationOk = findCASpawns(output); break; case LevelGenInput.GenerationType.BSP: generationOk = findBSPSpawns(output); break; case LevelGenInput.GenerationType.CABSPCombo: generationOk = findBSPCAComboSpawns(output); break; } if (generationOk) { if (_okToBegin) { _okToBegin = false; begin(); } else { _readyToSpawn = true; } } else { _starter.BeginGeneration(); } } }
private int pickMaybeGuaranteedEnemy(int guaranteesSpawned, int totalGuarantees, int enemiesSpawned, int difficulty, int[] guaranteedEnemiesPlaced, LevelGenOutput output, EnemySelector enemySelector) { if (guaranteesSpawned < totalGuarantees && Random.Range(0, this.NumEnemies) < enemiesSpawned + (totalGuarantees - guaranteesSpawned)) { // Use guarantee for united-spawn int guaranteedDifficulty = 0; for (int i = 0; i < guaranteedEnemiesPlaced.Length; ++i) { if (guaranteedEnemiesPlaced[i] < output.Input.GuaranteedEnemiesByDifficulty[i]) { guaranteedDifficulty = i; if (Random.value > 0.5f) { break; } } } return(enemySelector.ChooseEnemyOfDifficulty(guaranteedDifficulty)); } return(enemySelector.ChooseEnemy(difficulty)); }
private bool findBSPSpawns(LevelGenOutput output) { List <LevelGenMap.Coordinate> openTiles = new List <LevelGenMap.Coordinate>(output.OpenTiles); openTiles.Shuffle(); LevelGenRoomInfo roomInfo = output.MapInfo[LevelGenRoomInfo.KEY] as LevelGenRoomInfo; EnemySelector enemySelector = new EnemySelector(); IntegerVector enemyCountRange = output.Input.GetCurrentNumEnemiesRange(); this.NumEnemies = Random.Range(enemyCountRange.X, enemyCountRange.Y + 1); if (ProgressData.IsMiniBoss(ProgressData.MostRecentTile)) { findMinibossSpawn(openTiles, openTiles); } int difficulty = ProgressData.GetCurrentDifficulty(); int[] guaranteedEnemiesPlaced = new int[output.Input.GuaranteedEnemiesByDifficulty.Length]; int totalGuarantees = 0; for (int i = 0; i < guaranteedEnemiesPlaced.Length; ++i) { totalGuarantees += output.Input.GuaranteedEnemiesByDifficulty[i]; } if (openTiles.Count <= (this.NumEnemies + DynamicData.MAX_PLAYERS) * output.Input.MinDistanceBetweenSpawns * 2 + 1 || roomInfo == null || roomInfo.Data.Count < 4 + difficulty) { Debug.Log("Regeneration necessary - BSP 1"); return(false); } else { List <SimpleRect> availableRooms = new List <SimpleRect>(roomInfo.Data as List <SimpleRect>); availableRooms.Shuffle(); // Player room SimpleRect playerRoom = availableRooms[availableRooms.Count - 1]; availableRooms.RemoveAt(availableRooms.Count - 1); List <LevelGenMap.Coordinate> playerRoomCoords = coordinatesInRoom(playerRoom); openTiles.RemoveList(playerRoomCoords); playerRoomCoords.Shuffle(); for (int p = 0; p < DynamicData.MAX_PLAYERS; ++p) { if (DynamicData.GetSessionPlayer(p).HasJoined) { _playerSpawns.Add(playerRoomCoords[playerRoomCoords.Count - 1].integerVector); playerRoomCoords.RemoveAt(playerRoomCoords.Count - 1); } } if (openTiles.Count <= this.NumEnemies * output.Input.MinDistanceBetweenSpawns * 2 + 1) { Debug.Log("Regeneration necessary - BSP 2"); return(false); } else { int enemiesSpawned = 0; int guaranteesSpawned = 0; bool haveUnitedAllRoomsSoFar = true; // Enemy rooms for (int r = 0; r < availableRooms.Count; ++r) { SimpleRect room = availableRooms[r]; if (this.NumEnemies - enemiesSpawned < 4 || (r == availableRooms.Count - 1 && haveUnitedAllRoomsSoFar && guaranteesSpawned < totalGuarantees)) { break; } if (Random.value > 0.65f) { haveUnitedAllRoomsSoFar = false; continue; } List <EnemySpawn> roomSpawns = new List <EnemySpawn>(); EnemySelector.WeightSet roomWeightSet = new EnemySelector.WeightSet(); enemySelector.AddWeightSet(roomWeightSet); // United-spawn room int favoredEnemyId = pickMaybeGuaranteedEnemy(guaranteesSpawned, totalGuarantees, enemiesSpawned, difficulty, guaranteedEnemiesPlaced, output, enemySelector); roomWeightSet.WeightsByEnemyId[favoredEnemyId] = 100; List <IntegerVector> roomCorners = new List <IntegerVector>(); roomCorners.Add(new IntegerVector(room.X, room.Y)); roomCorners.Add(new IntegerVector(room.X + room.Width, room.Y)); roomCorners.Add(new IntegerVector(room.X, room.Y + room.Height)); roomCorners.Add(new IntegerVector(room.X + room.Width, room.Y + room.Height)); roomCorners.Shuffle(); IntegerVector firstPosition = roomCorners[roomCorners.Count - 1]; ++enemiesSpawned; roomSpawns.Add(new EnemySpawn(firstPosition, favoredEnemyId)); roomCorners.RemoveAt(roomCorners.Count - 1); int enemyDifficulty = StaticData.EnemyData.EnemyTypes[favoredEnemyId].Difficulty; if (guaranteedEnemiesPlaced[enemyDifficulty] < output.Input.GuaranteedEnemiesByDifficulty[enemyDifficulty]) { guaranteedEnemiesPlaced[enemyDifficulty] += 1; ++guaranteesSpawned; } foreach (IntegerVector position in roomCorners) { ++enemiesSpawned; int enemyId = enemySelector.ChooseEnemy(difficulty); roomSpawns.Add(new EnemySpawn(position, enemyId)); enemyDifficulty = StaticData.EnemyData.EnemyTypes[enemyId].Difficulty; if (guaranteedEnemiesPlaced[enemyDifficulty] < output.Input.GuaranteedEnemiesByDifficulty[enemyDifficulty]) { guaranteedEnemiesPlaced[enemyDifficulty] += 1; ++guaranteesSpawned; } } bool extraTwo = false; if (this.NumEnemies - enemiesSpawned > 2 && Random.value < CHANCE_FOR_EXTRA_TWO_IN_BSP_ROOM) { // Let's add 2 along the walls of the longest room dimension extraTwo = true; favoredEnemyId = pickMaybeGuaranteedEnemy(guaranteesSpawned, totalGuarantees, enemiesSpawned, difficulty, guaranteedEnemiesPlaced, output, enemySelector); roomWeightSet.WeightsByEnemyId[favoredEnemyId] = 100; IntegerVector position1; IntegerVector position2; if (room.Width > room.Height) { position1 = new IntegerVector(room.X + room.Width / 2, room.Y); position2 = new IntegerVector(room.X + room.Width / 2, room.Y + room.Height); } else { position1 = new IntegerVector(room.X, room.Y + room.Height / 2); position2 = new IntegerVector(room.X + room.Width, room.Y + room.Height / 2); } enemiesSpawned += 2; roomSpawns.Add(new EnemySpawn(position1, favoredEnemyId)); enemyDifficulty = StaticData.EnemyData.EnemyTypes[favoredEnemyId].Difficulty; if (guaranteedEnemiesPlaced[enemyDifficulty] < output.Input.GuaranteedEnemiesByDifficulty[enemyDifficulty]) { guaranteedEnemiesPlaced[enemyDifficulty] += 1; ++guaranteesSpawned; } int enemyId = enemySelector.ChooseEnemy(difficulty); roomSpawns.Add(new EnemySpawn(position2, enemyId)); enemyDifficulty = StaticData.EnemyData.EnemyTypes[enemyId].Difficulty; if (guaranteedEnemiesPlaced[enemyDifficulty] < output.Input.GuaranteedEnemiesByDifficulty[enemyDifficulty]) { guaranteedEnemiesPlaced[enemyDifficulty] += 1; ++guaranteesSpawned; } } _enemySpawns.Add(new EnemySpawnGroup(new IntegerVector(room.X + room.Width / 2, room.Y + room.Height / 2), roomSpawns, ((Mathf.Max(room.Width, room.Height) + 2.6f) / 2.0f) * _tileRenderer.TileRenderSize)); if (!enemySelector.RemoveWeightSet(roomWeightSet)) { Debug.Log("hrrmmmm"); } if (extraTwo || Random.value < CHANCE_FOR_REMOVE_SPAWN_ROOM_FOR_FUTURE_BSP) { openTiles.RemoveList(coordinatesInRoom(room)); } } // Non united-room spawns spawnSimple(enemiesSpawned, output, guaranteedEnemiesPlaced, enemySelector, difficulty, openTiles, false); } } return(true); }
private int pickMaybeGuaranteedEnemy(int guaranteesSpawned, int totalGuarantees, int enemiesSpawned, int difficulty, int[] guaranteedEnemiesPlaced, LevelGenOutput output, EnemySelector enemySelector) { if (guaranteesSpawned < totalGuarantees && Random.Range(0, this.NumEnemies) < enemiesSpawned + (totalGuarantees - guaranteesSpawned)) { // Use guarantee for united-spawn int guaranteedDifficulty = 0; for (int i = 0; i < guaranteedEnemiesPlaced.Length; ++i) { if (guaranteedEnemiesPlaced[i] < output.Input.GuaranteedEnemiesByDifficulty[i]) { guaranteedDifficulty = i; if (Random.value > 0.5f) break; } } return enemySelector.ChooseEnemyOfDifficulty(guaranteedDifficulty); } return enemySelector.ChooseEnemy(difficulty); }
private void spawnSimple(int enemiesSpawned, LevelGenOutput output, int[] guaranteedEnemiesPlaced, EnemySelector enemySelector, int difficulty, List<LevelGenMap.Coordinate> openTiles, bool spawnPlayers) { // Guaranteed enemies for (int i = 0; i < output.Input.GuaranteedEnemiesByDifficulty.Length; ++i) { while (guaranteedEnemiesPlaced[i] < output.Input.GuaranteedEnemiesByDifficulty[i]) { int enemyId = enemySelector.ChooseEnemyOfDifficulty(i); guaranteedEnemiesPlaced[i] = guaranteedEnemiesPlaced[i] + 1; ++enemiesSpawned; _enemySpawns.Add(new EnemySpawnGroup(findGoodOpenPosition(openTiles, output.Input.MinDistanceBetweenSpawns).integerVector, enemyId)); } } // Remaining enemies for (; enemiesSpawned < this.NumEnemies; ++enemiesSpawned) { int enemyId = enemySelector.ChooseEnemy(difficulty); _enemySpawns.Add(new EnemySpawnGroup(findGoodOpenPosition(openTiles, output.Input.MinDistanceBetweenSpawns).integerVector, enemyId)); } // Players if (spawnPlayers) { bool first = true; List<LevelGenMap.Coordinate> tiles = openTiles; for (int i = 0; i < DynamicData.MAX_PLAYERS; ++i) { if (DynamicData.GetSessionPlayer(i).HasJoined) { LevelGenMap.Coordinate playerSpawn = findGoodOpenPosition(tiles, 0); _playerSpawns.Add(playerSpawn.integerVector); if (first) { first = false; List<LevelGenMap.Coordinate> nearbySpawns = new List<LevelGenMap.Coordinate>(); foreach (LevelGenMap.Coordinate coord in openTiles) { if (Mathf.Abs(coord.x - playerSpawn.x) + Mathf.Abs(coord.y - playerSpawn.y) <= this.MaxPlayerSpawnDistance) nearbySpawns.Add(coord); } if (nearbySpawns.Count >= DynamicData.MAX_PLAYERS) tiles = nearbySpawns; } else { openTiles.Remove(playerSpawn); } } } } }
private bool findBSPCAComboSpawns(LevelGenOutput output) { List<LevelGenMap.Coordinate> openTiles = new List<LevelGenMap.Coordinate>(output.OpenTiles); openTiles.Shuffle(); EnemySelector enemySelector = new EnemySelector(); int difficulty = ProgressData.GetCurrentDifficulty(); IntegerVector enemyCountRange = output.Input.GetCurrentNumEnemiesRange(); int[] guaranteedEnemiesPlaced = new int[output.Input.GuaranteedEnemiesByDifficulty.Length]; this.NumEnemies = Random.Range(enemyCountRange.X, enemyCountRange.Y + 1); LevelGenCaveInfo caveInfo = output.MapInfo[LevelGenCaveInfo.KEY] as LevelGenCaveInfo; if (ProgressData.IsMiniBoss(ProgressData.MostRecentTile)) findMinibossSpawn(openTiles, (caveInfo.Data as List<List<LevelGenMap.Coordinate>>)[0]); LevelGenRoomInfo roomInfo = output.MapInfo[LevelGenRoomInfo.KEY] as LevelGenRoomInfo; List<SimpleRect> availableRooms = new List<SimpleRect>(roomInfo.Data as List<SimpleRect>); availableRooms.Shuffle(); // Player room SimpleRect playerRoom = availableRooms[availableRooms.Count - 1]; availableRooms.RemoveAt(availableRooms.Count - 1); List<LevelGenMap.Coordinate> playerRoomCoords = coordinatesInRoom(playerRoom); openTiles.RemoveList(playerRoomCoords); playerRoomCoords.Shuffle(); for (int p = 0; p < DynamicData.MAX_PLAYERS; ++p) { if (DynamicData.GetSessionPlayer(p).HasJoined) { _playerSpawns.Add(playerRoomCoords[playerRoomCoords.Count - 1].integerVector); playerRoomCoords.RemoveAt(playerRoomCoords.Count - 1); } } if (openTiles.Count <= (this.NumEnemies + DynamicData.MAX_PLAYERS) * output.Input.MinDistanceBetweenSpawns * 2 + 1) { Debug.Log("Regeneration necessary - CA"); return false; } else { spawnSimple(0, output, guaranteedEnemiesPlaced, enemySelector, difficulty, openTiles, false); } return true; }
private bool findBSPSpawns(LevelGenOutput output) { List<LevelGenMap.Coordinate> openTiles = new List<LevelGenMap.Coordinate>(output.OpenTiles); openTiles.Shuffle(); LevelGenRoomInfo roomInfo = output.MapInfo[LevelGenRoomInfo.KEY] as LevelGenRoomInfo; EnemySelector enemySelector = new EnemySelector(); IntegerVector enemyCountRange = output.Input.GetCurrentNumEnemiesRange(); this.NumEnemies = Random.Range(enemyCountRange.X, enemyCountRange.Y + 1); if (ProgressData.IsMiniBoss(ProgressData.MostRecentTile)) findMinibossSpawn(openTiles, openTiles); int difficulty = ProgressData.GetCurrentDifficulty(); int[] guaranteedEnemiesPlaced = new int[output.Input.GuaranteedEnemiesByDifficulty.Length]; int totalGuarantees = 0; for (int i = 0; i < guaranteedEnemiesPlaced.Length; ++i) { totalGuarantees += output.Input.GuaranteedEnemiesByDifficulty[i]; } if (openTiles.Count <= (this.NumEnemies + DynamicData.MAX_PLAYERS) * output.Input.MinDistanceBetweenSpawns * 2 + 1 || roomInfo == null || roomInfo.Data.Count < 4 + difficulty) { Debug.Log("Regeneration necessary - BSP 1"); return false; } else { List<SimpleRect> availableRooms = new List<SimpleRect>(roomInfo.Data as List<SimpleRect>); availableRooms.Shuffle(); // Player room SimpleRect playerRoom = availableRooms[availableRooms.Count - 1]; availableRooms.RemoveAt(availableRooms.Count - 1); List<LevelGenMap.Coordinate> playerRoomCoords = coordinatesInRoom(playerRoom); openTiles.RemoveList(playerRoomCoords); playerRoomCoords.Shuffle(); for (int p = 0; p < DynamicData.MAX_PLAYERS; ++p) { if (DynamicData.GetSessionPlayer(p).HasJoined) { _playerSpawns.Add(playerRoomCoords[playerRoomCoords.Count - 1].integerVector); playerRoomCoords.RemoveAt(playerRoomCoords.Count - 1); } } if (openTiles.Count <= this.NumEnemies * output.Input.MinDistanceBetweenSpawns * 2 + 1) { Debug.Log("Regeneration necessary - BSP 2"); return false; } else { int enemiesSpawned = 0; int guaranteesSpawned = 0; bool haveUnitedAllRoomsSoFar = true; // Enemy rooms for (int r = 0; r < availableRooms.Count; ++r) { SimpleRect room = availableRooms[r]; if (this.NumEnemies - enemiesSpawned < 4 || (r == availableRooms.Count - 1 && haveUnitedAllRoomsSoFar && guaranteesSpawned < totalGuarantees)) break; if (Random.value > 0.65f) { haveUnitedAllRoomsSoFar = false; continue; } List<EnemySpawn> roomSpawns = new List<EnemySpawn>(); EnemySelector.WeightSet roomWeightSet = new EnemySelector.WeightSet(); enemySelector.AddWeightSet(roomWeightSet); // United-spawn room int favoredEnemyId = pickMaybeGuaranteedEnemy(guaranteesSpawned, totalGuarantees, enemiesSpawned, difficulty, guaranteedEnemiesPlaced, output, enemySelector); roomWeightSet.WeightsByEnemyId[favoredEnemyId] = 100; List<IntegerVector> roomCorners = new List<IntegerVector>(); roomCorners.Add(new IntegerVector(room.X, room.Y)); roomCorners.Add(new IntegerVector(room.X + room.Width, room.Y)); roomCorners.Add(new IntegerVector(room.X, room.Y + room.Height)); roomCorners.Add(new IntegerVector(room.X + room.Width, room.Y + room.Height)); roomCorners.Shuffle(); IntegerVector firstPosition = roomCorners[roomCorners.Count - 1]; ++enemiesSpawned; roomSpawns.Add(new EnemySpawn(firstPosition, favoredEnemyId)); roomCorners.RemoveAt(roomCorners.Count - 1); int enemyDifficulty = StaticData.EnemyData.EnemyTypes[favoredEnemyId].Difficulty; if (guaranteedEnemiesPlaced[enemyDifficulty] < output.Input.GuaranteedEnemiesByDifficulty[enemyDifficulty]) { guaranteedEnemiesPlaced[enemyDifficulty] += 1; ++guaranteesSpawned; } foreach (IntegerVector position in roomCorners) { ++enemiesSpawned; int enemyId = enemySelector.ChooseEnemy(difficulty); roomSpawns.Add(new EnemySpawn(position, enemyId)); enemyDifficulty = StaticData.EnemyData.EnemyTypes[enemyId].Difficulty; if (guaranteedEnemiesPlaced[enemyDifficulty] < output.Input.GuaranteedEnemiesByDifficulty[enemyDifficulty]) { guaranteedEnemiesPlaced[enemyDifficulty] += 1; ++guaranteesSpawned; } } bool extraTwo = false; if (this.NumEnemies - enemiesSpawned > 2 && Random.value < CHANCE_FOR_EXTRA_TWO_IN_BSP_ROOM) { // Let's add 2 along the walls of the longest room dimension extraTwo = true; favoredEnemyId = pickMaybeGuaranteedEnemy(guaranteesSpawned, totalGuarantees, enemiesSpawned, difficulty, guaranteedEnemiesPlaced, output, enemySelector); roomWeightSet.WeightsByEnemyId[favoredEnemyId] = 100; IntegerVector position1; IntegerVector position2; if (room.Width > room.Height) { position1 = new IntegerVector(room.X + room.Width / 2, room.Y); position2 = new IntegerVector(room.X + room.Width / 2, room.Y + room.Height); } else { position1 = new IntegerVector(room.X, room.Y + room.Height / 2); position2 = new IntegerVector(room.X + room.Width, room.Y + room.Height / 2); } enemiesSpawned += 2; roomSpawns.Add(new EnemySpawn(position1, favoredEnemyId)); enemyDifficulty = StaticData.EnemyData.EnemyTypes[favoredEnemyId].Difficulty; if (guaranteedEnemiesPlaced[enemyDifficulty] < output.Input.GuaranteedEnemiesByDifficulty[enemyDifficulty]) { guaranteedEnemiesPlaced[enemyDifficulty] += 1; ++guaranteesSpawned; } int enemyId = enemySelector.ChooseEnemy(difficulty); roomSpawns.Add(new EnemySpawn(position2, enemyId)); enemyDifficulty = StaticData.EnemyData.EnemyTypes[enemyId].Difficulty; if (guaranteedEnemiesPlaced[enemyDifficulty] < output.Input.GuaranteedEnemiesByDifficulty[enemyDifficulty]) { guaranteedEnemiesPlaced[enemyDifficulty] += 1; ++guaranteesSpawned; } } _enemySpawns.Add(new EnemySpawnGroup(new IntegerVector(room.X + room.Width / 2, room.Y + room.Height / 2), roomSpawns, ((Mathf.Max(room.Width, room.Height) + 2.6f) / 2.0f) * _tileRenderer.TileRenderSize)); if (!enemySelector.RemoveWeightSet(roomWeightSet)) { Debug.Log("hrrmmmm"); } if (extraTwo || Random.value < CHANCE_FOR_REMOVE_SPAWN_ROOM_FOR_FUTURE_BSP) openTiles.RemoveList(coordinatesInRoom(room)); } // Non united-room spawns spawnSimple(enemiesSpawned, output, guaranteedEnemiesPlaced, enemySelector, difficulty, openTiles, false); } } return true; }
private bool findCASpawns(LevelGenOutput output) { List<LevelGenMap.Coordinate> openTiles = new List<LevelGenMap.Coordinate>(output.OpenTiles); openTiles.Shuffle(); EnemySelector enemySelector = new EnemySelector(); int difficulty = ProgressData.GetCurrentDifficulty(); IntegerVector enemyCountRange = output.Input.GetCurrentNumEnemiesRange(); int[] guaranteedEnemiesPlaced = new int[output.Input.GuaranteedEnemiesByDifficulty.Length]; this.NumEnemies = Random.Range(enemyCountRange.X, enemyCountRange.Y + 1); LevelGenCaveInfo caveInfo = output.MapInfo[LevelGenCaveInfo.KEY] as LevelGenCaveInfo; if (ProgressData.IsMiniBoss(ProgressData.MostRecentTile)) findMinibossSpawn(openTiles, (caveInfo.Data as List<List<LevelGenMap.Coordinate>>)[0]); if (openTiles.Count <= (this.NumEnemies + DynamicData.MAX_PLAYERS) * output.Input.MinDistanceBetweenSpawns * 2 + 1) { Debug.Log("Regeneration necessary - CA"); return false; } else { spawnSimple(0, output, guaranteedEnemiesPlaced, enemySelector, difficulty, openTiles, true); } return true; }