economy.cpp

Go to the documentation of this file.
00001 /* $Id: economy.cpp 14536 2008-10-25 22:00:51Z frosch $ */
00002 
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "currency.h"
00008 #include "landscape.h"
00009 #include "company_base.h"
00010 #include "company_func.h"
00011 #include "command_func.h"
00012 #include "saveload.h"
00013 #include "industry.h"
00014 #include "industry_map.h"
00015 #include "town.h"
00016 #include "news_func.h"
00017 #include "network/network.h"
00018 #include "network/network_func.h"
00019 #include "variables.h"
00020 #include "vehicle_gui.h"
00021 #include "ai/ai.h"
00022 #include "train.h"
00023 #include "roadveh.h"
00024 #include "aircraft.h"
00025 #include "newgrf_engine.h"
00026 #include "newgrf_sound.h"
00027 #include "newgrf_callbacks.h"
00028 #include "newgrf_industries.h"
00029 #include "newgrf_industrytiles.h"
00030 #include "newgrf_station.h"
00031 #include "unmovable.h"
00032 #include "cargotype.h"
00033 #include "group.h"
00034 #include "strings_func.h"
00035 #include "tile_cmd.h"
00036 #include "functions.h"
00037 #include "window_func.h"
00038 #include "date_func.h"
00039 #include "vehicle_func.h"
00040 #include "sound_func.h"
00041 #include "track_type.h"
00042 #include "track_func.h"
00043 #include "road_func.h"
00044 #include "rail_map.h"
00045 #include "signal_func.h"
00046 #include "gfx_func.h"
00047 #include "autoreplace_func.h"
00048 #include "company_gui.h"
00049 #include "signs_base.h"
00050 
00051 #include "table/strings.h"
00052 #include "table/sprites.h"
00053 
00065 static inline int32 BigMulS(const int32 a, const int32 b, const uint8 shift)
00066 {
00067   return (int32)((int64)a * (int64)b >> shift);
00068 }
00069 
00081 static inline uint32 BigMulSU(const uint32 a, const uint32 b, const uint8 shift)
00082 {
00083   return (uint32)((uint64)a * (uint64)b >> shift);
00084 }
00085 
00086 /* Score info */
00087 const ScoreInfo _score_info[] = {
00088   { SCORE_VEHICLES,        120, 100 },
00089   { SCORE_STATIONS,         80, 100 },
00090   { SCORE_MIN_PROFIT,    10000, 100 },
00091   { SCORE_MIN_INCOME,    50000,  50 },
00092   { SCORE_MAX_INCOME,   100000, 100 },
00093   { SCORE_DELIVERED,     40000, 400 },
00094   { SCORE_CARGO,             8,  50 },
00095   { SCORE_MONEY,      10000000,  50 },
00096   { SCORE_LOAN,         250000,  50 },
00097   { SCORE_TOTAL,             0,   0 }
00098 };
00099 
00100 int _score_part[MAX_COMPANIES][SCORE_END];
00101 Economy _economy;
00102 Subsidy _subsidies[MAX_COMPANIES];
00103 Prices _price;
00104 uint16 _price_frac[NUM_PRICES];
00105 Money  _cargo_payment_rates[NUM_CARGO];
00106 uint16 _cargo_payment_rates_frac[NUM_CARGO];
00107 Money _additional_cash_required;
00108 
00109 Money CalculateCompanyValue(const Company *c)
00110 {
00111   Owner owner = c->index;
00112   Money value = 0;
00113 
00114   Station *st;
00115   uint num = 0;
00116 
00117   FOR_ALL_STATIONS(st) {
00118     if (st->owner == owner) num += CountBits(st->facilities);
00119   }
00120 
00121   value += num * _price.station_value * 25;
00122 
00123   Vehicle *v;
00124   FOR_ALL_VEHICLES(v) {
00125     if (v->owner != owner) continue;
00126 
00127     if (v->type == VEH_TRAIN ||
00128         v->type == VEH_ROAD ||
00129         (v->type == VEH_AIRCRAFT && IsNormalAircraft(v)) ||
00130         v->type == VEH_SHIP) {
00131       value += v->value * 3 >> 1;
00132     }
00133   }
00134 
00135   /* Add real money value */
00136   value -= c->current_loan;
00137   value += c->money;
00138 
00139   return max(value, (Money)1);
00140 }
00141 
00148 int UpdateCompanyRatingAndValue(Company *c, bool update)
00149 {
00150   Owner owner = c->index;
00151   int score = 0;
00152 
00153   memset(_score_part[owner], 0, sizeof(_score_part[owner]));
00154 
00155   /* Count vehicles */
00156   {
00157     Vehicle *v;
00158     Money min_profit = 0;
00159     bool min_profit_first = true;
00160     uint num = 0;
00161 
00162     FOR_ALL_VEHICLES(v) {
00163       if (v->owner != owner) continue;
00164       if (IsCompanyBuildableVehicleType(v->type) && v->IsPrimaryVehicle()) {
00165         num++;
00166         if (v->age > 730) {
00167           /* Find the vehicle with the lowest amount of profit */
00168           if (min_profit_first || min_profit > v->profit_last_year) {
00169             min_profit = v->profit_last_year;
00170             min_profit_first = false;
00171           }
00172         }
00173       }
00174     }
00175 
00176     min_profit >>= 8; // remove the fract part
00177 
00178     _score_part[owner][SCORE_VEHICLES] = num;
00179     /* Don't allow negative min_profit to show */
00180     if (min_profit > 0)
00181       _score_part[owner][SCORE_MIN_PROFIT] = ClampToI32(min_profit);
00182   }
00183 
00184   /* Count stations */
00185   {
00186     uint num = 0;
00187     const Station* st;
00188 
00189     FOR_ALL_STATIONS(st) {
00190       if (st->owner == owner) num += CountBits(st->facilities);
00191     }
00192     _score_part[owner][SCORE_STATIONS] = num;
00193   }
00194 
00195   /* Generate statistics depending on recent income statistics */
00196   {
00197     int numec = min(c->num_valid_stat_ent, 12);
00198     if (numec != 0) {
00199       const CompanyEconomyEntry *cee = c->old_economy;
00200       Money min_income = cee->income + cee->expenses;
00201       Money max_income = cee->income + cee->expenses;
00202 
00203       do {
00204         min_income = min(min_income, cee->income + cee->expenses);
00205         max_income = max(max_income, cee->income + cee->expenses);
00206       } while (++cee,--numec);
00207 
00208       if (min_income > 0) {
00209         _score_part[owner][SCORE_MIN_INCOME] = ClampToI32(min_income);
00210       }
00211 
00212       _score_part[owner][SCORE_MAX_INCOME] = ClampToI32(max_income);
00213     }
00214   }
00215 
00216   /* Generate score depending on amount of transported cargo */
00217   {
00218     const CompanyEconomyEntry *cee;
00219     int numec;
00220     uint32 total_delivered;
00221 
00222     numec = min(c->num_valid_stat_ent, 4);
00223     if (numec != 0) {
00224       cee = c->old_economy;
00225       total_delivered = 0;
00226       do {
00227         total_delivered += cee->delivered_cargo;
00228       } while (++cee,--numec);
00229 
00230       _score_part[owner][SCORE_DELIVERED] = total_delivered;
00231     }
00232   }
00233 
00234   /* Generate score for variety of cargo */
00235   {
00236     uint num = CountBits(c->cargo_types);
00237     _score_part[owner][SCORE_CARGO] = num;
00238     if (update) c->cargo_types = 0;
00239   }
00240 
00241   /* Generate score for company's money */
00242   {
00243     if (c->money > 0) {
00244       _score_part[owner][SCORE_MONEY] = ClampToI32(c->money);
00245     }
00246   }
00247 
00248   /* Generate score for loan */
00249   {
00250     _score_part[owner][SCORE_LOAN] = ClampToI32(_score_info[SCORE_LOAN].needed - c->current_loan);
00251   }
00252 
00253   /* Now we calculate the score for each item.. */
00254   {
00255     int total_score = 0;
00256     int s;
00257     score = 0;
00258     for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) {
00259       /* Skip the total */
00260       if (i == SCORE_TOTAL) continue;
00261       /*  Check the score */
00262       s = Clamp(_score_part[owner][i], 0, _score_info[i].needed) * _score_info[i].score / _score_info[i].needed;
00263       score += s;
00264       total_score += _score_info[i].score;
00265     }
00266 
00267     _score_part[owner][SCORE_TOTAL] = score;
00268 
00269     /*  We always want the score scaled to SCORE_MAX (1000) */
00270     if (total_score != SCORE_MAX) score = score * SCORE_MAX / total_score;
00271   }
00272 
00273   if (update) {
00274     c->old_economy[0].performance_history = score;
00275     UpdateCompanyHQ(c, score);
00276     c->old_economy[0].company_value = CalculateCompanyValue(c);
00277   }
00278 
00279   InvalidateWindow(WC_PERFORMANCE_DETAIL, 0);
00280   return score;
00281 }
00282 
00283 /*  use INVALID_OWNER as new_owner to delete the company. */
00284 void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner)
00285 {
00286   Town *t;
00287   CompanyID old = _current_company;
00288 
00289   assert(old_owner != new_owner);
00290 
00291   {
00292     Company *c;
00293     uint i;
00294 
00295     /* See if the old_owner had shares in other companies */
00296     _current_company = old_owner;
00297     FOR_ALL_COMPANIES(c) {
00298       for (i = 0; i < 4; i++) {
00299         if (c->share_owners[i] == old_owner) {
00300           /* Sell his shares */
00301           CommandCost res = DoCommand(0, c->index, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY);
00302           /* Because we are in a DoCommand, we can't just execute an other one and
00303            *  expect the money to be removed. We need to do it ourself! */
00304           SubtractMoneyFromCompany(res);
00305         }
00306       }
00307     }
00308 
00309     /* Sell all the shares that people have on this company */
00310     c = GetCompany(old_owner);
00311     for (i = 0; i < 4; i++) {
00312       _current_company = c->share_owners[i];
00313       if (_current_company != INVALID_OWNER) {
00314         /* Sell the shares */
00315         CommandCost res = DoCommand(0, old_owner, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY);
00316         /* Because we are in a DoCommand, we can't just execute an other one and
00317          *  expect the money to be removed. We need to do it ourself! */
00318         SubtractMoneyFromCompany(res);
00319       }
00320     }
00321   }
00322 
00323   _current_company = old_owner;
00324 
00325   /* Temporarily increase the company's money, to be sure that
00326    * removing his/her property doesn't fail because of lack of money.
00327    * Not too drastically though, because it could overflow */
00328   if (new_owner == INVALID_OWNER) {
00329     GetCompany(old_owner)->money = UINT64_MAX >> 2; // jackpot ;p
00330   }
00331 
00332   if (new_owner == INVALID_OWNER) {
00333     Subsidy *s;
00334 
00335     for (s = _subsidies; s != endof(_subsidies); s++) {
00336       if (s->cargo_type != CT_INVALID && s->age >= 12) {
00337         if (GetStation(s->to)->owner == old_owner) s->cargo_type = CT_INVALID;
00338       }
00339     }
00340   }
00341 
00342   /* Take care of rating in towns */
00343   FOR_ALL_TOWNS(t) {
00344     /* If a company takes over, give the ratings to that company. */
00345     if (new_owner != INVALID_OWNER) {
00346       if (HasBit(t->have_ratings, old_owner)) {
00347         if (HasBit(t->have_ratings, new_owner)) {
00348           // use max of the two ratings.
00349           t->ratings[new_owner] = max(t->ratings[new_owner], t->ratings[old_owner]);
00350         } else {
00351           SetBit(t->have_ratings, new_owner);
00352           t->ratings[new_owner] = t->ratings[old_owner];
00353         }
00354       }
00355     }
00356 
00357     /* Reset the ratings for the old owner */
00358     t->ratings[old_owner] = RATING_INITIAL;
00359     ClrBit(t->have_ratings, old_owner);
00360   }
00361 
00362   {
00363     int num_train = 0;
00364     int num_road = 0;
00365     int num_ship = 0;
00366     int num_aircraft = 0;
00367     Vehicle *v;
00368 
00369     /*  Determine Ids for the new vehicles */
00370     FOR_ALL_VEHICLES(v) {
00371       if (v->owner == new_owner) {
00372         switch (v->type) {
00373           case VEH_TRAIN:    if (IsFrontEngine(v)) num_train++; break;
00374           case VEH_ROAD:     if (IsRoadVehFront(v)) num_road++; break;
00375           case VEH_SHIP:     num_ship++; break;
00376           case VEH_AIRCRAFT: if (IsNormalAircraft(v)) num_aircraft++; break;
00377           default: break;
00378         }
00379       }
00380     }
00381 
00382     FOR_ALL_VEHICLES(v) {
00383       if (v->owner == old_owner && IsInsideMM(v->type, VEH_TRAIN, VEH_AIRCRAFT + 1)) {
00384         if (new_owner == INVALID_OWNER) {
00385           DeleteWindowById(WC_VEHICLE_VIEW, v->index);
00386           DeleteWindowById(WC_VEHICLE_DETAILS, v->index);
00387           DeleteWindowById(WC_VEHICLE_ORDERS, v->index);
00388 
00389           if (v->IsPrimaryVehicle() || (v->type == VEH_TRAIN && IsFreeWagon(v))) {
00390             switch (v->type) {
00391               default: NOT_REACHED();
00392 
00393               case VEH_TRAIN: {
00394                 Vehicle *u = v;
00395                 do {
00396                   Vehicle *next = GetNextVehicle(u);
00397                   delete u;
00398                   u = next;
00399                 } while (u != NULL);
00400               } break;
00401 
00402               case VEH_ROAD:
00403               case VEH_SHIP:
00404                 delete v;
00405                 break;
00406 
00407               case VEH_AIRCRAFT:
00408                 DeleteVehicleChain(v);
00409                 break;
00410             }
00411           }
00412         } else {
00413           v->owner = new_owner;
00414           v->colormap = PAL_NONE;
00415           v->group_id = DEFAULT_GROUP;
00416           if (IsEngineCountable(v)) GetCompany(new_owner)->num_engines[v->engine_type]++;
00417           switch (v->type) {
00418             case VEH_TRAIN:    if (IsFrontEngine(v)) v->unitnumber = ++num_train; break;
00419             case VEH_ROAD:     if (IsRoadVehFront(v)) v->unitnumber = ++num_road; break;
00420             case VEH_SHIP:     v->unitnumber = ++num_ship; break;
00421             case VEH_AIRCRAFT: if (IsNormalAircraft(v)) v->unitnumber = ++num_aircraft; break;
00422             default: NOT_REACHED();
00423           }
00424         }
00425       }
00426     }
00427   }
00428 
00429   /*  Change ownership of tiles */
00430   {
00431     TileIndex tile = 0;
00432     do {
00433       ChangeTileOwner(tile, old_owner, new_owner);
00434     } while (++tile != MapSize());
00435 
00436     if (new_owner != INVALID_OWNER) {
00437       /* Update all signals because there can be new segment that was owned by two companies
00438        * and signals were not propagated
00439        * Similiar with crossings - it is needed to bar crossings that weren't before
00440        * because of different owner of crossing and approaching train */
00441       tile = 0;
00442 
00443       do {
00444         if (IsTileType(tile, MP_RAILWAY) && IsTileOwner(tile, new_owner) && HasSignals(tile)) {
00445           TrackBits tracks = GetTrackBits(tile);
00446           do { // there may be two tracks with signals for TRACK_BIT_HORZ and TRACK_BIT_VERT
00447             Track track = RemoveFirstTrack(&tracks);
00448             if (HasSignalOnTrack(tile, track)) AddTrackToSignalBuffer(tile, track, new_owner);
00449           } while (tracks != TRACK_BIT_NONE);
00450         } else if (IsLevelCrossingTile(tile) && IsTileOwner(tile, new_owner)) {
00451           UpdateLevelCrossing(tile);
00452         }
00453       } while (++tile != MapSize());
00454     }
00455 
00456     /* update signals in buffer */
00457     UpdateSignalsInBuffer();
00458   }
00459 
00460   /* In all cases clear replace engine rules.
00461    * Even if it was copied, it could interfere with new owner's rules */
00462   RemoveAllEngineReplacementForCompany(GetCompany(old_owner));
00463 
00464   if (new_owner == INVALID_OWNER) {
00465     RemoveAllGroupsForCompany(old_owner);
00466   } else {
00467     Group *g;
00468     FOR_ALL_GROUPS(g) {
00469       if (g->owner == old_owner) g->owner = new_owner;
00470     }
00471   }
00472 
00473   Sign *si;
00474   FOR_ALL_SIGNS(si) {
00475     if (si->owner == old_owner) si->owner = new_owner == INVALID_OWNER ? OWNER_NONE : new_owner;
00476   }
00477 
00478   /* Change color of existing windows */
00479   if (new_owner != INVALID_OWNER) ChangeWindowOwner(old_owner, new_owner);
00480 
00481   _current_company = old;
00482 
00483   MarkWholeScreenDirty();
00484 }
00485 
00486 static void ChangeNetworkOwner(Owner current_owner, Owner new_owner)
00487 {
00488 #ifdef ENABLE_NETWORK
00489   if (!_networking) return;
00490 
00491   if (current_owner == _local_company) {
00492     _network_playas = new_owner;
00493     SetLocalCompany(new_owner);
00494   }
00495 
00496   if (!_network_server) return;
00497 
00498   NetworkServerChangeOwner(current_owner, new_owner);
00499 #endif /* ENABLE_NETWORK */
00500 }
00501 
00502 static void CompanyCheckBankrupt(Company *c)
00503 {
00504   /*  If the company has money again, it does not go bankrupt */
00505   if (c->money >= 0) {
00506     c->quarters_of_bankrupcy = 0;
00507     return;
00508   }
00509 
00510   c->quarters_of_bankrupcy++;
00511 
00512   CompanyNewsInformation *cni = MallocT<CompanyNewsInformation>(1);
00513   cni->FillData(c);
00514 
00515   switch (c->quarters_of_bankrupcy) {
00516     default:
00517       free(cni);
00518       break;
00519 
00520     case 2:
00521       SetDParam(0, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE);
00522       SetDParam(1, STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED);
00523       SetDParamStr(2, cni->company_name);
00524       AddNewsItem(STR_02B6, NS_COMPANY_TROUBLE, 0, 0, cni);
00525       break;
00526     case 3: {
00527       /* XXX - In multiplayer, should we ask other companies if it wants to take
00528               over when it is a human company? -- TrueLight */
00529       if (IsHumanCompany(c->index)) {
00530         SetDParam(0, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE);
00531         SetDParam(1, STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED);
00532         SetDParamStr(2, cni->company_name);
00533         AddNewsItem(STR_02B6, NS_COMPANY_TROUBLE, 0, 0, cni);
00534         break;
00535       }
00536 
00537       /* Check if the company has any value.. if not, declare it bankrupt
00538        *  right now */
00539       Money val = CalculateCompanyValue(c);
00540       if (val > 0) {
00541         c->bankrupt_value = val;
00542         c->bankrupt_asked = 1 << c->index; // Don't ask the owner
00543         c->bankrupt_timeout = 0;
00544         free(cni);
00545         break;
00546       }
00547       /* Else, falltrue to case 4... */
00548     }
00549     case 4: {
00550       /* Close everything the owner has open */
00551       DeleteCompanyWindows(c->index);
00552 
00553       /* Show bankrupt news */
00554       SetDParam(0, STR_705C_BANKRUPT);
00555       SetDParam(1, STR_705D_HAS_BEEN_CLOSED_DOWN_BY);
00556       SetDParamStr(2, cni->company_name);
00557       AddNewsItem(STR_02B6, NS_COMPANY_BANKRUPT, 0, 0, cni);
00558 
00559       if (IsHumanCompany(c->index)) {
00560         /* XXX - If we are in offline mode, leave the company playing. Eg. there
00561          * is no THE-END, otherwise mark the client as spectator to make sure
00562          * he/she is no long in control of this company */
00563         if (!_networking) {
00564           c->bankrupt_asked = 0xFF;
00565           c->bankrupt_timeout = 0x456;
00566           break;
00567         }
00568 
00569         ChangeNetworkOwner(c->index, COMPANY_SPECTATOR);
00570       }
00571 
00572       /* Remove the company */
00573       ChangeOwnershipOfCompanyItems(c->index, INVALID_OWNER);
00574       /* Register the company as not-active */
00575 
00576       if (!IsHumanCompany(c->index) && (!_networking || _network_server) && _ai.enabled)
00577         AI_CompanyDied(c->index);
00578 
00579       delete c;
00580     }
00581   }
00582 }
00583 
00584 static void CompaniesGenStatistics()
00585 {
00586   Station *st;
00587   Company *c;
00588 
00589   FOR_ALL_STATIONS(st) {
00590     _current_company = st->owner;
00591     CommandCost cost(EXPENSES_PROPERTY, _price.station_value >> 1);
00592     SubtractMoneyFromCompany(cost);
00593   }
00594 
00595   if (!HasBit(1 << 0 | 1 << 3 | 1 << 6 | 1 << 9, _cur_month))
00596     return;
00597 
00598   FOR_ALL_COMPANIES(c) {
00599     memmove(&c->old_economy[1], &c->old_economy[0], sizeof(c->old_economy) - sizeof(c->old_economy[0]));
00600     c->old_economy[0] = c->cur_economy;
00601     memset(&c->cur_economy, 0, sizeof(c->cur_economy));
00602 
00603     if (c->num_valid_stat_ent != 24) c->num_valid_stat_ent++;
00604 
00605     UpdateCompanyRatingAndValue(c, true);
00606     CompanyCheckBankrupt(c);
00607 
00608     if (c->block_preview != 0) c->block_preview--;
00609   }
00610 
00611   InvalidateWindow(WC_INCOME_GRAPH, 0);
00612   InvalidateWindow(WC_OPERATING_PROFIT, 0);
00613   InvalidateWindow(WC_DELIVERED_CARGO, 0);
00614   InvalidateWindow(WC_PERFORMANCE_HISTORY, 0);
00615   InvalidateWindow(WC_COMPANY_VALUE, 0);
00616   InvalidateWindow(WC_COMPANY_LEAGUE, 0);
00617 }
00618 
00619 static void AddSingleInflation(Money *value, uint16 *frac, int32 amt)
00620 {
00621   /* Is it safe to add inflation ? */
00622   if ((INT64_MAX / amt) < (*value + 1)) {
00623     *value = INT64_MAX / amt;
00624     *frac = 0;
00625   } else {
00626     int64 tmp = (int64)*value * amt + *frac;
00627     *frac   = GB(tmp, 0, 16);
00628     *value += tmp >> 16;
00629   }
00630 }
00631 
00632 static void AddInflation(bool check_year = true)
00633 {
00634   /* The cargo payment inflation differs from the normal inflation, so the
00635    * relative amount of money you make with a transport decreases slowly over
00636    * the 170 years. After a few hundred years we reach a level in which the
00637    * games will become unplayable as the maximum income will be less than
00638    * the minimum running cost.
00639    *
00640    * Furthermore there are a lot of inflation related overflows all over the
00641    * place. Solving them is hardly possible because inflation will always
00642    * reach the overflow threshold some day. So we'll just perform the
00643    * inflation mechanism during the first 170 years (the amount of years that
00644    * one had in the original TTD) and stop doing the inflation after that
00645    * because it only causes problems that can't be solved nicely and the
00646    * inflation doesn't add anything after that either; it even makes playing
00647    * it impossible due to the diverging cost and income rates.
00648    */
00649   if (check_year && (_cur_year - _settings_game.game_creation.starting_year) >= (ORIGINAL_MAX_YEAR - ORIGINAL_BASE_YEAR)) return;
00650 
00651   /* Approximation for (100 + infl_amount)% ** (1 / 12) - 100%
00652    * scaled by 65536
00653    * 12 -> months per year
00654    * This is only a good approxiamtion for small values
00655    */
00656   int32 inf = _economy.infl_amount * 54;
00657 
00658   for (uint i = 0; i != NUM_PRICES; i++) {
00659     AddSingleInflation((Money*)&_price + i, _price_frac + i, inf);
00660   }
00661 
00662   AddSingleInflation(&_economy.max_loan_unround, &_economy.max_loan_unround_fract, inf);
00663 
00664   if (_economy.max_loan + 50000 <= _economy.max_loan_unround) _economy.max_loan += 50000;
00665 
00666   inf = _economy.infl_amount_pr * 54;
00667   for (CargoID i = 0; i < NUM_CARGO; i++) {
00668     AddSingleInflation(
00669       (Money*)_cargo_payment_rates + i,
00670       _cargo_payment_rates_frac + i,
00671       inf
00672     );
00673   }
00674 
00675   InvalidateWindowClasses(WC_BUILD_VEHICLE);
00676   InvalidateWindowClasses(WC_REPLACE_VEHICLE);
00677   InvalidateWindowClasses(WC_VEHICLE_DETAILS);
00678   InvalidateWindow(WC_PAYMENT_RATES, 0);
00679 }
00680 
00681 static void CompaniesPayInterest()
00682 {
00683   const Company *c;
00684   int interest = _economy.interest_rate * 54;
00685 
00686   FOR_ALL_COMPANIES(c) {
00687     _current_company = c->index;
00688 
00689     SubtractMoneyFromCompany(CommandCost(EXPENSES_LOAN_INT, (Money)BigMulSU(c->current_loan, interest, 16)));
00690 
00691     SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, _price.station_value >> 2));
00692   }
00693 }
00694 
00695 static void HandleEconomyFluctuations()
00696 {
00697   if (_settings_game.difficulty.economy == 0) return;
00698 
00699   if (--_economy.fluct == 0) {
00700     _economy.fluct = -(int)GB(Random(), 0, 2);
00701     AddNewsItem(STR_7073_WORLD_RECESSION_FINANCIAL, NS_ECONOMY, 0, 0);
00702   } else if (_economy.fluct == -12) {
00703     _economy.fluct = GB(Random(), 0, 8) + 312;
00704     AddNewsItem(STR_7074_RECESSION_OVER_UPTURN_IN, NS_ECONOMY, 0, 0);
00705   }
00706 }
00707 
00708 static byte _price_category[NUM_PRICES] = {
00709   0, 2, 2, 2, 2, 2, 2, 2,
00710   2, 2, 2, 2, 2, 2, 2, 2,
00711   2, 2, 2, 2, 2, 2, 2, 2,
00712   2, 2, 2, 2, 2, 2, 2, 2,
00713   2, 2, 2, 2, 2, 2, 2, 2,
00714   2, 2, 1, 1, 1, 1, 1, 1,
00715   2,
00716 };
00717 
00718 static const Money _price_base[NUM_PRICES] = {
00719       100, 
00720       100, 
00721        95, 
00722        65, 
00723       275, 
00724       600, 
00725       500, 
00726       700, 
00727       450, 
00728       200, 
00729       180, 
00730       600, 
00731       200, 
00732       200, 
00733       350, 
00734    400000, 
00735      2000, 
00736    700000, 
00737     14000, 
00738     65000, 
00739        20, 
00740       250, 
00741        20, 
00742        40, 
00743       200, 
00744       500, 
00745        20, 
00746       -70, 
00747        10, 
00748        50, 
00749        80, 
00750        80, 
00751        90, 
00752        30, 
00753     10000, 
00754        50, 
00755        30, 
00756        50, 
00757        50, 
00758        55, 
00759      1600, 
00760        40, 
00761      5600, 
00762      5200, 
00763      4800, 
00764      9600, 
00765      1600, 
00766      5600, 
00767   1000000, 
00768 };
00769 
00770 static byte price_base_multiplier[NUM_PRICES];
00771 
00775 void ResetPriceBaseMultipliers()
00776 {
00777   uint i;
00778 
00779   /* 8 means no multiplier. */
00780   for (i = 0; i < NUM_PRICES; i++)
00781     price_base_multiplier[i] = 8;
00782 }
00783 
00791 void SetPriceBaseMultiplier(uint price, byte factor)
00792 {
00793   assert(price < NUM_PRICES);
00794   price_base_multiplier[price] = factor;
00795 }
00796 
00801 static void StartupIndustryDailyChanges(bool init_counter)
00802 {
00803   uint map_size = MapLogX() + MapLogY();
00804   /* After getting map size, it needs to be scaled appropriately and divided by 31,
00805    * which stands for the days in a month.
00806    * Using just 31 will make it so that a monthly reset (based on the real number of days of that month)
00807    * would not be needed.
00808    * Since it is based on "fractionnal parts", the leftover days will not make much of a difference
00809    * on the overall total number of changes performed */
00810   _economy.industry_daily_increment = (1 << map_size) / 31;
00811 
00812   if (init_counter) {
00813     /* A new game or a savegame from an older version will require the counter to be initialized */
00814     _economy.industry_daily_change_counter = 0;
00815   }
00816 }
00817 
00818 void StartupEconomy()
00819 {
00820   int i;
00821 
00822   assert(sizeof(_price) == NUM_PRICES * sizeof(Money));
00823 
00824   for (i = 0; i != NUM_PRICES; i++) {
00825     Money price = _price_base[i];
00826     if (_price_category[i] != 0) {
00827       uint mod = _price_category[i] == 1 ? _settings_game.difficulty.vehicle_costs : _settings_game.difficulty.construction_cost;
00828       if (mod < 1) {
00829         price = price * 3 >> 2;
00830       } else if (mod > 1) {
00831         price = price * 9 >> 3;
00832       }
00833     }
00834     if (price_base_multiplier[i] > 8) {
00835       price <<= price_base_multiplier[i] - 8;
00836     } else {
00837       price >>= 8 - price_base_multiplier[i];
00838     }
00839     ((Money*)&_price)[i] = price;
00840     _price_frac[i] = 0;
00841   }
00842 
00843   _economy.interest_rate = _settings_game.difficulty.initial_interest;
00844   _economy.infl_amount = _settings_game.difficulty.initial_interest;
00845   _economy.infl_amount_pr = max(0, _settings_game.difficulty.initial_interest - 1);
00846   _economy.max_loan_unround = _economy.max_loan = _settings_game.difficulty.max_loan;
00847   _economy.fluct = GB(Random(), 0, 8) + 168;
00848 
00849   StartupIndustryDailyChanges(true); // As we are starting a new game, initialize the counter too
00850 
00851 }
00852 
00853 void ResetEconomy()
00854 {
00855   /* Test if resetting the economy is needed. */
00856   bool needed = false;
00857 
00858   for (CargoID c = 0; c < NUM_CARGO; c++) {
00859     const CargoSpec *cs = GetCargo(c);
00860     if (!cs->IsValid()) continue;
00861     if (_cargo_payment_rates[c] == 0) {
00862       needed = true;
00863       break;
00864     }
00865   }
00866 
00867   if (!needed) return;
00868 
00869   /* Remember old unrounded maximum loan value. NewGRF has the ability
00870    * to change all the other inflation affected base costs. */
00871   Money old_value = _economy.max_loan_unround;
00872 
00873   /* Reset the economy */
00874   StartupEconomy();
00875   InitializeLandscapeVariables(false);
00876 
00877   /* Reapply inflation, ignoring the year */
00878   while (old_value > _economy.max_loan_unround) {
00879     AddInflation(false);
00880   }
00881 }
00882 
00883 Money GetPriceByIndex(uint8 index)
00884 {
00885   if (index > NUM_PRICES) return 0;
00886 
00887   return ((Money*)&_price)[index];
00888 }
00889 
00890 
00891 Pair SetupSubsidyDecodeParam(const Subsidy* s, bool mode)
00892 {
00893   TileIndex tile;
00894   TileIndex tile2;
00895   Pair tp;
00896 
00897   /* if mode is false, use the singular form */
00898   const CargoSpec *cs = GetCargo(s->cargo_type);
00899   SetDParam(0, mode ? cs->name : cs->name_single);
00900 
00901   if (s->age < 12) {
00902     if (cs->town_effect != TE_PASSENGERS && cs->town_effect != TE_MAIL) {
00903       SetDParam(1, STR_INDUSTRY);
00904       SetDParam(2, s->from);
00905       tile = GetIndustry(s->from)->xy;
00906 
00907       if (cs->town_effect != TE_GOODS && cs->town_effect != TE_FOOD) {
00908         SetDParam(4, STR_INDUSTRY);
00909         SetDParam(5, s->to);
00910         tile2 = GetIndustry(s->to)->xy;
00911       } else {
00912         SetDParam(4, STR_TOWN);
00913         SetDParam(5, s->to);
00914         tile2 = GetTown(s->to)->xy;
00915       }
00916     } else {
00917       SetDParam(1, STR_TOWN);
00918       SetDParam(2, s->from);
00919       tile = GetTown(s->from)->xy;
00920 
00921       SetDParam(4, STR_TOWN);
00922       SetDParam(5, s->to);
00923       tile2 = GetTown(s->to)->xy;
00924     }
00925   } else {
00926     SetDParam(1, s->from);
00927     tile = GetStation(s->from)->xy;
00928 
00929     SetDParam(2, s->to);
00930     tile2 = GetStation(s->to)->xy;
00931   }
00932 
00933   tp.a = tile;
00934   tp.b = tile2;
00935 
00936   return tp;
00937 }
00938 
00939 void DeleteSubsidyWithTown(TownID index)
00940 {
00941   Subsidy *s;
00942 
00943   for (s = _subsidies; s != endof(_subsidies); s++) {
00944     if (s->cargo_type != CT_INVALID && s->age < 12) {
00945       const CargoSpec *cs = GetCargo(s->cargo_type);
00946       if (((cs->town_effect == TE_PASSENGERS || cs->town_effect == TE_MAIL) && (index == s->from || index == s->to)) ||
00947         ((cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) && index == s->to)) {
00948         s->cargo_type = CT_INVALID;
00949       }
00950     }
00951   }
00952 }
00953 
00954 void DeleteSubsidyWithIndustry(IndustryID index)
00955 {
00956   Subsidy *s;
00957 
00958   for (s = _subsidies; s != endof(_subsidies); s++) {
00959     if (s->cargo_type != CT_INVALID && s->age < 12) {
00960       const CargoSpec *cs = GetCargo(s->cargo_type);
00961       if (cs->town_effect != TE_PASSENGERS && cs->town_effect != TE_MAIL &&
00962         (index == s->from || (cs->town_effect != TE_GOODS && cs->town_effect != TE_FOOD && index == s->to))) {
00963         s->cargo_type = CT_INVALID;
00964       }
00965     }
00966   }
00967 }
00968 
00969 void DeleteSubsidyWithStation(StationID index)
00970 {
00971   Subsidy *s;
00972   bool dirty = false;
00973 
00974   for (s = _subsidies; s != endof(_subsidies); s++) {
00975     if (s->cargo_type != CT_INVALID && s->age >= 12 &&
00976         (s->from == index || s->to == index)) {
00977       s->cargo_type = CT_INVALID;
00978       dirty = true;
00979     }
00980   }
00981 
00982   if (dirty)
00983     InvalidateWindow(WC_SUBSIDIES_LIST, 0);
00984 }
00985 
00986 struct FoundRoute {
00987   uint distance;
00988   CargoID cargo;
00989   void *from;
00990   void *to;
00991 };
00992 
00993 static void FindSubsidyPassengerRoute(FoundRoute *fr)
00994 {
00995   Town *from,*to;
00996 
00997   fr->distance = UINT_MAX;
00998 
00999   fr->from = from = GetRandomTown();
01000   if (from == NULL || from->population < 400) return;
01001 
01002   fr->to = to = GetRandomTown();
01003   if (from == to || to == NULL || to->population < 400 || to->pct_pass_transported > 42)
01004     return;
01005 
01006   fr->distance = DistanceManhattan(from->xy, to->xy);
01007 }
01008 
01009 static void FindSubsidyCargoRoute(FoundRoute *fr)
01010 {
01011   Industry *i;
01012   int trans, total;
01013   CargoID cargo;
01014 
01015   fr->distance = UINT_MAX;
01016 
01017   fr->from = i = GetRandomIndustry();
01018   if (i == NULL) return;
01019 
01020   /* Randomize cargo type */
01021   if (HasBit(Random(), 0) && i->produced_cargo[1] != CT_INVALID) {
01022     cargo = i->produced_cargo[1];
01023     trans = i->last_month_pct_transported[1];
01024     total = i->last_month_production[1];
01025   } else {
01026     cargo = i->produced_cargo[0];
01027     trans = i->last_month_pct_transported[0];
01028     total = i->last_month_production[0];
01029   }
01030 
01031   /* Quit if no production in this industry
01032    * or if the cargo type is passengers
01033    * or if the pct transported is already large enough */
01034   if (total == 0 || trans > 42 || cargo == CT_INVALID) return;
01035 
01036   const CargoSpec *cs = GetCargo(cargo);
01037   if (cs->town_effect == TE_PASSENGERS) return;
01038 
01039   fr->cargo = cargo;
01040 
01041   if (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) {
01042     /*  The destination is a town */
01043     Town *t = GetRandomTown();
01044 
01045     /* Only want big towns */
01046     if (t == NULL || t->population < 900) return;
01047 
01048     fr->distance = DistanceManhattan(i->xy, t->xy);
01049     fr->to = t;
01050   } else {
01051     /* The destination is an industry */
01052     Industry *i2 = GetRandomIndustry();
01053 
01054     /* The industry must accept the cargo */
01055     if (i2 == NULL || i == i2 ||
01056         (cargo != i2->accepts_cargo[0] &&
01057         cargo != i2->accepts_cargo[1] &&
01058         cargo != i2->accepts_cargo[2])) {
01059       return;
01060     }
01061     fr->distance = DistanceManhattan(i->xy, i2->xy);
01062     fr->to = i2;
01063   }
01064 }
01065 
01066 static bool CheckSubsidyDuplicate(Subsidy *s)
01067 {
01068   const Subsidy* ss;
01069 
01070   for (ss = _subsidies; ss != endof(_subsidies); ss++) {
01071     if (s != ss &&
01072         ss->from == s->from &&
01073         ss->to == s->to &&
01074         ss->cargo_type == s->cargo_type) {
01075       s->cargo_type = CT_INVALID;
01076       return true;
01077     }
01078   }
01079   return false;
01080 }
01081 
01082 
01083 static void SubsidyMonthlyHandler()
01084 {
01085   Subsidy *s;
01086   Pair pair;
01087   Station *st;
01088   uint n;
01089   FoundRoute fr;
01090   bool modified = false;
01091 
01092   for (s = _subsidies; s != endof(_subsidies); s++) {
01093     if (s->cargo_type == CT_INVALID) continue;
01094 
01095     if (s->age == 12-1) {
01096       pair = SetupSubsidyDecodeParam(s, 1);
01097       AddNewsItem(STR_202E_OFFER_OF_SUBSIDY_EXPIRED, NS_SUBSIDIES, pair.a, pair.b);
01098       s->cargo_type = CT_INVALID;
01099       modified = true;
01100     } else if (s->age == 2*12-1) {
01101       st = GetStation(s->to);
01102       if (st->owner == _local_company) {
01103         pair = SetupSubsidyDecodeParam(s, 1);
01104         AddNewsItem(STR_202F_SUBSIDY_WITHDRAWN_SERVICE, NS_SUBSIDIES, pair.a, pair.b);
01105       }
01106       s->cargo_type = CT_INVALID;
01107       modified = true;
01108     } else {
01109       s->age++;
01110     }
01111   }
01112 
01113   /* 25% chance to go on */
01114   if (Chance16(1,4)) {
01115     /*  Find a free slot*/
01116     s = _subsidies;
01117     while (s->cargo_type != CT_INVALID) {
01118       if (++s == endof(_subsidies))
01119         goto no_add;
01120     }
01121 
01122     n = 1000;
01123     do {
01124       FindSubsidyPassengerRoute(&fr);
01125       if (fr.distance <= 70) {
01126         s->cargo_type = CT_PASSENGERS;
01127         s->from = ((Town*)fr.from)->index;
01128         s->to = ((Town*)fr.to)->index;
01129         goto add_subsidy;
01130       }
01131       FindSubsidyCargoRoute(&fr);
01132       if (fr.distance <= 70) {
01133         s->cargo_type = fr.cargo;
01134         s->from = ((Industry*)fr.from)->index;
01135         {
01136           const CargoSpec *cs = GetCargo(fr.cargo);
01137           s->to = (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) ? ((Town*)fr.to)->index : ((Industry*)fr.to)->index;
01138         }
01139   add_subsidy:
01140         if (!CheckSubsidyDuplicate(s)) {
01141           s->age = 0;
01142           pair = SetupSubsidyDecodeParam(s, 0);
01143           AddNewsItem(STR_2030_SERVICE_SUBSIDY_OFFERED, NS_SUBSIDIES, pair.a, pair.b);
01144           modified = true;
01145           break;
01146         }
01147       }
01148     } while (n--);
01149   }
01150 no_add:;
01151   if (modified)
01152     InvalidateWindow(WC_SUBSIDIES_LIST, 0);
01153 }
01154 
01155 static const SaveLoad _subsidies_desc[] = {
01156       SLE_VAR(Subsidy, cargo_type, SLE_UINT8),
01157       SLE_VAR(Subsidy, age,        SLE_UINT8),
01158   SLE_CONDVAR(Subsidy, from,       SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
01159   SLE_CONDVAR(Subsidy, from,       SLE_UINT16,                5, SL_MAX_VERSION),
01160   SLE_CONDVAR(Subsidy, to,         SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
01161   SLE_CONDVAR(Subsidy, to,         SLE_UINT16,                5, SL_MAX_VERSION),
01162   SLE_END()
01163 };
01164 
01165 static void Save_SUBS()
01166 {
01167   int i;
01168   Subsidy *s;
01169 
01170   for (i = 0; i != lengthof(_subsidies); i++) {
01171     s = &_subsidies[i];
01172     if (s->cargo_type != CT_INVALID) {
01173       SlSetArrayIndex(i);
01174       SlObject(s, _subsidies_desc);
01175     }
01176   }
01177 }
01178 
01179 static void Load_SUBS()
01180 {
01181   int index;
01182   while ((index = SlIterateArray()) != -1)
01183     SlObject(&_subsidies[index], _subsidies_desc);
01184 }
01185 
01186 Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type)
01187 {
01188   const CargoSpec *cs = GetCargo(cargo_type);
01189 
01190   /* Use callback to calculate cargo profit, if available */
01191   if (HasBit(cs->callback_mask, CBM_CARGO_PROFIT_CALC)) {
01192     uint32 var18 = min(dist, 0xFFFF) | (min(num_pieces, 0xFF) << 16) | (transit_days << 24);
01193     uint16 callback = GetCargoCallback(CBID_CARGO_PROFIT_CALC, 0, var18, cs);
01194     if (callback != CALLBACK_FAILED) {
01195       int result = GB(callback, 0, 14);
01196 
01197       /* Simulate a 15 bit signed value */
01198       if (HasBit(callback, 14)) result = 0x4000 - result;
01199 
01200       /* "The result should be a signed multiplier that gets multiplied
01201        * by the amount of cargo moved and the price factor, then gets
01202        * divided by 8192." */
01203       return result * num_pieces * _cargo_payment_rates[cargo_type] / 8192;
01204     }
01205   }
01206 
01207   /* zero the distance (thus income) if it's the bank and very short transport. */
01208   if (_settings_game.game_creation.landscape == LT_TEMPERATE && cs->label == 'VALU' && dist < 10) return 0;
01209 
01210 
01211   static const int MIN_TIME_FACTOR = 31;
01212   static const int MAX_TIME_FACTOR = 255;
01213 
01214   const int days1 = cs->transit_days[0];
01215   const int days2 = cs->transit_days[1];
01216   const int days_over_days1 = transit_days - days1;
01217 
01218   /*
01219    * The time factor is calculated based on the time it took
01220    * (transit_days) compared two cargo-depending values. The
01221    * range is divided into three parts:
01222    *
01223    *  - constant for fast transits
01224    *  - linear decreasing with time with a slope of -1 for medium transports
01225    *  - linear decreasing with time with a slope of -2 for slow transports
01226    *
01227    */
01228   int time_factor;
01229   if (days_over_days1 <= 0) {
01230     time_factor = MAX_TIME_FACTOR;
01231   } else if (days_over_days1 <= days2) {
01232     time_factor = MAX_TIME_FACTOR - days_over_days1;
01233   } else {
01234     time_factor = MAX_TIME_FACTOR - 2 * days_over_days1 + days2;
01235   }
01236 
01237   if (time_factor < MIN_TIME_FACTOR) time_factor = MIN_TIME_FACTOR;
01238 
01239   return BigMulS(dist * time_factor * num_pieces, _cargo_payment_rates[cargo_type], 21);
01240 }
01241 
01242 
01243 struct FindIndustryToDeliverData {
01244   const Rect *rect;            
01245   CargoID cargo_type;          
01246 
01247   Industry *ind;               
01248   const IndustrySpec *indspec; 
01249   uint cargo_index;            
01250 };
01251 
01252 static bool FindIndustryToDeliver(TileIndex ind_tile, void *user_data)
01253 {
01254   FindIndustryToDeliverData *callback_data = (FindIndustryToDeliverData *)user_data;
01255   const Rect *rect = callback_data->rect;
01256   CargoID cargo_type = callback_data->cargo_type;
01257 
01258   /* Only process industry tiles */
01259   if (!IsTileType(ind_tile, MP_INDUSTRY)) return false;
01260 
01261   /* Only process tiles in the station acceptance rectangle */
01262   int x = TileX(ind_tile);
01263   int y = TileY(ind_tile);
01264   if (x < rect->left || x > rect->right || y < rect->top || y > rect->bottom) return false;
01265 
01266   Industry *ind = GetIndustryByTile(ind_tile);
01267   const IndustrySpec *indspec = GetIndustrySpec(ind->type);
01268 
01269   uint cargo_index;
01270   for (cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
01271     if (cargo_type == ind->accepts_cargo[cargo_index]) break;
01272   }
01273   /* Check if matching cargo has been found */
01274   if (cargo_index >= lengthof(ind->accepts_cargo)) return false;
01275 
01276   /* Check if industry temporarly refuses acceptance */
01277   if (HasBit(indspec->callback_flags,