Page 1 of 14

Various NML related questions

Posted: 27 Mar 2015 11:10
by 3iff
When defining an industry (a farm in this case), there's a line for setting production when the industry is built.

prod_multiplier: [7, 5]; // (Grain and Plant Fibres - from FIRS)

Grain is set for 7 per 256 ticks, Plant Fibres at 5 per 256 ticks...subject to the industry production rating.

Is there any way to randomise the 7 and 5 so that it might be possible for grain to be (say) range 5-9 and plant fibres range 5-9 so that there's the opportunity for plant fibres to be produced at a higher level than grain at some farms?

The desire is to have industries with varied production levels. I can get different production levels at game start but here I have the problem that grain production is always higher than plant fibres at all farms, there's always a fixed relationship between the cargos. I want more variation.

Is it possible?

Re: Randomising prod_multiplier values

Posted: 27 Mar 2015 17:45
by frosch
Yes, but it is requires a bit more than a single line.

Using the production callback you can modify all aspects of production:
* Disable the default production mechanics: prod_multiplier: [0,0]
* Enable automatic handling of production changes: spec_flags: IND_FLAG_AUTOMATIC_PRODUCTION_MULTIPLIER
* Enable custom production: callback produce_256_ticks -> produce(..., 0, 0, 0, 4 + (random_bits & 7), 4 + ((random_bits >> 3) & 7)

Note that using custom production mechanics disables the "smooth economy" setting of OpenTTD. If you also want finer random production changes, you need to add a monthly_prod_change callback with the CB_RESULT_IND_PROD_SET_BY_0x100 result, and some magic computation from the random bits and the previous production multiplier.

Re: Randomising prod_multiplier values

Posted: 30 Mar 2015 07:17
by 3iff
Thanks for that. It looks complicated but I'll have a play around. I may be back with more questions later.

I'm building my own version of Firs with a lot of changes (including no in-game industry production variations) so I should be able to get something I'm happy with if I can make this work. It's pretty much at the edge of my capabilities at the moment but I'm gradually getting better.

What exactly does ((random_bits >> 3) & 7) mean? I'm guessing & 7 means the last three bits? Not sure what the >> 3 is.

Re: Randomising prod_multiplier values

Posted: 30 Mar 2015 08:20
by PikkaBird
3iff wrote:What exactly does ((random_bits >> 3) & 7) mean? I'm guessing & 7 means the last three bits? Not sure what the >> 3 is.
">> 3" shifts 3 bits, so while "& 7" reads the value of bits 0-2, ">> 3 & 7" reads bits 3-5.

Re: Randomising prod_multiplier values

Posted: 30 Mar 2015 10:04
by 3iff
Thanks, it makes more sense now. I've seen that in various places but never knew what it meant.

I now have something that works exactly as I wish. I'm going to have to play around with numbers to get the output value ranges I'm looking for but I will soon be spreading this to other 'produce only' industries where there are 2 cargo products.

------

I've managed to amend the grf with the changes you suggested. I did find that adding

spec_flags: bitmask(IND_FLAG_AUTOMATIC_PRODUCTION_MULTIPLIER);

caused some bizarre values for my sheep farm and dairy farm (some 4-10 times the intended amounts) so I removed the spec_flag change and everything now seems fine. I wasn't sure if the bitmask() part was required but I added it as all other spec_flag entries had it.

I shall be playing around with values but it's very close to what I wanted. I'll be doing some proper testing when I get a chance.

Re: Randomising prod_multiplier values

Posted: 30 Mar 2015 17:58
by frosch
Without that flags, production will never change.

Re: Randomising prod_multiplier values

Posted: 01 Apr 2015 07:15
by 3iff
frosch wrote:Without that flags, production will never change.
That's fine, because I don't want it to change.

I've managed to do a bit of in-game testing and it's all working as I want it to, so I'm very happy.

Re: Randomising prod_multiplier values

Posted: 25 Jun 2015 14:32
by 3iff
Probably not related but I might as well keep my questions in the same place.

Forest production is all over the place. This is in standard OTTD (nightly 27238), no grfs loaded.

I know there are either 8 or 9 production cycles per month and for coal mines (for example) they exhibit that behaviour. Productions oscillate from 176-198 or 160-180 or 56-63, just as expected.

Forests don't do that. I'm getting 35-72, 72-108, 66-99 and 90-135. I can't spot any reason why they do that. Forest production hasn't changed in that period.

They behave exactly the same way when I use my own industry set or FIRS, but as it's in the default game then it's not my grf causing the problem.

Anyone have any idea what's going on?

Re: Randomising prod_multiplier values

Posted: 25 Jun 2015 20:06
by frosch
That is caused by the "min_cargo_distr" property (Minimal amount of cargo before transporting to stations).

For most of the default industries it is "5". For forests, candyfloss forest and battery farm it is 30. For fruit and rubber plantation it is 15. For the temperate bank it is 2.

Re: Randomising prod_multiplier values

Posted: 26 Jun 2015 06:59
by 3iff
Thanks,

I'll set/change that value and see what happens.
-----------------
Yes, that's it.

Re: Randomising prod_multiplier values

Posted: 30 Jun 2015 13:41
by 3iff
Another problem...

I have an industry that has a fixed output (LVST) and a random output (FICR or GRAI).

Currently, these are set via: prod_cargo_types: [LVST,FICR]; but FICR might be GRAI instead (or possibly others). At the moment this is hardcoded and it causes problems elsewhere. Nothing game breaking but the info isn't correctly provided to the minimap.

I can set the cargo_output values to LVST and the random cargo but I need a way to load the random cargo into... prod_cargo_types: [LVST,FICR]; or prod_cargo_types: [LVST,GRAI];

I can't figure out a way to do it - if it can be done. Any ideas?

Re: Randomising prod_multiplier values

Posted: 30 Jun 2015 13:47
by planetmaker
3iff wrote:Another problem...

I have an industry that has a fixed output (LVST) and a random output (FICR or GRAI).

Currently, these are set via: prod_cargo_types: [LVST,FICR]; but FICR might be GRAI instead (or possibly others). At the moment this is hardcoded and it causes problems elsewhere. Nothing game breaking but the info isn't correctly provided to the minimap.

I can set the cargo_output values to LVST and the random cargo but I need a way to load the random cargo into... prod_cargo_types: [LVST,FICR]; or prod_cargo_types: [LVST,GRAI];

I can't figure out a way to do it - if it can be done. Any ideas?
When you change the produced cargo types of an industry at runtime, then the game has no chance to figure that out. All information provided on the minimap for cargo support and for the industry chain view which deviate from the industry's defaults will be wrong as they rely on the default property values you provide in the NewGRF instead of the values as changed by callbacks.

(Or was it something else you were asking? Then please re-phrase :) )

Re: Randomising prod_multiplier values

Posted: 30 Jun 2015 13:58
by 3iff
No, that's what I was asking. (I think).

It's what I thought as I'm doing something 'unexpected'. The only logical way around it is to have real alternative industries rather than randomise existing industries.

I'll have to rethink how I do this... I'm slowly getting a handle on how all this fits together, it's a slow process. :(

Thanks.

Re: Randomising prod_multiplier values

Posted: 30 Jun 2015 15:09
by planetmaker
3iff wrote:It's what I thought as I'm doing something 'unexpected'. The only logical way around it is to have real alternative industries rather than randomise existing industries.
Yes indeed. But as you can (meanwhile in trunk) have 128 different industries in your NewGRF, that probably is not a big issue (you could mostly duplicate the code except for cargo and some other minor details)

http://hg.openttd.org/trunk.hg/rev/3fc58450901b

Re: Randomising prod_multiplier values

Posted: 30 Jun 2015 15:26
by 3iff
Yes, that's a possibility. I haven't yet tried the later nightlies (... but soon).

I've removed the randomising for now and will look to expanding the industry set, maybe. It's easy enough to do but I'm wary of adding new things that aren't actually needed. I don't want it to become too complex.

Thanks again for the advice.

Re: Randomising prod_multiplier values

Posted: 09 Jul 2015 10:07
by 3iff
Another question.

(LOAD_PERM(1) > SOMEVALUE ? 1 : 0)

Does this mean if the value of LOAD_PERM(1) is greater than SOMEVALUE then it returns 1 otherwise it returns zero?

and what is the meaning of the ? symbol. It's been puzzling me for a while.

And another one that I cannot even guess at...

(VALUE) / (1 << 21) - what does (1 << 21) mean?

Re: Randomising prod_multiplier values

Posted: 09 Jul 2015 11:12
by Alberth
3iff wrote:Another question.
Actually, it's three questions, but never mind :)
3iff wrote:(LOAD_PERM(1) > SOMEVALUE ? 1 : 0)

Does this mean if the value of LOAD_PERM(1) is greater than SOMEVALUE then it returns 1 otherwise it returns zero?
That is what it means.
3iff wrote:and what is the meaning of the ? symbol. It's been puzzling me for a while.
It's the ternary ?: operator. Its form is "<cond> ? <true-val> : <false-val>" which is similar to "if <cond> then return <true-val> else return <false-val> end", except the ?: form is an expression and not a statement, thus ((x > 1) : 1 : 2) + y works.
The ternary operator comes from C/C++.
3iff wrote:And another one that I cannot even guess at...

(VALUE) / (1 << 21) - what does (1 << 21) mean?
The << means 'shift to the left', (there is also >>, which means 'shift to the right). In the binary system, shifting is logical (see below). In the decimal system that we normally use, "x << 1" is equal to "x * 2", x << 2 = (x << 1) << 1, so 1 << 21 thus means 1 * 2 * 2 * ... * 2 (=1 * 2^21 = 2097152).

The more sane explanation is if you don't use the decimal system, but switch to binary numbers instead. Decimal value 1 in the binary system is 1 or 00000000000000000000000000000001 for a 32 bit number (just as with the decimal system, adding prefix zeroes is allowed, 5 == 0000005).
In the binary system "shifting" means literally shifting.
1 = 1 << 0 = 00000000000000000000000000000001, 1 << 1 = 00000000000000000000000000000010, 1 << 2 = 00000000000000000000000000000100, etc. The '1' shifts to the left each time.
1 << 21 is thus 00000000001000000000000000000000.
An this is what it is used for normally. It allows for very compact notation of bit patterns, especially when you use hexadecimal numbers (since four 0/1 bits become a single digit then). It takes some getting used to however.

While 'shifting' may be a new term for you, the concept itself also exists in the decimal system, it is known as 'exponent'. we write 2000 as 2e03 or 2e3 (= 2*10^3).

Re: Various NML related questions

Posted: 09 Jul 2015 11:47
by 3iff
Thanks, and I'm almost sorry I asked! I'll have to try and read that a few times to understand it. Coding in binary is something I haven't really done. It's a bit of a culture shock.

So, (1 << 21) is a clever way of saying ~2 million

I'm reading some of the nml code in other grfs and I have an eye on including some of it in my code, but most of it is a case of trial and error as a lot of it is currently beyond my comprehension. Some of my code is quite long winded at the moment (but it mostly works and that's what counts).

I should have asked this in the general NML thread. I'll do that next time.

Your patience is appreciated. :wink:

Re: Various NML related questions

Posted: 09 Jul 2015 12:44
by Eddi
3iff wrote:So, (1 << 21) is a clever way of saying ~2 million
while that is technically true, it's usually not used that way. it's usually meant in the more literal "i want bit 21 set to 1, and all other bits set to 0", the decimal value of such a construct is usually not interesting for anybody.

Re: Various NML related questions

Posted: 09 Jul 2015 12:53
by 3iff
I see. In the example I was looking at, (setting a price_factor) a very large number is generated (using decimal numbers) then it needs to be divided by something around 2 million. There didn't seem to be any particular reason to just set bit 21 to do the division.

I do know about bit manipulation but I almost never use it (so far).