Worker deployment
Contents
Or how can worker of various professions be sent to where they are needed.
Motivation
Training up my soldiers at a trainingsite I noticed that although I don't want to make heroes the evolve as such if I don't swap the occupants of the trainingsite.
furthermore there is the now closed bug Improve handling of workers and the resulting feature request Downgrade skilled workers when possible. These show there is some real issue in the sending not just any worker to a requesting site but specific workers.
Considerations
Excerpt from the mailing list (ToDo: work out the points)
Considerations from Nicolai Hähnle:
- What is the right subsystem in which to tackle this problem?
- How can you integrate this balancing into existing systems?
- Are there other parts of Widelands that can benefit from a balance system?
Some explanations:
Step 2 would be to actually implement the balancing. The more I think about
it, the more I believe that this should be in the Economy code. The only
viable alternative would be inside building code, but I think that would be
inferior, mostly for two reasons:
-
(I) All kinds of buildings need to support and be involved in balancing, and
those buildings are not really uniform. So implementing it in buildings would
result in code - and therefore bug - duplication.
-
(II) Players will perceive the system as good if it produces a globally good
solution. A decision that seems clever from the point of view of one building
could be horrible from a global perspective. So make the decision on a global
level (or, to be more precise, on a per-Economy level, since it's not
possible to be more global than that)
Note that this doesn't prohibit support code in the buildings - in fact, such
support code will be necessary. To avoid code duplication, it could take the
form of a "WorkerArray", similar to the already existing WaresQueue. It's
just that the main routine that actually makes the decision "Okay, this
master-miner should get a replacement from warehouse X" should reside in the
transport code.
- A Building or more General a PlayerImovable sends a Request for a Worker ore a WareInstance ==> a Map_Object. A Request contains a Requirement that is list of MinMax attributes. Currently only attributes for soldiers are defined. So a Request can only a soldier of a specific 'quality' any other workers are requested by a specific Transfer object. Therefore the Transfer Object of a miner is different from the one of a chief miner.
A Transfer object is something that only exists when something is actually being transported. A typical lifetime looks
like this:
- Building creates a Request object for a ware, say a trunk.
- Economy tries to satisfy the Request, but nothing is currently available.
- Lumberjack creates a trunk WareInstance. This WareInstance creates a Supply
object describing itself.
- Economy sees the matching Supply for the Request and starts a Transfer that
attaches itself to the WareInstances.
- Now the trunk will be transported to the requesting building.
- The trunk arrives at the building. The Transfer object is destroyed, and
the building is notified (via a callback routine; usually, this detail is
handled by WaresQueue) and removes the Request, unless it needs even more
trunks.
If the Requirement would have attached a attribute minQos to indicate what the minimum requirement must be a Request for a miner with minQos 0 can be answered by a chief miner, but a Request with minQos 1 can only be answered by a chief miner or a master miner. The interpretation of the QoS (mapping of the integer value to the level of the worker) must obviously be defined by the worker itself. Currently this issue is solved as follows but perhaps can be simplified with this approach:
Actually, a plain mine just says "I want a miner". Deep in the bowels of
Supply implementations, you will find stuff like the code for
Warehouse::count_workers (which is called via WarehouseSupply::nr_supplies).
Notice the loop with get_worker_descr(ware)->becomes()? The becomes()
indicates the kind of worker that a miner becomes once he collects enough
experience - which implies that that type of worker can also be used in place
of a normal miner.
Where to implement
The whole transfer of workers (which is the main issue of this discussion) and wares (which may also profit from the idea) is handled with Widelands::Request that are satisfied with Widelands::Supply. The maching of a Supply to a request is handled by the Widelands::Economy. The whole interaction should be handled by improved Request that the economy can handle.
Where to start
So the first (after knowing how the Widelands::Request must be improved) add a branch to the Widelands::Economy::process_requests to handle the improved Widelands::Request and test for regression. Then improve the Widelands::Request. Finally implement the request handling in Widelands::Economy.
Algorithms
Balancing algorithm for requesting soldiers of the trainingsite
initialize counter with 0 and the max_counter with capacity
when the capacity is changed reset the counter.
when a soldier is updated increase the counter.
if (counter==max_counter){
initiate exchange soldier
max_counter = ciel(max_counter/2.0)
}
Common balancing algorithm
Requests can be biased either towards high-end supplies or low-end supplies. For example, one could
give each requirement axis (attributes for soldiers, becomes-hierarchy for
other workers) an integer, where 0 says "don't care as long as it matches",
positive values are biased towards the high end (high-level/high-experience)
and negative values are biased towards the low end.
Algorithm to exchange soldiers
-
(I) if the least trained soldier of the site is better trained then any on the outside: engage exchange
-
(II) if there is a soldier in the heandquaters or any of the warehouses that is not as well trained as the least trained of the site select this soldier.
-
(III) if not (II) and if there is a soldier in any militarysite that is not only occupied by himself (and not under attack... ) that is not as well trained as the least trained of the site select this soldier.
-
(IV) exchange:
-
(a) if the soldier to be exchanged is a free (case ii) one send this one to the trainingsite. When he arrives there (note that the capacity is full else the soldier would have been requested earlier), the trainingsite kicks out the best trained soldier.
- (b) if the soldier to be exchanged is not free (case iii) (part of military building X), reduce the capacity of the trainingsite by one by kicking out the best soldier. Then a request in the name of X is issued requesting a soldier with the exact specification of the kicked out soldier and a special callback function. When the soldier arrives at X it is consumed by X and the callback is called. The callback then will kick out the least trained soldier. (Note this results in a overpopulated military site as capacity+1 soldiers are present between consuming and the end of the callback.) The callback function will then initiate the increasing of the capacity of the trainingsite. This therefore will request a soldier. If the trainingsite is not set to making heroes it should always request a soldier of the least qualification.
Algorithm to send a higher qualified miner to a lower position
Example: Mine Y requests a Chief Miner
1. look if Chief Miner can be made available as free man
(see algo "Free Miner") (send off)
2. if not, look if any mine has one Chief Miner aa in a
over-qualified position.
3. if yes, send aa to mine Y and let X request a miner for
the vacant position, where X is the request fulfilling mine.