Improved smooth_economy patch

Forum for technical discussions regarding development. If you have a general suggestion, problem or comment, please use one of the other forums.

Moderator: OpenTTD Developers

Post Reply
User avatar
SirkoZ
Tycoon
Tycoon
Posts: 1518
Joined: 06 Mar 2004 23:51
Location: The sunny side of Alps

Improved smooth_economy patch

Post by SirkoZ »

Greetings!

Looks like everyone is asleep on IRC, so I'll post it here. :)
I have tested quite some time different implementations of smooth industries and I made one, that really works nicely.
Industry nicely responds to demand and increases production if there is large demand on the station (high station ratings),
or decreases it actively (very shortly), if demand (station ratings) drop, so there is very little "wasted" goods waiting on the station.
I think, that this behaviour of industries would go very nicely together with very large systems (with path-based signalling).

It would be also nice if it could get included into the trunk.

If you want an .exe, say so - here is the change in industry_cmd.c:
(Line 1688 of the latest "trunk" - I think 2221. Line 1700 and beyond stays the same.)

INSTEAD OF THIS (original):

Code: Select all

default: /* INDUSTRY_PRODUCTION */
			for (j = 0; j < 2 && i->produced_cargo[j] != 255; j++){
				uint32 r = Random();
				int old, new, percent;
				int mag;

				new = old = i->production_rate[j];
				if (CHANCE16I(20, 1024, r))
					new -= ((RandomRange(50) + 10) * old) >> 8;
				if (CHANCE16I(20 + (i->pct_transported[j] * 20 >> 8), 1024, r >> 16))
					new += ((RandomRange(50) + 10) * old) >> 8;
THIS (my - now v2.8_NS - main part):

Code: Select all

default: /* INDUSTRY_PRODUCTION */
			for (j = 0; j < 2 && i->produced_cargo[j] != CT_INVALID; j++){
				uint32 r = Random();
				int old, new, percent;
				int mag;
				int influence = (i->pct_transported[j] > 153) ? _patches.prod_changes : -(_patches.prod_changes);

				new = old = i->production_rate[j];
				
				// if more than 60% of cargo is transported, there is an up to 3% chance we increase - bigger production = lesser increase
				if (CHANCE16I((10 + influence), 500, r))
					new += (1 + (((old >> 3) * (i->pct_transported[j] + 75)) >> 8) + (old >> 4) - (old >> (5 + ((i->pct_transported[j] + 25) >> 7))) - (old >> 6) - (old >> 7));

				// if less than 60% of cargo is transported, there is an up to 3% chance we decrease - bigger production = bigger decrease
				if (CHANCE16I((10 - influence), 500, r >> 16))
					new -= (RandomRange((old >> 2) + 1) - (old >> 3) + (old >> 4) + (old >> 5) + (old >> 6) + (old >> 7));

				// make sure prod_rate doesn't exceed 255 or oil rig doesn't produce too many passengers
				new = clamp(new, 0, 255);
				if (i->type == IT_OIL_RIG && j == 1) new = clamp(new, 0, 16);
				if (i->type == IT_BANK_TEMP && _opt.landscape == LT_NORMAL) new = clamp(new, 0, 64);
				
Here are the files:
Attachments
smooth_economy_sz_v2-8_r8435_NS.patch
diff
(6.28 KiB) Downloaded 499 times
Last edited by SirkoZ on 29 Jul 2007 00:18, edited 39 times in total.
DaleStan
TTDPatch Developer
TTDPatch Developer
Posts: 10285
Joined: 18 Feb 2004 03:06
Contact:

Post by DaleStan »

You'll have better luck getting this included if you create and post a diff.

If you want it comitted, the diff should go to SourceForge, but if you want discussion, it should go here.

No EXE unless you plan on uploading the *full* source. A diff is not sufficient.
To get a good answer, ask a Smart Question. Similarly, if you want a bug fixed, write a Useful Bug Report. No TTDPatch crashlog? Then follow directions.
Projects: NFORenum (download) | PlaneSet (Website) | grfcodec (download) | grfdebug.log parser
User avatar
SirkoZ
Tycoon
Tycoon
Posts: 1518
Joined: 06 Mar 2004 23:51
Location: The sunny side of Alps

Post by SirkoZ »

All the needed info is in my above post and no diff is required. If one wishes, one can instantly copy 3 lines into the designated file, if not, then we'll have the crappy patch, like we do now! :roll:
User avatar
LKRaider
Transport Coordinator
Transport Coordinator
Posts: 360
Joined: 23 Mar 2005 04:05
Location: Brasil
Contact:

Post by LKRaider »

I made a diff against svn r2233, so it is easier to patch. It seems to work fine.
The file is attached below.
Attachments
Industries.diff
Industries diff file
(1.16 KiB) Downloaded 565 times
User avatar
Darkvater
Tycoon
Tycoon
Posts: 3053
Joined: 24 Feb 2003 18:45
Location: Hong Kong

Post by Darkvater »

1. Use Chance16I()
2. I think production should fall if you are not using the industry.
TrueLight: "Did you bother to read any of the replies, or you just pressed 'Reply' and started typing?"
<@[R-Dk]FoRbiDDeN> "HELP, this litte arrow thing keeps following my mouse, and I can't make it go away."
User avatar
SirkoZ
Tycoon
Tycoon
Posts: 1518
Joined: 06 Mar 2004 23:51
Location: The sunny side of Alps

Post by SirkoZ »

Well - I'm sorry - but - how do you - very simply - make a .diff? That subversion book is all fine and dandy, but too long to wade thorough for a non-programmer (at best beginner)/TTD fan. :))

Anyhow - Darkvater:
"1. Use CHANCE16I()"

I don't think it is needed - I will explain the behaviour.

"2. I think production should fall if you are not using the industry."

Good point - now I have improved it a bit - so the behaviour is:
- if it is used well - it will go up, if station ratings fall, production falls (through the next months)
- if the industry is not used at all (anymore), the production will fall back to value between 40 and 128 units and range between those values (=starting productions).

The improved code is here:
(LKRaider - please make the .diff, or please - kindly explain to me how to make it. :))

Code: Select all

default: /* INDUSTRY_PRODUCTION */ 
         for (j = 0; j < 2 && i->produced_cargo[j] != 255; j++){ 
            int old, new, percent; 
            int mag; 

            new = old = i->production_rate[j];                  
            if ((i->pct_transported[j] > 153) ^ CHANCE16(1,4400)) 
               new += ((RandomRange(50)+10)*old)>>8; 
            if ((i->pct_transported[j] < 153) ^ CHANCE16(1,4400)) 
               new -= ((RandomRange(50)+10)*old)>>8; 
            if ((i->pct_transported[j] == 0) ^ CHANCE16(1,4400))
               new = (RandomRange(7)+5);
(I changed/improved only the last 2 lines)
User avatar
Darkvater
Tycoon
Tycoon
Posts: 3053
Joined: 24 Feb 2003 18:45
Location: Hong Kong

Post by Darkvater »

SirkoZ wrote:"1. Use CHANCE16I()"

I don't think it is needed - I will explain the behaviour.
Still waiting... current code used Interactive random (eg, local only) and that worked, didn't cause any desyncs. Don't know if using the other random will work. But so if I don't transport any cargo production drops back to 7 - 12 ?

Create a diff:

Code: Select all

linux: 'svn diff > mypatchfile.diff'

Code: Select all

windows: install tortoisesvn, rightclick on openttd svn map, create patch
TrueLight: "Did you bother to read any of the replies, or you just pressed 'Reply' and started typing?"
<@[R-Dk]FoRbiDDeN> "HELP, this litte arrow thing keeps following my mouse, and I can't make it go away."
Nanaki13
Traffic Manager
Traffic Manager
Posts: 151
Joined: 08 Jan 2005 16:08

Post by Nanaki13 »

Is there any max value of production?
wizeman
Engineer
Engineer
Posts: 18
Joined: 28 Jun 2004 22:53
Location: Portugal
Contact:

Post by wizeman »

SirkoZ, I like your changes, just a few comments:

Code: Select all

           if ((i->pct_transported[j] == 0) ^ CHANCE16(1,4400)) 
               new = (RandomRange(7)+5);
Be careful, you're doing a xor, so that will reset production to the initial value even when the cargo is being transported, when the CHANCE16() macro returns 1..

BTW, why don't you let the production return slowly to the initial values (when the cargo is not being transported), instead of resetting it?

And also: why are you using such low chances for the unpredictability? 1 in 4400? That is so insignificant as to almost never happen..
User avatar
SirkoZ
Tycoon
Tycoon
Posts: 1518
Joined: 06 Mar 2004 23:51
Location: The sunny side of Alps

Post by SirkoZ »

Darkvater wrote:
SirkoZ wrote:"1. Use CHANCE16I()"

I don't think it is needed - I will explain the behaviour.
Still waiting... current code used Interactive random (eg, local only) and that worked, didn't cause any desyncs. Don't know if using the other random will work. But so if I don't transport any cargo production drops back to 7 - 12 ?
Well - I will try to change that to interactive random then.
If none of the cargo is transported though, the cargo drops to 8*/9* 6-12 (=54-128 units per month). TTD/OpenTTD industries give cargo to stations 8 or 9 times per month (sometimes a forest gives it 10 times) the production_rate (TTOriginal industries gave the cargo to station 12/13/14x per month (a bit longer month there...).
Darkvater wrote: Create a diff:

Code: Select all

linux: 'svn diff > mypatchfile.diff'

Code: Select all

windows: install tortoisesvn, rightclick on openttd svn map, create patch
Thank you very much. :D
User avatar
SirkoZ
Tycoon
Tycoon
Posts: 1518
Joined: 06 Mar 2004 23:51
Location: The sunny side of Alps

Post by SirkoZ »

Nanaki13 wrote:Is there any max value of production?
Max value of total production per month is max production_rate (=255) x 8 or x9 (x10 sometimes with forest) - so it is 2040 or 2295 or 2550 tonnes per month.
User avatar
SirkoZ
Tycoon
Tycoon
Posts: 1518
Joined: 06 Mar 2004 23:51
Location: The sunny side of Alps

Post by SirkoZ »

wizeman wrote:SirkoZ, I like your changes, just a few comments:

Code: Select all

           if ((i->pct_transported[j] == 0) ^ CHANCE16(1,4400)) 
               new = (RandomRange(7)+5);
Be careful, you're doing a xor, so that will reset production to the initial value even when the cargo is being transported, when the CHANCE16() macro returns 1..

BTW, why don't you let the production return slowly to the initial values (when the cargo is not being transported), instead of resetting it?

And also: why are you using such low chances for the unpredictability? 1 in 4400? That is so insignificant as to almost never happen..
Thank you for your comments - I will change them, however I have to warn you - I'm not really a programmer - more of an avid fan, so I may ask you for some help. :))
Nanaki13
Traffic Manager
Traffic Manager
Posts: 151
Joined: 08 Jan 2005 16:08

Post by Nanaki13 »

This patch doesn't cause any desynchs. Not that i noticed. (played with 2 other players for a couple of hours continuing an old game)
But before i applied it, my problem was smaller and smaller production in industries. After it i loaded my savegame, and every industry went BOOM.
from 50 to 500.
My whole network got clogged every train got up and went to the factory :)

So the problem changed from not enough to too much.
User avatar
LKRaider
Transport Coordinator
Transport Coordinator
Posts: 360
Joined: 23 Mar 2005 04:05
Location: Brasil
Contact:

Post by LKRaider »

I think production increases too fast, and with a too high upper limit.

How about inverse logarithmic (exponential) increase? Like, the higher the production goes, the smaller the production increase each time; or the longer the time between each production increase.

(something like the graphics below, if I understand correctly)

Image or Image
wizeman
Engineer
Engineer
Posts: 18
Joined: 28 Jun 2004 22:53
Location: Portugal
Contact:

Post by wizeman »

I'm using this code:

Code: Select all

			for (j = 0; j < 2 && i->produced_cargo[j] != 255; j++){
				int old, new, percent;
				int mag;
				int mult = (i->pct_transported[j] < 153) ? -1 : 1;

				new = old = i->production_rate[j];

				if (CHANCE16(1, 3))
					mult *= -1;

				if (CHANCE16(1, 50))
					new += mult * (((RandomRange(50) + 10) * old) >> 8);
The industries will eventually close if not used (but new ones will come), and most of the times (2/3rds of the times) production will increase/decrease based on cargo transported.

EDIT: It was changing productions too fast, now it only updates about 1 in 50 times (which is about the same as the before 20/1024)
User avatar
SirkoZ
Tycoon
Tycoon
Posts: 1518
Joined: 06 Mar 2004 23:51
Location: The sunny side of Alps

Post by SirkoZ »

Interesting...

I will try your code in a moment, wizeman.

The problem is, that if I put CHANCE16I in my code, it messes everything up - the production is too chance-dependent and doesn't even decrease, if station ratings go down...Maybe wizeman's solution is best - I'll test...
wizeman
Engineer
Engineer
Posts: 18
Joined: 28 Jun 2004 22:53
Location: Portugal
Contact:

Post by wizeman »

It isn't necessary to use CHANCE16I, check this:

Code: Select all

#define CHANCE16(a,b) ((uint16)Random() <= (uint16)((65536 * a) / b))
#define CHANCE16R(a,b,r) ((uint16)(r=Random()) <= (uint16)((65536 * a) / b))
#define CHANCE16I(a,b,v) ((uint16)(v) <= (uint16)((65536 * a) / b))
The only difference between CHANCE16I and CHANCE16 is that CHANCE16 calls Random() for us.
Notice the original code used CHANCE16I but it also called Random().

Besides, the old code (when smooth economy is disabled) also uses CHANCE16.
User avatar
SirkoZ
Tycoon
Tycoon
Posts: 1518
Joined: 06 Mar 2004 23:51
Location: The sunny side of Alps

Post by SirkoZ »

Yes - I know - I found it too. :)

Anyhow - the problem with your code, aswell as with previous/original smooth_economy code is, that industry barely reacts to your high station ratings - usually it just decreases to 32/40.

I realise high productions can be achieved with my upper code, but because of small room for chance (1,4400) (BTW - I got that 4400 number in a 2048x2048 map - when generated, in 1950 - it had approx. 4400 industries :))), ratings can have great effect on actual production and it turns out, that they really have it. :D
Nanaki13 - sure - you got great productions - but as soon as "% transported" in industry window falls under some 65%, it will start decreasing - I'm sure you've seen it - until the rating goes up again.

I'm staying with my above patch, because it's nicely responsive, also for a large system of trains, but most of all - SHARING. Now - that has always been a big problem on OTTD servers. Quite many times I would see industries or the whole pieces of land full of "I OWN THIS" signs, so only 1 user/client could use the industry.
Imagine it now - multiple systems on one (not even "large" (more than 256 squares)) map, all sharing industries, all happy and mostly taking care of optimisations of their systems. I think that is the biggest challenge.
I mean, sure, one could make a 12(or more)-square single station, but that is rediculuos, because they aren't really trying to play the game as a simulation. Anyway - I hope you'll agree with me and try some more this code (from above post and a bit improved).

Code: Select all

default: /* INDUSTRY_PRODUCTION */ 
         for (j = 0; j < 2 && i->produced_cargo[j] != 255; j++){ 
            int old, new, percent; 
            int mag; 

            new = old = i->production_rate[j];                  
            if ((i->pct_transported[j] > 153) ^ CHANCE16(1,4400)) 
               new += ((RandomRange(50)+10)*old)>>8; 
            if ((i->pct_transported[j] < 153) ^ CHANCE16(1,4400)) 
               new -= ((RandomRange(50)+10)*old)>>8 && new >= 6; 
            if ((i->pct_transported[j] == 0) ^ CHANCE16(1,3))
               new -= ((RandomRange(50)+10)*old)>>8 && new == (RandomRange(6)+6);
User avatar
SirkoZ
Tycoon
Tycoon
Posts: 1518
Joined: 06 Mar 2004 23:51
Location: The sunny side of Alps

Post by SirkoZ »

Here is the diff with the above change:
Attachments
sir_ind.diff
(1.33 KiB) Downloaded 532 times
User avatar
SirkoZ
Tycoon
Tycoon
Posts: 1518
Joined: 06 Mar 2004 23:51
Location: The sunny side of Alps

Post by SirkoZ »

I must have been a bit too hasty, or just sleepy. :)

Anyhow - here's the above code with Chance16I, and it works quite nicely too. The chances are the same as with wizeman's patch/OTTD previous patch:

Code: Select all

default: /* INDUSTRY_PRODUCTION */ 
         for (j = 0; j < 2 && i->produced_cargo[j] != 255; j++){ 
            uint32 r = Random();
            int old, new, percent; 
            int mag; 

            new = old = i->production_rate[j];                  
            if ((i->pct_transported[j] > 153) ^ CHANCE16I(1,50,r)) 
               new += ((RandomRange(50)+10)*old)>>8; 
            if ((i->pct_transported[j] < 153) ^ CHANCE16I(1,3,r)) 
               new -= ((RandomRange(50)+10)*old)>>8 && new >= 6; 
            if ((i->pct_transported[j] == 0) ^ CHANCE16I(1,3,r)) 
               new -= ((RandomRange(50)+10)*old)>>8 && new == (RandomRange(6)+6);
Here's the diff:
Attachments
sir_ind_i.diff
(1.37 KiB) Downloaded 489 times
Post Reply

Return to “OpenTTD Development”

Who is online

Users browsing this forum: No registered users and 44 guests