File diff r23057:0c9ab2c5719b → r23058:64521dfbcce5
src/economy.cpp
Show inline comments
 
@@ -74,49 +74,49 @@ INSTANTIATE_POOL_METHODS(CargoPayment)
 
 */
 
static inline int32 BigMulS(const int32 a, const int32 b, const uint8 shift)
 
{
 
	return (int32)((int64)a * (int64)b >> shift);
 
}
 

	
 
typedef SmallVector<Industry *, 16> SmallIndustryList;
 

	
 
/**
 
 * Score info, values used for computing the detailed performance rating.
 
 */
 
const ScoreInfo _score_info[] = {
 
	{     120, 100}, // SCORE_VEHICLES
 
	{      80, 100}, // SCORE_STATIONS
 
	{   10000, 100}, // SCORE_MIN_PROFIT
 
	{   50000,  50}, // SCORE_MIN_INCOME
 
	{  100000, 100}, // SCORE_MAX_INCOME
 
	{   40000, 400}, // SCORE_DELIVERED
 
	{       8,  50}, // SCORE_CARGO
 
	{10000000,  50}, // SCORE_MONEY
 
	{  250000,  50}, // SCORE_LOAN
 
	{       0,   0}  // SCORE_TOTAL
 
};
 

	
 
int _score_part[MAX_COMPANIES][SCORE_END];
 
int64 _score_part[MAX_COMPANIES][SCORE_END];
 
Economy _economy;
 
Prices _price;
 
Money _additional_cash_required;
 
static PriceMultipliers _price_base_multiplier;
 

	
 
/**
 
 * Calculate the value of the company. That is the value of all
 
 * assets (vehicles, stations, etc) and money minus the loan,
 
 * except when including_loan is \c false which is useful when
 
 * we want to calculate the value for bankruptcy.
 
 * @param c              the company to get the value of.
 
 * @param including_loan include the loan in the company value.
 
 * @return the value of the company.
 
 */
 
Money CalculateCompanyValue(const Company *c, bool including_loan)
 
{
 
	Owner owner = c->index;
 

	
 
	Station *st;
 
	uint num = 0;
 

	
 
	FOR_ALL_STATIONS(st) {
 
		if (st->owner == owner) num += CountBits((byte)st->facilities);
 
	}
 
@@ -162,114 +162,114 @@ int UpdateCompanyRatingAndValue(Company 
 
		Vehicle *v;
 
		Money min_profit = 0;
 
		bool min_profit_first = true;
 
		uint num = 0;
 

	
 
		FOR_ALL_VEHICLES(v) {
 
			if (v->owner != owner) continue;
 
			if (IsCompanyBuildableVehicleType(v->type) && v->IsPrimaryVehicle()) {
 
				if (v->profit_last_year > 0) num++; // For the vehicle score only count profitable vehicles
 
				if (v->age > 730) {
 
					/* Find the vehicle with the lowest amount of profit */
 
					if (min_profit_first || min_profit > v->profit_last_year) {
 
						min_profit = v->profit_last_year;
 
						min_profit_first = false;
 
					}
 
				}
 
			}
 
		}
 

	
 
		min_profit >>= 8; // remove the fract part
 

	
 
		_score_part[owner][SCORE_VEHICLES] = num;
 
		/* Don't allow negative min_profit to show */
 
		if (min_profit > 0) {
 
			_score_part[owner][SCORE_MIN_PROFIT] = ClampToI32(min_profit);
 
			_score_part[owner][SCORE_MIN_PROFIT] = min_profit;
 
		}
 
	}
 

	
 
	/* Count stations */
 
	{
 
		uint num = 0;
 
		const Station *st;
 

	
 
		FOR_ALL_STATIONS(st) {
 
			/* Only count stations that are actually serviced */
 
			if (st->owner == owner && (st->time_since_load <= 20 || st->time_since_unload <= 20)) num += CountBits((byte)st->facilities);
 
		}
 
		_score_part[owner][SCORE_STATIONS] = num;
 
	}
 

	
 
	/* Generate statistics depending on recent income statistics */
 
	{
 
		int numec = min(c->num_valid_stat_ent, 12);
 
		if (numec != 0) {
 
			const CompanyEconomyEntry *cee = c->old_economy;
 
			Money min_income = cee->income + cee->expenses;
 
			Money max_income = cee->income + cee->expenses;
 

	
 
			do {
 
				min_income = min(min_income, cee->income + cee->expenses);
 
				max_income = max(max_income, cee->income + cee->expenses);
 
			} while (++cee, --numec);
 

	
 
			if (min_income > 0) {
 
				_score_part[owner][SCORE_MIN_INCOME] = ClampToI32(min_income);
 
				_score_part[owner][SCORE_MIN_INCOME] = min_income;
 
			}
 

	
 
			_score_part[owner][SCORE_MAX_INCOME] = ClampToI32(max_income);
 
			_score_part[owner][SCORE_MAX_INCOME] = max_income;
 
		}
 
	}
 

	
 
	/* Generate score depending on amount of transported cargo */
 
	{
 
		int numec = min(c->num_valid_stat_ent, 4);
 
		if (numec != 0) {
 
			const CompanyEconomyEntry *cee = c->old_economy;
 
			OverflowSafeInt64 total_delivered = 0;
 
			do {
 
				total_delivered += cee->delivered_cargo.GetSum<OverflowSafeInt64>();
 
			} while (++cee, --numec);
 

	
 
			_score_part[owner][SCORE_DELIVERED] = ClampToI32(total_delivered);
 
			_score_part[owner][SCORE_DELIVERED] = total_delivered;
 
		}
 
	}
 

	
 
	/* Generate score for variety of cargo */
 
	{
 
		_score_part[owner][SCORE_CARGO] = c->old_economy->delivered_cargo.GetCount();
 
	}
 

	
 
	/* Generate score for company's money */
 
	{
 
		if (c->money > 0) {
 
			_score_part[owner][SCORE_MONEY] = ClampToI32(c->money);
 
			_score_part[owner][SCORE_MONEY] = c->money;
 
		}
 
	}
 

	
 
	/* Generate score for loan */
 
	{
 
		_score_part[owner][SCORE_LOAN] = ClampToI32(_score_info[SCORE_LOAN].needed - c->current_loan);
 
		_score_part[owner][SCORE_LOAN] = _score_info[SCORE_LOAN].needed - c->current_loan;
 
	}
 

	
 
	/* Now we calculate the score for each item.. */
 
	{
 
		int total_score = 0;
 
		int s;
 
		score = 0;
 
		for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) {
 
			/* Skip the total */
 
			if (i == SCORE_TOTAL) continue;
 
			/*  Check the score */
 
			s = Clamp(_score_part[owner][i], 0, _score_info[i].needed) * _score_info[i].score / _score_info[i].needed;
 
			score += s;
 
			total_score += _score_info[i].score;
 
		}
 

	
 
		_score_part[owner][SCORE_TOTAL] = score;
 

	
 
		/*  We always want the score scaled to SCORE_MAX (1000) */
 
		if (total_score != SCORE_MAX) score = score * SCORE_MAX / total_score;
 
	}
 

	
 
	if (update) {
 
		c->old_economy[0].performance_history = score;