yairm210 / Unciv

Open-source Android/Desktop remake of Civ V
Mozilla Public License 2.0
8.32k stars 1.56k forks source link

I have suspicions about WorkBoat construction AI #10060

Closed SomeTroglodyte closed 5 months ago

SomeTroglodyte commented 1 year ago

Questions about ConstructionAutomation.addWorkBoatChoice:

hackedpassword commented 1 year ago

CreateWaterImprovements

But aren't civilians hardcored to only be able to construct? (observation not code analysis)

Being able to convert a military unit to civilian, or vice versa has mod value. If that is possible, I wouldn't "fix" it unless actual problems are resulting.

SeventhM commented 12 months ago

But aren't civilians hardcored to only be able to construct?

I'm not sure where this assumption comes from

SomeTroglodyte commented 11 months ago
  • Isn't if (!alreadyHasWorkBoat) return the wrong way 'round????????

It's the right way 'round, but the flag's name is the wrong way 'round, both in and out. It's on if the ruleset has some workboat unit and none was found with a limited BFS. So it's correct to bail if it's off.

I still have to add another point to the list above...

SomeTroglodyte commented 11 months ago

Demo for that last point:

![image](https://github.com/yairm210/Unciv/assets/63000004/baf2008a-2d73-4ef1-92e8-459c53f64123)
SeventhM commented 11 months ago

Uh... Did you upload the wrong image?

SomeTroglodyte commented 11 months ago

Thanks. Fixed. Gimp and its virtual layers for text that you never know how to finalize - flatten does it but it's not always evident...

SomeTroglodyte commented 11 months ago

Anyway - any coder welcome to eval this patch:

```patch Index: core/src/com/unciv/logic/city/CityConstructions.kt IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/core/src/com/unciv/logic/city/CityConstructions.kt b/core/src/com/unciv/logic/city/CityConstructions.kt --- a/core/src/com/unciv/logic/city/CityConstructions.kt (revision 6d4603431bb2190d4df1ac6f156818d7670f6d8e) +++ b/core/src/com/unciv/logic/city/CityConstructions.kt (date 1696793673582) @@ -31,7 +31,6 @@ import com.unciv.models.stats.Stats import com.unciv.models.translations.tr import com.unciv.ui.components.Fonts -import com.unciv.ui.components.extensions.addToMapOfSets import com.unciv.ui.components.extensions.withItem import com.unciv.ui.components.extensions.withoutItem import com.unciv.ui.screens.civilopediascreen.CivilopediaCategories @@ -350,6 +349,7 @@ city.civ.addNotification("No space available to place [${construction.name}] near [${city.name}]", city.location, NotificationCategory.Production, construction.name) } + chooseNextConstruction() // Has the checks for autoAssignCityProduction and isQueueEmptyOrIdle } } } Index: core/src/com/unciv/logic/automation/city/ConstructionAutomation.kt IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/core/src/com/unciv/logic/automation/city/ConstructionAutomation.kt b/core/src/com/unciv/logic/automation/city/ConstructionAutomation.kt --- a/core/src/com/unciv/logic/automation/city/ConstructionAutomation.kt (revision 6d4603431bb2190d4df1ac6f156818d7670f6d8e) +++ b/core/src/com/unciv/logic/automation/city/ConstructionAutomation.kt (date 1696796615511) @@ -14,6 +14,7 @@ import com.unciv.models.ruleset.MilestoneType import com.unciv.models.ruleset.PerpetualConstruction import com.unciv.models.ruleset.Victory +import com.unciv.models.ruleset.tile.ResourceType import com.unciv.models.ruleset.unique.StateForConditionals import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.stats.Stat @@ -158,11 +159,11 @@ it.hasUnique(UniqueType.CreateWaterImprovements) && Automation.allowAutomatedConstruction(civInfo, city, it) }.filterBuildable() - val alreadyHasWorkBoat = buildableWorkboatUnits.any() - && !city.getTiles().any { + val alreadyHasWorkBoat = buildableWorkboatUnits.none() + || city.getTiles().any { it.civilianUnit?.hasUnique(UniqueType.CreateWaterImprovements) == true } - if (!alreadyHasWorkBoat) return + if (alreadyHasWorkBoat) return val bfs = BFS(city.getCenterTile()) { @@ -170,14 +171,22 @@ } repeat(20) { bfs.nextStep() } - if (!bfs.getReachedTiles() - .any { tile -> + val goodTilesFilter = bfs.getReachedTiles().asSequence() + .filter {tile -> + // Look for owned tiles with unimproved resource tile.hasViewableResource(civInfo) && tile.improvement == null && tile.getOwner() == civInfo - && tile.tileResource.getImprovements().any { + }.filter { tile -> + // Limit to those we can improve + tile.tileResource.getImprovements().any { tile.improvementFunctions.canBuildImprovement(tile.ruleset.tileImprovements[it]!!, civInfo) } + }.filter { tile -> + tile.tileResource.resourceType != ResourceType.Bonus + || tile.getTilesInDistance(3).any { + it.isCityCenter() && it.getOwner() == civInfo + } } - ) return + if (goodTilesFilter.none()) return addChoice( relativeCostEffectiveness, buildableWorkboatUnits.minByOrNull { it.cost }!!.name, ```

... started out as attempt to fix #10258, which it does, but with roughly 90% certainty the wrong way. Testing led to looking at ConstructionAutomation.addWorkBoatChoice again... Patch also only addresses the last points.

SeventhM commented 11 months ago

started out as attempt to fix #10258

Ugh... Wait, I'm knee deep checking something else rn, but why is this in constructIfEnough? Seems to me free buildings from policies will come along and trample over this anyways because I added the call to validate the construction queue (in case you get a free building that was building, which was a missed bug before to my knowledge). Shouldn't this be in addBuilding?

SomeTroglodyte commented 11 months ago

Yeah exactly - I grok'ed that the validate the construction queue call might drive around the automation call from remove, but haven't really got a clue how the code flow really is and how it should be...

SomeTroglodyte commented 11 months ago

Anyway, that one line is the kludge that allowed to test the AI, and it threw me that it insisted on useless workboats. That patch is still far from good, it probably needs to make that BFS supply scope for both the need test and the 'already covered' test - I just saw it automate a WB for a tile where the automation already had just finished one in the closer city. Locked closed seas, no chance to mistake, there was only the one unimproved tile in the entire ocean.

SeventhM commented 11 months ago

but haven't really got a clue how the code flow really is and how it should be...

Doing some quick searches, chooseNextConstruction is called in CityConstuctionTable.purchaseConstruction and CityConstuctions.removeFromQueue. It seems obvious that it's supposed to be called at the start of a turn to decide if it still makes sense (ideally before stuff is calculated to have the same information as a player) and after anything changes the calculation mid turn (through something being built). Seems to me that if you put it at the bottom of addBuilding, it'll cover these situations as intended with even less side effects (removeFromQueue is called before validating anyways in constructionComplete, so it never actually worked as intended and purchaseConstrcution checks for the improvement set for some reason when I swear chooseNextConstruction already dealt with...)

SeventhM commented 11 months ago

Actually, maybe also put it in BaseUnit.postBuildEvent to keep correct functionality

Edit: I'm dumb, that's still before validation. It would need to be in the validation code tbh

SomeTroglodyte commented 11 months ago

Well, if you think you have a clear "big picture".... Me, I'll pause after a good git gc --prune=now --aggressive

rmingkil71 commented 9 months ago

Bugs and other bugs

rmingkil71 commented 9 months ago

Applicatio@n

github-actions[bot] commented 6 months ago

This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 15 days.