CivOne Request: AI City building Logic

fire-eggs

Chieftain
Joined
Jun 19, 2019
Messages
36
TLDR: seeking detailed "what should this city build next" logic for AI players in CivOne

I've been working on moving SWY's CivOne re-creation forward, fixing bugs and adding missing features. [You can find the releases on Github here]. I've started writing the AI players' unit movement logic, mostly thanks to darkpanda's reverse-engineering.

A blockage I have is what logic to use for the AI city production. SWY has simple build logic in place, but isn't very close to Microprose's behavior [which I'm aiming for, initially]. darkpanda's reverse engineering has a reference to a function selectCityProduction , but no code for said function.

I'm looking for some detailed ideas for how the AI City production logic would work, ideally approaching the original Microprose logic. Since it is tied to available advances, the AI logic for which advance to research should be included [right now is pure random].

The Civilization behaviors need to be taken into account: Aggression, Development, and Militarism. Essentially a 9-value matrix to dictate which research / unit the civilization would likely target. You can see all the values at the bottom of this : https://www.civfanatics.com/civ1/cia/allcivs.htm

[If you have questions or comments on CivOne in general, please go to this topic.]

My thanks in advance!
 
So I should post in this topic when it will be ready. For now I can say only that
1) Ghidra cannot decompile this function (at least at my machine and from .05 version of civ), so I'm trying to understand it from disassembly only, which is much harder
2) this function is enourmous. It consists of 'draw selection menu'/what AI can build part and 'ai chooses what to build' part (also used for AUTO regime). First of them is pretty simple, but nothing interesting is here. But I found that game indeed has an additional check for nuclear fission tech for Nuclear unit. All these years I thought that 'and Nuclear Fission' in Civilopedia is an allude to Manhattan Project and nothing more.
3) there're many still unknown flags/variables, some of them with pretty abstract meaning, like 'despotism desire' or 'republic desire'.
 
Last edited:
My thanks for the update, and sorry for the late reply. I started poking at the disassembly, but was dragged away by other priorities. I'm looking forward to any and all updates!
 
Here we go again.
https://pastebin.com/1X7AvpkP
I think that code to select a city which should build a new palace exists in game, but somewhere else. Also probably game uses some other code to build SS components and SS modules (and it probably's cheating hard with them). But apart from that, everything is here.

Some simplest rules from it:
1) AI doesn't build Carriers
2) AI doesn't build Militias if government's not despotism
3) AI doesn't build nukes, if it already has 4 of them or 2 under construction
4) if AI has 0 units and its government is despotism, it always builds militia (even if it's obsolete!). This rule doesn't seem to work, probably because when city is founded, settler is not destroyed immediately (for example, you can see it on city screen).
5) AI cannot build air and sea units if its total defence power on continent is less than 8 (hello, English on Earth map)
 
Last edited:
But... I've seen an AI carrier! True, it happened only once in over 25 years of playing, and it probably was some sort of overflow, which caused the AI to build one.
 

Wonderful! Another step forward!

Re: your comment on the usage of DX:
//1ade:06d4 MOV DX,word ptr [BX + CITIES_BUILDINGS2]

First, we might be looking at slightly different apples. The line you mention is at
1ADE:06CF in my disassembly, which is from Civ.01 (which matches DarkPanda).
But I think it's all close enough that the differences won't matter.

Second, I think what we're seeing is the compiler using AX,DX as a pair of
registers in order to handle a 32-bit value. I.e. the registers are set from a pair
of 2-byte addresses, read into a pair of 2-byte addresses and so on.
 
Well, I use Civ.05 (as I more interested in its 'final' rules), so it should be different.

Thank you for your suggestion about AX/DX pair. It looks more clear for me now. I don't understand assembly quite well, so for me it was just some very strange code. I mostly use decompiled c code in Ghidra, but whenever some, how to name it... "table jumps" happen (probably when switch was in original code) it cannot decompile anything and even skip such parts in disassembly (they should be 'manually' disassembled, which means I just need to press D key, but anyway). Probably free version of IDA is better in such cases, for disassembly only.

BTW, I still did not find any code for palace building (very unlikely that it's in overlays or in not disassembled skipped parts). It can be that AI doesn't care if it does not have a palace and only can build it by chance, when all other options are less preferred. I only have found that if AI finished palace construction, it immediately changes production to barracks, so it can select new production (without that, AI city would continue to build a palace endlessly).

EDIT: btw, "unknown_array_civ_x_civ" for diplomat is just good old 'diplomacy' status, so != 2 means 'war with the player'.
 
Last edited:
To actually implement this logic, we also need to know how AI determines 'continent policy' for every continent. Here is this logic. It called at beginning of every turn for every civ, including player civ and barbarians:
https://pastebin.com/dWuQ8hMn

Basically, there can be only 4 policies: 0 = no danger(settle/develop cities) 1 = attack 2 = defend 5 = send transports from here. Everytime when policy is changed, AI civ changed production in all its cities on this continent.

By default, continent policy is 0.

AI will set policy to 5 (transport) if 1) it knows Mapmaking AND 2) there's too many cities on this continent (civ_cities+total_cities)*6+2 > good_squares (grassland, rivers, plains) on this continent) OR 3) total defence power in this continent is too great ((civ_defence+total_defence)*2-continent_size > 0)

if civ is not barbs, total_cities includes civ own cities (so they're counted twice). It does not include barbarian cities.
if civ is not barbs, total_defence incudes civ own defence (so it is counted twice). It does not include defence of barbarian units on continent.

AFTER THAT AI checks if it have at least 1 'attack desire' score for this continent, and if it's so, it sets policy to 1 (attack). So 'attack' policy has a priority over 0 (nothing) and 5 (transport) policies.
AFTER THAT AI checks if it has at least 1 'defence desire' score for this continent, and if it's so, it sets policy to 2 (defend). So 'defence scores' are more important than 'attack scores' (AI basically ignores 'attack desire scores' if 'defence desire scores' are not 0).

AFTER THAT if AI civ has no cities on continent AND no defence (=no units) on continent, and pol_flags* is not equal to 1, then policy sets to 1 (attack). This rule is applied last, so it has a priority over anything else.

*pol_flags: set first bit ON if other civ has some defence (=units) on this continent and we at peace with it. Set second bit ON if other civ has some defence (=units) on this continent and we at war with it. So, if no enemy power here: pol_flags = 0. If we at peace with everybody here: pol_flags = 1. If we at war with everybody here: pol_flags = 2. If we at peace with some civs and at war with some civs: pol_flags = 3. BTW, civ 'at the war' with itself, so if we only has our forces here, pol_flags = 2. If we at peace with everybody, BUT have our forces here, then pol_flags = 3.

Rules to count 'attack desire' and 'defence desire' scores are pretty simple, but still not so easy for me to write in plain text. Read C pseudocode in pastebin above.

Only unclear part for me in this logic is 0x100 diplomacy status (I have no idea about its meaning), which checked once along with contact+war status.
 
Last edited:
tupi, thank you so much! This is really great, I'm sorry that CivOne has been on my back-burner for a while.
 
I can confirm now that AI actually builds SS components and modules in its cities (it doesn't get it for free). But I don't understand how it select to build them. Can be in space ship logic in an overlay (I did not investigate it yet).
Even more strange thing happens for me today: Russians built Michelangelo's Chapel in Leningrad normal way, without cheating! When this happens, you get newspaper message (just like when you build it yourself in your city when animations are disabled).

EDIT: now I partially understand how AI builds Components and Modules.

1) AI just finished current production in a city. It immediately selects new production.
2) if finished production was a SS Structural or SS Component, and if AI somehow decided that it has enough of this type of SS parts for now (I don't understand exactly logic for this yet, but AI can decide it even if there's still a place for them), then:
2.1) AI adds full shield cost of this SS part to city shield counter - can be because it failed to add SS part to the ship?
2.2) and, if both old and new production are space ship parts but not Modules, then AI changes production: SS structure to SS component and SS component to SS module.
 
Last edited:
I'm not sure that this will help your research, but the thread seems appropriate to post it. I have a very strong suspicion that the AI can build components and modules even if it does not have the technology. It seems to only need space flight to build all spaceship parts. Another option is that it is able to build components and modules, while it is researching the respective technology, but as far as I know the AI doesn't select what tech to research like a human does, so this is rather implausible.
 
Yes, you're right, Mize. It's simply 'if Structural, then switch to Component; if Component, then switch to Module' rule. It doesn't check if AI have a technology for components and modules. But what if AI knows plastics or robotics advance, but not space flight (for example, when it got plastics/robotics from player)? Well, in this case it can't select structural parts in the first place, so it cannot start to build spaceship. BUT. I actually witnessed this once. Greeks got Robotics from me (and after AI got Robotics, it sets its research rate to 0%). They were a very huge civilization and were moving their capital from time to time (they had nothing to do). After some long time they built one pathetic SS Module... Impossible, just like your carrier. Or SDI. Or Mass Transit. Or wonders. Comp. player still manages to do it sometimes - can it be a bug or feature, I don't know. When it has nothing to do, it should always select Palace (-1), actually...

EDIT: there's a check for civ. advance for SS module (Robotics) in 'AI adds new SS part' routine, but I don't understand this routine well enough for now, so cannot say if AI will not build a module without the tech or if this check used for some other reason. Anyway, AI already have built a module in a city and some additional check is used when it's trying to add this module to SS.
 
Last edited:
Tupi, your continent policy description explains (I think) some odd behavior I’ve observed from AI. I notice that AI often leaves land unimproved and desirable sites unsettled on large continents. Larger continents will tend to have more enemy civs/units, which means (based on your description) AI is more likely to select 1 “attack” over 0 “settle”. AI could definitely be more competitive on larger land masses if it would build a settler or two instead of its 6th militia.
 
I implemented most of this logic in CivGen so now I understand it better. AI tries to build "the fastest and the strongest (also cheapest!)" units, but the more units of some type (militia, chariot...) it already has, the less it want to built more. That's why it produces so many "bad" units, cavalry and legions. In a long run, AI basically produces equal quantities of every type of land units. And for sea and air units, in common, desire to build them is less than for land units, but as long as AI don't have any unit of this type, desire is very high (0, the less is "better"). So AI always wants to produce at least 1 bomber, at least 1 battleship etc (if doesn't have any).

Also it seems militaristic AI almost never builds any city improvements (at least with somebody around).

By and large, deterministic style of this logic can be problematic sometimes. For example, when AI want to build a caravan, but there's no any other AI civ left. Then AI will anyway try and try to build this caravan endlessly. Or if AI want to build a unit, then it will never ever try to build a city improvement, as it simply doesn't have enough shields in a city to support an army it wants to have before it will eventually switch to a city improvement.

Speaking of CivGen, I did not implement settler production logic, because in the original game AI produces them too rarely. I think in the original game settlers are very narrow-minded and don't wander around, they immediately go to found a new city. Also I did not implement original logic for transport ships, because they, too, pretty effective in the original and AI can transport its land armies rationally having not so many ships.
 
  • Like
Reactions: GPR
Hello. I still use Ghidra. In decompilation, there are just numbers (=addresses in memory for variables) instead of some variable names (it can be that there's a way to fix that, but I don't know how), but at least all if/else branches are very visual and understenable so I like it. In some cases, decompiler is just failed to create something, so then I use disasm only. Maybe for these cases IDA (even freeware version) is a better tool.
 
In Mega Drive port I noticed erratic behavior, which I think should be presented in the original: if AI switched to monarchy but it still doesn't know Bronze Working, it cannot build any units in its undefended cities! Because "build defender" rule prohibits AI to build any other units, and only available defender is Militia, but it's prohibited for AI to build Militias under Monarchy... Such civ tries to build some city improvements and becomes an easy prey for enemy civs and barbarians alike...
 
Back
Top Bottom