Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions C7Engine/AI/PlayerAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,26 @@ public static void SetAIForUnit(MapUnit unit, Player player)
//Isn't a Settler. If there's a city at the location, it's defended. No boats involved. What's our priority?
//If there is land to explore, we'll try to explore it.
//Long-term TODO: Should only send tiles on this landmass.
KeyValuePair<Tile, int> tileToExplore = ExplorerAI.FindTopScoringTileForExploration(player, player.tileKnowledge.AllKnownTiles().Where(t => t.IsLand()));
KeyValuePair<Tile, float> tileToExplore = ExplorerAI.FindTopScoringTileForExploration(player, player.tileKnowledge.AllKnownTiles().Where(t => t.IsLand()), ExplorerAIData.ExplorationType.RANDOM);
if (tileToExplore.Value > 0) {
ExplorerAIData ai = new ExplorerAIData();
ai.type = ExplorerAIData.ExplorationType.RANDOM;
//What type of exploration should we do?
int nearbyExplorers = 0;
foreach (MapUnit mapUnit in player.units)
{
if (mapUnit.currentAIData is ExplorerAIData explorerAI) {
if (explorerAI.type == ExplorerAIData.ExplorationType.NEAR_CITIES) {
nearbyExplorers++;
}
}
}
if (nearbyExplorers < (player.cities.Count + 1)) {
ai.type = ExplorerAIData.ExplorationType.NEAR_CITIES;
} else {
ai.type = ExplorerAIData.ExplorationType.RANDOM;
}
unit.currentAIData = ai;
Console.WriteLine("Set random exploration AI for " + unit);
Console.WriteLine($"Set {ai.type} exploration AI for {unit}");
}
else {
//Nowhere to explore. What to do now?
Expand Down
37 changes: 28 additions & 9 deletions C7Engine/AI/UnitAI/ExplorerAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public bool PlayTurn(Player player, MapUnit unit)
return MoveToNextTileOnPath(explorerData, unit);
}
else {
bool foundNeighboringTileToExplore = ExploreNeighboringTile(player, unit);
bool foundNeighboringTileToExplore = ExploreNeighboringTile(player, unit, explorerData);
if (foundNeighboringTileToExplore) {
return true;
}
Expand Down Expand Up @@ -45,13 +45,14 @@ private static bool MoveToNextTileOnPath(ExplorerAIData explorerData, MapUnit un
return false;
}

private static bool ExploreNeighboringTile(Player player, MapUnit unit) {
private static bool ExploreNeighboringTile(Player player, MapUnit unit, ExplorerAIData aiData) {
List<Tile> validNeighboringTiles = unit.unitType.categories.Contains("Sea") ? unit.location.GetCoastNeighbors() : unit.location.GetLandNeighbors();
if (validNeighboringTiles.Count == 0) {
Console.WriteLine("No valid locations for unit " + unit + " at location " + unit.location);
return false;
}
KeyValuePair<Tile, int> topScoringTile = FindTopScoringTileForExploration(player, validNeighboringTiles);
//Console.WriteLine($"Exploring for unit {unit}"); //debugging print
KeyValuePair<Tile, float> topScoringTile = FindTopScoringTileForExploration(player, validNeighboringTiles, aiData.type);
Tile newLocation = topScoringTile.Key;

if (newLocation != Tile.NONE && topScoringTile.Value > 0) {
Expand Down Expand Up @@ -100,16 +101,34 @@ private static bool FindPathToNewExplorationArea(Player player, ExplorerAIData e
return true;
}

public static KeyValuePair<Tile, int> FindTopScoringTileForExploration(Player player, IEnumerable<Tile> possibleNewLocations)
public static KeyValuePair<Tile, float> FindTopScoringTileForExploration(Player player, IEnumerable<Tile> possibleNewLocations, ExplorerAIData.ExplorationType type)
{
//Technically, this should be the *estimated* new tiles revealed. If a mountain blocks visibility,
//we won't know that till we move there.
Dictionary<Tile, int> numNewTilesRevealed = new Dictionary<Tile, int>();
foreach (Tile t in possibleNewLocations)
{
numNewTilesRevealed[t] = numUnknownNeighboringTiles(player, t);
Dictionary<Tile, float> explorationScore = new Dictionary<Tile, float>();
foreach (Tile t in possibleNewLocations) {
int baseScore = numUnknownNeighboringTiles(player, t);
if (baseScore == 0) {
explorationScore[t] = 0;
}
else if (type == ExplorerAIData.ExplorationType.NEAR_CITIES) {
if (baseScore == 0) {
explorationScore[t] = 0;
}
int distanceToNearestCity = int.MaxValue;
foreach (City c in player.cities) {
int distance = t.distanceTo(c.location);
if (distance < distanceToNearestCity) {
distanceToNearestCity = distance;
}
}
explorationScore[t] = 100 - 4 * distanceToNearestCity * distanceToNearestCity + baseScore;
// Console.WriteLine($"Exploration score for {t}: {explorationScore[t]}"); //debugging print
} else {
explorationScore[t] = baseScore;
}
}
IOrderedEnumerable<KeyValuePair<Tile, int>> orderedScores = numNewTilesRevealed.OrderByDescending(t => t.Value);
IOrderedEnumerable<KeyValuePair<Tile, float>> orderedScores = explorationScore.OrderByDescending(t => t.Value);
return orderedScores.First();
}

Expand Down
5 changes: 3 additions & 2 deletions C7GameData/AIData/ExplorerAIData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ public class ExplorerAIData : UnitAIData
public enum ExplorationType
{
RANDOM,
NEAR_CITIES,
COASTLINE,
DIRECTIONAL,
SCOUT_RIVAL,
ON_A_BOAT
}
public ExplorationType type;
public TilePath path;

public override string ToString()
{
return type + " exploration";
}
}
}
}