Example #1
0
/**
 * 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);
	}
}
Example #3
0
/**
 * 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;
}
Example #4
0
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;
}
Example #5
0
	template <> inline int Return<Money>       (HSQUIRRELVM vm, Money res)       { sq_pushinteger(vm, ClampToI32(res)); return 1; }
Example #6
0
	template <> inline int Return<int64>       (HSQUIRRELVM vm, int64 res)       { sq_pushinteger(vm, ClampToI32(res)); return 1; }
Example #7
0
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);
	}
}