Skip to content

Commit

Permalink
Change: Calculate efficiency rating for vehicles, as actual over pote…
Browse files Browse the repository at this point in the history
…ntial cargo-tiles delivered
  • Loading branch information
nielsmh committed May 23, 2018
1 parent 17257b9 commit acb32bc
Show file tree
Hide file tree
Showing 20 changed files with 280 additions and 56 deletions.
5 changes: 1 addition & 4 deletions src/aircraft_cmd.cpp
Expand Up @@ -506,11 +506,8 @@ static void HelicopterTickHandler(Aircraft *v)
*/
void SetAircraftPosition(Aircraft *v, int x, int y, int z)
{
v->x_pos = x;
v->y_pos = y;
v->z_pos = z;

v->UpdatePosition();
v->Travel(x, y);
v->UpdateViewport(true, false);
if (v->subtype == AIR_HELICOPTER) {
GetRotorImage(v, EIT_ON_MAP, &v->Next()->Next()->sprite_seq);
Expand Down
77 changes: 75 additions & 2 deletions src/economy.cpp
Expand Up @@ -86,6 +86,7 @@ const ScoreInfo _score_info[] = {
{ 120, 100}, // SCORE_VEHICLES
{ 80, 100}, // SCORE_STATIONS
{ 10000, 100}, // SCORE_MIN_PROFIT
{ 50, 100}, // SCORE_MIN_EFFICIENCY
{ 50000, 50}, // SCORE_MIN_INCOME
{ 100000, 100}, // SCORE_MAX_INCOME
{ 40000, 400}, // SCORE_DELIVERED
Expand All @@ -95,6 +96,24 @@ const ScoreInfo _score_info[] = {
{ 0, 0} // SCORE_TOTAL
};

/**
* Score elements in use for calculation/display.
* Not const since it should be possible to change with game settings.
*/
bool _score_part_active[SCORE_END] = {
true, // SCORE_VEHICLES
true, // SCORE_STATIONS
false, // SCORE_MIN_PROFIT
true, // SCORE_MIN_EFFICIENCY
true, // SCORE_MIN_INCOME
true, // SCORE_MAX_INCOME
true, // SCORE_DELIVERED
true, // SCORE_CARGO
true, // SCORE_MONEY
true, // SCORE_LOAN
true, // SCORE_TOTAL
};

int _score_part[MAX_COMPANIES][SCORE_END];
Economy _economy;
Prices _price;
Expand Down Expand Up @@ -162,6 +181,8 @@ int UpdateCompanyRatingAndValue(Company *c, bool update)
Vehicle *v;
Money min_profit = 0;
bool min_profit_first = true;
int32 min_efficiency = 0;
bool min_efficiency_first = true;
uint num = 0;

FOR_ALL_VEHICLES(v) {
Expand All @@ -174,6 +195,11 @@ int UpdateCompanyRatingAndValue(Company *c, bool update)
min_profit = v->profit_last_year;
min_profit_first = false;
}
/* Find the vehicle with the lowest capacity utilization */
if (min_efficiency_first || min_efficiency > v->GetEfficiencyLastYear()) {
min_efficiency = v->GetEfficiencyLastYear();
min_efficiency_first = false;
}
}
}
}
Expand All @@ -185,6 +211,9 @@ int UpdateCompanyRatingAndValue(Company *c, bool update)
if (min_profit > 0) {
_score_part[owner][SCORE_MIN_PROFIT] = ClampToI32(min_profit);
}
if (min_efficiency > 0) {
_score_part[owner][SCORE_MIN_EFFICIENCY] = min_efficiency;
}
}

/* Count stations */
Expand Down Expand Up @@ -259,6 +288,8 @@ int UpdateCompanyRatingAndValue(Company *c, bool update)
for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) {
/* Skip the total */
if (i == SCORE_TOTAL) continue;
/* Skip inactive score parts */
if (!_score_part_active[i]) 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;
Expand All @@ -281,6 +312,19 @@ int UpdateCompanyRatingAndValue(Company *c, bool update)
return score;
}

/**
* Call when game settings that affect performance rating calculation change.
* @note Signature must match other setting-changed callback functions
* @param p1 ignored
* @return always true
*/
bool PerformanceRatingCalculationChanged(int32)
{
_score_part_active[SCORE_MIN_PROFIT] = (_settings_game.economy.scoring_use_efficiency == 0);
_score_part_active[SCORE_MIN_EFFICIENCY] = (_settings_game.economy.scoring_use_efficiency == 1);
return true;
}

/**
* Change the ownership of all the items of a company.
* @param old_owner The company that gets removed.
Expand Down Expand Up @@ -935,6 +979,7 @@ void StartupEconomy()

StartupIndustryDailyChanges(true); // As we are starting a new game, initialize the counter too

PerformanceRatingCalculationChanged(0);
}

/**
Expand Down Expand Up @@ -1183,6 +1228,7 @@ CargoPayment::~CargoPayment()

SubtractMoneyFromCompany(CommandCost(this->front->GetExpenseType(true), -this->route_profit));
this->front->profit_this_year += (this->visual_profit + this->visual_transfer) << 8;
this->front->delivered_cargotiles_this_year += this->cargo_distance;

if (this->route_profit != 0 && IsLocalCompany() && !PlayVehicleSound(this->front, VSE_LOAD_UNLOAD)) {
SndPlayVehicleFx(SND_14_CASHTILL, this->front);
Expand Down Expand Up @@ -1216,6 +1262,12 @@ void CargoPayment::PayFinalDelivery(const CargoPacket *cp, uint count)

/* The vehicle's profit is whatever route profit there is minus feeder shares. */
this->visual_profit += profit - cp->FeederShare(count);

/* Delivered cargo over distance uses the single-leg calculation
* similar to Transfer, as a measure of the activity/usefulness
* of the vehicle */
uint leg_distance = DistanceManhattan(cp->LoadedAtXY(), Station::Get(this->current_station)->xy);
this->cargo_distance += count * leg_distance;
}

/**
Expand All @@ -1226,15 +1278,18 @@ void CargoPayment::PayFinalDelivery(const CargoPacket *cp, uint count)
*/
Money CargoPayment::PayTransfer(const CargoPacket *cp, uint count)
{
/* pay transfer vehicle for only the part of transfer it has done: ie. cargo_loaded_at_xy to here */
uint leg_distance = DistanceManhattan(cp->LoadedAtXY(), Station::Get(this->current_station)->xy);

Money profit = GetTransportedGoodsIncome(
count,
/* pay transfer vehicle for only the part of transfer it has done: ie. cargo_loaded_at_xy to here */
DistanceManhattan(cp->LoadedAtXY(), Station::Get(this->current_station)->xy),
leg_distance,
cp->DaysInTransit(),
this->ct);

profit = profit * _settings_game.economy.feeder_payment_share / 100;

this->cargo_distance += count * leg_distance; // accumulate cargo over distance
this->visual_transfer += profit; // accumulate transfer profits for whole vehicle
return profit; // account for the (virtual) profit already made for the cargo packet
}
Expand Down Expand Up @@ -1853,6 +1908,24 @@ static void LoadUnloadVehicle(Vehicle *front)
if (!finished_loading) LinkRefresher::Run(front, true, true);
}

/* If the vehicle did not load/unload anything during this period,
* and did not just finish up loading, count up the potential delivered
* cargo-tiles as a penalty for sitting idle at a station. */
if (!finished_loading && _settings_game.economy.idle_loading_ct_penalty > 0) {
int assumed_speed;
if (front->type == VEH_ROAD) {
assumed_speed = front->vcache.cached_max_speed / 2;
} else if (front->type == VEH_AIRCRAFT) {
assumed_speed = Aircraft::From(front)->GetSpeedOldUnits();
} else {
assumed_speed = front->vcache.cached_max_speed;
}
int potential = assumed_speed * front->GetConsistTotalCapacity(); // 16x potential cargo-tiles transported in 256 ticks
potential = (potential * front->load_unload_ticks + 255) / 256; // potential over actual ticks passed, rounding up
potential = potential * _settings_game.economy.idle_loading_ct_penalty / 4;
front->potential_cargotiles_this_year += (potential + 15) / 16; // divide sub-tiles to whole tiles, rounding up
}

SB(front->vehicle_flags, VF_LOADING_FINISHED, 1, finished_loading);
}

Expand Down
1 change: 1 addition & 0 deletions src/economy_base.h
Expand Up @@ -28,6 +28,7 @@ struct CargoPayment : CargoPaymentPool::PoolItem<&_cargo_payment_pool> {
Money route_profit; ///< The amount of money to add/remove from the bank account
Money visual_profit; ///< The visual profit to show
Money visual_transfer; ///< The transfer credits to be shown
OverflowSafeInt32 cargo_distance; ///< cargo units * distance delivered

/* Unsaved variables */
Company *owner; ///< The owner of the vehicle
Expand Down
2 changes: 2 additions & 0 deletions src/economy_func.h
Expand Up @@ -23,11 +23,13 @@ void SetPriceBaseMultiplier(Price price, int factor);

extern const ScoreInfo _score_info[];
extern int _score_part[MAX_COMPANIES][SCORE_END];
extern bool _score_part_active[SCORE_END];
extern Economy _economy;
/* Prices and also the fractional part. */
extern Prices _price;

int UpdateCompanyRatingAndValue(Company *c, bool update);
bool PerformanceRatingCalculationChanged(int32 p1);
void StartupIndustryDailyChanges(bool init_counter);

Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type);
Expand Down
19 changes: 10 additions & 9 deletions src/economy_type.h
Expand Up @@ -39,15 +39,16 @@ enum ScoreID {
SCORE_BEGIN = 0,
SCORE_VEHICLES = 0,
SCORE_STATIONS = 1,
SCORE_MIN_PROFIT = 2,
SCORE_MIN_INCOME = 3,
SCORE_MAX_INCOME = 4,
SCORE_DELIVERED = 5,
SCORE_CARGO = 6,
SCORE_MONEY = 7,
SCORE_LOAN = 8,
SCORE_TOTAL = 9, ///< This must always be the last entry
SCORE_END = 10, ///< How many scores are there..
SCORE_MIN_PROFIT = 2, // only one of this or the next are used
SCORE_MIN_EFFICIENCY = 3,
SCORE_MIN_INCOME = 4,
SCORE_MAX_INCOME = 5,
SCORE_DELIVERED = 6,
SCORE_CARGO = 7,
SCORE_MONEY = 8,
SCORE_LOAN = 9,
SCORE_TOTAL = 10, ///< This must always be the last entry
SCORE_END = 11, ///< How many scores are there..

SCORE_MAX = 1000, ///< The max score that can be in the performance history
/* the scores together of score_info is allowed to be more! */
Expand Down
9 changes: 8 additions & 1 deletion src/graph_gui.cpp
Expand Up @@ -1408,7 +1408,10 @@ struct PerformanceRatingDetailWindow : Window {

/* SCORE_TOTAL has his own rules ;) */
if (score_type == SCORE_TOTAL) {
for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) score += _score_info[i].score;
for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) {
if (!_score_part_active[i]) continue;
score += _score_info[i].score;
}
needed = SCORE_MAX;
}

Expand Down Expand Up @@ -1530,6 +1533,7 @@ static NWidgetBase *MakePerformanceDetailPanels(int *biggest_index)
STR_PERFORMANCE_DETAIL_VEHICLES_TOOLTIP,
STR_PERFORMANCE_DETAIL_STATIONS_TOOLTIP,
STR_PERFORMANCE_DETAIL_MIN_PROFIT_TOOLTIP,
STR_PERFORMANCE_DETAIL_MIN_EFFICIENCY_TOOLTIP,
STR_PERFORMANCE_DETAIL_MIN_INCOME_TOOLTIP,
STR_PERFORMANCE_DETAIL_MAX_INCOME_TOOLTIP,
STR_PERFORMANCE_DETAIL_DELIVERED_TOOLTIP,
Expand All @@ -1543,6 +1547,9 @@ static NWidgetBase *MakePerformanceDetailPanels(int *biggest_index)

NWidgetVertical *vert = new NWidgetVertical(NC_EQUALSIZE);
for (int widnum = WID_PRD_SCORE_FIRST; widnum <= WID_PRD_SCORE_LAST; widnum++) {
/* Verify if the score element is in use */
if (!_score_part_active[widnum - WID_PRD_SCORE_FIRST]) continue;
/* Create the widget */
NWidgetBackground *panel = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, widnum);
panel->SetFill(1, 1);
panel->SetDataTip(0x0, performance_tips[widnum - WID_PRD_SCORE_FIRST]);
Expand Down
20 changes: 20 additions & 0 deletions src/lang/english.txt
Expand Up @@ -286,6 +286,8 @@ STR_SORT_BY_TRANSPORTED :Transported
STR_SORT_BY_NUMBER :Number
STR_SORT_BY_PROFIT_LAST_YEAR :Profit last year
STR_SORT_BY_PROFIT_THIS_YEAR :Profit this year
STR_SORT_BY_EFFICIENCY_LAST_YEAR :Efficiency last year
STR_SORT_BY_EFFICIENCY_THIS_YEAR :Efficiency this year
STR_SORT_BY_AGE :Age
STR_SORT_BY_RELIABILITY :Reliability
STR_SORT_BY_TOTAL_CAPACITY_PER_CARGOTYPE :Total capacity per cargo type
Expand Down Expand Up @@ -615,6 +617,7 @@ STR_PERFORMANCE_DETAIL_SELECT_COMPANY_TOOLTIP :{BLACK}View det
STR_PERFORMANCE_DETAIL_VEHICLES :{BLACK}Vehicles:
STR_PERFORMANCE_DETAIL_STATIONS :{BLACK}Stations:
STR_PERFORMANCE_DETAIL_MIN_PROFIT :{BLACK}Min. profit:
STR_PERFORMANCE_DETAIL_MIN_EFFICIENCY :{BLACK}Min. efficiency
STR_PERFORMANCE_DETAIL_MIN_INCOME :{BLACK}Min. income:
STR_PERFORMANCE_DETAIL_MAX_INCOME :{BLACK}Max. income:
STR_PERFORMANCE_DETAIL_DELIVERED :{BLACK}Delivered:
Expand All @@ -626,6 +629,7 @@ STR_PERFORMANCE_DETAIL_TOTAL :{BLACK}Total:
STR_PERFORMANCE_DETAIL_VEHICLES_TOOLTIP :{BLACK}Number of vehicles that turned a profit last year. This includes road vehicles, trains, ships and aircraft
STR_PERFORMANCE_DETAIL_STATIONS_TOOLTIP :{BLACK}Number of recently-serviced stations. Train stations, bus stops, airports and so on are counted separately even if they belong to the same station
STR_PERFORMANCE_DETAIL_MIN_PROFIT_TOOLTIP :{BLACK}The profit of the vehicle with the lowest income (only vehicles older than two years are considered)
STR_PERFORMANCE_DETAIL_MIN_EFFICIENCY_TOOLTIP :{BLACK}The efficiency of the vehicle with the lowest efficiency (only vehicles older than two years are considered)
STR_PERFORMANCE_DETAIL_MIN_INCOME_TOOLTIP :{BLACK}Amount of cash made in the quarter with the lowest profit of the last 12 quarters
STR_PERFORMANCE_DETAIL_MAX_INCOME_TOOLTIP :{BLACK}Amount of cash made in the quarter with the highest profit of the last 12 quarters
STR_PERFORMANCE_DETAIL_DELIVERED_TOOLTIP :{BLACK}Units of cargo delivered in the last four quarters
Expand Down Expand Up @@ -1087,6 +1091,14 @@ STR_CITY_APPROVAL_PERMISSIVE :Permissive
STR_CITY_APPROVAL_TOLERANT :Tolerant
STR_CITY_APPROVAL_HOSTILE :Hostile

STR_VEHICLE_SCORING_PROFIT :Profit
STR_VEHICLE_SCORING_EFFICIENCY :Efficiency

STR_IDLING_PENALTY_NONE :None
STR_IDLING_PENALTY_LOW :Low
STR_IDLING_PENALTY_MEDIUM :Medium
STR_IDLING_PENALTY_HIGH :High

STR_WARNING_NO_SUITABLE_AI :{WHITE}No suitable AIs available...{}You can download several AIs via the 'Online Content' system

# Settings tree window
Expand Down Expand Up @@ -1162,6 +1174,10 @@ STR_CONFIG_SETTING_DISASTERS :Disasters: {STR
STR_CONFIG_SETTING_DISASTERS_HELPTEXT :Toggle disasters which may occasionally block or destroy vehicles or infrastructure
STR_CONFIG_SETTING_CITY_APPROVAL :Town council's attitude towards area restructuring: {STRING2}
STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :Choose how much noise and environmental damage by companies affect their town rating and further construction actions in their area
STR_CONFIG_SETTING_VEHICLE_SCORING :Vehicle performance rating is based on: {STRING2}
STR_CONFIG_SETTING_VEHICLE_SCORING_HELPTEXT :The profit-based vehicle performance rating component can be difficult to achieve when playing with Cargo Distribution and feeder line profit sharing, the efficiency based calculation presents a different challenge.
STR_CONFIG_SETTING_EFFICIENCY_IDLE_PENALTY :Efficiency penalty for vehicles idling at stations: {STRING2}
STR_CONFIG_SETTING_EFFICIENCY_IDLE_PENALTY_HELPTEXT :Vehicles sitting idle at a station (neither receiving or unloading cargo) will receive an Efficiency penalty based on running at 1/4, 1/2, or 3/4 speed.

STR_CONFIG_SETTING_MAX_HEIGHTLEVEL :Maximum map height: {STRING2}
STR_CONFIG_SETTING_MAX_HEIGHTLEVEL_HELPTEXT :Set the maximum allowed height for mountains on the map
Expand Down Expand Up @@ -3322,7 +3338,9 @@ STR_VEHICLE_LIST_ROAD_VEHICLE_TOOLTIP :{BLACK}Road veh
STR_VEHICLE_LIST_SHIP_TOOLTIP :{BLACK}Ships - click on ship for information
STR_VEHICLE_LIST_AIRCRAFT_TOOLTIP :{BLACK}Aircraft - click on aircraft for information

STR_VEHICLE_LIST_PROFIT_EFFICIENCY_LINE :{STRING2} {STRING2}
STR_VEHICLE_LIST_PROFIT_THIS_YEAR_LAST_YEAR :{TINY_FONT}{BLACK}Profit this year: {CURRENCY_LONG} (last year: {CURRENCY_LONG})
STR_VEHICLE_LIST_EFFICIENCY_THIS_YEAR_LAST_YEAR :{TINY_FONT}{BLACK}Efficiency this year: {NUM}% (last year: {NUM}%)

STR_VEHICLE_LIST_AVAILABLE_TRAINS :Available Trains
STR_VEHICLE_LIST_AVAILABLE_ROAD_VEHICLES :Available Vehicles
Expand Down Expand Up @@ -3672,7 +3690,9 @@ STR_VEHICLE_INFO_MAX_SPEED_TYPE_RANGE :{BLACK}Max. spe
STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Weight: {LTBLUE}{WEIGHT_SHORT} {BLACK}Power: {LTBLUE}{POWER}{BLACK} Max. speed: {LTBLUE}{VELOCITY}
STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Weight: {LTBLUE}{WEIGHT_SHORT} {BLACK}Power: {LTBLUE}{POWER}{BLACK} Max. speed: {LTBLUE}{VELOCITY} {BLACK}Max. T.E.: {LTBLUE}{FORCE}

STR_VEHICLE_INFO_PROFIT_EFFICIENCY_LINE :{STRING2} {STRING2}
STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit this year: {LTBLUE}{CURRENCY_LONG} (last year: {CURRENCY_LONG})
STR_VEHICLE_INFO_EFFICIENCY_THIS_YEAR_LAST_YEAR :{BLACK}Efficiency this year: {LTBLUE}{NUM}% (last year: {NUM}%)
STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS :{BLACK}Reliability: {LTBLUE}{COMMA}% {BLACK}Breakdowns since last service: {LTBLUE}{COMMA}

STR_VEHICLE_INFO_BUILT_VALUE :{LTBLUE}{ENGINE} {BLACK}Built: {LTBLUE}{NUM}{BLACK} Value: {LTBLUE}{CURRENCY_LONG}
Expand Down

0 comments on commit acb32bc

Please sign in to comment.