Of course, expanding into truncated Taylor series is a kind of aproximation.Alberth wrote:Can't you make an approximation? People are not going to notice it's not a prefect exp function.
How large integers are in use in openttd? dwords?
Moderator: OpenTTD Developers
Of course, expanding into truncated Taylor series is a kind of aproximation.Alberth wrote:Can't you make an approximation? People are not going to notice it's not a prefect exp function.
Thank you, it bring me closer to transform my model to integers - but I must refit my model parameters (I must to refit them anyway,Eddi wrote: but wouldn't it be easier to use an exponential function based on 2^-x (aka shift-right) instead of e^-x?
Code: Select all
//replace Money GetTransportedGoodsIncome from MIN_TIME_FACTOR declaration
static const int DECAY1 = 10;
static const int DECAY2 = 40;
static const float INV_VA = 1/330;
static const int EXP2_AMPL = 80;
static const int INCOME_DIVIDER = 900;
static const int LOW_SPEED_DIVIDER = 200;
static const int LOW_SPEED_OFFSET = 50;
static const float TILE2KM = 28.66;
const float d = dist;
float transitdays = transit_days;
transitdays = 2.5*maxf(transitdays, 1.0);
const int cargo_payment = cs->current_payment;
const int days1 = cs->transit_days[0];
const int days2 = cs->transit_days[1];
const float inv_vt1 =days1/(200*TILE2KM); // reciprocal of first threshold velocity
const float inv_vt2 =days2/(200*TILE2KM); // reciprocal of second threshold velocity
const float v_avg = d*TILE2KM/(transitdays); //average transit velocity
const float inv_v_avg = 1/maxf(v_avg,0.1); //reciprocal of average transit velocity
const float max_1v_1vt1 = maxf(inv_v_avg,inv_vt1); //threshold 1
const float max_1v_1vt2 = maxf(inv_v_avg,inv_vt2); //threshold 2
/*
* The income factor is calculated based on the average velocity
* compared to two cargo-depending threshold velocities.
* Formula is divided into three parts:
*
* - fast exponential growth limited by 1st threshold velocity
* - slow exponential growth which can be negative or positive, depending on 2nd threshold
* - residual correction for very slow local transit
*
*/
const float exp1 = (1-exp(d*(-max_1v_1vt1-INV_VA)/DECAY1))/(max_1v_1vt2);
const float exp2 = (inv_vt2-inv_v_avg)*EXP2_AMPL*(1-exp(d*(-max_1v_1vt2-INV_VA)/DECAY2))/max_1v_1vt2;
const int32 test1 =
trunc(cargo_payment*num_pieces*maxf(exp1+exp2,minf(d/LOW_SPEED_DIVIDER,v_avg/LOW_SPEED_OFFSET))/INCOME_DIVIDER);
return test1;
}
Code: Select all
static inline float maxf(const float a, const float b)
{
return max<float>(a, b);
}
static inline int min(const int a, const int b)
{
return min<int>(a, b);
}
If you used TortoiseSVN/TortoiseHG to check out the source code, there is a right-click context menu entry to create a patch.McZapkie wrote:My programming skills stopped at the XX century stage, I have no idea how to create patch file
It is my case, but I have no idea, which sources should be considered to apply a diff - stable, trunc, most recent?Eddi wrote:If you used command line hg, type or "hg diff" to show the patch and use "... > file.diff" to write it to a file
Achieving any kind of "balance" in OpenTTD is very difficult. It's even more difficult when people start swinging sledgehammers around in the source code.McZapkie wrote:Another question - I need a global variable, which would be updated every year (for optional change of payment curve, to reflect change of life style across centuries and also decreasing tolerance for slow transit).
In my model, I would rather change the shape of payment vs distance curve according to speed and date.PikkaBird wrote: But in this case, the "optional change of payment curve" already exists; it's in the TTD inflation model, which increases running costs by 1% more each year than payments.
I really like the idea of fixing the hump in the income/distance curves, and I hope that your intention is to see that patch included in trunk some day - but if that is your intention, all I'm saying is keep it simple.McZapkie wrote:BTW, my personal feelings are, that you suggested me to write own patch, and now you are writing about sledgehammering of the code. I just tapped a body of one (ok, most important) function.
cargo_decay is a static parameter, AFAIK, and is not displayed in purchase menu.PikkaBird wrote: early vehicles' slowness can be compensated for in newgrfs by cheaper costs or reduced cargo decay
What is the max vehicle speed going to accomplish? I'd simply let the final delivery be done by transporting cargo one tile by the slowest possible vehicle, then I'd get loads more money than delivering directly with the faster vehicle.McZapkie wrote:One simple question:
I need to send max vehicle speed to PayFinalDelivery and PayTransfer function.
There is *first pointer in Cargo Payment struct, but I need max speed of train, not a first engine only.
May I use GetDisplayMaxSpeed() ?
My idea is to count late delivery penalty as difference betweenRubidium wrote:McZapkie wrote: GetDisplayMaxSpeed() seems to be a reasonable function to use for getting the speed. However, for NewGRF ships the maximum speed might increase significantly once the vehicle has been unloaded (but before payment), and for NewGRF aircraft the maximum speed might be very low because the NewGRF is limiting the taxiing speed.
Code: Select all
W = list of all available vehicles capable of loading the cargo
E = list of all available vehicles carrying no (normal) cargo
considered_speed = min(max(W->speed), max(E->speed))
[recalculate this on new month, when prototypes become available]
My idea was just opposite, to calculate expected delivery time for a given vehicle (I want to split calculations of revenue based on distance and penalty based on time).Eddi wrote:i'd not use the speed of the vehicle doing the delivery, but the (average or highest) speed of the available engines.
this would consider wagon speed limits and stuff, and doing this for every vehicle type individually means fast planes available won't make ship delivery useless.
CargoPacket has already position of last loaded point, so it should be sufficient to send (for example via CargoAge called in RunVehicleDayProc)Eddi wrote: something might be necessary to separate the transfer legs for intermodal transport, to prevent abuse like making the last tile delivery by ship, or so. like record cargo age for each transport type individually (or finally resolve the long-standing issues with leg payment by recording a list of all transfer legs, including which company and which vehicle type made this transfer)
Code: Select all
int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed / 2; }
int GetCurrentMaxSpeed() const { return min(this->vcache.cached_max_speed, this->current_order.max_speed * 2); }
i don't think this works as you think it does.McZapkie wrote:CargoPacket has already position of last loaded point, so it should be sufficient to send (for example via CargoAge called in RunVehicleDayProc)Eddi wrote: something might be necessary to separate the transfer legs for intermodal transport, to prevent abuse like making the last tile delivery by ship, or so. like record cargo age for each transport type individually (or finally resolve the long-standing issues with leg payment by recording a list of all transfer legs, including which company and which vehicle type made this transfer)
current tile position and nominal max velocity, to allow cp estimate expected time increment.
After delivery, if sum of expected time increments is greater than actual days_in_transit plus transit_days[1], penalty would be substracted form payment base, until it reach 0.
I think, that it should also fix problems with unfair transit shares.
the internal speed units are different for various vehicle types, otherwise things like airplane speed easily overflow. this is a remnant of the old TTD way of doing things. you should not worry about these, just GetDisplayMaxSpeed should be fine.But I still don't know, which velocity should I use.
For example, I don't understand these multipliers ans dividers used in ship.h:?Code: Select all
int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed / 2; } int GetCurrentMaxSpeed() const { return min(this->vcache.cached_max_speed, this->current_order.max_speed * 2); }
OK, it is clear now, I noticed it in engine_type.h file reference.Eddi wrote:the internal speed units are different for various vehicle types, otherwise things like airplane speed easily overflow. this is a remnant of the old TTD way of doing things. you should not worry about these, just GetDisplayMaxSpeed should be fine.
Not suddenly, if there is rolling average max speed taken for every vehicles.PikkaBird wrote:Sooo when you start your new airline, suddenly my buses on the other side of the map become unprofitable?
Users browsing this forum: No registered users and 17 guests