View Full Version : [AI behavior] Improvement decisions
Padmewan Apr 19, 2006, 10:56 AM We are running into some interesting AI issues related to workers not building certain improvements in our mod (see sig). Like the Moon mod, our world starts with 0 food on all terrain, so the AI is very hungry for food in the beginning. There are two improvements that can provide food:
1. Hothouse, +1 food, +1 with default civic
2. Terraform, +2 food, -1 hammer
The tech for Terraform comes within 2 techs of Hothouse.
In my playtesting I am finding that the AI refuses to build the Hothouse, but will (over)build the Terraform. I have a few theories for this:
(a) The AI "sees" the Terraform coming up, and since it considers it "better" than the Hothouse, refuses to build now and waits for that "better" improvement.
(b) This is because the AI is programmed NOT to destroy existing improvements. Thus, even though it SHOULD build a hothouse now and then decide later whether to replace it with a Terraform, the programmers removed this thought pattern.
(c) The AI doesn't see the +1 food from the civic and sees the Hothouse as only +1 food, not +2 food.
I know there are experiments I can run to verify/disprove at least (a) and (c), but can anyone who has playtested extensively and/or is familiar with the AI programming chip in with some explanations for what we are observing in AI behavior?
(Has anyone ever seen the AI replace an elephant camp with a cottage in vanilla Civ after Ivory goes obsolete?)
NikG Apr 19, 2006, 11:36 AM After having gone through hundres of lines of code in the SDK, I may have a solution, I am not 100 % sure, but I think I have it. There are just 1000 functions calls to this and that, and trying to determine the function in which a function calls bla bla....
It is a combination of a and b.
When the AI determines what to improve and with what, it does not take the civic into account. Only when it assign new citizen it will take civic into account.
Hope it helped.
Padmewan Apr 19, 2006, 02:47 PM That is very helpful; thank you!
I suppose to account for not considering civic changes, leaderheads with a particular leaning towards a civic are specially coded to also prefer that improvement. This suggests that a starting civic should not offer any bonuses, and that we shouldn't rely on the AI "knowing" about civic changes. (We had wanted different lifeforms to get different values from different improvements, but this will be much harder to model now without delving into the SDK. Oh well).
dsplaisted Apr 19, 2006, 11:31 PM That is very helpful; thank you!
I suppose to account for not considering civic changes, leaderheads with a particular leaning towards a civic are specially coded to also prefer that improvement. This suggests that a starting civic should not offer any bonuses, and that we shouldn't rely on the AI "knowing" about civic changes. (We had wanted different lifeforms to get different values from different improvements, but this will be much harder to model now without delving into the SDK. Oh well).
Do you guys not have anyone who can do C++ SDK work?
Padmewan Apr 20, 2006, 12:30 AM Do you guys not have anyone who can do C++ SDK work?
No, not really. I was willing to take it up at some point if necessary, but Python's been challenging enough. Are you volunteering? :mischief:
woodelf Apr 20, 2006, 05:25 AM Do you guys not have anyone who can do C++ SDK work?
I'll throw in my "are you volunteering?" as well. ;)
Chalid Apr 20, 2006, 05:26 AM I actually plan to review and partially rewrite the SDK-Improvementcode sometime in the next two weeks and want to add in a dependence on the state religion (thats for FfH), so if i'am done with this i'll let you know.
woodelf Apr 20, 2006, 05:29 AM I actually plan to review and partially rewrite the SDK-Improvementcode sometime in the next two weeks and want to add in a dependence on the state religion (thats for FfH), so if i'am done with this i'll let you know.
:wow:
War machines and SDK coding! We need to lure you away from FfH somehow....
NikG Apr 20, 2006, 08:06 AM If needed I can quickly fix this problem so the AI would consider tile with civic bonus. WOuld take me 10 minutes. Can then send the DLL to you.
Chalid Apr 20, 2006, 08:19 AM I think this should take you 0 Minutes ... its already in...
look at:
CvPlayer::processCivics
CvPlot::calculateImprovementYieldChange
dsplaisted Apr 20, 2006, 09:16 AM No, not really. I was willing to take it up at some point if necessary, but Python's been challenging enough. Are you volunteering? :mischief:
Well, not at the moment. Right now I don't really have the time. I am working on a pluggable AI system which will allow you to override the default AI behavior but still have the option of using the original behavior easily. Then of course I am going to Brazil for two weeks starting next week. After both of those things are done I might be available to help you with the odd SDK improvement, but it looks like there might already be people willing to do that for you.
NikG Apr 20, 2006, 09:51 AM Chalid yes, but the way I have interprented the code, the AI doesnt take civics changes into account when determine which plot to improve, something like xxx::calculateNaturalYield or something cant remember, I am at work right now, so I cant check it. Here it doesnt calculate any possible civic changes, and and this is called when trying to determine which to plot to improve. However I am not 100 % sure, so try check it out.
Chalid Apr 20, 2006, 11:04 AM I have checked it out. I considers Civics for sure.
It finally comes to CvPlot::calculateNaturalYield + CvPlot::calculateImprovementYieldChange
And the calulateImprovementYieldChange gets a ImprovementModifier-Variable from CyPlayer - when i remember correctly - that is changed in CvPlayer::processCivics.
Nevertheless it only calculates the best field with the civic it is using at the moment, and so all the choises get probably invalid on civic changes and of course civic Changes in the near Future are not considered.
Padmewan Apr 20, 2006, 11:56 AM Krikkitone has suggested a workaround that could work if the AI does account for civics and tech changes, which is to link the newer, better improvement to a tech advance. E.g. the improvement provides +0 yield at first, but with a new tech that happens to be the same tech that enables its building, it produces +3 yield or whatever, making it at first less attractive but later more attractive than the earlier improvement.
As a workaround this should let us move forward without twiddling with SDK... Though I appreciate all of this deconstruction, agree with everyone that the Improvement AI can be tweaked, and hope you'll continue to help us SDK innocents as we hack our way through this wonderful game...
NikG Apr 20, 2006, 05:04 PM Okay Chalid, thanks for update. Will check it my self tomorrow, going to bed now. But were does it calls CvPlot::calculateNaturalYield and CvPlot::calculateImprovementYieldChange to add them together..?
Chalid Apr 21, 2006, 02:57 AM Okay Chalid, thanks for update. Will check it my self tomorrow, going to bed now. But were does it calls CvPlot::calculateNaturalYield and CvPlot::calculateImprovementYieldChange to add them together..?
CvCityAI::AI_bestPlotBuild
aiFinalYields[iJ] = (pPlot->calculateNatureYield(((YieldTypes)iJ), getTeam(), bIgnoreFeature) + pPlot->calculateImprovementYieldChange(eFinalImprovement, ((YieldTypes)iJ), getOwnerINLINE(), true));
It comes to this line when the improvement is valid and of some value to the AI. Some value means that it
a) does change the tile yield in a positive way
b) spread irrigation when irrigation is needed
c) make a bonus available
Interestingly the different yields are assigned the following weights:
Food: 19 (when there is abundance) up to 48 (on absolut shortage and emphasisis, emphasisis depends on the natural yield of the field)
Production: 35 or 15 (emphasised or not)
Commerce: 8 or 7 (emphasised or not)
So the Ai doesn't really appreciate commerce gain when it can get food or production instead.
Padmewan Apr 21, 2006, 09:26 AM Thanks for all the to-ing and fro-ing, guys. From further experimentation, I can confirm that the AI takes into account (a) civics and (b) tech advances. So the AI still refuses to build a +1 food improvement when at Tech X a +1 food improvement appears that gets a +1 food bonus from Tech X. Our attempt to trick the AI was foiled!
However, the AI will build the +1 food improvement to gain access to a resource. I'm not sure if the AI will then replace that improvement with the better improvement (which also gains access to the resource) -- its little AI logic may stop at the first improvement it sees that offers access to a bonus and just stop there.
Interestingly the different yields are assigned the following weights:
Food: 19 (when there is abundance) up to 48 (on absolut shortage and emphasisis, emphasisis depends on the natural yield of the field)
Production: 35 or 15 (emphasised or not)
Commerce: 8 or 7 (emphasised or not)
Very interesting! In our food-starved mod, in which the value of production is relatively higher than in vanilla, this might be why our AI is gagging.
Would this weighting change if, e.g., it taked 3 or 4 food to support a pop point rather than 2? Just seeking ways to outsmart the AI without resorting to deep SDK changes...
Padmewan Apr 21, 2006, 09:56 AM Interestingly the different yields are assigned the following weights:
Food: 19 (when there is abundance) up to 48 (on absolut shortage and emphasisis, emphasisis depends on the natural yield of the field)
Production: 35 or 15 (emphasised or not)
Commerce: 8 or 7 (emphasised or not)
My guess is that these values are multiplied by the potential tile yield? Therefore, when deciding what to do with an irrigated grass tile, using averages in the Classical era:
Farm
food: 3 x 35 = 105
prod: 0 x 25 = 0
com: 1 x 7 = 7
TOTAL: 112
Workshop
food: 2 x 35 = 70
prod: 1 x 25 = 25
com: 1 x 7 = 7
TOTAL: 102
Hamlet
food: 2 x 35 = 70
prod:0 x 25 = 0
com: 6 x 6 = 36 [AI looks at final result]
TOTAL: 106
Wow... these numbers are close enough that they can't be an accident. When the first boost to the Hamlet series comes with Printing Press, the value of a hamlet is exactly equal to a farm on a river tile (assuming an average weighting as is assumed above).
Very interesting... do you know where those numbers come from, Chalid? Are they at all derived from the Yields XML weighting (which gives food 100, prod 120, and commerce 80)? How is the leaderhead bias for improvements accounted for -- is it a raw number added after this calculation that "tips the scale" so to speak?
This will vastly improve our ability to calibrate the AI, either by changing this default weighting or by adjusting our improvements to match these values... thanks a billion!!!!
Chalid Apr 21, 2006, 10:03 AM The amount of food needed per person is taken into consideration somewhere along the line. ..
Oh I have found which part in the code leads to the consideration of improvements that become available later.
if (GC.getBuildInfo(eBuild).getTechPrereq() != NO_TECH)
{
if (!(GET_TEAM(getTeam()).isHasTech((TechTypes)GC.get BuildInfo(eBuild).getTechPrereq())))
{
if ((!bTestEra && !bTestVisible) || ((getCurrentEra() + 1) < GC.getTechInfo((TechTypes) GC.getBuildInfo(eBuild).getTechPrereq()).getEra()) )
{
return false;
}
}
}
It considers the improvement as soon as it comes within the next Era. So you will have to move it up two Eras. Fortunatley you can do archive this by including an additional ERA in your Erainfos without linking any techs or units or so to that ERA... so its kind of a Dummy Era.
Something like
ERA_IMPROVEMENT1
ERA_DUMMY
ERA_IMPROVEMENT2
As the AI will never get into ERA_DUMMY the improvement will only be considerd when the AI is within the ERA_IMPROVEMENT2
However, the AI will build the +1 food improvement to gain access to a resource. I'm not sure if the AI will then replace that improvement with the better improvement (which also gains access to the resource) -- its little AI logic may stop at the first improvement it sees that offers access to a bonus and just stop there.
You are absolutley right here... it will not build the second improvement when the first one grants access to the resource.
Chalid Apr 21, 2006, 10:16 AM My guess is that these values are multiplied by the potential tile yield? Therefore, when deciding what to do with an irrigated grass tile, using averages in the Classical era:
YEs they are quite close!
But there are some other factors as well. One is the additional gain by the improvement is added with weights:
food*4+production*3+commerce*2 and
19 Points are added if the improvement spreads irrigation and irrigation is needed.
and when more food is generated then needed 21 or 12 points are further added.
ery interesting... do you know where those numbers come from, Chalid? Are they at all derived from the Yields XML weighting (which gives food 100, prod 120, and commerce 80)? How is the leaderhead bias for improvements accounted for -- is it a raw number added after this calculation that "tips the scale" so to speak?
No those numbers are strictly hard coded and no XML is involved. To change them you'll have to modify the sourcecode ~ SDK usage.
The leaderhead weights are multiplied on that with (100+Weight)/100
I gladly dig into this as it helps understand the way the game and the ai is working and possibly shows where it can be improved. :)
Padmewan Apr 21, 2006, 11:04 AM But there are some other factors as well. One is the additional gain by the improvement is added with weights:
food*4+production*3+commerce*2 and
Sorry, let me restate what you're saying I'm sure I understand: this is the ADDITIONAL gain by the improvement, e.g. a decision by the AI to change from an existing improvement?
So the steps are:
1. Calculate tile's current value for each yield with Improvement A
2. Calculate tile's potential value for each yield with Improvement B
3. Calculate B-A for each yield
4. Weight the difference (4 / 3 / 2 for food/prod/comm) between yield A and B to get a sum
5. Repeat 1-4 for Improvements C...X
6. Pick the best Improvement for this tile
7. Repeat 1-5 for all tiles
8. Pick the highest value and go!
Am I reading you right? Or does the weighting (4/3/2) happen somewhere else (at steps 1 and 2, or at step 6).
and when more food is generated then needed 21 or 12 points are further added.
21 or 12 points are further added to food, or to other yields?
No those numbers are strictly hard coded and no XML is involved. To change them you'll have to modify the sourcecode ~ SDK usage.
So what is the purpose of the "weights" node in the Yields XML file?
The leaderhead weights are multiplied on that with (100+Weight)/100
If steps 1-8 above are accurate, then when does this happen, at step 6.1 presumably?
I gladly dig into this as it helps understand the way the game and the ai is working and possibly shows where it can be improved. :)
When our team was young and naive we had proposed that one choice for the civ would be to mutate from a terrain/yield-driven mechanism into a building/yield-driven one (a Borg city, as it were). The idea is that this could best be done by building terrain-destroying improvements that gave huge production boosts to build these massive buildings. A human would figure this out pretty easily, but the AI...?
Anyway, would be interesting if the AI could be made to understand present discounted value of a cottage, though presumably only if it understood what that value could buy. I assume the AI has the best thinking that powergamers have brought to bear on the Civ series built into it...?
Chalid Apr 21, 2006, 11:53 AM Hmm it seems i havent been absolutly clear on that, but befor discussing further read the post 3 above.. there i solved your initial problem http://forums.civfanatics.com/showpost.php?p=3956011&postcount=19 ;)
its actually:
1. Calculate Weighting factors for Plot (EmphasiseFood, EmphasiseProduction, Emphaissie Commerse, EmphasiseIrrigation, and LowFood)
2. Repeat for all Improvments do:
2a) Can I build this improvement
2b) Calculate Gain by improvment (in contrast to unimproved Tile) and weight this by 4/3/2
2c) Calculate Total Yields and weight those
2d) Add 19 if Spread irrigation and Irrigation emphasised
2e) Add 21 od 12 for each (total food - food per person)
2f) Add weight by Leader
3) Select best improvement
4) Do this for all plots within the city to find the plot that should be improved
If you want the AI to understand a System like you propose it can be done, but some parts of the City Managing AI will have to be changed, and it should actually not be as hard. So your dream is not yet gone ;)
Edit: About the Yeild Weight i haven't found out yet but i will ;)
Padmewan Apr 21, 2006, 12:16 PM Hmm it seems i havent been absolutly clear on that, but befor discussing further read the post 3 above.. there i solved your initial problem
Yes, you did, and it's a brilliant solution -- thank you.
But this is so much fun!
1. Calculate Weighting factors for Plot (EmphasiseFood, EmphasiseProduction, Emphasise Commerse, EmphasiseIrrigation, and LowFood) -- this is where the 19-48 Food, 15-35 Prod, 7-8 Comm weight you mentioned earlier plays in? Or ar those applied at step 2c?
2b) Calculate Gain by improvment (in contrast to unimproved Tile) and weight this by 4/3/2 - OK, so this step considers the DIFFERENCE in yield (marginal change).
2c) Calculate Total Yields and weight those - This step considers the FINAL yield (absolute value). Is this, or step 1, or both, where the 19-48 / 15-35 / 7-8 weights come in?
Also, what is the relationship between 2b and 2c? Are the values totaled?
2e) Add 21 od 12 for each (total food - food per person) -- I don't understand this at all. :confused:
So very interesting -- assuming that 2b and 2c are totaled or averaged or something, the AI has a system for caculating MARGINAL change as well as final ABSOLUTE value. This would lead the AI to slightly prefer improving naked tiles rather than changing improvements. However, because the weight is 4/3/2, depending on the interplay between these two steps, there could be a double-weighting in favor food and against commerce? I guess I will wait for the explanation of how steps 2b and 2c interact...
THANKS Chalid.
Chalid Apr 21, 2006, 01:26 PM Ist simply added up everything in step 2. In step 1 there is no weighting but a series of yes no descision.
Something like.. oh there nor river near us so we should try to get some irrigation here (Emphasise Irrigation) or oh this tile produces a lot even without an improvement, so lets build something here that even increases the production (emphasise Production)
To give another example: grassland with river that belogs to a city that has low food will will get values like this:
Farm:
2a) +1 food => value = 4
2b) total 3 food (3*48) + 1 Commerce (1*7) + 2a (4) = 155
2d) 1 food surplus (3 Produced 2 needed per population) (+1*21) => Value 176
If the need for irrigation exists another 19 would be added.
Workshop_
2a) -1 food +1production => value -1
2b) total 1 Food(48) 1Production(15) 1 commerce (7) +2a=> Value 69
2d) No food surplus so it statys at 69
Town
2a) +5 Commerce => value 10
2b) total 2 food(2*48) 6 commerce (6*7) + 2a => Value 148
2d) No food surplus
When food is abundand:
Farm:
2a) +1 food => value = 4
2b) total 3 food (3*19) + 1 Commerce (1*7) + 2a (4) = 68
2d) 1 food surplus (+12) => Value 80
If the need for irrigation exists another 19 would be added.
Workshop_
2a) -1 food +1production => value -1
2b) total 1 Food(19) 1Production(15) 1 commerce (7) +2a=> Value 40
2d) No surplus so it statys at 40
Town
2a) +5 Commerce => value 10
2b) total 2 food(2*19) 6 commerce (6*7) + 2a => Value 90
2d) No food surplus
So it depends stongli on the emphasisis calculated in step 1 which is the best improvement for a plot.
Padmewan Apr 21, 2006, 02:00 PM Thanks for the clarification and example; this really helps. I would point out, though, that all but your last calculation does not include 2a; so the first set should be Farm = 180, Workshop = 68; Town = 158, etc...
Then is this score MULTIPLIED by the leader weight, e.g. if the leader weight is 40, it would be multiplied by 1.4 (100+40/100)? There must be some cap to the weight...
Anyway, the moral of this story seems to be not to stray too far from the core game mechanics or you'll get smashed. :crazyeye: Even with all this explanation we still need to know when the AI decides that "food is abundant" and moves on. But now I know why the AI does what it does...
woodelf Apr 21, 2006, 02:09 PM You'll need a weekend of deep meditation (or medication) to clear your head now Gene. I'm sure it hurts by now!
Chalid Apr 21, 2006, 02:13 PM Then is this score MULTIPLIED by the leader weight, e.g. if the leader weight is 40, it would be multiplied by 1.4 (100+40/100)? There must be some cap to the weight...
Only the Interger cap at 65535...
Anyway, the moral of this story seems to be not to stray too far from the core game mechanics or you'll get smashed. :crazyeye: Even with all this explanation we still need to know when the AI decides that "food is abundant" and moves on. But now I know why the AI does what it does...
Or hire someone who changes the CoreGame via the SDK for you ;)
Kael Apr 21, 2006, 02:30 PM :wow:
War machines and SDK coding! We need to lure you away from FfH somehow....
HEY!!! Hands off elf boy!
woodelf Apr 21, 2006, 02:39 PM HEY!!! Hands off elf boy!
:p
We call him Mr. Elf Boy so he likes us more now. ;)
Kael Apr 21, 2006, 03:32 PM :p
We call him Mr. Elf Boy so he likes us more now. ;)
I meant you! :crazyeye:
woodelf Apr 21, 2006, 06:34 PM I meant you! :crazyeye:
:lol:
I thought Chalid was elf boy....long day at work I guess....
They call Mr. Elf Boy. That works.
Padmewan Apr 23, 2006, 03:29 PM One more thing to add:
I also found that if two units are able to build the same improvement, the AI will never use the slower unit. Presumably this is related to the fact that the AI never deploys more than one worker to the same tile to do a task (which I also presume to be because every turn the AI could change its mind on what to do with a tile and have workers all undoing each others' work every turn).
In this mod we had an unbuildable Agribot that could instantly build a farm but be consumed in the process (it is coded as a replacement for the worker and warrior in goody huts). That kept the AI from deploying workers to do that same job, and therefore farms never got built.
Padmewan May 04, 2006, 09:43 AM I've done some tests and am fairly confident that the AI does not consider civic effects when calculating improvement values and decision-making.
==========
Parameters
Unmodified:
Improvement A: +1 food
Improvement B: +2 energy
Civic 1:
Improvement A: +2 food
Improvement B: +2 energy
Civic 2:
Improvement A: +1 food
Improvement B: +2 food, +2 energy
==========
Naturally, under Civic 1 the AI spams Improvement A (particularly as our terrain is nutrient-poor).
However, switching to Civic 2 the AI continues to spam Improvement A, even though Improvement B is clearly better. I have done this from scratch using WorldBuilder, to make sure that the AI is not doing this because of the lower marginal value of changing an existing improvement, but even with a blank slate it continues to behave the same.
I suspect this is a bug, perhaps somewhat corrected for in Vanilla by giving the leaderheads who like State Property a predeliction for Workshops.
Can anyone who has looked at the code and spotted the civic adjustment show me where my mistake in the setup or in my reasoning is? Improvement A does not upgrade, etc.
Chalid May 04, 2006, 10:17 AM Hmm does Improvement A change somewhere later in the tech tree.
I investigated this and found one more thing that i had overlocked. When deciding what to build the flag bOptimal is set, what means all technologies and all Civics that change the Improvement are already taken into consideration. And it takes into consideration that the tile will be irrigated sometime in the future.
So actually the Ai should built Improvement B even before it changes its civic when Improvement A is not changed later in the tech tree.
Quite a mess this improvement placing AI. :(
Padmewan May 04, 2006, 11:19 AM When deciding what to build the flag bOptimal is set, what means all technologies and all Civics that change the Improvement are already taken into consideration. And it takes into consideration that the tile will be irrigated sometime in the future.
That would make the AI incredibly stupid -- an early-era civ would not refuse to build cottages on unirrigated grass just because it could later build a farm much further down the road (because it needs food NOW). If it's not already there, the AI needs some kind of "present discounted value" analysis and/or at least some sense of how long until said improvement becomes available.
So actually the Ai should built Improvement B even before it changes its civic when Improvement A is not changed later in the tech tree.
But it doesn't, and so that gives me hope that bOptimal is not controling but rather contributing to the final decision. Didn't you share earlier that sticking in a fake era would cause the AI to not "see" an improvement that arrives in the next era and therefore be willing to build its inferior predecessor?
btw, thanks to some code adapted from Kael, Civics A and B are attached to religions, (e.g. you need Religion B to adopt Civic B) and so when you have no religion (Civic A) you don't have access to Civic B. Neither do you have access to Civic A while you are in Civic B. Don't know how that factors into this analysis, if at all -- it seems to me from your description that bOptimal doesn't care whether the option is available or forthcoming, just possible...
???
Padmewan May 12, 2006, 01:34 PM :bump:
HEEEELLLLPPP!
:D
hate to pile it on, but if anyone has any insight into how the AI chooses civics, that would also be illuminating!
The Great Apple May 12, 2006, 01:45 PM Open up CvPlayerAI.ccp, and go to line 5722 - that is where it is determined. It is based on rather a lot of things though. If you want explaination of a little bit of it post it up here, and I'll do a translation of it. I think you could probably read quite a bit of it without knowing much about it.
bdmarti Oct 19, 2006, 10:33 AM Can someone tell me how to encourage the AI to GUARD a particular resource?
I've noticed that the AI will fortify units on particular Resources...but I haven't been able to figure out what flags will cause it to choose those resources.
|
|