1. I suggest separate demand counters (and switch), for each input good.
That is what I did? Each input and output has a demand counter and each input uses their demand counter separately. The reason outputs also have one that is never used or visible is because of poor design decisions (inputs and outputs should extend a production parent type, instead they share members for both of which some are never used).
- if the factory is producing and input is not over limit - increment by amount consumed
A special case is needed on the tick that consumes the last of the product in storage. This was not modelled as the current factory tick system is rather poorly structured.
- if the factory is producing and input is over limit - increment by 50% of consumed amount (+1 I really like this - thats big improvement comapared to my original proposal)
Percentage is adjustable. The only problem is no mater what you do it will still run at at-least 50% efficiency. It would be nice if people really messed up that it could reach lower percentages maybe (a hard mode?). However for such a loose definition as Simutrans industry this is the best one can do.
- if the factory is not producing and input is empty - increment by possibly consumed amount (with or without power/pax/mail boost)
The one I made goes through extensive effort to make sure to order the correct amount. This is especially problematic with power as if the factory has a transformer and is not actually producing anything you have to assume that it has sufficient power and order as if it did.
- if the factory is not producing and input is not empty - do not increment (this means that factory cannot produce because its consumers are overcrowded, or that it does not have all needed input goods available)
Not as easy as it may sound. Factories will keep producing even without a supplier at a diminishing rate until their output storage is full. Also you still need to order all goods that are consumed in equal ratios unless an overflow is applied. I also implemented this to some extent with the first rule, ordering as consumed, and a special refund case where if the order amount is too large it will scale back the other (under supplied situation).
3. further improvements could be made in the algorithm when produced goods get their destination. The current behavior is that the goods go to the factory that has the least cargo waiting on the station. I recoomend sending it to the one with highest demand buffer.
It currently chooses them in a round robin fashion out of all the destinations accepting orders. Orders are accepted for the entire duration of a tick to assure fairness (all suppliers given a chance to fulfil order) There is a bias towards some factories as a result of internal order and just how the numbers play out however it should make little difference except under extreme circumstances (there exists a good destination allocation pattern such that all consumers have their orders fulfilled yet this algorithm does not find it).
4. Demand buffer should be initalized at its max value, equal to max input storage. I think it is sensible for real world factory to begin by ordering full storage...
Initialization does need improvement. I just choose 0 as it is a clean value to test with. The buffer also needs to be saved and loaded.
===> CXX simfab.cc
g++ -O3 -minline-all-stringops -DNDEBUG -DREVISION="7287M" -Wall -W -Wcast-qual -Wpointer-arith -Wcast-align -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT -DCOLOUR_DEPTH=16 -c -MMD -o build/default/simfab.o simfab.cc
simfab.cc: In function 'sint64 convert_goods(sint64)':
simfab.cc:65:95: warning: suggest parentheses around '-' inside '<<' [-Wparentheses]
simfab.cc: In member function 'void fabrik_t::step(uint32)':
simfab.cc:1393:77: warning: suggest parentheses around '-' in operand of '&' [-Wparentheses]
G++ pedantic errors. The code is valid and takes full advantage of the operator precedence of C++ (as defined by the standard) however G++ thinks it needs bracers as it could be I am an idiot and did not read operator precedence so is not executing in the intended order. Visual C++ compiler I used to write the code did not throw this warning which is why I never fixed it. I did not build with G++ so was not aware of it.
And I would like to try your patches. Where are they. The Simutrans JIT2.zip I cannot download, my provider tells me this is malware ... Please is there a zip with only the patch?
I have no idea how to generate a patch with the git system. I kind of downloaded the source code and hacked away on 2 files which I included in the zip. Unless dropbox somehow infected the zip it should not contain malware (your ISP probably is thinking that the 2 windows executables included are malware which is sad). Anyway I have no idea why I did not think to attach the code files directly here in the first place (it was only these two code files, which appear to be located in the root folder of the project).
In my opinion the entire industry tick function needs to be rewritten. There are too much hacky calculations applied everywhere that it is hard to get a proper industry production and consumption model working.
Of specific note is with factories that produce many output products the amount of raw material consumed is based on the most produced output and not the actual amount produced (especially case if one output is full). Also the outputs are all tied synchronously to the most produced output and do not scale production down in parallel as storage fills up (having a oil refinery using 100% gasoline and barely touching printer ink will result in the printer ink being restored at full production rate despite the output storage never getting near empty). In any case the result is that more product is consumed than is produced which usually means free money (more raw product to ship at a profit).
Same example, Oil Refinery with Gasoline used 100% and Printer Ink used 0-1% (hardly at all).
What is happening now is that it will be consuming oil at its full declared production rate. This is the same amount as if it was producing only Gasoline at 100% and if it was also producing Printer Ink at 100%.
What should happen is that it consumes oil at a reduced rate. This is because only part of the output is working at full power (lost production) so it consumes less.
There are many ways this could be implemented. Simplest is averaging production across all outputs (above example this would give 50% production) however some pak balancers may want different ratios (Printer Ink may use 2 times as much oil to produce as Gasoline so affects consumption rate more).
This is also the case with power where an industry will either use all or nothing. Power used should be based on the amount of work a factory does. This would make power grids a lot more stable as everything will settle to a largely stable base load which more accurately reflect a power fraction (out of maximum power demand).
There needs to be certain quantities defined.
Maximum Production: The absolute maximum amount of effort the factory can output. This is based on things like base production, pax, mail and power fulfilment.
Desired production: The amount of productive effort that is desired based on maximum production. This factors in production scaling down for each output with appropriate weightings and determines the amount to order (base order rate is always at the desired production rate scaled for the various inputs).
Actual production: The amount of production effort actually produced as a fraction of desired production. This is used with scaling and maximum production to determine the amount of product produced.
Maximum production factors in how much of the power demand was fulfilled. Actual production is used to scale power order for the next tick (so it uses only as much power as production done to get full power boost). Power plants need to work differently where their desired production is scaled based on the amount of power consumed (
? not possible ATM) and actual production is overwritten when storage runs empty to represent the amount of power produced from the remaining resources otherwise it is always 1. This would change game dynamics a lot (for the better?) as you can no longer simply supply power stations and expect them to generate electricity for nobody. Although they always appear to generate maximum power when working they will only consume based on what is used so they will reach 100% use when overloaded. Such a change as this fits quite well with the entire flow mechanics idea and JIT systems and even turns power into an industry chain (you need power consumers for power to work).
There should also be different industry flags for pakset authors to change how industries behave.
Synchronous Consumer: This is basically the current factory model, all inputs are consumed synchronously with all stopping if any storage runs empty.
Asynchronous Consumer: This is basically the current end consumers, all inputs are consumed asynchronously in parallel with overall production being lowered if at least one is empty (but not stopped).
Synchronous Producer: Like with the consumer, it is forced to produce synchronously. Factories kind of do this already but there would be stricter limits with a bottleneck occurring if output storage of 1 product is full.
Asynchronous Producer: Basically it fills the output storages as required with maximum production obtained when all outputs are empty all the time.
Power station: Produces power as described above. As long as it is working it will output maximum power but consumption is limited to how much power was used.
So what would these lose flags allow?
Something silly like a hamburger joint might have separate inputs for buns and patties yet require they are ordered synchronously as they cannot server a burger without both. This is currently not possible as the outlet would work at 50% production if 1 of the goods was lacking completely.
Something like a nuclear powerstation could be made to be a Synchronous Producer and Power Plant, meaning that you have to remove the atomic waste from it before it can generate more power.
The overall idea is to generalise behaviour away from hard coded implementations into mix and match flags/attributes you can assign an industry. You could even define other kinds of flags such as...
Shared Demand: All inputs share a common demand (scaled appropriately).
Interchangeable Input: Each input alone can now run the factory at full production if sufficiently supplied (intended with shared demand for a factory which can use 1 of many raw materials to make a product). If not shared demand present then it would order based on least demand.
Such flags would be a great extension but not directly needed for a production revision.