Skip to content

Commit 3bf9a5a

Browse files
committed
Expand Settler candidate tile scoring
1 parent c89cd13 commit 3bf9a5a

5 files changed

Lines changed: 62 additions & 21 deletions

File tree

C7Engine/AI/StrategicAI/ExpansionPriority.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public override void CalculateWeightAndMetadata(Player player) {
2020
if (player.cities.Count < 2) {
2121
this.calculatedWeight = 1000;
2222
} else {
23-
int score = UtilityCalculations.CalculateAvailableLandScore(player);
23+
float score = UtilityCalculations.CalculateAvailableLandScore(player);
2424
score = ApplyEarlyGameMultiplier(score);
2525
score = ApplyNationTraitMultiplier(score, player);
2626

@@ -58,18 +58,17 @@ public override string ToString() {
5858
return "ExpansionPriority";
5959
}
6060

61-
private int ApplyEarlyGameMultiplier(int score) {
61+
private float ApplyEarlyGameMultiplier(float score) {
6262
//If it's early game, multiply this score.
6363
//TODO: We haven't implemented the part for "how many turns does the game have?" yet. So this is hard-coded.
64-
int gameTurn = EngineStorage.gameData.turn;
65-
int percentOfGameFinished = (gameTurn * 100) / TEMP_GAME_LENGTH;
66-
if (percentOfGameFinished < EARLY_GAME_CUTOFF) {
67-
score = score * (EARLY_GAME_CUTOFF - percentOfGameFinished) / 5;
68-
}
69-
return score;
64+
var gameTurn = EngineStorage.gameData.turn;
65+
var percentOfGameFinished = (gameTurn * 100) / TEMP_GAME_LENGTH;
66+
var isEarlyGame = percentOfGameFinished < EARLY_GAME_CUTOFF;
67+
var multiplier = isEarlyGame ? (EARLY_GAME_CUTOFF - percentOfGameFinished) / 5.0f : 1.0f;
68+
return score * multiplier;
7069
}
7170

72-
private int ApplyNationTraitMultiplier(int score, Player player) {
71+
private float ApplyNationTraitMultiplier(float score, Player player) {
7372
// TODO: The "Expansionist" trait should give a higher priority to this strategic priority.
7473
return score;
7574
}
Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
using System.Collections.Generic;
3+
using System.Linq;
34
using C7GameData;
45

56
namespace C7Engine.AI.StrategicAI {
@@ -11,16 +12,14 @@ namespace C7Engine.AI.StrategicAI {
1112
public class UtilityCalculations {
1213

1314
private static readonly int PossibleCityLocationScore = 2; //how much weight to give to each possible city location
14-
private static readonly int TileScoreDivider = 10; //how much to divide each location's tile score by
15+
private static readonly float TileScoreDivider = 10f; //how much to divide each location's tile score by
1516

16-
public static int CalculateAvailableLandScore(Player player) {
17+
public static float CalculateAvailableLandScore(Player player) {
1718
//Figure out if there's land to settle, and how much
18-
Dictionary<Tile, float> possibleLocations = SettlerLocationAI.GetScoredSettlerCandidates(player.cities[0].location, player);
19-
int score = possibleLocations.Count * PossibleCityLocationScore;
20-
foreach (int i in possibleLocations.Values) {
21-
score += i / TileScoreDivider;
22-
}
23-
return score;
19+
var possibleLocations = SettlerLocationAI.GetScoredSettlerCandidates(player.cities[0].location, player);
20+
var availableLand = possibleLocations.Count * PossibleCityLocationScore;
21+
var settlementQuality = possibleLocations.Values.Sum(i => i / TileScoreDivider);
22+
return settlementQuality + availableLand;
2423
}
2524
}
2625
}

C7Engine/AI/StrategicAI/WarPriority.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public override void CalculateWeightAndMetadata(Player player) {
4646
}
4747
}
4848

49-
bool outOfLandToExpandTo = UtilityCalculations.CalculateAvailableLandScore(player) == 0;
49+
bool outOfLandToExpandTo = UtilityCalculations.CalculateAvailableLandScore(player) < 1;
5050

5151
// Don't go to war if there's still land we should be expanding to.
5252
if (!outOfLandToExpandTo) {

C7Engine/AI/UnitAI/SettlerLocationAI.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,16 @@ private static Dictionary<Tile, float> AssignTileScores(Tile startTile, Player p
3030
candidates = candidates.Where(t => !SettlerAlreadyMovingTowardsTile(t, playerSettlers) && t.IsAllowCities());
3131
foreach (Tile t in candidates) {
3232
float score = GetTileYieldScore(t, player);
33-
//For simplicity's sake, I'm only going to look at immediate neighbors here, but
34-
//a lot more things should be considered over time.
33+
34+
// Consider the immediate neighbors
3535
foreach (Tile nt in t.neighbors.Values) {
3636
score += GetTileYieldScore(nt, player);
3737
}
38-
//TODO #802: Also look at the next ring out, with lower weights.
38+
39+
// Consider the outer ring of the BFC
40+
foreach (var ot in t.GetBFCOuterRing()) {
41+
score += GetTileYieldScore(ot, player) / 3;
42+
}
3943

4044
//Prefer hills for defense, and coast for boats and such.
4145
if (t.baseTerrainType.Key == "hills") {
@@ -45,6 +49,9 @@ private static Dictionary<Tile, float> AssignTileScores(Tile startTile, Player p
4549
score += player.civilization.Adjustments.WaterBonus;
4650
}
4751

52+
// Let defensibility play a role
53+
score += (float)t.baseTerrainType.defenseBonus.amount * 20.0f;
54+
4855
//Lower scores if they are far away
4956
float preDistanceScore = score;
5057
int distance = startTile.distanceTo(t);

C7Engine/C7GameData/Tile.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,42 @@ public List<Tile> GetTilesWithinRankDistance(int rank) {
702702
return result;
703703
}
704704

705+
private List<Tile> _outerRing;
706+
707+
public List<Tile> GetBFCOuterRing() {
708+
if (_outerRing != null)
709+
return _outerRing;
710+
711+
// List of all the BFC tiles NOT including direct Neighbors
712+
// Essentially, this is every outer tile except North->North, South->South, West->West,East->East
713+
(TileDirection direction1, TileDirection direction2)[] outerRingDirections =
714+
{
715+
(TileDirection.NORTHWEST, TileDirection.NORTH),
716+
(TileDirection.NORTHWEST, TileDirection.NORTHWEST),
717+
(TileDirection.NORTHWEST, TileDirection.WEST),
718+
(TileDirection.SOUTHWEST, TileDirection.WEST),
719+
(TileDirection.SOUTHWEST, TileDirection.SOUTHWEST),
720+
(TileDirection.SOUTHWEST, TileDirection.SOUTH),
721+
(TileDirection.SOUTHEAST, TileDirection.EAST),
722+
(TileDirection.SOUTHEAST, TileDirection.SOUTHEAST),
723+
(TileDirection.SOUTHEAST, TileDirection.SOUTH),
724+
(TileDirection.NORTHEAST, TileDirection.NORTH),
725+
(TileDirection.NORTHEAST, TileDirection.NORTHEAST),
726+
(TileDirection.NORTHEAST, TileDirection.EAST)
727+
};
728+
729+
Dictionary<(TileDirection,TileDirection), Tile> outerRing = new Dictionary<(TileDirection,TileDirection), Tile>();
730+
foreach ((TileDirection dir1, TileDirection dir2) directions in outerRingDirections) {
731+
if (!neighbors.TryGetValue(directions.dir1, out var inner))
732+
continue;
733+
734+
if (inner != NONE && inner.neighbors.TryGetValue(directions.dir2, out var outer) && outer != NONE)
735+
outerRing[(directions.dir1, directions.dir2)] = outer;
736+
}
737+
_outerRing = outerRing.Values.ToList();
738+
return _outerRing;
739+
}
740+
705741
public MapUnit FindTopDefender(MapUnit opponent) {
706742
if (unitsOnTile.Count > 0) {
707743
IEnumerable<MapUnit> potentialDefenders = unitsOnTile.Where(u => u.CanDefendAgainst(opponent));

0 commit comments

Comments
 (0)