We-the-People-civ4col-mod / Mod

This is the repository where the mod resides.
90 stars 37 forks source link

How should the AI determine which yield to produce at the colony plot? #139

Open Nightinggale opened 6 years ago

Nightinggale commented 6 years ago

Currently unless the player specifically sets a yield, the AI will set a yield to produce at colony plots. The logic is fairly simple. It loops all yields, calculates the amount of yields produced and then it produces the highest value. In case of a tie, it will produce the one with the lowest YieldTypes ID.

I'm considering the option of multiplying the yields produced with the price in Europe. That way rather than getting as many yields as possible, it should produce whatever will provide the most money when exporting. This should increase the income for the AI since it will likely just export whatever is produced rather than being clever with production chains. It won't affect human made production chains because if needed, a human would specify which yield to produce consistently.

Potential issues:

The function in question (overloaded, hence full argument list)

int CvPlot::calculatePotentialYield(YieldTypes eYield, PlayerTypes ePlayer, ImprovementTypes eImprovement, bool bIgnoreFeature, RouteTypes eRoute, UnitTypes eUnit, bool bDisplay) const
abmpicoli commented 6 years ago

Notice that the price in europe is not necessarily the best measure: this will make lumber never to be produced... If the AI learns how to sell things to Africa and generates a "trade route" between Africa and some city, then the price at Africa should be better...

As a protection against have smaller stacks because the good that was being produced just got a smaller price, you could make the tie-breaker be, instead of "smaller id", choose the stack with is closer to a 100 multiple: that is , the bigger ( stock % 100 ) ...

I think that the ideal solution would have a function at the Player AI (CvPlayerAI) , getYieldValue... This YieldValue should be based on an evaluation of offer x demand, prices in europe, total production potential... But as a quick implementation, it should have strategic goods as per europe buy price (that is, lumber,stone,muskets,cannons,tools) should be evaluated by import value instead of export value...

Another thing that could be considered is that, industrial people, like tobacconists, will gain much more if they plant tobacco when they don't have a stock... Their profit can be evaluate as CIGARVALUE (CIGAR POTENTIAL PRODUCTION TOBACCO POTENTIAL PRODUCTION ) / (CIGAR POTENTIAL PRODUCTION + TOBACCO POTENTIAL PRODUCTION) ...

Later I think we should come with an even better algorithm, based on city offer x demand...

Nightinggale commented 6 years ago

We should consider just using price as a start and then add all that other stuff later. The price seems fairly simple to add while all the other stuff you mention could take a while to implement.

Another thing to consider would be to make some sort of code, which makes the decision on what to produce once each turn. If new yield != old yield, mark some graphical stuff dirty for redraw. This approach will also help performance because right now the yield is determined by looping all yields and it's done in each iteration of looping all yields.

We might actually have to save the chosen yield of the turn or there could be a risk of desync if a player joins a multiplayer game mid turn.

abmpicoli commented 6 years ago

I don't think you should implement price only ... lumber will never be produced this way... I think there should be at least a function that will tell the AI the lumbers is worth more than what europe says ....

abmpicoli commented 6 years ago

Maybe add an AI asset value for each good... instead of relying on price at europe...

Nightinggale commented 6 years ago

I'm not saying price is perfect, but it's the best I can come up with, which can be implemented within reasonable time. While your alternatives seems to be better, they feel like 2.8 if not later. The price approach could make it for 2.7.2, or even 2.7.1 if somebody wants to work on it right away.

abmpicoli commented 6 years ago

A simple extra field at the goods xml would make the same effect, and will allow the AI to produce lumber. Prices in europe will handicap the AI for lumber production... Making the matter of AI not producing lumber even worse...

abmpicoli commented 6 years ago

Well... another solution is to use prices at europe and then rebalance lumber value so the AI can also potentially build it... Notice that using the current stock as tie breaker is easy to implement as well: just make the value be 100 PRODUCTION EUROPEPRICE + (STOCK % 100)

Nightinggale commented 6 years ago

How do you produce lumber on the colony plot anyway? The feature is cleared when the colony is founded. If it isn't, then part of the problem of #120 wouldn't be a problem at all. I wouldn't mind NOT clearing the feature when founding, but that's a different topic.

As for the solutions you propose, I certainly won't mind if you think you can implement them within reasonable time. It's hard not to make it better than what we currently have and if it ends up as a function, which is easy to read and tweak, then we can always make adjustments later based on gaming experience.

ShadesOT commented 6 years ago

The yield to be produced on the colony plot, is part of the cities and maybe the factions overall strategy.

orlanth commented 6 years ago

This is maybe naive, but couldn’t you use the same function that tells the AI what to produce on any plot in the city?

abmpicoli commented 6 years ago

@orlanth I'm also not sure myself, but there is a fundamental difference : the code for the city plot doesn't have a colonist working it: so the unit doesn't count. This makes for a much simpler and at the same time different logic...

Nightinggale commented 6 years ago

The AI doesn't assign plots to production. It assigns professions to units and happens to assign plots to the units in the process. This mean there is no function to call, which tells which yield the AI wants from a certain plot.

However there has to be something, which tells how the AI values a certain yield. It would make sense to find that one and use it here. If the AI values certain yields incorrectly according to the needs, it should be fixed for all plots, not just the colony plot.

orlanth commented 6 years ago

Ok. I remember the MC version of Domestic Markets allows different Yield prices for each city, and we were thinking about letting these prices adjust in response to local supply and demand. If this were true here, using the product of units produced times local price could be ideal. If not, units times europescreen price would be a reasonable default (though maybe not totally ideal in cases of multiple trade screens and cases where that city is not likely to actually export).

Nightinggale commented 6 years ago

AI value != price. The AI has some calculations where it assigns value to yields, like it prefers tools over tobacco even if tools might earn less when being exported to Europe. However the AI is hardcoded to hoard tools, weapons, horses etc and not try to sell them at a profit. Also the AI value depends on other conditions as well, such as currently held stock. How the AI values yields precisely will be better known once we find the actual function to calculate the value.

devolution79 commented 6 years ago

Guys, check out CvCityAI::AI_estimateYieldValue and its associated call sites. That should explain how the AI evaluates the value of a yield. In the case of the city plot (which is not worked by any colonist and thus has no opportunity cost), I think that the correct thing to do for the AI will be to maximize the AI value.

devolution79 commented 6 years ago

Note that the AI yield evaluations are scheduled to be overhauled so what you see is a stop-gap solution that I added in 2.7.x to fix the most egregious issues.

devolution79 commented 4 years ago

https://github.com/We-the-People-civ4col-mod/Mod/commit/81aa3227cd717e2159be4b87a37b17c3529078b7

"Europeans AI players will now choose the city plot yield with the highest export price": I think this is a reasonable first-order approximation

Nightinggale commented 4 years ago

Looks good to me. The only issue is that you removed two lines near the read/write functions in the header, something I suspect will conflict with the savegame branch. However should that happen, it's luckily not a hard conflict to solve.

Naturally it would be best to take city needs into account, but maximizing the export profit would be a good start, particularly considering I added code to ensure that raw materials and the finished product won't be too close in price (I think it's a 2.8 change). This means a high price of a raw resource makes it more likely that something produced by said resource will also sell for a decent price. This means just looking at the price of the raw resource isn't as bad as it sounds even if the AI is producing a higher tier export yield from the resource.