ResourceMining
This document presents a model for resource dynamics. The goal of the model is to achieve reasonable realism while being efficient enough to be used in a real time simulation game.
Data
Resources are located in the triangles of the game's map. Resource types are limited to certain terrain types. (For example the resource fish can only be on the terrain type water.)
Each triangle stores a resource index (0.. 15) indicating the kind of resource that the triangle has, a capacity (0.. 15) and a resource amount (0.. 15). This uses 12 bits per triangle which means 3 bytes per node, which is rather efficient. The drawback is that the model has the following limitations. It is not possible to represent any of the following:
- That there are several different kinds of resources on a particular triangle,
- How the resource amount is distributed over the depth.
- That the resource amount is more than 15.
- That there are can be more than 16 different resource types per terrain type. The resource type and capacity are static while the amount is dynamic.
Man-made dynamics
Man-made dynamics are when the resource amount is changed as a result of human activity. The resource amount may decrease as a result of mining, fishing, harvesting and so on.
There could also be human activity that increases the resource amount. Suppose that there is a resource capercaillie. Hunting predators may increase its regeneration rate.
Mining
Realism in mining is achievable insofar that mining high concentrations can be made more rewarding than mining low concentrations and mining deep can be made more expensive than mining shallow. Concentration is represented by the capacity and depth is represented by the amount.
Depth is counted on a scale from 0 to 360360 (= lcm (1,..., 15) = 23 · 32 · 5 · 7 · 11 · 13), which is chosen to ensure that all depth calculations can be done with (unsigned 64 bit) integers. When the resource amount of a triangle equals the capacity (in other words, the triangle is full of resource), the resource amount is considered uniformly distributed across all depth levels. This means that if a triangle has the capacity 1 and the amount 1 of its resource, the whole depth must be excavated to mine the unit of resource.
But if a triangle has the capacity 15 of its resource, only 1/15th of the depth must be excavated to mine each unit of resource on the triangle. When mining the first unit, the mine excavates from depth 0 (= 0 / 15 · 360360) to 24024 (= 1 / 15 · 360360). When mining the second unit, the mine excavates from depth 24024 (= 1 / 15 · 360360) to depth 480480 (= 2 / 15 · 360360). And so on.
If a triangle had the initial amount 13 of the resource and 2 units are remaining, the 11 shallowest height levels have already been excavated. To mine the next unit, the mine must excavate from depth 304920 (= 11 / 13 · 360360) to depth 332640 (= 12 / 13 · 360360).
The time it takes to excavate an infinitesimal element is proportional to the size of the element and its depth. It is natural to call the size of the element ddepth (because size is a volume in 3 dimensions and depth is one of those dimensions). We get the equation:
_d_time proportional to depth · _d_depth
The time it takes to excavate the resource of a triangle from level start_depth to level end_depth is therefore:
time proportional to integral( start_depthend_depthdepth · _d_depth) = [depth2/ 2]start_depthend_depth= (end_depth2- start_depth2) / 2 proportional to end_depth2- start_depth2
This means for example that the time it takes to mine the resource of a triangle that has capacity 1 and amount 1 of its resource is some constant that depends on the mine's efficiency multiplied by 129 859 329 600. The corresponding value when the triangle has capacity 15 is only 577 152 576 when amount is 15 (in other words, when mining the first resource) and 16 737 424 704 when amount is 1 (in other words, when mining the last resource). Reasonable efficiency constants should therefore be no larger than 2-16. With this value it would take from 8 806 ms (1st of 15) to 1981 496 ms (33 minutes, 1st of 1) to mine a unit of resource, depending on how easily accessible it is. (Mining resource 15 of 15 would take 255 392 ms (4 minutes) with this efficiency constant.) Mine configurations should specify an efficiency exponent (such as 16 in this example). To prevent small mines (with low efficiency) from attempting to do deep and very time-consuming excavations, they should specify a maximum working time. If the mining operation would take more than that time, it is not done. The player should upgrade to larger (more efficient) mines instead. Mine configurations should also specify a radius >= 0 that indicates how many steps away from the mine's location (a node) they can reach (from each node the 6 surrounding triangles can be mined so radius 0 makes 6 triangles available while radius 1 makes 24 triangles available and so on). Larger mines could be configured to have larger radius as well as higher efficiency. Mine configurations should also specify which resource kinds they can mine.
In each mining iteration the mine will always chose one of the triangles that is fastest to excavate.
Fishing
The mining model can also be used for fishing since the cost calculations provide realism for this case as well. Fishing at a location with high fish capacity is faster than fishing at a location with low capacity. Fishing at a location with high amount is faster than fishing at a location with low amount.
The cost calculation for fishing not only involves the actual fishing but also the walking (or rowing) from the fisher's hut to the fishing site and back. The fishing program specifies a maximal cost. If the total cost of transportation and fishing exceeds the maximal cost, the fishing is not done. This will make the fisher walk a longer distance to fish at a good fishing site than he would to fish at a less good fishing site.
Natural dynamics
Natural dynamics are changes to resource amount caused by natural processes such as regeneration and migration.
Regeneration
Some resources may regenerate, one unit at a time, up to the capacity, at a rate determined by a function of a constant defined in the resource configuration, the amount and the remaining capacity (= capacity - amount). Some resources may be configured to not regenerate (such as minerals). Others (such as fish) may follow a logistic function, growing slowly when the amount is low and, faster when the amount is higher and then slower again when the amount reaches the capacity.
Implementation
The game has an object called resource manager. When a resource amount is changed, an update method is invoked on the resource manager with the coordinates of the triangle as argument. The resource manager has a table that maps triangle coordinates to a regeneration record with numbers indicating how far the regeneration has proceeded and when it will produce the next unit of resource if nothing happens in the meantime that alters the calculation. If the triangle coordinates are not present in the table, the resource manager calculates a regeneration record and adds it to the table. If they are, the resource manager updates the record. Then it invokes schedules a call to itself with the triangle coordinate as a parameter. When the scheduled time has come, the resource manager checks if there is still an entry for those triangle coordinates in the table. If not then the resources in the triangle have already been regenerated and there is nothing more for the resource manager to do about it. If they are, the resource manager checks whether regenerating there at this time is still the right thing to do. If not the record has been updated in the meantime with a later regeneration time and the resource manager needs not do anything in this call, because a new call was scheduled when the record was updated. If the record still indicates that it is time to regenerate, the resource manager increments the resource amount of the triangle. If this causes the amount to reach the initial amount, the resource manager is done with the regeneration of the triangle and removes the record from the table. Since the amount changed, the resource manager now has to invoke the update method on itself.
Migration
Migration is when a unit of resource moves from one location to another. The migration rate is considered proportional to the amount. This means that when the program has executed a migration, it calculates the time when the next migration will occur. The higher the amount, the sooner it will occur. There are different migration mechanisms.
Seed migrations
The seed migration mechanism is modeled after plant seeds that are carried by the wind or animals. A seed migration event will not reduce the amount at the source location, because it is only the seed that migrates, not the plant itself. The seed has no influence on where it ends up. The probability of travelling a certain distance is inversely proportional to the distance, so the probability of ending up at a certain target location is inversely proportional to the square of the location's distance to the source location. If the seed ends up at a location with matching resource type and remaining capacity, it starts to grow there (the amount is incremented). Otherwise it dies. The the target location may be the same as the source location. Therefore seed migration is also a form of regeneration.
Animal migration
The animal migration mechanism is is modeled after animal individuals that walk, swim or fly. An animal migration event will reduce the amount at the source location, because the animal individual moves away from there. Animals move from one triangle to an adjacent triangle. Each animal type has a maximum migration distance. It moves from triangle to triangle until it finds one with matching resource type and remaining capacity. Then it stops there (and the amount there is incremented). If it has moved its maximum migration distance without finding a location to settle down, it dies. When locations are triangles, each location has 3 adjacent locations. The animal first moves to one of them randomly. If it has to move further, it moves to an adjacent location, but not the one it came from (it has some memory), so there are only 2 locations to chose from in subsequent steps.
There is a difference between walking and walking and swimming animals on one hand and flying animals on the other. Walking/swimming animals will never move to a location with an incompatible terrain type. (For example fish will not swim up on land and marmots will not move across oceans or lava fields.) But flying animals will move regardless of terrain type.
Choosing constants
There are 2 numeric constants, the regeneration duration constant and the migration duration constant, and some boolean constants that affect the natural dynamics. They have to be chosen carefully by the game designer to get a suitable equilibrium. A spreadsheet can be used to try out how a set of constant values affect the regeneration and migration times for each combination of capacity and amount.