Skip to content

Commit 4856b3e

Browse files
authored
Merge pull request #836 from stavrosfa/improvement/tech-research-improvements
Research improvements
2 parents 0d90a33 + 8d98af3 commit 4856b3e

File tree

6 files changed

+56
-59
lines changed

6 files changed

+56
-59
lines changed

C7/Game.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,14 @@ private void OnPlayerStartTurn() {
322322
// once they have a city.
323323
if (controller.cities.Count > 0
324324
&& controller.currentlyResearchedTech == null
325-
&& controller.GetAvailableTechsToResearch(gameData).Count > 0) {
325+
&& controller.GetAvailableTechsToResearch(gameData.techs).Count > 0) {
326326
popupOverlay.ShowPopup(
327327
new ScienceSelection(controller),
328328
PopupOverlay.PopupCategory.Info);
329+
330+
if (controller.currentlyResearchedTech == null && controller.GetAvailableTechsToResearch(gameData.techs).Count > 0) {
331+
PlayerAI.MaybePickTechToResearch(controller, gameData.techs);
332+
}
329333
}
330334

331335
// Allow fast forwarding in observer mode.

C7/UIElements/Advisors/ScienceAdvisor.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ public override void _Ready() {
3838
this.CreateUI();
3939

4040
EngineStorage.ReadGameData((GameData gameData) => {
41-
List<Tech> techs = gameData.techs;
41+
List<Tech> allTechs = gameData.techs;
4242
Player player = gameData.GetFirstHumanPlayer();
4343
eraName = string.IsNullOrEmpty(lastOpenedEra) ? player.eraCivilopediaName : lastOpenedEra;
44-
this.DrawTechTree(eraName, player, techs, player.GetAvailableTechsToResearch(gameData));
44+
this.DrawTechTree(eraName, player, allTechs, player.GetAvailableTechsToResearch(allTechs));
4545
});
4646
}
4747

@@ -205,12 +205,12 @@ private void ChangeEraAndDrawTree(int delta) {
205205
techBoxes.Clear();
206206

207207
EngineStorage.ReadGameData((GameData gameData) => {
208-
List<Tech> techs = gameData.techs;
208+
List<Tech> allTechs = gameData.techs;
209209
Player player = gameData.GetFirstHumanPlayer();
210210
eraName = string.IsNullOrEmpty(lastOpenedEra)
211211
? EraIndexToEra(GetEraIndex(eraName) + delta)
212212
: EraIndexToEra(GetEraIndex(lastOpenedEra) + delta);
213-
DrawTechTree(eraName, player, techs, player.GetAvailableTechsToResearch(gameData));
213+
DrawTechTree(eraName, player, allTechs, player.GetAvailableTechsToResearch(allTechs));
214214
});
215215
}
216216

C7/UIElements/Popups/ScienceSelection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ private OptionButton MakeStyledOptionButton() {
7979
AddItem(gameData, player.ResearchQueue.Peek(), optionButton);
8080
}
8181
// then the rest
82-
foreach (Tech tech in player.GetAvailableTechsToResearch(gameData)) {
82+
foreach (Tech tech in player.GetAvailableTechsToResearch(gameData.techs)) {
8383
if (!options.Contains(tech)) {
8484
AddItem(gameData, tech, optionButton);
8585
}

C7Engine/AI/PlayerAI.cs

Lines changed: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,20 @@ private static void MaybeDoPriorityReevaluation(Player player) {
6868
}
6969
}
7070

71-
private static void MaybePickTechToResearch(Player player, List<Tech> techs) {
72-
while (player.currentlyResearchedTech == null) {
73-
Tech toResearch = PickTechToResearch(player, techs);
71+
public static void MaybePickTechToResearch(Player player, List<Tech> techs) {
72+
while (player.currentlyResearchedTech == null || player.knownTechs.Contains(player.currentlyResearchedTech)) {
73+
Tech toResearch = player.GetAvailableTechsToResearch(techs).FirstOrDefault();
7474
if (toResearch == null) {
7575
log.Information($"Player {player.civilization.name} has no techs available to research.");
7676
player.SetCurrentlyResearchedTech(null);
7777
break;
78-
} else {
79-
log.Information($"Player {player.civilization.name} is researching {toResearch.Name}.");
80-
player.SetCurrentlyResearchedTech(toResearch.id);
8178
}
79+
80+
if (player.ResearchQueue.Count <= 0) {
81+
player.AddTechItemToResearchQueue(toResearch);
82+
}
83+
player.SetCurrentlyResearchedTech(player.ResearchQueue.Peek().id);
84+
log.Information($"Player {player.civilization.name} is researching {player.ResearchQueue.Peek().Name}.");
8285
}
8386
}
8487

@@ -268,39 +271,6 @@ private static UnitAI GetCombatAIIfUnitCanAttackNearbyBarbCamp(MapUnit unit, Pla
268271
return null;
269272
}
270273

271-
private static Tech PickTechToResearch(Player player, List<Tech> techs) {
272-
List<Tech> possibleTechs = new();
273-
274-
// Figure out what techs we're allowed to research.
275-
foreach (Tech tech in techs) {
276-
if (tech.EraCivilopediaName != player.eraCivilopediaName) {
277-
continue;
278-
}
279-
if (player.knownTechs.Contains(tech.id)) {
280-
continue;
281-
}
282-
283-
bool prereqsKnown = true;
284-
foreach (Tech prereq in tech.Prerequisites) {
285-
if (!player.knownTechs.Contains(prereq.id)) {
286-
prereqsKnown = false;
287-
break;
288-
}
289-
}
290-
if (!prereqsKnown) {
291-
continue;
292-
}
293-
possibleTechs.Add(tech);
294-
}
295-
296-
if (possibleTechs.Count == 0) {
297-
return null;
298-
}
299-
300-
// Details on how Civ3 does it: https://forums.civfanatics.com/threads/what-will-the-ai-research-next.45559/
301-
return possibleTechs[(int)GameData.rng.NextInt64(possibleTechs.Count)];
302-
}
303-
304274
private static async Task AttemptTrading(Player us) {
305275
GameData gD = EngineStorage.gameData;
306276

C7Engine/C7GameData/GameData.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ public Player GetPlayer(ID id) {
106106
return players.Find(p => p.id == id);
107107
}
108108

109+
public Tech GetTech(ID id) {
110+
return techs.Find(p => p.id == id);
111+
}
112+
109113
public ExperienceLevel GetExperienceLevelAfter(ExperienceLevel experienceLevel) {
110114
int n = experienceLevels.IndexOf(experienceLevel);
111115
if (n + 1 < experienceLevels.Count)

C7Engine/C7GameData/Player.cs

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ public void SetCurrentlyResearchedTech(ID id) {
142142

143143
Tech tech = EngineStorage.gameData.techs.Find(x => x.id == id);
144144
log.Information($"Awarding {tech.Name} to player {this}");
145-
CompleteResearchingTech(EngineStorage.gameData, tech);
145+
CompleteResearchAndBeginNew(EngineStorage.gameData, tech);
146146
return;
147147
}
148148

@@ -363,13 +363,8 @@ public void ExecuteDeal(GameData gameData, Player other, TradeOffer theirOffer,
363363
other.gold -= theirOffer.gold.Value;
364364
}
365365

366-
foreach (Tech t in ourOffer.techs) {
367-
other.knownTechs.Add(t.id);
368-
}
369-
370-
foreach (Tech t in theirOffer.techs) {
371-
this.knownTechs.Add(t.id);
372-
}
366+
other.CompleteResearchAndBeginNew(gameData, ourOffer.techs);
367+
this.CompleteResearchAndBeginNew(gameData, theirOffer.techs);
373368
}
374369

375370
public int EstimateTurnsToResearch(GameData gameData, Tech tech) {
@@ -444,9 +439,7 @@ private Queue<Tech> GetResearchQueueFor(Tech tech, Queue<Tech> tempQueue) {
444439
return new Queue<Tech>();
445440
}
446441

447-
// TODO: maybe sort these on some other score, perhaps the order the AI would have picked them
448-
// Right now the tech with the highest cost comes first
449-
List<Tech> requiredTechs = tech.Prerequisites.OrderBy(t => t.Cost).ToList();
442+
List<Tech> requiredTechs = OrderTechs(tech.Prerequisites).ToList();
450443

451444
// first, add the tech the user clicked
452445
if (!tempQueue.Contains(tech)) {
@@ -473,9 +466,14 @@ private Queue<Tech> GetResearchQueueFor(Tech tech, Queue<Tech> tempQueue) {
473466
return tempQueue;
474467
}
475468

476-
public HashSet<Tech> GetAvailableTechsToResearch(GameData gameData) {
469+
/// <summary>
470+
/// Takes all the techs in the game and keeps only what could be researched next at a particular point in the game.
471+
/// </summary>
472+
/// <param name="allTechs"></param>
473+
/// <returns></returns>
474+
public HashSet<Tech> GetAvailableTechsToResearch(List<Tech> allTechs) {
477475
HashSet<Tech> result = new();
478-
foreach (Tech tech in gameData.techs) {
476+
foreach (Tech tech in allTechs) {
479477
if (knownTechs.Contains(tech.id)) {
480478
continue;
481479
}
@@ -494,7 +492,17 @@ public HashSet<Tech> GetAvailableTechsToResearch(GameData gameData) {
494492
result.Add(tech);
495493
}
496494
}
497-
return result;
495+
return OrderTechs(result.ToList());
496+
}
497+
498+
// Placeholder ordering of techs
499+
private HashSet<Tech> OrderTechs(List<Tech> techs) {
500+
if (techs == null || techs.Count == 0) {
501+
return new HashSet<Tech>();
502+
}
503+
// TODO: We would want to eventually order them based on how the AI would do it
504+
// Details on how Civ3 does it: https://forums.civfanatics.com/threads/what-will-the-ai-research-next.45559/
505+
return techs.OrderBy(t => t.Cost).ToHashSet();
498506
}
499507

500508
public List<Government> GetAvailableGovernments(GameData gameData) {
@@ -679,7 +687,18 @@ public void DoPerTurnScienceUpdates(GameData gameData) {
679687
return;
680688
}
681689

690+
CompleteResearchAndBeginNew(gameData, tech);
691+
}
692+
693+
private void CompleteResearchAndBeginNew(GameData gameData, IEnumerable<Tech> techs) {
694+
foreach (Tech tech in techs) {
695+
CompleteResearchingTech(gameData, tech);
696+
}
697+
PlayerAI.MaybePickTechToResearch(this, gameData.techs);
698+
}
699+
private void CompleteResearchAndBeginNew(GameData gameData, Tech tech) {
682700
CompleteResearchingTech(gameData, tech);
701+
PlayerAI.MaybePickTechToResearch(this, gameData.techs);
683702
}
684703

685704
private void CompleteResearchingTech(GameData gameData, Tech tech) {

0 commit comments

Comments
 (0)