Transport Tycoon Forums

The place to talk about Transport Tycoon
It is currently Thu Mar 21, 2019 8:43 am

All times are UTC




Post new topic  Reply to topic  [ 12 posts ] 
Author Message
PostPosted: Mon Mar 04, 2019 12:29 pm 
Offline
Engineer
Engineer

Joined: Mon Mar 04, 2019 12:10 pm
Posts: 7
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

you transfer 200 passengers across 100 tiles in 25 days (with loading/unloading) => 25>c1+c2, so time factor would be 255-2*(25-0)+24 = 229
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!


Top
   
PostPosted: Mon Mar 04, 2019 2:53 pm 
Offline
Tycoon
Tycoon

Joined: Wed Jan 17, 2007 12:14 am
Posts: 7300
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 :)


Top
   
PostPosted: Tue Mar 05, 2019 3:15 pm 
Offline
Engineer
Engineer

Joined: Mon Mar 04, 2019 12:10 pm
Posts: 7
Hi, thanks a lot for the link that's immensely helpful

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

you transfer 200 passengers across 100 tiles in 25 days (with loading/unloading) => 25>c1+c2, so time factor would be 255-(25-0)-(25-22-0)=227

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?


Top
   
PostPosted: Wed Mar 06, 2019 10:04 am 
Offline
Tycoon
Tycoon

Joined: Wed Jan 17, 2007 12:14 am
Posts: 7300
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 :)


Top
   
PostPosted: Wed Mar 06, 2019 1:36 pm 
Offline
Engineer
Engineer

Joined: Mon Mar 04, 2019 12:10 pm
Posts: 7
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


Top
   
PostPosted: Wed Mar 06, 2019 6:55 pm 
Offline
Tycoon
Tycoon

Joined: Wed Jan 17, 2007 12:14 am
Posts: 7300
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

Quote:
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 :)


Top
   
PostPosted: Fri Mar 08, 2019 1:12 pm 
Offline
Engineer
Engineer

Joined: Mon Mar 04, 2019 12:10 pm
Posts: 7
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:

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 */
   if (HasBit(cs->callback_mask, CBM_CARGO_PROFIT_CALC)) {
      
      /* 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


Top
   
PostPosted: Fri Mar 08, 2019 1:31 pm 
Offline
OpenTTD Developer
OpenTTD Developer

Joined: Sun Sep 09, 2007 5:03 am
Posts: 4694
Location: home
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 OpenTTD developer does not mean I know what I am doing.
Also, other OpenTTD developers may have different opinions.


Top
   
PostPosted: Fri Mar 08, 2019 1:36 pm 
Offline
Tycoon
Tycoon
User avatar

Joined: Sat Mar 31, 2007 2:23 pm
Posts: 4806
Location: Lost in Music
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.

_________________
FIRS Industry Replacement Set (Released) | HEQS Heavy Equipment Set (trucks, industrial trams and more) (Finished)
Squid Ate FISH (ships) (Released) | CHIPS Has Improved Players' Stations (Finished)
Iron Horse (trains, released) | Termite (tracks for Iron Horse, released) | Busy Bee (game script, released)

Road Hog (road vehicles, released)


Top
   
PostPosted: Fri Mar 08, 2019 3:42 pm 
Offline
Engineer
Engineer

Joined: Mon Mar 04, 2019 12:10 pm
Posts: 7
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


Top
   
PostPosted: Tue Mar 12, 2019 4:44 pm 
Offline
Engineer
Engineer

Joined: Mon Mar 04, 2019 12:10 pm
Posts: 7
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:
we transport 360,000 L of MILK (price_factor = 145, days1= 0, days2 = 16) across 131 tiles within 54 days (with loading/unloading)

^ 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 :)


Top
   
PostPosted: Thu Mar 14, 2019 2:20 pm 
Offline
Tycoon
Tycoon

Joined: Wed Jan 17, 2007 12:14 am
Posts: 7300
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 :)


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 12 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000-2019 phpBB Limited

Copyright © Owen Rudge/The Transport Tycoon Forums 2001-2019.
Hosted by Zernebok Hosting.