Latest Posts

Topic: Introducing limits in building ratios of AI

king_of_nowhere
Avatar
Topic Opener
Joined: 2014-09-15, 17:35
Posts: 1668
Ranking
One Elder of Players
Posted at: 2015-12-05, 05:12

I'm a bit sorry to put forward yet another suggestion when my latest three or four are still open discussions; I know programmers have limited time, and I should limit the amount of stuff i propose, otherwise they'd have to do nothing but working on my ideas.

And yet, after my last game, I could not refrain from posting this.

I've seen that the ai often has huge buildings imbalances. sometimes it makes 5 war mills with only a couple smelting works. or it makes 10 metalwork shops, one wonders what it does need all those tools for. or it makes 20 inns, when it only has a handful of farms to feed the bakeries that are needed to make them work. Apparently the algorithms that regulate the ai needs can malfunction sometimes. Also, AI tend to be highly inefficient: if you look at the "ware"statistic, you'll see ai tend to accumulate lots of wares - and those are unused wares, gathering dust in a warehouse; you'll want to minimize those.

So I thought that setting some hard limits in the form of "don't build more than 1 war mill for every smelting work, but no more than 5 smelting works for one war mill either" could be introduced, to ensure that the ratio of primary producers to secondary producers do not stray too far from optimal levels. After a bit of work looking at working times in the lua files, I came up with the following table for barbarians. When there is more than one limit for the same building, the lower one applies. All values are rounded down.

  • max bakeries = 1 + (farms/6) // a bakery takes 45 second to make a bread, and consumes 3 grain. a farm makes a grain in 100 seconds on average, as per experimets i did
  • max wells = 2+ (farms) // water is always consumed together with grain. there's no point in producing much more water than grain.
  • max (metal_workshop + ax_workshop + war_mill + helmsmiths) = 1 + smelting_works // a smelting works produce a metal in 70 seconds. the workshops consume at least one and have a working time of 60 seconds.
  • max smelting_works = 2 + 2 * metal_workshop + 4 * ax_workshop + 5 * war_mill
  • max metal_workshop = 2 // I never needed more than 1. The second is for upgrading
  • max helmsmiths = 1 + (war_mill + ax_workshop) // you need less helms than axes
  • max smelting_works = (2 + 4 * deeper_coal_mines + 3 * deep_coal_mines + 2 * coal_mines + charcoal_kilns)
  • max (iron_mine + 1.5 * deep_iron_mine + 2 * deeper_iron_mines) = 1 + 1.5 * (coal_mine + 1.5 * deep_coal_mine + 2 * deeper_coal_mines + 0.5 * charcoal_kilns) // IMPORTANT: for all kinds of mines, this limit should affect decision to build new mines, but not to upgrade existing ones. I can picture some situation where a mine is exhausted and need to be upgraded, but the ai won't because it already reached its limit, so ai should be allowed to break the limit to upgrade.
  • max iron_mine > 0 // sometimes the ai could have plenty of deep mines, but only have rations have food. this condition make sure it can continue to mine even if it lacks bread or beer
  • max coal_mine > 0
  • max gold_mine > 0
  • max (iron_mine + 1.5 * deep_iron_mine + 2 * deeper_iron_mines) = 2 + smelting_works
  • max (gold_mine + 1.5 * deep_gold_mine + 2*deeper_gold_mines) = ( 1 + (coal_mine + 1.5 * deep_coal_mine + 2 * deeper_coal_mines + 0.5 * charcoal_kilns))
  • max (gold_mine + 1.5 * deep_gold_mine + 2 * deeper_gold_mines) = ( 1+(iron_mine + 1.5 * deep_iron_mine + 2 * deeper_iron_mines)) // you never use gold without iron, so it's pointless to have more. exception for collectors win condition, where making gold ingots is the best way to make points
  • max (coal_mine + 1.5 * deep_coal_mine + 2 * deeper_coal_mines + 0.5 * charcoal_kilns) = 4 + 3 * (iron_mine + 1.5 * deep_iron_mine + 2 * deeper_iron_mines) + 3 * (gold_mine + 1.5 * deep_gold_mine + 2 * deeper_gold_mines) // I want the upper limit for coal production to be comfortably high to avoid malfunctions
  • max (tavern + inn + big inn) = 3 + 2 * (total mines) // I can't understand well how those buildings work, so I'm setting a prudentially high limit
  • max (tavern + inn + big inn) = 1 + (hunters + fishers) // none of those buildings can work without meat/fish. I am not putting a limit on inns and big inns alone because they can still make regular rations
  • max micro_breweries = 2 + (farms/1.5)
  • max breweries = 1 + (farms/1.5)
  • max cattle_famr = 0.8 + farms/10
  • max cattle_farm = 2 // I never needed more than 1 anyway
  • max reed_yard = 3 // I never needed more than 1 anyway; i'm setting a higher limit just in case the ai manages to block its fields
  • max farms = 5 + 8 * bakeries + 2 * breweries + 2 * micro_breweries // i limited cattle farms to 2, so i see no reason to include them in the equation
  • max charcoal_kiln = woodcutters/2
  • max battle_arena = 1 + training_camp/3 // the training camp takes much longer to train a soldier than the arena, so no point having 3 arenas with 1 training camp.
  • max training_camp = (0.5 + helmsmiths + ax_factory + war_mill)
  • max (battle_arena + training_camp) = 1.25 + bakeries * 0.75
  • max (battle_arena + training_camp) = 1 + (hunter + fischer)/2
  • max hunter = 2 + gamekeeper * 1.25
  • max gamekeeper = 2 + hunter * 1.25

If you like the idea of including conditions like those, I can work similar ones for empire and atlanteans. I tried to keep large intervals to let the ai be flexible enough. If you think I got some values wrong, or I forgot something, feel free to point it out.

Edited: 2015-12-05, 05:23

Top Quote
GunChleoc
Avatar
Joined: 2013-10-07, 14:56
Posts: 3324
Ranking
One Elder of Players
Location: RenderedRect
Posted at: 2015-12-05, 09:24

Before you continue to make our calculations, we should discuss how we want to implement this and what the restrictions are. At the moment, the only way to implement something like min or max would be hard coding it to specific buildings in C++.

This should also not go into the tribe's init files, because the tribes shouldn't care about the AI. Maybe it is time to start thinking about a Lua interface for the AI to handle AI hints etc? Each AI would then have its own Lua files with its own hints and there would be an AI API. This would be a big change though and something we should only think about for Build 20.


Busy indexing nil values

Top Quote
king_of_nowhere
Avatar
Topic Opener
Joined: 2014-09-15, 17:35
Posts: 1668
Ranking
One Elder of Players
Posted at: 2015-12-05, 10:15

well, i was thinking, since currently in the lua files there is a mention of limits for the ai to build a specific building depending on the difficulty level in the form of

aihints = { prohibited_till = 600, weak_ai_limit = 1, normal_ai_limit = 2 }

that it could be possible to add a limit depending not on difficulty level, but on the number of other buildings possessed by the player.


Top Quote
GunChleoc
Avatar
Joined: 2013-10-07, 14:56
Posts: 3324
Ranking
One Elder of Players
Location: RenderedRect
Posted at: 2015-12-05, 10:58

The AI hints are loaded only once at the start of the game. So, at the time the AI hints are loaded, the current number of buildings for all buildings will be 0. You could add a list of buildings with a minimum number for each building, but you can't do a min/max formula or a multiplication there, because it will always give you 0.

Any formula will have to be programmed in C++ at the moment - the AI hints can only give you some variable configuration values.

Edited: 2015-12-05, 10:59

Busy indexing nil values

Top Quote
DragonAtma
Avatar
Joined: 2014-09-14, 00:54
Posts: 351
Ranking
Tribe Member
Posted at: 2015-12-05, 11:00

If we're going with something like that,m it may be best to go with a smart/average/dumb setting for the AI.

I should add that larger maps will need larger building limits. Crater (2 players, 64x64) would do find with one or two of multiple building types, while Riverlands (7 players, 192x176) would need a lot more.

It may be best to have aihints instead limit them to (1+int(territory/1000)) and (2+int(territory/500)) or something.


Top Quote
GunChleoc
Avatar
Joined: 2013-10-07, 14:56
Posts: 3324
Ranking
One Elder of Players
Location: RenderedRect
Posted at: 2015-12-05, 11:06

DragonAtma wrote:

I should add that larger maps will need larger building limits. Crater (2 players, 64x64) would do find with one or two of multiple building types, while Riverlands (7 players, 192x176) would need a lot more.

It may be best to have aihints instead limit them to (1+int(territory/1000)) and (2+int(territory/500)) or something.

I made a similar suggestion in the bug

At the moment, we just have a simple setup that lets us work with this at all - now we need to tweak the values we have in the init.lua files - maybe we should balance this for small maps first, then think about a territory size factor as a second step?


Busy indexing nil values

Top Quote
king_of_nowhere
Avatar
Topic Opener
Joined: 2014-09-15, 17:35
Posts: 1668
Ranking
One Elder of Players
Posted at: 2015-12-05, 11:07

GunChleoc wrote:

The AI hints are loaded only once at the start of the game. So, at the time the AI hints are loaded, the current number of buildings for all buildings will be 0. You could add a list of buildings with a minimum number for each building, but you can't do a min/max formula or a multiplication there, because it will always give you 0.

Any formula will have to be programmed in C++ at the moment - the AI hints can only give you some variable configuration values.

so that means that the ai can only build one single smelting work, and will not be able to build another if that one is destroied? if it is so, seems like something that needs to be fixed.

As for the rest, pity. there goes my hope that the worst parts of the ai could be fixed with a few equations.


Top Quote
GunChleoc
Avatar
Joined: 2013-10-07, 14:56
Posts: 3324
Ranking
One Elder of Players
Location: RenderedRect
Posted at: 2015-12-05, 11:18

king_of_nowhere wrote:

so that means that the ai can only build one single smelting work, and will not be able to build another if that one is destroied? if it is so, seems like something that needs to be fixed.

No, that's not the case. The AI hint means "You are not allowed to build more than 1 Smelting Works". So, if it gets destroyed, the AI can build a replacement.

king_of_nowhere wrote:

As for the rest, pity. there goes my hope that the worst parts of the ai could be fixed with a few equations.

Maybe you could come up with a standardized formula that then gets fed a building list with number of buildings required? Then the AI cold check if those buildings have been built in the required number. Something like:

required_buildings {
    farm = 3
    micro_brewery = 1
}

We should wait for Tibor's input though.

Edited: 2015-12-05, 11:19

Busy indexing nil values

Top Quote
king_of_nowhere
Avatar
Topic Opener
Joined: 2014-09-15, 17:35
Posts: 1668
Ranking
One Elder of Players
Posted at: 2015-12-05, 12:31

wouldn't work, because there is no required number, but an economy should keep growing as one expands.

as i mentioned other times, the way i go is to look at stock-wares in warehouses, see what wares i am accumulating and what i am missing, and make buildings that use the stuff i am accumulating and other buildings that make the stuff i'm missing. I start from the more advanced wares and go down the line; a simplified logical process could be described as such

  • do i have excess weapon? yes, build new dungeon
  • no: do i have excess metals and coal? yes, build another weapon smith
  • no: do I have excess food? yes, build more mines of the appropriate type
  • no: do I have excess corn/blackroot/fish/wood? yes, build more mills/bakeries/smokeries
  • no: build more fisheeries/fish breeders, woodcutters/foresters, farms/blackroot farms/wells.

it works really well and it's fairly foolproof: if you are accumulating food, you can afford to build more mines, there's not much to argue. using productivity can get you in all sort of troubles instead: for example, you may see your mines are working at 100%, and decide you must have food and can make more mines, but in truth you have little food and your mines register high productivity only because they are skipping work because you have few smelting works. With a ware-oriented, top-down approach, you'd immediately see you have excess of metal ores and you need to build smelting works. hmm, now that i think about it, you can do it with productivity too, as long as you start form the top; so you'd see the smelting works at 100% and decide to make more. but if the smelting works are not working you'd need to look whether you're missing coal, iron or gold, so you still need to look at wares in warehouses. but apparently getting the ai to do that is very complex.

in any case, setting a few hard limits in the ratios of primary and secondary producers should at least avoid the worst cases of imbalancement. if the ai works properly, it wouldd never stray out of those limits anyway. think of it as a safety check.

Edited: 2015-12-05, 12:32

Top Quote
DragonAtma
Avatar
Joined: 2014-09-14, 00:54
Posts: 351
Ranking
Tribe Member
Posted at: 2015-12-05, 12:31

GunChleoc wrote:

DragonAtma wrote:

I should add that larger maps will need larger building limits. Crater (2 players, 64x64) would do find with one or two of multiple building types, while Riverlands (7 players, 192x176) would need a lot more.

It may be best to have aihints instead limit them to (1+int(territory/1000)) and (2+int(territory/500)) or something.

I made a similar suggestion in the bug

At the moment, we just have a simple setup that lets us work with this at all - now we need to tweak the values we have in the init.lua files - maybe we should balance this for small maps first, then think about a territory size factor as a second step?

I've thought about using map size in the limits, but there's two problems: (1) The amount of controlled land -- if a CPU is in last place in in a large map, it probably wouldn't help for them to spam a building just because it's a large map. (2) The amount of usable land varies from map to map. Maybe half of Riverlands is usable land, while Atoll is at least 90% water (and, therefore, only 10% land).

So that's why I suggested using the amount of land currently controlled by the AI instead of the whole map.


Top Quote