## FIRS cargo payment calculation

OpenTTD is a fully open-sourced reimplementation of TTD, written in C++, boasting improved gameplay and many new features.

Moderator: OpenTTD Developers

drsh1
Engineer Posts: 7
Joined: 04 Mar 2019 12:10

### FIRS cargo payment calculation

Hi, can someone give me some insight on how the cargo payment in FIRS new grf is calculated?

I got this process worked out in vanilla open ttd, using this formula and cargo parameters (https://wiki.openttd.org/Cargo_income)

for example:
Passengers: base=3185, c1 days=0, c2 days=24

therefore payment: 3185 (base) * 200 (passengers) * 100 (tiles) * 229 (time factor) / 2^21 = 6,955.77 GBP

from my observations in-game, it is correct

As for FIRS, I found out there's some different approach used, the payment parameters don't look like in base version at all (eg for price_factor='109' for ACID in https://hg.openttdcoop.org/firs/files/9 ... src/cargos)

I know the document says price_factor='109' is for 10 units of cargo across 20 tiles

Still, no matter how I try to tackle the problem I can't get those numbers right

Can someone enlighten me?

Thanks!

Eddi
Tycoon Posts: 7424
Joined: 17 Jan 2007 00:14

### Re: FIRS cargo payment calculation

income calculation for NewGRF cargos can be found here: https://newgrf-specs.tt-wiki.net/wiki/A ... 11.2C12.29
You might not exactly be interested in Ferion, but if you are, have fun drsh1
Engineer Posts: 7
Joined: 04 Mar 2019 12:10

### Re: FIRS cargo payment calculation

Still, the numbers don't match, using this formula:
income=((((distance/2) * timefactor * amount_moved) >> 7) * cargopricefactor) >> 13

continuing previous example, in FIRS we have:
Passengers: pricefactor=105, c1 days=0, c2 days=22

therefore payment:
step 1) 50 (distance in tiles/2) * 227 (timefactor) * 100 (passengers) = 1,135,000.00
step 2) shift right 1,135,000.00 by 7 bits => 8867 (i'm using excel BITRSHIFT and checked with some online bit calculator)
step 3) 8867 * 105 (cargo price factor) = 931,035.00
step 4) shift right 931,035.00 by 13 bits => 113.00 GBP profit per 1 trip

that's way too low

where's the catch?

Eddi
Tycoon Posts: 7424
Joined: 17 Jan 2007 00:14

### Re: FIRS cargo payment calculation

have you considered the conversion from game days (74 ticks) to cargo age units (185 ticks, can be changed by some vehicles)? if you're transporting for 25 game days, the cargo only aged 10 times, not 25 times.
You might not exactly be interested in Ferion, but if you are, have fun drsh1
Engineer Posts: 7
Joined: 04 Mar 2019 12:10

### Re: FIRS cargo payment calculation

no, but that's not it

that only means cargo payments function counts game days in "2.5 day" batches => if your cargo travelled exactly 16 game days, you'd get a payment for 17.5 days (2.5x7 batches) - that's how I understand it at least and it made sense with vanilla game calculations

here, in firs, the error is more of a factor of 100x than 2x

Eddi
Tycoon Posts: 7424
Joined: 17 Jan 2007 00:14

### Re: FIRS cargo payment calculation

drsh1 wrote:if your cargo travelled exactly 16 game days, you'd get a payment for 17.5 days (2.5x7 batches) - that's how I understand it at least
no, that's not how that works. if the cargo was loaded 16 days ago, then "days_in_transit" in all the relevant formulas will be 6
here, in firs, the error is more of a factor of 100x than 2x
it could be that firs hides some factor elsewhere in its code... have you tried other industry GRFs?
You might not exactly be interested in Ferion, but if you are, have fun drsh1
Engineer Posts: 7
Joined: 04 Mar 2019 12:10

### Re: FIRS cargo payment calculation

Eddi wrote:no, that's not how that works. if the cargo was loaded 16 days ago, then "days_in_transit" in all the relevant formulas will be 6
But it only applies to new grfs then? I'm sure I got numbers for vanilla game right and this wasn't the case there.

Plus, I investigated the cargo payment graphs ingame and it seems you're right - the graphs are shifted. By default, the graph should be a downward trending line with turning points in "day1" and "day2" value where slope becomes steeper. With FIRS active, it looks like the turning points are in values for "day1", "day2" x2.5 than in documentation (eg for wood day1=about 60 when it should be 24)

As for the calculation, I run through code and found a formula that makes even less sense for me:

Code: Select all

``````
Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type)
{

/* non-important */
const CargoSpec *cs = CargoSpec::Get(cargo_type);
if (!cs->IsValid()) {
/* User changed newgrfs and some vehicle still carries some cargo which is no longer available. */
return 0;
}

/* Use callback to calculate cargo profit, if available */
/* starts here */

/* bitwise sum of distance, amount moved, transit days */
uint32 var18 = min(dist, 0xFFFF) | (min(num_pieces, 0xFF) << 16) | (transit_days << 24);

/* CBID_CARGO_PROFIT_CALC = 0x39 = 57 */
uint16 callback = GetCargoCallback(CBID_CARGO_PROFIT_CALC, 0, var18, cs);

/* apply GB function to "callback" */
/* GB can be found https://github.com/OpenTTD/OpenTTD/blob/18ca3e8660f90737d672b6780301ff4b998df56f/src/core/bitmath_func.hpp */
/* GB (x, s, n) = (x << s) & ( 1U << n) - 1) where 1U << 1 = 1 = 00000001, 1U << 2 = 2 = 00000010 etc * /

if (callback != CALLBACK_FAILED) {
int result = GB(callback, 0, 14);

/* Simulate a 15 bit signed value */
/* if "callback" is max value for 14bits, lower it by 1, result = 16384-1 = 16383; this is max "result" */
if (HasBit(callback, 14)) result -= 0x4000;

/* "The result should be a signed multiplier that gets multiplied
* by the amount of cargo moved and the price factor, then gets
* divided by 8192." */
return result * num_pieces * cs->current_payment / 8192;
}
}
``````
I'm not really skilled in C++ so I may be making some mistakes here, I can elaborate if someone's willing to check me up with this

Alberth
OpenTTD Developer Posts: 4754
Joined: 09 Sep 2007 05:03
Location: home

### Re: FIRS cargo payment calculation

That code just implements a call to https://newgrf-specs.tt-wiki.net/wiki/C ... s_.2839.29 Stuff gets encoded in a single variable with some shifting and capping at the upper limit, and the result gets decoded again for the signed 14 bit number, which looks a bit weird, since C/C++ doesn't have native 14 bit numbers.

Otherwise, it just does what the description of the call says.
Being a retired OpenTTD developer does not mean I know what I am doing.

andythenorth
Tycoon Posts: 5096
Joined: 31 Mar 2007 14:23
Location: Lost in Music

### Re: FIRS cargo payment calculation

I think you've got CB 39 there https://newgrf-specs.tt-wiki.net/wiki/C ... s_.2839.29

AFAIK, FIRS doesn't use CB 39.

I am watching this with interest. I've got no useful information to add, but I'm not convinced that FIRS cargo payments are working as I want them to. They were set a long time ago, and there's been no attention to them since then.

drsh1
Engineer Posts: 7
Joined: 04 Mar 2019 12:10

### Re: FIRS cargo payment calculation

thanks for feedback guys later I'll try to convert the code to somewhat more user-friendly math formulas and I'll show you why the "callback approach" makes no sense to me

drsh1
Engineer Posts: 7
Joined: 04 Mar 2019 12:10

### Re: FIRS cargo payment calculation

ok guys I think I got this

actually, the whole thing is astonishingly simple. the correct formula is:

CARGO PRICE from the in-game graph /200 * AMOUNT * DISTANCE

where CARGO PRICE is calculated followingly:

FIRS pricefactor * timefactor scaled with 2,5days correction

^ FIRS pricefactor is price_factor value from https://hg.openttdcoop.org/firs/files/9 ... src/cargos. has to be divided by 200 because it's a payment for transporting 10t across 20 tiles
^ timefactor is calculated in exactly the same way as in base game (or in the code chunk above) ONLY the in-game days used for calculation must be divided by 2.5 (new grfs feature?)

example:

^ effective days are 54/2.5 = 21.6 -> 22 (i'm not sure how the game handles rounding - I use mathematical rounding)
^ .. so the timefactor for 22 days is 255-(22-0)-(22-0-16)= 227
^ CARGO PRICE would be 145 (price_factor) * 227 (timefactor) / 255 = 129,08 GBP => this is the approximate payment rate you can read from in-game graph for transporting MILK within 22 days
^ 129.08 / 200 (10t across 20 tiles) * 360 (amount) * 131 (distance) = 30,437.06 GBP which is very close to real game payment

now, what part of code does this - I have no idea Eddi
Tycoon Posts: 7424
Joined: 17 Jan 2007 00:14

### Re: FIRS cargo payment calculation

drsh1 wrote:(i'm not sure how the game handles rounding - I use mathematical rounding)
for the travel time, this is always rounded down, as it is a counter that is increased by 1 in a regular interval. if the interval hasn't expired, there will be no counting up
You might not exactly be interested in Ferion, but if you are, have fun ### Who is online

Users browsing this forum: No registered users and 2 guests