I’ve been playing and watching Civilization 5, and I thought of a cute optimization problem that I’d like some ideas on. For those of you have played Civ 5, the idea is optimizing your production time on a wonder in certain ideal conditions. The “ideal conditions” being assuming a city with no border pops, unchanging tile improvements, no special buildings like an aqueduct, no hammer/food trade ships, infinite happiness, and so on. Basically a city that is JUST working tiles.
I tried to define the problem as formally as possible:
We start with a city with population p, current surplus food f, and food income i. A city grows when its current surplus food, f (as above), is greater than or equal to some value given by the function foodCost(p) where p is the same value as before. The exact value of foodCost is known, but irrelevant (in that the problem can be solved in terms of the function, not that it doesn’t matter).
Each turn, f is increased/decreased by i-2p (the income minus 2 times the population), whenever the population grows (the surplus is greater than the food cost), f is reset to f-foodCost(p) and p is increased by one. That is, the population grows by 1 and the current supply of food is equal to the amount of surplus exceeding the requirements for growth. If f dips below 0, f is set to 0, and p decreases by 1.
This city is trying to build a wonder, which requires a resource called hammers. We start with some value of hammers called h, and each turn we get b hammers. Meaning: each turn h is updated to h+b. If the number of hammers exceeds some value requiredHammers, the wonder is built and the problem is satisfied (this is our “end condition” or “goal state”).
Now comes the tricky interaction: The city has some set of tiles t ∈ T. On any given turn we are working min(p,|T|) tiles – we work as many tiles as we have people, unless we exceed the number of tiles in which case we just work all of them. The values of i and b are directly determined by the tiles we’re working. Specifically, each tile has two values we’ll call t.i and t.b that are greater than or equal to zero. Each turn the values i and b are equal to the sum of the t.i and t.b values (respectively) of the min(p,|T|) tiles we’re working.
The problem is then: optimize the selection of tiles to minimize the production time of the wonder (number of turns to complete it). The tricky part is that increasing p and getting another tile to work may or may not decrease production time, so it may be advantageous to not take a tile with extra hammers in the early turns to increase the hammers in later turns.
We can assume that there always exists at least one tile selection such that b is positive.
I used my optimization crutch, a graph search, to solve it. And it works. Given some initial state I can generate successor states upon request and run BFS to determine exactly which tiles I should have selected each turn. But I feel like there should be a better way to do this. Any ideas?