Economy.cpp, line 986 states;
Code: Select all
return BigMulS(dist * time_factor * num_pieces, cs->current_payment, 21);
Let's use the following shorthand names in the following bit of logic;
- 'dist' = d'
'time_factor' = t
'num_pieces' = n
train length in cars = c
max. cargo per car = m
We know the following statements are true:
m < 2^8 (from NewGRF spec)
c < 2^8 (127 tiles max train length from game)
d < 2^12 (technically slightly less due to a map array error, but we assume a safe number here)
t < 2^8.
8+8+12+8 = 36 > 31.
Thus, technically, in corner cases, trains can make less money than they should. To test this, you need a train with the full complement of 255 cars that have a high capacity (above 64 units per car will do the trick), going the full corner-to-corner distance on a 2Kx2K map in a very short time. To test this try making a maglev MU train with the following specs:
max. speed: 4,000 kph
power: 65535 hp per unit
capacity: 200 passengers per unit.
The total train contains 50,800 passengers. Multiply that by 4000 tiles and say 200 for the time factor we get 40640000000, or 40,64*10^9, which is about 20 times more than 2^31.
. Because the integer is signed in the multiplication, the integer overflow will do weird things.
I'm In the process of writing a patch to allow 'square' distance payments and wondering how to best deal with this. I'm thinking of using doubles for the entire calculation and converting the double to an int64. (edit: and replacing the C-style casts with static_cast as is used for all other type conversion between standard numerics) Since a double has 52 bits of mantissa there is no effect. Ideas?