/** * Determines order of engines by running costs * @param *a first engine to compare * @param *b second engine to compare * @return for descending order: returns < 0 if a < b and > 0 for a > b. Vice versa for ascending order and 0 for equal */ static int CDECL EngineRunningCostSorter(const EngineID *a, const EngineID *b) { Money va = Engine::Get(*a)->GetRunningCost(); Money vb = Engine::Get(*b)->GetRunningCost(); int r = ClampToI32(va - vb); /* Use EngineID to sort instead since we want consistent sorting */ if (r == 0) return EngineNumberSorter(a, b); return _internal_sort_order ? -r : r; }
/** * Handle the bankruptcy take over of a company. * Companies going bankrupt will ask the other companies in order of their * performance rating, so better performing companies get the 'do you want to * merge with Y' question earlier. The question will then stay till either the * company has gone bankrupt or got merged with a company. * * @param c the company that is going bankrupt. */ static void HandleBankruptcyTakeover(Company *c) { /* Amount of time out for each company to take over a company; * Timeout is a quarter (3 months of 30 days) divided over the * number of companies. The minimum number of days in a quarter * is 90: 31 in January, 28 in February and 31 in March. * Note that the company going bankrupt can't buy itself. */ static const int TAKE_OVER_TIMEOUT = 3 * 30 * DAY_TICKS / (MAX_COMPANIES - 1); assert(c->bankrupt_asked != 0); /* We're currently asking some company to buy 'us' */ if (c->bankrupt_timeout != 0) { c->bankrupt_timeout -= MAX_COMPANIES; if (c->bankrupt_timeout > 0) return; c->bankrupt_timeout = 0; return; } /* Did we ask everyone for bankruptcy? If so, bail out. */ if (c->bankrupt_asked == MAX_UVALUE(CompanyMask)) return; Company *c2, *best = NULL; int32 best_performance = -1; /* Ask the company with the highest performance history first */ FOR_ALL_COMPANIES(c2) { if (c2->bankrupt_asked == 0 && // Don't ask companies going bankrupt themselves !HasBit(c->bankrupt_asked, c2->index) && best_performance < c2->old_economy[1].performance_history && MayCompanyTakeOver(c2->index, c->index)) { best_performance = c2->old_economy[1].performance_history; best = c2; } } /* Asked all companies? */ if (best_performance == -1) { c->bankrupt_asked = MAX_UVALUE(CompanyMask); return; } SetBit(c->bankrupt_asked, best->index); c->bankrupt_timeout = TAKE_OVER_TIMEOUT; if (best->is_ai) { AI::NewEvent(best->index, new ScriptEventCompanyAskMerger(c->index, ClampToI32(c->bankrupt_value))); } else if (IsInteractiveCompany(best->index)) { ShowBuyCompanyDialog(c->index); } }
/** * Determines order of engines by running costs * @param *a first engine to compare * @param *b second engine to compare * @return for descending order: returns < 0 if a < b and > 0 for a > b. Vice versa for ascending order and 0 for equal */ static int CDECL EnginePowerVsRunningCostSorter(const EngineID *a, const EngineID *b) { const Engine *e_a = Engine::Get(*a); const Engine *e_b = Engine::Get(*b); /* Here we are using a few tricks to get the right sort. * We want power/running cost, but since we usually got higher running cost than power and we store the result in an int, * we will actually calculate cunning cost/power (to make it more than 1). * Because of this, the return value have to be reversed as well and we return b - a instead of a - b. * Another thing is that both power and running costs should be doubled for multiheaded engines. * Since it would be multipling with 2 in both numerator and denumerator, it will even themselves out and we skip checking for multiheaded. */ Money va = (e_a->GetRunningCost()) / max(1U, (uint)e_a->GetPower()); Money vb = (e_b->GetRunningCost()) / max(1U, (uint)e_b->GetPower()); int r = ClampToI32(vb - va); /* Use EngineID to sort instead since we want consistent sorting */ if (r == 0) return EngineNumberSorter(a, b); return _internal_sort_order ? -r : r; }
void HandleOnEditText(const char *str) { switch (_rename_what) { case 3: { // Give money, you can only give money in excess of loan const Company *c = Company::GetIfValid(_local_company); if (c == nullptr) break; Money money = min(c->money - c->current_loan, (Money)(atoi(str) / _currency->rate)); uint32 money_c = Clamp(ClampToI32(money), 0, 20000000); // Clamp between 20 million and 0 /* Give 'id' the money, and subtract it from ourself */ DoCommandP(0, money_c, _rename_id, CMD_GIVE_MONEY | CMD_MSG(STR_ERROR_INSUFFICIENT_FUNDS), CcGiveMoney, str); break; } default: NOT_REACHED(); } _rename_id = _rename_what = -1; }
template <> inline int Return<Money> (HSQUIRRELVM vm, Money res) { sq_pushinteger(vm, ClampToI32(res)); return 1; }
template <> inline int Return<int64> (HSQUIRRELVM vm, int64 res) { sq_pushinteger(vm, ClampToI32(res)); return 1; }
int GroundVehicle<T, Type>::GetAcceleration() const { /* Templated class used for function calls for performance reasons. */ const T *v = T::From(this); /* Speed is used squared later on, so U16 * U16, and then multiplied by other values. */ int64 speed = v->GetCurrentSpeed(); // [km/h-ish] /* Weight is stored in tonnes. */ int32 mass = this->gcache.cached_weight; /* Power is stored in HP, we need it in watts. * Each vehicle can have U16 power, 128 vehicles, HP -> watt * and km/h to m/s conversion below result in a maxium of * about 1.1E11, way more than 4.3E9 of int32. */ int64 power = this->gcache.cached_power * 746ll; /* This is constructed from: * - axle resistance: U16 power * 10 for 128 vehicles. * * 8.3E7 * - rolling friction: U16 power * 144 for 128 vehicles. * * 1.2E9 * - slope resistance: U16 weight * 100 * 10 (steepness) for 128 vehicles. * * 8.4E9 * - air drag: 28 * (U8 drag + 3 * U8 drag * 128 vehicles / 20) * U16 speed * U16 speed * * 6.2E14 before dividing by 1000 * Sum is 6.3E11, more than 4.3E9 of int32, so int64 is needed. */ int64 resistance = 0; bool maglev = v->GetAccelerationType() == 2; const int area = v->GetAirDragArea(); if (!maglev) { /* Static resistance plus rolling friction. */ resistance = this->gcache.cached_axle_resistance; resistance += mass * v->GetRollingFriction(); } /* Air drag; the air drag coefficient is in an arbitrary NewGRF-unit, * so we need some magic conversion factor. */ resistance += (area * this->gcache.cached_air_drag * speed * speed) / 1000; resistance += this->GetSlopeResistance(); /* This value allows to know if the vehicle is accelerating or braking. */ AccelStatus mode = v->GetAccelerationStatus(); const int max_te = this->gcache.cached_max_te; // [N] /* Constructued from power, with need to multiply by 18 and assuming * low speed, it needs to be a 64 bit integer too. */ int64 force; if (speed > 0) { if (!maglev) { /* Conversion factor from km/h to m/s is 5/18 to get [N] in the end. */ force = power * 18 / (speed * 5); if (mode == AS_ACCEL && force > max_te) force = max_te; } else { force = power / 25; } } else { /* "Kickoff" acceleration. */ force = (mode == AS_ACCEL && !maglev) ? min(max_te, power) : power; force = max(force, (mass * 8) + resistance); } if (mode == AS_ACCEL) { /* Easy way out when there is no acceleration. */ if (force == resistance) return 0; /* When we accelerate, make sure we always keep doing that, even when * the excess force is more than the mass. Otherwise a vehicle going * down hill will never slow down enough, and a vehicle that came up * a hill will never speed up enough to (eventually) get back to the * same (maximum) speed. */ int accel = ClampToI32((force - resistance) / (mass * 4)); return force < resistance ? min(-1, accel) : max(1, accel); } else { return ClampToI32(min(-force - resistance, -10000) / mass); } }