SettlementGenerator.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. public class SettlementGenerator
  4. {
  5. private readonly List<string> usedNames = new List<string>();
  6. private static readonly string[] townNames = {
  7. "Ashford", "Brookhaven", "Clearwater", "Drakemoor", "Emberfall",
  8. "Frostholm", "Goldmeadow", "Ironbridge", "Moonhaven", "Oakenford",
  9. "Ravenshollow", "Silverdale", "Thornwick", "Wolfsburg", "Brightwater"
  10. };
  11. private static readonly string[] villageNames = {
  12. "Millbrook", "Stonefield", "Greenhill", "Redrock", "Fairhaven",
  13. "Smallwood", "Riverside", "Hillcrest", "Meadowbrook", "Pinewood",
  14. "Sunset", "Morning", "Pleasant", "Quiet", "Little"
  15. };
  16. public void GenerateSettlements(MapData mapData)
  17. {
  18. // Clear used names for new generation
  19. usedNames.Clear();
  20. GenerateTowns(mapData);
  21. GenerateVillages(mapData);
  22. }
  23. private void GenerateTowns(MapData mapData)
  24. {
  25. int townCount = Random.Range(2, 5);
  26. int attempts = 0;
  27. int maxAttempts = 100;
  28. while (mapData.GetTowns().Count < townCount && attempts < maxAttempts)
  29. {
  30. attempts++;
  31. int x = Random.Range(15, mapData.Width - 15);
  32. int y = Random.Range(15, mapData.Height - 15);
  33. if (CanPlaceSettlement(mapData, x, y, 3, 20))
  34. {
  35. CreateTown(mapData, x, y);
  36. }
  37. }
  38. }
  39. private void GenerateVillages(MapData mapData)
  40. {
  41. int villageCount = Random.Range(8, 15);
  42. int attempts = 0;
  43. int maxAttempts = 100;
  44. while (mapData.GetVillages().Count < villageCount && attempts < maxAttempts)
  45. {
  46. attempts++;
  47. int x = Random.Range(5, mapData.Width - 5);
  48. int y = Random.Range(5, mapData.Height - 5);
  49. if (CanPlaceSettlement(mapData, x, y, 1, 10))
  50. {
  51. CreateVillage(mapData, x, y);
  52. }
  53. }
  54. }
  55. private bool CanPlaceSettlement(MapData mapData, int x, int y, int size, int minDistance)
  56. {
  57. // Check if area is suitable (plains terrain)
  58. for (int dx = -size / 2; dx <= size / 2; dx++)
  59. {
  60. for (int dy = -size / 2; dy <= size / 2; dy++)
  61. {
  62. int checkX = x + dx;
  63. int checkY = y + dy;
  64. if (!mapData.IsValidPosition(checkX, checkY))
  65. return false;
  66. MapTile tile = mapData.GetTile(checkX, checkY);
  67. if (tile.terrainType != TerrainType.Plains &&
  68. tile.terrainType != TerrainType.Shore)
  69. return false;
  70. }
  71. }
  72. // Check distance from other settlements
  73. foreach (var settlement in mapData.GetTowns())
  74. {
  75. float distance = Vector2.Distance(new Vector2(x, y),
  76. new Vector2(settlement.position.x, settlement.position.y));
  77. if (distance < minDistance)
  78. return false;
  79. }
  80. foreach (var settlement in mapData.GetVillages())
  81. {
  82. float distance = Vector2.Distance(new Vector2(x, y),
  83. new Vector2(settlement.position.x, settlement.position.y));
  84. if (distance < minDistance)
  85. return false;
  86. }
  87. return true;
  88. }
  89. private void CreateTown(MapData mapData, int centerX, int centerY)
  90. {
  91. string name = GetUniqueRandomName(townNames);
  92. var settlement = new Settlement(name, SettlementType.Town, new Vector2Int(centerX, centerY));
  93. // Create 3x3 town area
  94. for (int dx = -1; dx <= 1; dx++)
  95. {
  96. for (int dy = -1; dy <= 1; dy++)
  97. {
  98. int x = centerX + dx;
  99. int y = centerY + dy;
  100. if (mapData.IsValidPosition(x, y))
  101. {
  102. mapData.GetTile(x, y).featureType = FeatureType.Town;
  103. mapData.GetTile(x, y).name = name;
  104. settlement.tiles.Add(new Vector2Int(x, y));
  105. }
  106. }
  107. }
  108. mapData.AddSettlement(settlement);
  109. }
  110. private void CreateVillage(MapData mapData, int x, int y)
  111. {
  112. string name = GetUniqueRandomName(villageNames);
  113. var settlement = new Settlement(name, SettlementType.Village, new Vector2Int(x, y));
  114. mapData.GetTile(x, y).featureType = FeatureType.Village;
  115. mapData.GetTile(x, y).name = name;
  116. settlement.tiles.Add(new Vector2Int(x, y));
  117. mapData.AddSettlement(settlement);
  118. }
  119. private string GetUniqueRandomName(string[] nameArray)
  120. {
  121. // Find available names not already used
  122. List<string> availableNames = new List<string>();
  123. foreach (string name in nameArray)
  124. {
  125. if (!usedNames.Contains(name))
  126. {
  127. availableNames.Add(name);
  128. }
  129. }
  130. // If all names are used, fallback to numbered names
  131. if (availableNames.Count == 0)
  132. {
  133. string baseName = nameArray[Random.Range(0, nameArray.Length)];
  134. int counter = 2;
  135. string numberedName;
  136. do
  137. {
  138. numberedName = $"{baseName} {counter}";
  139. counter++;
  140. } while (usedNames.Contains(numberedName));
  141. usedNames.Add(numberedName);
  142. return numberedName;
  143. }
  144. // Select random name from available names
  145. string selectedName = availableNames[Random.Range(0, availableNames.Count)];
  146. usedNames.Add(selectedName);
  147. return selectedName;
  148. }
  149. }