using System.Collections.Generic; using UnityEngine; public class SettlementGenerator { private readonly List usedNames = new List(); private static readonly string[] townNames = { "Ashford", "Brookhaven", "Clearwater", "Drakemoor", "Emberfall", "Frostholm", "Goldmeadow", "Ironbridge", "Moonhaven", "Oakenford", "Ravenshollow", "Silverdale", "Thornwick", "Wolfsburg", "Brightwater" }; private static readonly string[] villageNames = { "Millbrook", "Stonefield", "Greenhill", "Redrock", "Fairhaven", "Smallwood", "Riverside", "Hillcrest", "Meadowbrook", "Pinewood", "Sunset", "Morning", "Pleasant", "Quiet", "Little" }; public void GenerateSettlements(MapData mapData) { // Clear used names for new generation usedNames.Clear(); GenerateTowns(mapData); GenerateVillages(mapData); } private void GenerateTowns(MapData mapData) { int townCount = Random.Range(2, 5); int attempts = 0; int maxAttempts = 100; while (mapData.GetTowns().Count < townCount && attempts < maxAttempts) { attempts++; int x = Random.Range(15, mapData.Width - 15); int y = Random.Range(15, mapData.Height - 15); if (CanPlaceSettlement(mapData, x, y, 3, 20)) { CreateTown(mapData, x, y); } } } private void GenerateVillages(MapData mapData) { int villageCount = Random.Range(8, 15); int attempts = 0; int maxAttempts = 100; while (mapData.GetVillages().Count < villageCount && attempts < maxAttempts) { attempts++; int x = Random.Range(5, mapData.Width - 5); int y = Random.Range(5, mapData.Height - 5); if (CanPlaceSettlement(mapData, x, y, 1, 10)) { CreateVillage(mapData, x, y); } } } private bool CanPlaceSettlement(MapData mapData, int x, int y, int size, int minDistance) { // Check if area is suitable (plains terrain) for (int dx = -size / 2; dx <= size / 2; dx++) { for (int dy = -size / 2; dy <= size / 2; dy++) { int checkX = x + dx; int checkY = y + dy; if (!mapData.IsValidPosition(checkX, checkY)) return false; MapTile tile = mapData.GetTile(checkX, checkY); if (tile.terrainType != TerrainType.Plains && tile.terrainType != TerrainType.Shore) return false; } } // Check distance from other settlements foreach (var settlement in mapData.GetTowns()) { float distance = Vector2.Distance(new Vector2(x, y), new Vector2(settlement.position.x, settlement.position.y)); if (distance < minDistance) return false; } foreach (var settlement in mapData.GetVillages()) { float distance = Vector2.Distance(new Vector2(x, y), new Vector2(settlement.position.x, settlement.position.y)); if (distance < minDistance) return false; } return true; } private void CreateTown(MapData mapData, int centerX, int centerY) { string name = GetUniqueRandomName(townNames); var settlement = new Settlement(name, SettlementType.Town, new Vector2Int(centerX, centerY)); // Create 3x3 town area for (int dx = -1; dx <= 1; dx++) { for (int dy = -1; dy <= 1; dy++) { int x = centerX + dx; int y = centerY + dy; if (mapData.IsValidPosition(x, y)) { mapData.GetTile(x, y).featureType = FeatureType.Town; mapData.GetTile(x, y).name = name; settlement.tiles.Add(new Vector2Int(x, y)); } } } mapData.AddSettlement(settlement); } private void CreateVillage(MapData mapData, int x, int y) { string name = GetUniqueRandomName(villageNames); var settlement = new Settlement(name, SettlementType.Village, new Vector2Int(x, y)); mapData.GetTile(x, y).featureType = FeatureType.Village; mapData.GetTile(x, y).name = name; settlement.tiles.Add(new Vector2Int(x, y)); mapData.AddSettlement(settlement); } private string GetUniqueRandomName(string[] nameArray) { // Find available names not already used List availableNames = new List(); foreach (string name in nameArray) { if (!usedNames.Contains(name)) { availableNames.Add(name); } } // If all names are used, fallback to numbered names if (availableNames.Count == 0) { string baseName = nameArray[Random.Range(0, nameArray.Length)]; int counter = 2; string numberedName; do { numberedName = $"{baseName} {counter}"; counter++; } while (usedNames.Contains(numberedName)); usedNames.Add(numberedName); return numberedName; } // Select random name from available names string selectedName = availableNames[Random.Range(0, availableNames.Count)]; usedNames.Add(selectedName); return selectedName; } }