# economy.cpp

Go to the documentation of this file.

    00001 /* $Id: economy.cpp 16742 2009-07-04 17:39:00Z rubidium $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "openttd.h"
    00007 #include "tile_cmd.h"
    00008 #include "company_func.h"
    00009 #include "command_func.h"
    00010 #include "industry_map.h"
    00011 #include "town.h"
    00012 #include "news_func.h"
    00013 #include "network/network.h"
    00014 #include "network/network_func.h"
    00015 #include "vehicle_gui.h"
    00016 #include "ai/ai.hpp"
    00017 #include "aircraft.h"
    00018 #include "newgrf_engine.h"
    00019 #include "newgrf_sound.h"
    00020 #include "newgrf_industries.h"
    00021 #include "newgrf_industrytiles.h"
    00022 #include "newgrf_station.h"
    00023 #include "unmovable.h"
    00024 #include "group.h"
    00025 #include "strings_func.h"
    00026 #include "functions.h"
    00027 #include "window_func.h"
    00028 #include "date_func.h"
    00029 #include "vehicle_func.h"
    00030 #include "sound_func.h"
    00031 #include "gfx_func.h"
    00032 #include "autoreplace_func.h"
    00033 #include "company_gui.h"
    00034 #include "signs_base.h"
    00035 #include "economy_base.h"
    00036 #include "oldpool_func.h"
    00037
    00038 #include "table/strings.h"
    00039 #include "table/sprites.h"
    00040
    00041
    00042 /* Initialize the cargo payment-pool */
    00043 DEFINE_OLD_POOL_GENERIC(CargoPayment, CargoPayment)
    00044
    00045
    00056 static inline int32 BigMulS(const int32 a, const int32 b, const uint8 shift)
    00057 {
    00058   return (int32)((int64)a * (int64)b >> shift);
    00059 }
    00060
    00072 static inline uint32 BigMulSU(const uint32 a, const uint32 b, const uint8 shift)
    00073 {
    00074   return (uint32)((uint64)a * (uint64)b >> shift);
    00075 }
    00076
    00077 typedef SmallVector<Industry *, 16> SmallIndustryList;
    00078
    00079 /* Score info */
    00080 const ScoreInfo _score_info[] = {
    00081   { SCORE_VEHICLES,        120, 100 },
    00082   { SCORE_STATIONS,         80, 100 },
    00083   { SCORE_MIN_PROFIT,    10000, 100 },
    00084   { SCORE_MIN_INCOME,    50000,  50 },
    00085   { SCORE_MAX_INCOME,   100000, 100 },
    00086   { SCORE_DELIVERED,     40000, 400 },
    00087   { SCORE_CARGO,             8,  50 },
    00088   { SCORE_MONEY,      10000000,  50 },
    00089   { SCORE_LOAN,         250000,  50 },
    00090   { SCORE_TOTAL,             0,   0 }
    00091 };
    00092
    00093 int _score_part[MAX_COMPANIES][SCORE_END];
    00094 Economy _economy;
    00095 Subsidy _subsidies[MAX_COMPANIES];
    00096 Prices _price;
    00097 uint16 _price_frac[NUM_PRICES];
    00098 Money  _cargo_payment_rates[NUM_CARGO];
    00099 uint16 _cargo_payment_rates_frac[NUM_CARGO];
    00100 Money _additional_cash_required;
    00101
    00102 Money CalculateCompanyValue(const Company *c)
    00103 {
    00104   Owner owner = c->index;
    00105   Money value = 0;
    00106
    00107   Station *st;
    00108   uint num = 0;
    00109
    00110   FOR_ALL_STATIONS(st) {
    00111     if (st->owner == owner) num += CountBits(st->facilities);
    00112   }
    00113
    00114   value += num * _price.station_value * 25;
    00115
    00116   Vehicle *v;
    00117   FOR_ALL_VEHICLES(v) {
    00118     if (v->owner != owner) continue;
    00119
    00120     if (v->type == VEH_TRAIN ||
    00121         v->type == VEH_ROAD ||
    00122         (v->type == VEH_AIRCRAFT && IsNormalAircraft(v)) ||
    00123         v->type == VEH_SHIP) {
    00124       value += v->value * 3 >> 1;
    00125     }
    00126   }
    00127
    00128   /* Add real money value */
    00129   value -= c->current_loan;
    00130   value += c->money;
    00131
    00132   return max(value, (Money)1);
    00133 }
    00134
    00141 int UpdateCompanyRatingAndValue(Company *c, bool update)
    00142 {
    00143   Owner owner = c->index;
    00144   int score = 0;
    00145
    00146   memset(_score_part[owner], 0, sizeof(_score_part[owner]));
    00147
    00148   /* Count vehicles */
    00149   {
    00150     Vehicle *v;
    00151     Money min_profit = 0;
    00152     bool min_profit_first = true;
    00153     uint num = 0;
    00154
    00155     FOR_ALL_VEHICLES(v) {
    00156       if (v->owner != owner) continue;
    00157       if (IsCompanyBuildableVehicleType(v->type) && v->IsPrimaryVehicle()) {
    00158         num++;
    00159         if (v->age > 730) {
    00160           /* Find the vehicle with the lowest amount of profit */
    00161           if (min_profit_first || min_profit > v->profit_last_year) {
    00162             min_profit = v->profit_last_year;
    00163             min_profit_first = false;
    00164           }
    00165         }
    00166       }
    00167     }
    00168
    00169     min_profit >>= 8; // remove the fract part
    00170
    00171     _score_part[owner][SCORE_VEHICLES] = num;
    00172     /* Don't allow negative min_profit to show */
    00173     if (min_profit > 0)
    00174       _score_part[owner][SCORE_MIN_PROFIT] = ClampToI32(min_profit);
    00175   }
    00176
    00177   /* Count stations */
    00178   {
    00179     uint num = 0;
    00180     const Station *st;
    00181
    00182     FOR_ALL_STATIONS(st) {
    00183       if (st->owner == owner) num += CountBits(st->facilities);
    00184     }
    00185     _score_part[owner][SCORE_STATIONS] = num;
    00186   }
    00187
    00188   /* Generate statistics depending on recent income statistics */
    00189   {
    00190     int numec = min(c->num_valid_stat_ent, 12);
    00191     if (numec != 0) {
    00192       const CompanyEconomyEntry *cee = c->old_economy;
    00193       Money min_income = cee->income + cee->expenses;
    00194       Money max_income = cee->income + cee->expenses;
    00195
    00196       do {
    00197         min_income = min(min_income, cee->income + cee->expenses);
    00198         max_income = max(max_income, cee->income + cee->expenses);
    00199       } while (++cee, --numec);
    00200
    00201       if (min_income > 0) {
    00202         _score_part[owner][SCORE_MIN_INCOME] = ClampToI32(min_income);
    00203       }
    00204
    00205       _score_part[owner][SCORE_MAX_INCOME] = ClampToI32(max_income);
    00206     }
    00207   }
    00208
    00209   /* Generate score depending on amount of transported cargo */
    00210   {
    00211     const CompanyEconomyEntry *cee;
    00212     int numec;
    00213     uint32 total_delivered;
    00214
    00215     numec = min(c->num_valid_stat_ent, 4);
    00216     if (numec != 0) {
    00217       cee = c->old_economy;
    00218       total_delivered = 0;
    00219       do {
    00220         total_delivered += cee->delivered_cargo;
    00221       } while (++cee, --numec);
    00222
    00223       _score_part[owner][SCORE_DELIVERED] = total_delivered;
    00224     }
    00225   }
    00226
    00227   /* Generate score for variety of cargo */
    00228   {
    00229     uint num = CountBits(c->cargo_types);
    00230     _score_part[owner][SCORE_CARGO] = num;
    00231     if (update) c->cargo_types = 0;
    00232   }
    00233
    00234   /* Generate score for company's money */
    00235   {
    00236     if (c->money > 0) {
    00237       _score_part[owner][SCORE_MONEY] = ClampToI32(c->money);
    00238     }
    00239   }
    00240
    00241   /* Generate score for loan */
    00242   {
    00243     _score_part[owner][SCORE_LOAN] = ClampToI32(_score_info[SCORE_LOAN].needed - c->current_loan);
    00244   }
    00245
    00246   /* Now we calculate the score for each item.. */
    00247   {
    00248     int total_score = 0;
    00249     int s;
    00250     score = 0;
    00251     for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) {
    00252       /* Skip the total */
    00253       if (i == SCORE_TOTAL) continue;
    00254       /*  Check the score */
    00255       s = Clamp(_score_part[owner][i], 0, _score_info[i].needed) * _score_info[i].score / _score_info[i].needed;
    00256       score += s;
    00257       total_score += _score_info[i].score;
    00258     }
    00259
    00260     _score_part[owner][SCORE_TOTAL] = score;
    00261
    00262     /*  We always want the score scaled to SCORE_MAX (1000) */
    00263     if (total_score != SCORE_MAX) score = score * SCORE_MAX / total_score;
    00264   }
    00265
    00266   if (update) {
    00267     c->old_economy[0].performance_history = score;
    00268     UpdateCompanyHQ(c, score);
    00269     c->old_economy[0].company_value = CalculateCompanyValue(c);
    00270   }
    00271
    00272   InvalidateWindow(WC_PERFORMANCE_DETAIL, 0);
    00273   return score;
    00274 }
    00275
    00276 /*  use INVALID_OWNER as new_owner to delete the company. */
    00277 void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner)
    00278 {
    00279   Town *t;
    00280   CompanyID old = _current_company;
    00281
    00282   assert(old_owner != new_owner);
    00283
    00284   {
    00285     Company *c;
    00286     uint i;
    00287
    00288     /* See if the old_owner had shares in other companies */
    00289     _current_company = old_owner;
    00290     FOR_ALL_COMPANIES(c) {
    00291       for (i = 0; i < 4; i++) {
    00292         if (c->share_owners[i] == old_owner) {
    00293           /* Sell his shares */
    00294           CommandCost res = DoCommand(0, c->index, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY);
    00295           /* Because we are in a DoCommand, we can't just execute an other one and
    00296            *  expect the money to be removed. We need to do it ourself! */
    00297           SubtractMoneyFromCompany(res);
    00298         }
    00299       }
    00300     }
    00301
    00302     /* Sell all the shares that people have on this company */
    00303     c = GetCompany(old_owner);
    00304     for (i = 0; i < 4; i++) {
    00305       _current_company = c->share_owners[i];
    00306       if (_current_company != INVALID_OWNER) {
    00307         /* Sell the shares */
    00308         CommandCost res = DoCommand(0, old_owner, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY);
    00309         /* Because we are in a DoCommand, we can't just execute an other one and
    00310          *  expect the money to be removed. We need to do it ourself! */
    00311         SubtractMoneyFromCompany(res);
    00312       }
    00313     }
    00314   }
    00315
    00316   _current_company = old_owner;
    00317
    00318   /* Temporarily increase the company's money, to be sure that
    00319    * removing his/her property doesn't fail because of lack of money.
    00320    * Not too drastically though, because it could overflow */
    00321   if (new_owner == INVALID_OWNER) {
    00322     GetCompany(old_owner)->money = UINT64_MAX >> 2; // jackpot ;p
    00323   }
    00324
    00325   if (new_owner == INVALID_OWNER) {
    00326     Subsidy *s;
    00327
    00328     for (s = _subsidies; s != endof(_subsidies); s++) {
    00329       if (s->cargo_type != CT_INVALID && s->age >= 12) {
    00330         if (GetStation(s->to)->owner == old_owner) s->cargo_type = CT_INVALID;
    00331       }
    00332     }
    00333   }
    00334
    00335   /* Take care of rating in towns */
    00336   FOR_ALL_TOWNS(t) {
    00337     /* If a company takes over, give the ratings to that company. */
    00338     if (new_owner != INVALID_OWNER) {
    00339       if (HasBit(t->have_ratings, old_owner)) {
    00340         if (HasBit(t->have_ratings, new_owner)) {
    00341           /* use max of the two ratings. */
    00342           t->ratings[new_owner] = max(t->ratings[new_owner], t->ratings[old_owner]);
    00343         } else {
    00344           SetBit(t->have_ratings, new_owner);
    00345           t->ratings[new_owner] = t->ratings[old_owner];
    00346         }
    00347       }
    00348     }
    00349
    00350     /* Reset the ratings for the old owner */
    00351     t->ratings[old_owner] = RATING_INITIAL;
    00352     ClrBit(t->have_ratings, old_owner);
    00353   }
    00354
    00355   {
    00356     FreeUnitIDGenerator unitidgen[] = {
    00357       FreeUnitIDGenerator(VEH_TRAIN, new_owner), FreeUnitIDGenerator(VEH_ROAD,     new_owner),
    00358       FreeUnitIDGenerator(VEH_SHIP,  new_owner), FreeUnitIDGenerator(VEH_AIRCRAFT, new_owner)
    00359     };
    00360
    00361     Vehicle *v;
    00362     FOR_ALL_VEHICLES(v) {
    00363       if (v->owner == old_owner && IsCompanyBuildableVehicleType(v->type)) {
    00364         if (new_owner == INVALID_OWNER) {
    00365           if (v->Previous() == NULL) delete v;
    00366         } else {
    00367           v->owner = new_owner;
    00368           v->colourmap = PAL_NONE;
    00369           if (IsEngineCountable(v)) GetCompany(new_owner)->num_engines[v->engine_type]++;
    00370           if (v->IsPrimaryVehicle()) v->unitnumber = unitidgen[v->type].NextID();
    00371         }
    00372       }
    00373     }
    00374   }
    00375
    00376   /*  Change ownership of tiles */
    00377   {
    00378     TileIndex tile = 0;
    00379     do {
    00380       ChangeTileOwner(tile, old_owner, new_owner);
    00381     } while (++tile != MapSize());
    00382
    00383     if (new_owner != INVALID_OWNER) {
    00384       /* Update all signals because there can be new segment that was owned by two companies
    00385        * and signals were not propagated
    00386        * Similiar with crossings - it is needed to bar crossings that weren't before
    00387        * because of different owner of crossing and approaching train */
    00388       tile = 0;
    00389
    00390       do {
    00391         if (IsTileType(tile, MP_RAILWAY) && IsTileOwner(tile, new_owner) && HasSignals(tile)) {
    00392           TrackBits tracks = GetTrackBits(tile);
    00393           do { // there may be two tracks with signals for TRACK_BIT_HORZ and TRACK_BIT_VERT
    00394             Track track = RemoveFirstTrack(&tracks);
    00395             if (HasSignalOnTrack(tile, track)) AddTrackToSignalBuffer(tile, track, new_owner);
    00396           } while (tracks != TRACK_BIT_NONE);
    00397         } else if (IsLevelCrossingTile(tile) && IsTileOwner(tile, new_owner)) {
    00398           UpdateLevelCrossing(tile);
    00399         }
    00400       } while (++tile != MapSize());
    00401     }
    00402
    00403     /* update signals in buffer */
    00404     UpdateSignalsInBuffer();
    00405   }
    00406
    00407   /* convert owner of stations (including deleted ones, but excluding buoys) */
    00408   Station *st;
    00409   FOR_ALL_STATIONS(st) {
    00410     if (st->owner == old_owner) {
    00411       /* if a company goes bankrupt, set owner to OWNER_NONE so the sign doesn't disappear immediately
    00412        * also, drawing station window would cause reading invalid company's colour */
    00413       st->owner = new_owner == INVALID_OWNER ? OWNER_NONE : new_owner;
    00414     }
    00415   }
    00416
    00417   /* do the same for waypoints (we need to do this here so deleted waypoints are converted too) */
    00418   Waypoint *wp;
    00419   FOR_ALL_WAYPOINTS(wp) {
    00420     if (wp->owner == old_owner) {
    00421       wp->owner = new_owner == INVALID_OWNER ? OWNER_NONE : new_owner;
    00422     }
    00423   }
    00424
    00425   /* In all cases clear replace engine rules.
    00426    * Even if it was copied, it could interfere with new owner's rules */
    00427   RemoveAllEngineReplacementForCompany(GetCompany(old_owner));
    00428
    00429   if (new_owner == INVALID_OWNER) {
    00430     RemoveAllGroupsForCompany(old_owner);
    00431   } else {
    00432     Group *g;
    00433     FOR_ALL_GROUPS(g) {
    00434       if (g->owner == old_owner) g->owner = new_owner;
    00435     }
    00436   }
    00437
    00438   Sign *si;
    00439   FOR_ALL_SIGNS(si) {
    00440     if (si->owner == old_owner) si->owner = new_owner == INVALID_OWNER ? OWNER_NONE : new_owner;
    00441   }
    00442
    00443   /* Change colour of existing windows */
    00444   if (new_owner != INVALID_OWNER) ChangeWindowOwner(old_owner, new_owner);
    00445
    00446   _current_company = old;
    00447
    00448   MarkWholeScreenDirty();
    00449 }
    00450
    00451 static void ChangeNetworkOwner(Owner current_owner, Owner new_owner)
    00452 {
    00453 #ifdef ENABLE_NETWORK
    00454   if (!_networking) return;
    00455
    00456   if (current_owner == _local_company) {
    00457     _network_playas = new_owner;
    00458     SetLocalCompany(new_owner);
    00459   }
    00460
    00461   if (!_network_server) return;
    00462
    00463   NetworkServerChangeOwner(current_owner, new_owner);
    00464 #endif /* ENABLE_NETWORK */
    00465 }
    00466
    00467 static void CompanyCheckBankrupt(Company *c)
    00468 {
    00469   /*  If the company has money again, it does not go bankrupt */
    00470   if (c->money >= 0) {
    00471     c->quarters_of_bankrupcy = 0;
    00472     return;
    00473   }
    00474
    00475   c->quarters_of_bankrupcy++;
    00476
    00477   CompanyNewsInformation *cni = MallocT<CompanyNewsInformation>(1);
    00478   cni->FillData(c);
    00479
    00480   switch (c->quarters_of_bankrupcy) {
    00481     case 0:
    00482     case 1:
    00483       free(cni);
    00484       break;
    00485
    00486     case 2:
    00487       SetDParam(0, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE);
    00488       SetDParam(1, STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED);
    00489       SetDParamStr(2, cni->company_name);
    00490       AddNewsItem(STR_02B6, NS_COMPANY_TROUBLE, 0, 0, cni);
    00491       AI::BroadcastNewEvent(new AIEventCompanyInTrouble(c->index));
    00492       break;
    00493     case 3: {
    00494       /* XXX - In multiplayer, should we ask other companies if it wants to take
    00495               over when it is a human company? -- TrueLight */
    00496       if (IsHumanCompany(c->index)) {
    00497         SetDParam(0, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE);
    00498         SetDParam(1, STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED);
    00499         SetDParamStr(2, cni->company_name);
    00500         AddNewsItem(STR_02B6, NS_COMPANY_TROUBLE, 0, 0, cni);
    00501         break;
    00502       }
    00503
    00504       /* Check if the company has any value.. if not, declare it bankrupt
    00505        *  right now */
    00506       Money val = CalculateCompanyValue(c);
    00507       if (val > 0) {
    00508         c->bankrupt_value = val;
    00509         c->bankrupt_asked = 1 << c->index; // Don't ask the owner
    00510         c->bankrupt_timeout = 0;
    00511         free(cni);
    00512         break;
    00513       }
    00514       /* Else, falltrue to case 4... */
    00515     }
    00516     default:
    00517     case 4:
    00518       if (!_networking && _local_company == c->index) {
    00519         /* If we are in offline mode, leave the company playing. Eg. there
    00520          * is no THE-END, otherwise mark the client as spectator to make sure
    00521          * he/she is no long in control of this company. However... when you
    00522          * join another company (cheat) the "unowned" company can bankrupt. */
    00523         c->bankrupt_asked = MAX_UVALUE(CompanyMask);
    00524         c->bankrupt_timeout = 0x456;
    00525         break;
    00526       }
    00527
    00528       /* Close everything the owner has open */
    00529       DeleteCompanyWindows(c->index);
    00530
    00531       /* Show bankrupt news */
    00532       SetDParam(0, STR_705C_BANKRUPT);
    00533       SetDParam(1, STR_705D_HAS_BEEN_CLOSED_DOWN_BY);
    00534       SetDParamStr(2, cni->company_name);
    00535       AddNewsItem(STR_02B6, NS_COMPANY_BANKRUPT, 0, 0, cni);
    00536
    00537       /* Remove the company */
    00538       ChangeNetworkOwner(c->index, COMPANY_SPECTATOR);
    00539       ChangeOwnershipOfCompanyItems(c->index, INVALID_OWNER);
    00540
    00541       if (!IsHumanCompany(c->index)) AI::Stop(c->index);
    00542
    00543       CompanyID c_index = c->index;
    00544       delete c;
    00545       AI::BroadcastNewEvent(new AIEventCompanyBankrupt(c_index));
    00546   }
    00547 }
    00548
    00549 static void CompaniesGenStatistics()
    00550 {
    00551   Station *st;
    00552   Company *c;
    00553
    00554   FOR_ALL_STATIONS(st) {
    00555     _current_company = st->owner;
    00556     CommandCost cost(EXPENSES_PROPERTY, _price.station_value >> 1);
    00557     SubtractMoneyFromCompany(cost);
    00558   }
    00559
    00560   if (!HasBit(1 << 0 | 1 << 3 | 1 << 6 | 1 << 9, _cur_month))
    00561     return;
    00562
    00563   FOR_ALL_COMPANIES(c) {
    00564     memmove(&c->old_economy[1], &c->old_economy[0], sizeof(c->old_economy) - sizeof(c->old_economy[0]));
    00565     c->old_economy[0] = c->cur_economy;
    00566     memset(&c->cur_economy, 0, sizeof(c->cur_economy));
    00567
    00568     if (c->num_valid_stat_ent != 24) c->num_valid_stat_ent++;
    00569
    00570     UpdateCompanyRatingAndValue(c, true);
    00571     CompanyCheckBankrupt(c);
    00572
    00573     if (c->block_preview != 0) c->block_preview--;
    00574   }
    00575
    00576   InvalidateWindow(WC_INCOME_GRAPH, 0);
    00577   InvalidateWindow(WC_OPERATING_PROFIT, 0);
    00578   InvalidateWindow(WC_DELIVERED_CARGO, 0);
    00579   InvalidateWindow(WC_PERFORMANCE_HISTORY, 0);
    00580   InvalidateWindow(WC_COMPANY_VALUE, 0);
    00581   InvalidateWindow(WC_COMPANY_LEAGUE, 0);
    00582 }
    00583
    00584 static void AddSingleInflation(Money *value, uint16 *frac, int32 amt)
    00585 {
    00586   /* Is it safe to add inflation ? */
    00587   if ((INT64_MAX / amt) < (*value + 1)) {
    00588     *value = INT64_MAX / amt;
    00589     *frac = 0;
    00590   } else {
    00591     int64 tmp = (int64)*value * amt + *frac;
    00592     *frac   = GB(tmp, 0, 16);
    00593     *value += tmp >> 16;
    00594   }
    00595 }
    00596
    00597 static void AddInflation(bool check_year = true)
    00598 {
    00599   /* The cargo payment inflation differs from the normal inflation, so the
    00600    * relative amount of money you make with a transport decreases slowly over
    00601    * the 170 years. After a few hundred years we reach a level in which the
    00602    * games will become unplayable as the maximum income will be less than
    00603    * the minimum running cost.
    00604    *
    00605    * Furthermore there are a lot of inflation related overflows all over the
    00606    * place. Solving them is hardly possible because inflation will always
    00607    * reach the overflow threshold some day. So we'll just perform the
    00608    * inflation mechanism during the first 170 years (the amount of years that
    00609    * one had in the original TTD) and stop doing the inflation after that
    00610    * because it only causes problems that can't be solved nicely and the
    00611    * inflation doesn't add anything after that either; it even makes playing
    00612    * it impossible due to the diverging cost and income rates.
    00613    */
    00614   if (check_year && (_cur_year - _settings_game.game_creation.starting_year) >= (ORIGINAL_MAX_YEAR - ORIGINAL_BASE_YEAR)) return;
    00615
    00616   /* Approximation for (100 + infl_amount)% ** (1 / 12) - 100%
    00617    * scaled by 65536
    00618    * 12 -> months per year
    00619    * This is only a good approxiamtion for small values
    00620    */
    00621   int32 inf = _economy.infl_amount * 54;
    00622
    00623   for (uint i = 0; i != NUM_PRICES; i++) {
    00624     AddSingleInflation((Money*)&_price + i, _price_frac + i, inf);
    00625   }
    00626
    00627   AddSingleInflation(&_economy.max_loan_unround, &_economy.max_loan_unround_fract, inf);
    00628
    00629   if (_economy.max_loan + 50000 <= _economy.max_loan_unround) _economy.max_loan += 50000;
    00630
    00631   inf = _economy.infl_amount_pr * 54;
    00632   for (CargoID i = 0; i < NUM_CARGO; i++) {
    00633     AddSingleInflation(
    00634       (Money*)_cargo_payment_rates + i,
    00635       _cargo_payment_rates_frac + i,
    00636       inf
    00637     );
    00638   }
    00639
    00640   InvalidateWindowClasses(WC_BUILD_VEHICLE);
    00641   InvalidateWindowClasses(WC_REPLACE_VEHICLE);
    00642   InvalidateWindowClasses(WC_VEHICLE_DETAILS);
    00643   InvalidateWindow(WC_PAYMENT_RATES, 0);
    00644 }
    00645
    00646 static void CompaniesPayInterest()
    00647 {
    00648   const Company *c;
    00649
    00650   FOR_ALL_COMPANIES(c) {
    00651     _current_company = c->index;
    00652
    00653     /* Over a year the paid interest should be "loan * interest percentage",
    00654      * but... as that number is likely not dividable by 12 (pay each month),
    00655      * one needs to account for that in the monthly fee calculations.
    00656      * To easily calculate what one should pay "this" month, you calculate
    00657      * what (total) should have been paid up to this month and you substract
    00658      * whatever has been paid in the previous months. This will mean one month
    00659      * it'll be a bit more and the other it'll be a bit less than the average
    00660      * monthly fee, but on average it will be exact. */
    00661     Money yearly_fee = c->current_loan * _economy.interest_rate / 100;
    00662     Money up_to_previous_month = yearly_fee * _cur_month / 12;
    00663     Money up_to_this_month = yearly_fee * (_cur_month + 1) / 12;
    00664
    00665     SubtractMoneyFromCompany(CommandCost(EXPENSES_LOAN_INT, up_to_this_month - up_to_previous_month));
    00666
    00667     SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, _price.station_value >> 2));
    00668   }
    00669 }
    00670
    00671 static void HandleEconomyFluctuations()
    00672 {
    00673   if (_settings_game.difficulty.economy == 0) return;
    00674
    00675   if (--_economy.fluct == 0) {
    00676     _economy.fluct = -(int)GB(Random(), 0, 2);
    00677     AddNewsItem(STR_7073_WORLD_RECESSION_FINANCIAL, NS_ECONOMY, 0, 0);
    00678   } else if (_economy.fluct == -12) {
    00679     _economy.fluct = GB(Random(), 0, 8) + 312;
    00680     AddNewsItem(STR_7074_RECESSION_OVER_UPTURN_IN, NS_ECONOMY, 0, 0);
    00681   }
    00682 }
    00683
    00684 static byte _price_category[NUM_PRICES] = {
    00685   0, 2, 2, 2, 2, 2, 2, 2,
    00686   2, 2, 2, 2, 2, 2, 2, 2,
    00687   2, 2, 2, 2, 2, 2, 2, 2,
    00688   2, 2, 2, 2, 2, 2, 2, 2,
    00689   2, 2, 2, 2, 2, 2, 2, 2,
    00690   2, 2, 1, 1, 1, 1, 1, 1,
    00691   2,
    00692 };
    00693
    00694 static const Money _price_base[NUM_PRICES] = {
    00695       100,
    00696       100,
    00697        95,
    00698        65,
    00699       275,
    00700       600,
    00701       500,
    00702       700,
    00703       450,
    00704       200,
    00705       180,
    00706       600,
    00707       200,
    00708       200,
    00709       350,
    00710    400000,
    00711      2000,
    00712    700000,
    00713     14000,
    00714     65000,
    00715        20,
    00716       250,
    00717        20,
    00718        40,
    00719       200,
    00720       500,
    00721        20,
    00722       -70,
    00723        10,
    00724        50,
    00725        80,
    00726        80,
    00727        90,
    00728        30,
    00729     10000,
    00730        50,
    00731        30,
    00732        50,
    00733        50,
    00734        55,
    00735      1600,
    00736        40,
    00737      5600,
    00738      5200,
    00739      4800,
    00740      9600,
    00741      1600,
    00742      5600,
    00743   1000000,
    00744 };
    00745
    00746 static byte price_base_multiplier[NUM_PRICES];
    00747
    00751 void ResetPriceBaseMultipliers()
    00752 {
    00753   uint i;
    00754
    00755   /* 8 means no multiplier. */
    00756   for (i = 0; i < NUM_PRICES; i++)
    00757     price_base_multiplier[i] = 8;
    00758 }
    00759
    00767 void SetPriceBaseMultiplier(uint price, byte factor)
    00768 {
    00769   assert(price < NUM_PRICES);
    00770   price_base_multiplier[price] = factor;
    00771 }
    00772
    00777 void StartupIndustryDailyChanges(bool init_counter)
    00778 {
    00779   uint map_size = MapLogX() + MapLogY();
    00780   /* After getting map size, it needs to be scaled appropriately and divided by 31,
    00781    * which stands for the days in a month.
    00782    * Using just 31 will make it so that a monthly reset (based on the real number of days of that month)
    00783    * would not be needed.
    00784    * Since it is based on "fractionnal parts", the leftover days will not make much of a difference
    00785    * on the overall total number of changes performed */
    00786   _economy.industry_daily_increment = (1 << map_size) / 31;
    00787
    00788   if (init_counter) {
    00789     /* A new game or a savegame from an older version will require the counter to be initialized */
    00790     _economy.industry_daily_change_counter = 0;
    00791   }
    00792 }
    00793
    00794 void StartupEconomy()
    00795 {
    00796   int i;
    00797
    00798   assert(sizeof(_price) == NUM_PRICES * sizeof(Money));
    00799
    00800   for (i = 0; i != NUM_PRICES; i++) {
    00801     Money price = _price_base[i];
    00802     if (_price_category[i] != 0) {
    00803       uint mod = _price_category[i] == 1 ? _settings_game.difficulty.vehicle_costs : _settings_game.difficulty.construction_cost;
    00804       if (mod < 1) {
    00805         price = price * 3 >> 2;
    00806       } else if (mod > 1) {
    00807         price = price * 9 >> 3;
    00808       }
    00809     }
    00810     if (price_base_multiplier[i] > 8) {
    00811       price <<= price_base_multiplier[i] - 8;
    00812     } else {
    00813       price >>= 8 - price_base_multiplier[i];
    00814     }
    00815     ((Money*)&_price)[i] = price;
    00816     _price_frac[i] = 0;
    00817   }
    00818
    00819   _economy.interest_rate = _settings_game.difficulty.initial_interest;
    00820   _economy.infl_amount = _settings_game.difficulty.initial_interest;
    00821   _economy.infl_amount_pr = max(0, _settings_game.difficulty.initial_interest - 1);
    00822   _economy.max_loan_unround = _economy.max_loan = _settings_game.difficulty.max_loan;
    00823   _economy.fluct = GB(Random(), 0, 8) + 168;
    00824
    00825   StartupIndustryDailyChanges(true); // As we are starting a new game, initialize the counter too
    00826
    00827 }
    00828
    00829 void ResetEconomy()
    00830 {
    00831   /* Test if resetting the economy is needed. */
    00832   bool needed = false;
    00833
    00834   for (CargoID c = 0; c < NUM_CARGO; c++) {
    00835     const CargoSpec *cs = GetCargo(c);
    00836     if (!cs->IsValid()) continue;
    00837     if (_cargo_payment_rates[c] == 0) {
    00838       needed = true;
    00839       break;
    00840     }
    00841   }
    00842
    00843   if (!needed) return;
    00844
    00845   /* Remember old unrounded maximum loan value. NewGRF has the ability
    00846    * to change all the other inflation affected base costs. */
    00847   Money old_value = _economy.max_loan_unround;
    00848
    00849   /* Reset the economy */
    00850   StartupEconomy();
    00851   InitializeLandscapeVariables(false);
    00852
    00853   /* Reapply inflation, ignoring the year */
    00854   while (old_value > _economy.max_loan_unround) {
    00855     AddInflation(false);
    00856   }
    00857 }
    00858
    00859 Money GetPriceByIndex(uint8 index)
    00860 {
    00861   if (index > NUM_PRICES) return 0;
    00862
    00863   return ((Money*)&_price)[index];
    00864 }
    00865
    00866
    00867 Pair SetupSubsidyDecodeParam(const Subsidy *s, bool mode)
    00868 {
    00869   TileIndex tile;
    00870   TileIndex tile2;
    00871   Pair tp;
    00872
    00873   /* if mode is false, use the singular form */
    00874   const CargoSpec *cs = GetCargo(s->cargo_type);
    00875   SetDParam(0, mode ? cs->name : cs->name_single);
    00876
    00877   if (s->age < 12) {
    00878     if (cs->town_effect != TE_PASSENGERS && cs->town_effect != TE_MAIL) {
    00879       SetDParam(1, STR_INDUSTRY);
    00880       SetDParam(2, s->from);
    00881       tile = GetIndustry(s->from)->xy;
    00882
    00883       if (cs->town_effect != TE_GOODS && cs->town_effect != TE_FOOD) {
    00884         SetDParam(4, STR_INDUSTRY);
    00885         SetDParam(5, s->to);
    00886         tile2 = GetIndustry(s->to)->xy;
    00887       } else {
    00888         SetDParam(4, STR_TOWN);
    00889         SetDParam(5, s->to);
    00890         tile2 = GetTown(s->to)->xy;
    00891       }
    00892     } else {
    00893       SetDParam(1, STR_TOWN);
    00894       SetDParam(2, s->from);
    00895       tile = GetTown(s->from)->xy;
    00896
    00897       SetDParam(4, STR_TOWN);
    00898       SetDParam(5, s->to);
    00899       tile2 = GetTown(s->to)->xy;
    00900     }
    00901   } else {
    00902     SetDParam(1, s->from);
    00903     tile = GetStation(s->from)->xy;
    00904
    00905     SetDParam(2, s->to);
    00906     tile2 = GetStation(s->to)->xy;
    00907   }
    00908
    00909   tp.a = tile;
    00910   tp.b = tile2;
    00911
    00912   return tp;
    00913 }
    00914
    00915 void DeleteSubsidyWithTown(TownID index)
    00916 {
    00917   Subsidy *s;
    00918
    00919   for (s = _subsidies; s != endof(_subsidies); s++) {
    00920     if (s->cargo_type != CT_INVALID && s->age < 12) {
    00921       const CargoSpec *cs = GetCargo(s->cargo_type);
    00922       if (((cs->town_effect == TE_PASSENGERS || cs->town_effect == TE_MAIL) && (index == s->from || index == s->to)) ||
    00923         ((cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) && index == s->to)) {
    00924         s->cargo_type = CT_INVALID;
    00925       }
    00926     }
    00927   }
    00928 }
    00929
    00930 void DeleteSubsidyWithIndustry(IndustryID index)
    00931 {
    00932   Subsidy *s;
    00933
    00934   for (s = _subsidies; s != endof(_subsidies); s++) {
    00935     if (s->cargo_type != CT_INVALID && s->age < 12) {
    00936       const CargoSpec *cs = GetCargo(s->cargo_type);
    00937       if (cs->town_effect != TE_PASSENGERS && cs->town_effect != TE_MAIL &&
    00938         (index == s->from || (cs->town_effect != TE_GOODS && cs->town_effect != TE_FOOD && index == s->to))) {
    00939         s->cargo_type = CT_INVALID;
    00940       }
    00941     }
    00942   }
    00943 }
    00944
    00945 void DeleteSubsidyWithStation(StationID index)
    00946 {
    00947   Subsidy *s;
    00948   bool dirty = false;
    00949
    00950   for (s = _subsidies; s != endof(_subsidies); s++) {
    00951     if (s->cargo_type != CT_INVALID && s->age >= 12 &&
    00952         (s->from == index || s->to == index)) {
    00953       s->cargo_type = CT_INVALID;
    00954       dirty = true;
    00955     }
    00956   }
    00957
    00958   if (dirty)
    00959     InvalidateWindow(WC_SUBSIDIES_LIST, 0);
    00960 }
    00961
    00962 struct FoundRoute {
    00963   uint distance;
    00964   CargoID cargo;
    00965   void *from;
    00966   void *to;
    00967 };
    00968
    00969 static void FindSubsidyPassengerRoute(FoundRoute *fr)
    00970 {
    00971   Town *from, *to;
    00972
    00973   fr->distance = UINT_MAX;
    00974
    00975   fr->from = from = GetRandomTown();
    00976   if (from == NULL || from->population < 400) return;
    00977
    00978   fr->to = to = GetRandomTown();
    00979   if (from == to || to == NULL || to->population < 400 || to->pct_pass_transported > 42)
    00980     return;
    00981
    00982   fr->distance = DistanceManhattan(from->xy, to->xy);
    00983 }
    00984
    00985 static void FindSubsidyCargoRoute(FoundRoute *fr)
    00986 {
    00987   Industry *i;
    00988   int trans, total;
    00989   CargoID cargo;
    00990
    00991   fr->distance = UINT_MAX;
    00992
    00993   fr->from = i = GetRandomIndustry();
    00994   if (i == NULL) return;
    00995
    00996   /* Randomize cargo type */
    00997   if (HasBit(Random(), 0) && i->produced_cargo[1] != CT_INVALID) {
    00998     cargo = i->produced_cargo[1];
    00999     trans = i->last_month_pct_transported[1];
    01000     total = i->last_month_production[1];
    01001   } else {
    01002     cargo = i->produced_cargo[0];
    01003     trans = i->last_month_pct_transported[0];
    01004     total = i->last_month_production[0];
    01005   }
    01006
    01007   /* Quit if no production in this industry
    01008    * or if the cargo type is passengers
    01009    * or if the pct transported is already large enough */
    01010   if (total == 0 || trans > 42 || cargo == CT_INVALID) return;
    01011
    01012   const CargoSpec *cs = GetCargo(cargo);
    01013   if (cs->town_effect == TE_PASSENGERS) return;
    01014
    01015   fr->cargo = cargo;
    01016
    01017   if (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) {
    01018     /*  The destination is a town */
    01019     Town *t = GetRandomTown();
    01020
    01021     /* Only want big towns */
    01022     if (t == NULL || t->population < 900) return;
    01023
    01024     fr->distance = DistanceManhattan(i->xy, t->xy);
    01025     fr->to = t;
    01026   } else {
    01027     /* The destination is an industry */
    01028     Industry *i2 = GetRandomIndustry();
    01029
    01030     /* The industry must accept the cargo */
    01031     if (i2 == NULL || i == i2 ||
    01032         (cargo != i2->accepts_cargo[0] &&
    01033         cargo != i2->accepts_cargo[1] &&
    01034         cargo != i2->accepts_cargo[2])) {
    01035       return;
    01036     }
    01037     fr->distance = DistanceManhattan(i->xy, i2->xy);
    01038     fr->to = i2;
    01039   }
    01040 }
    01041
    01042 static bool CheckSubsidyDuplicate(Subsidy *s)
    01043 {
    01044   const Subsidy *ss;
    01045
    01046   for (ss = _subsidies; ss != endof(_subsidies); ss++) {
    01047     if (s != ss &&
    01048         ss->from == s->from &&
    01049         ss->to == s->to &&
    01050         ss->cargo_type == s->cargo_type) {
    01051       s->cargo_type = CT_INVALID;
    01052       return true;
    01053     }
    01054   }
    01055   return false;
    01056 }
    01057
    01058
    01059 static void SubsidyMonthlyHandler()
    01060 {
    01061   Subsidy *s;
    01062   Pair pair;
    01063   Station *st;
    01064   uint n;
    01065   FoundRoute fr;
    01066   bool modified = false;
    01067
    01068   for (s = _subsidies; s != endof(_subsidies); s++) {
    01069     if (s->cargo_type == CT_INVALID) continue;
    01070
    01071     if (s->age == 12 - 1) {
    01072       pair = SetupSubsidyDecodeParam(s, 1);
    01073       AddNewsItem(STR_202E_OFFER_OF_SUBSIDY_EXPIRED, NS_SUBSIDIES, pair.a, pair.b);
    01074       s->cargo_type = CT_INVALID;
    01075       modified = true;
    01076       AI::BroadcastNewEvent(new AIEventSubsidyOfferExpired(s - _subsidies));
    01077     } else if (s->age == 2 * 12 - 1) {
    01078       st = GetStation(s->to);
    01079       if (st->owner == _local_company) {
    01080         pair = SetupSubsidyDecodeParam(s, 1);
    01081         AddNewsItem(STR_202F_SUBSIDY_WITHDRAWN_SERVICE, NS_SUBSIDIES, pair.a, pair.b);
    01082       }
    01083       s->cargo_type = CT_INVALID;
    01084       modified = true;
    01085       AI::BroadcastNewEvent(new AIEventSubsidyExpired(s - _subsidies));
    01086     } else {
    01087       s->age++;
    01088     }
    01089   }
    01090
    01091   /* 25% chance to go on */
    01092   if (Chance16(1, 4)) {
    01093     /*  Find a free slot*/
    01094     s = _subsidies;
    01095     while (s->cargo_type != CT_INVALID) {
    01096       if (++s == endof(_subsidies))
    01097         goto no_add;
    01098     }
    01099
    01100     n = 1000;
    01101     do {
    01102       FindSubsidyPassengerRoute(&fr);
    01103       if (fr.distance <= 70) {
    01104         s->cargo_type = CT_PASSENGERS;
    01105         s->from = ((Town*)fr.from)->index;
    01106         s->to = ((Town*)fr.to)->index;
    01107         goto add_subsidy;
    01108       }
    01109       FindSubsidyCargoRoute(&fr);
    01110       if (fr.distance <= 70) {
    01111         s->cargo_type = fr.cargo;
    01112         s->from = ((Industry*)fr.from)->index;
    01113         {
    01114           const CargoSpec *cs = GetCargo(fr.cargo);
    01115           s->to = (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) ? ((Town*)fr.to)->index : ((Industry*)fr.to)->index;
    01116         }
    01117   add_subsidy:
    01118         if (!CheckSubsidyDuplicate(s)) {
    01119           s->age = 0;
    01120           pair = SetupSubsidyDecodeParam(s, 0);
    01121           AddNewsItem(STR_2030_SERVICE_SUBSIDY_OFFERED, NS_SUBSIDIES, pair.a, pair.b);
    01122           AI::BroadcastNewEvent(new AIEventSubsidyOffer(s - _subsidies));
    01123           modified = true;
    01124           break;
    01125         }
    01126       }
    01127     } while (n--);
    01128   }
    01129 no_add:;
    01130   if (modified)
    01131     InvalidateWindow(WC_SUBSIDIES_LIST, 0);
    01132 }
    01133
    01134 Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type)
    01135 {
    01136   const CargoSpec *cs = GetCargo(cargo_type);
    01137
    01138   /* Use callback to calculate cargo profit, if available */
    01139   if (HasBit(cs->callback_mask, CBM_CARGO_PROFIT_CALC)) {
    01140     uint32 var18 = min(dist, 0xFFFF) | (min(num_pieces, 0xFF) << 16) | (transit_days << 24);
    01141     uint16 callback = GetCargoCallback(CBID_CARGO_PROFIT_CALC, 0, var18, cs);
    01142     if (callback != CALLBACK_FAILED) {
    01143       int result = GB(callback, 0, 14);
    01144
    01145       /* Simulate a 15 bit signed value */
    01146       if (HasBit(callback, 14)) result = 0x4000 - result;
    01147
    01148       /* "The result should be a signed multiplier that gets multiplied
    01149        * by the amount of cargo moved and the price factor, then gets
    01150        * divided by 8192." */
    01151       return result * num_pieces * _cargo_payment_rates[cargo_type] / 8192;
    01152     }
    01153   }
    01154
    01155   /* zero the distance (thus income) if it's the bank and very short transport. */
    01156   if (_settings_game.game_creation.landscape == LT_TEMPERATE && cs->label == 'VALU' && dist < 10) return 0;
    01157
    01158
    01159   static const int MIN_TIME_FACTOR = 31;
    01160   static const int MAX_TIME_FACTOR = 255;
    01161
    01162   const int days1 = cs->transit_days[0];
    01163   const int days2 = cs->transit_days[1];
    01164   const int days_over_days1 = max(   transit_days - days1, 0);
    01165   const int days_over_days2 = max(days_over_days1 - days2, 0);
    01166
    01167   /*
    01168    * The time factor is calculated based on the time it took
    01169    * (transit_days) compared two cargo-depending values. The
    01170    * range is divided into three parts:
    01171    *
    01172    *  - constant for fast transits
    01173    *  - linear decreasing with time with a slope of -1 for medium transports
    01174    *  - linear decreasing with time with a slope of -2 for slow transports
    01175    *
    01176    */
    01177   const int time_factor = max(MAX_TIME_FACTOR - days_over_days1 - days_over_days2, MIN_TIME_FACTOR);
    01178
    01179   return BigMulS(dist * time_factor * num_pieces, _cargo_payment_rates[cargo_type], 21);
    01180 }
    01181
    01182
    01183 struct FindIndustryToDeliverData {
    01184   const Rect *rect;
    01185   CargoID cargo_type;
    01186
    01187   Industry *ind;
    01188   const IndustrySpec *indspec;
    01189   uint cargo_index;
    01190 };
    01191
    01192 static bool FindIndustryToDeliver(TileIndex ind_tile, void *user_data)
    01193 {
    01194   FindIndustryToDeliverData *callback_data = (FindIndustryToDeliverData *)user_data;
    01195   const Rect *rect = callback_data->rect;
    01196   CargoID cargo_type = callback_data->cargo_type;
    01197
    01198   /* Only process industry tiles */
    01199   if (!IsTileType(ind_tile, MP_INDUSTRY)) return false;
    01200
    01201   /* Only process tiles in the station acceptance rectangle */
    01202   int x = TileX(ind_tile);
    01203   int y = TileY(ind_tile);
    01204   if (x < rect->left || x > rect->right || y < rect->top || y > rect->bottom) return false;
    01205
    01206   Industry *ind = GetIndustryByTile(ind_tile);
    01207   const IndustrySpec *indspec = GetIndustrySpec(ind->type);
    01208
    01209   uint cargo_index;
    01210   for (cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
    01211     if (cargo_type == ind->accepts_cargo[cargo_index]) break;
    01212   }
    01213   /* Check if matching cargo has been found */
    01214   if (cargo_index >= lengthof(ind->accepts_cargo)) return false;
    01215
    01216   /* Check if industry temporarly refuses acceptance */
    01217   if (HasBit(indspec->callback_flags, CBM_IND_REFUSE_CARGO)) {
    01218     uint16 res = GetIndustryCallback(CBID_INDUSTRY_REFUSE_CARGO, 0, GetReverseCargoTranslation(cargo_type, indspec->grf_prop.grffile), ind, ind->type, ind->xy);
    01219     if (res == 0) return false;
    01220   }
    01221
    01222   /* Found industry accepting the cargo */
    01223   callback_data->ind = ind;
    01224   callback_data->indspec = indspec;
    01225   callback_data->cargo_index = cargo_index;
    01226   return true;
    01227 }
    01228
    01230 static SmallIndustryList _cargo_delivery_destinations;
    01231
    01239 static void DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, int num_pieces)
    01240 {
    01241   if (st->rect.IsEmpty()) return;
    01242
    01243   /* Compute acceptance rectangle */
    01244   int catchment_radius = st->GetCatchmentRadius();
    01245   Rect rect = {
    01246     max<int>(st->rect.left   - catchment_radius, 0),
    01247     max<int>(st->rect.top    - catchment_radius, 0),
    01248     min<int>(st->rect.right  + catchment_radius, MapMaxX()),
    01249     min<int>(st->rect.bottom + catchment_radius, MapMaxY())
    01250   };
    01251
    01252   /* Compute maximum extent of acceptance rectangle wrt. station sign */
    01253   TileIndex start_tile = st->xy;
    01254   uint max_radius = max(
    01255     max(DistanceManhattan(start_tile, TileXY(rect.left , rect.top)), DistanceManhattan(start_tile, TileXY(rect.left , rect.bottom))),
    01256     max(DistanceManhattan(start_tile, TileXY(rect.right, rect.top)), DistanceManhattan(start_tile, TileXY(rect.right, rect.bottom)))
    01257   );
    01258
    01259   FindIndustryToDeliverData callback_data;
    01260   callback_data.rect = &rect;
    01261   callback_data.cargo_type = cargo_type;
    01262   callback_data.ind = NULL;
    01263   callback_data.indspec = NULL;
    01264   callback_data.cargo_index = 0;
    01265
    01266   /* Find the nearest industrytile to the station sign inside the catchment area, whose industry accepts the cargo.
    01267    * This fails in three cases:
    01268    *  1) The station accepts the cargo because there are enough houses around it accepting the cargo.
    01269    *  2) The industries in the catchment area temporarily reject the cargo, and the daily station loop has not yet updated station acceptance.
    01270    *  3) The results of callbacks CBID_INDUSTRY_REFUSE_CARGO and CBID_INDTILE_CARGO_ACCEPTANCE are inconsistent. (documented behaviour)
    01271    */
    01272   if (CircularTileSearch(&start_tile, 2 * max_radius + 1, FindIndustryToDeliver, &callback_data)) {
    01273     Industry *best = callback_data.ind;
    01274     uint accepted_cargo_index = callback_data.cargo_index;
    01275     assert(best != NULL);
    01276
    01277     /* Insert the industry into industry_set, if not yet contained */
    01278     _cargo_delivery_destinations.Include(best);
    01279
    01280     best->incoming_cargo_waiting[accepted_cargo_index] = min(num_pieces + best->incoming_cargo_waiting[accepted_cargo_index], 0xFFFF);
    01281   }
    01282 }
    01283
    01284
    01285 static bool CheckSubsidised(Station *from, Station *to, CargoID cargo_type, CompanyID company)
    01286 {
    01287   Subsidy *s;
    01288   TileIndex xy;
    01289   Pair pair;
    01290
    01291   /* check if there is an already existing subsidy that applies to us */
    01292   for (s = _subsidies; s != endof(_subsidies); s++) {
    01293     if (s->cargo_type == cargo_type &&
    01294         s->age >= 12 &&
    01295         s->from == from->index &&
    01296         s->to == to->index) {
    01297       return true;
    01298     }
    01299   }
    01300
    01301   /* check if there's a new subsidy that applies.. */
    01302   for (s = _subsidies; s != endof(_subsidies); s++) {
    01303     if (s->cargo_type == cargo_type && s->age < 12) {
    01304       /* Check distance from source */
    01305       const CargoSpec *cs = GetCargo(cargo_type);
    01306       if (cs->town_effect == TE_PASSENGERS || cs->town_effect == TE_MAIL) {
    01307         xy = GetTown(s->from)->xy;
    01308       } else {
    01309         xy = GetIndustry(s->from)->xy;
    01310       }
    01311       if (DistanceMax(xy, from->xy) > 9) continue;
    01312
    01313       /* Check distance from dest */
    01314       switch (cs->town_effect) {
    01315         case TE_PASSENGERS:
    01316         case TE_MAIL:
    01317         case TE_GOODS:
    01318         case TE_FOOD:
    01319           xy = GetTown(s->to)->xy;
    01320           break;
    01321
    01322         default:
    01323           xy = GetIndustry(s->to)->xy;
    01324           break;
    01325       }
    01326       if (DistanceMax(xy, to->xy) > 9) continue;
    01327
    01328       /* Found a subsidy, change the values to indicate that it's in use */
    01329       s->age = 12;
    01330       s->from = from->index;
    01331       s->to = to->index;
    01332
    01333       /* Add a news item */
    01334       pair = SetupSubsidyDecodeParam(s, 0);
    01335       InjectDParam(1);
    01336
    01337       SetDParam(0, company);
    01338       AddNewsItem(
    01339         STR_2031_SERVICE_SUBSIDY_AWARDED + _settings_game.difficulty.subsidy_multiplier,
    01340         NS_SUBSIDIES,
    01341         pair.a, pair.b
    01342       );
    01343       AI::BroadcastNewEvent(new AIEventSubsidyAwarded(s - _subsidies));
    01344
    01345       InvalidateWindow(WC_SUBSIDIES_LIST, 0);
    01346       return true;
    01347     }
    01348   }
    01349   return false;
    01350 }
    01351
    01362 static Money DeliverGoods(int num_pieces, CargoID cargo_type, StationID source, StationID dest, TileIndex source_tile, byte days_in_transit, Company *company)
    01363 {
    01364   bool subsidised;
    01365   Station *s_from, *s_to;
    01366   Money profit;
    01367
    01368   assert(num_pieces > 0);
    01369
    01370   /* Update company statistics */
    01371   company->cur_economy.delivered_cargo += num_pieces;
    01372   SetBit(company->cargo_types, cargo_type);
    01373
    01374   /* Get station pointers. */
    01375   s_from = IsValidStationID(source) ? GetStation(source) : NULL;
    01376   s_to = GetStation(dest);
    01377
    01378   /* Check if a subsidy applies. */
    01379   subsidised = s_from != NULL && CheckSubsidised(s_from, s_to, cargo_type, company->index);
    01380
    01381   /* Increase town's counter for some special goods types */
    01382   const CargoSpec *cs = GetCargo(cargo_type);
    01383   if (cs->town_effect == TE_FOOD) s_to->town->new_act_food += num_pieces;
    01384   if (cs->town_effect == TE_WATER) s_to->town->new_act_water += num_pieces;
    01385
    01386   /* Give the goods to the industry. */
    01387   DeliverGoodsToIndustry(s_to, cargo_type, num_pieces);
    01388
    01389   /* Determine profit */
    01390   profit = GetTransportedGoodsIncome(num_pieces, DistanceManhattan(source_tile, s_to->xy), days_in_transit, cargo_type);
    01391
    01392   /* Modify profit if a subsidy is in effect */
    01393   if (subsidised) {
    01394     switch (_settings_game.difficulty.subsidy_multiplier) {
    01395       case 0:  profit += profit >> 1; break;
    01396       case 1:  profit *= 2; break;
    01397       case 2:  profit *= 3; break;
    01398       default: profit *= 4; break;
    01399     }
    01400   }
    01401
    01402   return profit;
    01403 }
    01404
    01410 static void TriggerIndustryProduction(Industry *i)
    01411 {
    01412   const IndustrySpec *indspec = GetIndustrySpec(i->type);
    01413   uint16 callback = indspec->callback_flags;
    01414
    01415   i->was_cargo_delivered = true;
    01416   i->last_cargo_accepted_at = _date;
    01417
    01418   if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(callback, CBM_IND_PRODUCTION_256_TICKS)) {
    01419     if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) {
    01420       IndustryProductionCallback(i, 0);
    01421     } else {
    01422       InvalidateWindow(WC_INDUSTRY_VIEW, i->index);
    01423     }
    01424   } else {
    01425     for (uint cargo_index = 0; cargo_index < lengthof(i->incoming_cargo_waiting); cargo_index++) {
    01426       uint cargo_waiting = i->incoming_cargo_waiting[cargo_index];
    01427       if (cargo_waiting == 0) continue;
    01428
    01429       i->produced_cargo_waiting[0] = min(i->produced_cargo_waiting[0] + (cargo_waiting * indspec->input_cargo_multiplier[cargo_index][0] / 256), 0xFFFF);
    01430       i->produced_cargo_waiting[1] = min(i->produced_cargo_waiting[1] + (cargo_waiting * indspec->input_cargo_multiplier[cargo_index][1] / 256), 0xFFFF);
    01431
    01432       i->incoming_cargo_waiting[cargo_index] = 0;
    01433     }
    01434   }
    01435
    01436   TriggerIndustry(i, INDUSTRY_TRIGGER_RECEIVED_CARGO);
    01437   StartStopIndustryTileAnimation(i, IAT_INDUSTRY_RECEIVED_CARGO);
    01438 }
    01439
    01445 CargoPayment::CargoPayment(Vehicle *front) :
    01446   front(front),
    01447   current_station(front->last_station_visited)
    01448 {
    01449 }
    01450
    01451 CargoPayment::~CargoPayment()
    01452 {
    01453   if (this->CleaningPool()) return;
    01454
    01455   this->front->cargo_payment = NULL;
    01456
    01457   if (this->visual_profit == 0) {
    01458     this->front = NULL;
    01459     return;
    01460   }
    01461
    01462   CompanyID old_company = _current_company;
    01463   _current_company = this->front->owner;
    01464
    01465   SubtractMoneyFromCompany(CommandCost(this->front->GetExpenseType(true), -this->route_profit));
    01466   this->front->profit_this_year += this->visual_profit << 8;
    01467
    01468   if (this->route_profit != 0) {
    01469     if (IsLocalCompany() && !PlayVehicleSound(this->front, VSE_LOAD_UNLOAD)) {
    01470       SndPlayVehicleFx(SND_14_CASHTILL, this->front);
    01471     }
    01472
    01473     ShowCostOrIncomeAnimation(this->front->x_pos, this->front->y_pos, this->front->z_pos, -this->visual_profit);
    01474   } else {
    01475     ShowFeederIncomeAnimation(this->front->x_pos, this->front->y_pos, this->front->z_pos, this->visual_profit);
    01476   }
    01477
    01478   _current_company = old_company;
    01479
    01480   this->front = NULL;
    01481 }
    01482
    01488 void CargoPayment::PayFinalDelivery(CargoPacket *cp, uint count)
    01489 {
    01490   if (this->owner == NULL) {
    01491     this->owner = GetCompany(this->front->owner);
    01492   }
    01493
    01494   /* Handle end of route payment */
    01495   Money profit = DeliverGoods(count, this->ct, cp->source, this->current_station, cp->source_xy, cp->days_in_transit, this->owner);
    01496   this->route_profit += profit;
    01497
    01498   /* The vehicle's profit is whatever route profit there is minus feeder shares. */
    01499   this->visual_profit += profit - cp->feeder_share;
    01500 }
    01501
    01507 void CargoPayment::PayTransfer(CargoPacket *cp, uint count)
    01508 {
    01509   Money profit = GetTransportedGoodsIncome(
    01510     count,
    01511     /* pay transfer vehicle for only the part of transfer it has done: ie. cargo_loaded_at_xy to here */
    01512     DistanceManhattan(cp->loaded_at_xy, GetStation(this->current_station)->xy),
    01513     cp->days_in_transit,
    01514     this->ct);
    01515
    01516   this->visual_profit += profit; // accumulate transfer profits for whole vehicle
    01517   cp->feeder_share    += profit; // account for the (virtual) profit already made for the cargo packet
    01518 }
    01519
    01524 void PrepareUnload(Vehicle *front_v)
    01525 {
    01526   /* At this moment loading cannot be finished */
    01527   ClrBit(front_v->vehicle_flags, VF_LOADING_FINISHED);
    01528
    01529   /* Start unloading in at the first possible moment */
    01530   front_v->load_unload_time_rem = 1;
    01531
    01532   if ((front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
    01533     for (Vehicle *v = front_v; v != NULL; v = v->Next()) {
    01534       if (v->cargo_cap > 0 && !v->cargo.Empty()) {
    01535         SetBit(v->vehicle_flags, VF_CARGO_UNLOADING);
    01536       }
    01537     }
    01538   }
    01539
    01540   assert(front_v->cargo_payment == NULL);
    01541   front_v->cargo_payment = new CargoPayment(front_v);
    01542 }
    01543
    01552 static void LoadUnloadVehicle(Vehicle *v, int *cargo_left)
    01553 {
    01554   assert(v->current_order.IsType(OT_LOADING));
    01555
    01556   /* We have not waited enough time till the next round of loading/unloading */
    01557   if (--v->load_unload_time_rem != 0) {
    01558     if (_settings_game.order.improved_load && (v->current_order.GetLoadType() & OLFB_FULL_LOAD)) {
    01559       /* 'Reserve' this cargo for this vehicle, because we were first. */
    01560       for (; v != NULL; v = v->Next()) {
    01561         int cap_left = v->cargo_cap - v->cargo.Count();
    01562         if (cap_left > 0) cargo_left[v->cargo_type] -= cap_left;
    01563       }
    01564     }
    01565     return;
    01566   }
    01567
    01568   StationID last_visited = v->last_station_visited;
    01569   Station *st = GetStation(last_visited);
    01570
    01571   if (v->type == VEH_TRAIN && (!IsTileType(v->tile, MP_STATION) || GetStationIndex(v->tile) != st->index)) {
    01572     /* The train reversed in the station. Take the "easy" way
    01573      * out and let the train just leave as it always did. */
    01574     SetBit(v->vehicle_flags, VF_LOADING_FINISHED);
    01575     return;
    01576   }
    01577
    01578   int unloading_time = 0;
    01579   Vehicle *u = v;
    01580   int result = 0;
    01581
    01582   bool completely_emptied = true;
    01583   bool anything_unloaded = false;
    01584   bool anything_loaded   = false;
    01585   uint32 cargo_not_full  = 0;
    01586   uint32 cargo_full      = 0;
    01587
    01588   v->cur_speed = 0;
    01589
    01590   CargoPayment *payment = v->cargo_payment;
    01591
    01592   for (; v != NULL; v = v->Next()) {
    01593     if (v->cargo_cap == 0) continue;
    01594
    01595     byte load_amount = EngInfo(v->engine_type)->load_amount;
    01596
    01597     /* The default loadamount for mail is 1/4 of the load amount for passengers */
    01598     if (v->type == VEH_AIRCRAFT && !IsNormalAircraft(v)) load_amount = (load_amount + 3) / 4;
    01599
    01600     if (_settings_game.order.gradual_loading && HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_LOAD_AMOUNT)) {
    01601       uint16 cb_load_amount = GetVehicleCallback(CBID_VEHICLE_LOAD_AMOUNT, 0, 0, v->engine_type, v);
    01602       if (cb_load_amount != CALLBACK_FAILED && GB(cb_load_amount, 0, 8) != 0) load_amount = GB(cb_load_amount, 0, 8);
    01603     }
    01604
    01605     GoodsEntry *ge = &st->goods[v->cargo_type];
    01606
    01607     if (HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) && (u->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
    01608       uint cargo_count = v->cargo.Count();
    01609       uint amount_unloaded = _settings_game.order.gradual_loading ? min(cargo_count, load_amount) : cargo_count;
    01610       bool remaining = false; // Are there cargo entities in this vehicle that can still be unloaded here?
    01611       bool accepted  = false; // Is the cargo accepted by the station?
    01612
    01613       payment->SetCargo(v->cargo_type);
    01614
    01615       if (HasBit(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && !(u->current_order.GetUnloadType() & OUFB_TRANSFER)) {
    01616         /* The cargo has reached it's final destination, the packets may now be destroyed */
    01617         remaining = v->cargo.MoveTo(NULL, amount_unloaded, CargoList::MTA_FINAL_DELIVERY, payment, last_visited);
    01618
    01619         result |= 1;
    01620         accepted = true;
    01621       }
    01622
    01623       /* The !accepted || v->cargo.Count == cargo_count clause is there
    01624        * to make it possible to force unload vehicles at the station where
    01625        * they were loaded, but to not force unload the vehicle when the
    01626        * station is still accepting the cargo in the vehicle. It doesn't
    01627        * accept cargo that was loaded at the same station. */
    01628       if (u->current_order.GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER) && (!accepted || v->cargo.Count() == cargo_count)) {
    01629         remaining = v->cargo.MoveTo(&ge->cargo, amount_unloaded, u->current_order.GetUnloadType() & OUFB_TRANSFER ? CargoList::MTA_TRANSFER : CargoList::MTA_UNLOAD, payment);
    01630         SetBit(ge->acceptance_pickup, GoodsEntry::PICKUP);
    01631
    01632         result |= 2;
    01633       } else if (!accepted) {
    01634         /* The order changed while unloading (unset unload/transfer) or the
    01635          * station does not accept our goods. */
    01636         ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING);
    01637
    01638         /* Say we loaded something, otherwise we'll think we didn't unload
    01639          * something and we didn't load something, so we must be finished
    01640          * at this station. Setting the unloaded means that we will get a
    01641          * retry for loading in the next cycle. */
    01642         anything_unloaded = true;
    01643         continue;
    01644       }
    01645
    01646       /* Deliver goods to the station */
    01647       st->time_since_unload = 0;
    01648
    01649       unloading_time += amount_unloaded;
    01650
    01651       anything_unloaded = true;
    01652       if (_settings_game.order.gradual_loading && remaining) {
    01653         completely_emptied = false;
    01654       } else {
    01655         /* We have finished unloading (cargo count == 0) */
    01656         ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING);
    01657       }
    01658
    01659       continue;
    01660     }
    01661
    01662     /* Do not pick up goods when we have no-load set. */
    01663     if (u->current_order.GetLoadType() & OLFB_NO_LOAD) continue;
    01664
    01665     /* update stats */
    01666     int t;
    01667     switch (u->type) {
    01668       case VEH_TRAIN: t = u->u.rail.cached_max_speed; break;
    01669       case VEH_ROAD:  t = u->max_speed / 2;           break;
    01670       default:        t = u->max_speed;               break;
    01671     }
    01672
    01673     /* if last speed is 0, we treat that as if no vehicle has ever visited the station. */
    01674     ge->last_speed = min(t, 255);
    01675     ge->last_age = _cur_year - u->build_year;
    01676     ge->days_since_pickup = 0;
    01677
    01678     /* If there's goods waiting at the station, and the vehicle
    01679      * has capacity for it, load it on the vehicle. */
    01680     int cap_left = v->cargo_cap - v->cargo.Count();
    01681     if (!ge->cargo.Empty() && cap_left > 0) {
    01682       uint cap = cap_left;
    01683       uint count = ge->cargo.Count();
    01684
    01685       /* Skip loading this vehicle if another train/vehicle is already handling
    01686        * the same cargo type at this station */
    01687       if (_settings_game.order.improved_load && cargo_left[v->cargo_type] <= 0) {
    01688         SetBit(cargo_not_full, v->cargo_type);
    01689         continue;
    01690       }
    01691
    01692       if (cap > count) cap = count;
    01693       if (_settings_game.order.gradual_loading) cap = min(cap, load_amount);
    01694       if (_settings_game.order.improved_load) {
    01695         /* Don't load stuff that is already 'reserved' for other vehicles */
    01696         cap = min((uint)cargo_left[v->cargo_type], cap);
    01697         cargo_left[v->cargo_type] -= cap;
    01698       }
    01699
    01700       if (v->cargo.Empty()) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
    01701
    01702       /* TODO: Regarding this, when we do gradual loading, we
    01703        * should first unload all vehicles and then start
    01704        * loading them. Since this will cause
    01705        * VEHICLE_TRIGGER_EMPTY to be called at the time when
    01706        * the whole vehicle chain is really totally empty, the
    01707        * completely_emptied assignment can then be safely
    01708        * removed; that's how TTDPatch behaves too. --pasky */
    01709       completely_emptied = false;
    01710       anything_loaded = true;
    01711
    01712       ge->cargo.MoveTo(&v->cargo, cap, CargoList::MTA_CARGO_LOAD, NULL, st->xy);
    01713
    01714       st->time_since_load = 0;
    01715       st->last_vehicle_type = v->type;
    01716
    01717       StationAnimationTrigger(st, st->xy, STAT_ANIM_CARGO_TAKEN, v->cargo_type);
    01718
    01719       unloading_time += cap;
    01720
    01721       result |= 2;
    01722     }
    01723
    01724     if (v->cargo.Count() >= v->cargo_cap) {
    01725       SetBit(cargo_full, v->cargo_type);
    01726     } else {
    01727       SetBit(cargo_not_full, v->cargo_type);
    01728     }
    01729   }
    01730
    01731   /* Only set completly_emptied, if we just unloaded all remaining cargo */
    01732   completely_emptied &= anything_unloaded;
    01733
    01734   /* We update these variables here, so gradual loading still fills
    01735    * all wagons at the same time instead of using the same 'improved'
    01736    * loading algorithm for the wagons (only fill wagon when there is
    01737    * enough to fill the previous wagons) */
    01738   if (_settings_game.order.improved_load && (u->current_order.GetLoadType() & OLFB_FULL_LOAD)) {
    01739     /* Update left cargo */
    01740     for (v = u; v != NULL; v = v->Next()) {
    01741       int cap_left = v->cargo_cap - v->cargo.Count();
    01742       if (cap_left > 0) cargo_left[v->cargo_type] -= cap_left;
    01743     }
    01744   }
    01745
    01746   v = u;
    01747
    01748   if (!anything_unloaded) delete payment;
    01749
    01750   if (anything_loaded || anything_unloaded) {
    01751     if (_settings_game.order.gradual_loading) {
    01752       /* The time it takes to load one 'slice' of cargo or passengers depends
    01753        * on the vehicle type - the values here are those found in TTDPatch */
    01754       const uint gradual_loading_wait_time[] = { 40, 20, 10, 20 };
    01755
    01756       unloading_time = gradual_loading_wait_time[v->type];
    01757     }
    01758   } else {
    01759     bool finished_loading = true;
    01760     if (v->current_order.GetLoadType() & OLFB_FULL_LOAD) {
    01761       if (v->current_order.GetLoadType() == OLF_FULL_LOAD_ANY) {
    01762         /* if the aircraft carries passengers and is NOT full, then
    01763          * continue loading, no matter how much mail is in */
    01764         if ((v->type == VEH_AIRCRAFT && IsCargoInClass(v->cargo_type, CC_PASSENGERS) && v->cargo_cap > v->cargo.Count()) ||
    01765             (cargo_not_full && (cargo_full & ~cargo_not_full) == 0)) { // There are stull non-full cargos
    01766           finished_loading = false;
    01767         }
    01768       } else if (cargo_not_full != 0) {
    01769         finished_loading = false;
    01770       }
    01771     }
    01772     unloading_time = 20;
    01773
    01774     SB(v->vehicle_flags, VF_LOADING_FINISHED, 1, finished_loading);
    01775   }
    01776
    01777   if (v->type == VEH_TRAIN) {
    01778     /* Each platform tile is worth 2 rail vehicles. */
    01779     int overhang = v->u.rail.cached_total_length - st->GetPlatformLength(v->tile) * TILE_SIZE;
    01780     if (overhang > 0) {
    01781       unloading_time <<= 1;
    01782       unloading_time += (overhang * unloading_time) / 8;
    01783     }
    01784   }
    01785
    01786   /* Calculate the loading indicator fill percent and display
    01787    * In the Game Menu do not display indicators
    01788    * If _settings_client.gui.loading_indicators == 2, show indicators (bool can be promoted to int as 0 or 1 - results in 2 > 0,1 )
    01789    * if _settings_client.gui.loading_indicators == 1, _local_company must be the owner or must be a spectator to show ind., so 1 > 0
    01790    * if _settings_client.gui.loading_indicators == 0, do not display indicators ... 0 is never greater than anything
    01791    */
    01792   if (_game_mode != GM_MENU && (_settings_client.gui.loading_indicators > (uint)(v->owner != _local_company && _local_company != COMPANY_SPECTATOR))) {
    01793     StringID percent_up_down = STR_NULL;
    01794     int percent = CalcPercentVehicleFilled(v, &percent_up_down);
    01795     if (v->fill_percent_te_id == INVALID_TE_ID) {
    01796       v->fill_percent_te_id = ShowFillingPercent(v->x_pos, v->y_pos, v->z_pos + 20, percent, percent_up_down);
    01797     } else {
    01798       UpdateFillingPercent(v->fill_percent_te_id, percent, percent_up_down);
    01799     }
    01800   }
    01801
    01802   v->load_unload_time_rem = unloading_time;
    01803
    01804   if (completely_emptied) {
    01805     TriggerVehicle(v, VEHICLE_TRIGGER_EMPTY);
    01806   }
    01807
    01808   if (result != 0) {
    01809     InvalidateWindow(GetWindowClassForVehicleType(v->type), v->owner);
    01810     InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
    01811
    01812     st->MarkTilesDirty(true);
    01813     v->MarkDirty();
    01814
    01815     if (result & 2) InvalidateWindow(WC_STATION_VIEW, last_visited);
    01816   }
    01817 }
    01818
    01824 void LoadUnloadStation(Station *st)
    01825 {
    01826   /* No vehicle is here... */
    01827   if (st->loading_vehicles.empty()) return;
    01828
    01829   int cargo_left[NUM_CARGO];
    01830
    01831   for (uint i = 0; i < NUM_CARGO; i++) cargo_left[i] = st->goods[i].cargo.Count();
    01832
    01833   std::list<Vehicle *>::iterator iter;
    01834   for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
    01835     Vehicle *v = *iter;
    01836     if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED))) LoadUnloadVehicle(v, cargo_left);
    01837   }
    01838
    01839   /* Call the production machinery of industries */
    01840   const Industry * const *isend = _cargo_delivery_destinations.End();
    01841   for (Industry **iid = _cargo_delivery_destinations.Begin(); iid != isend; iid++) {
    01842     TriggerIndustryProduction(*iid);
    01843   }
    01844   _cargo_delivery_destinations.Clear();
    01845 }
    01846
    01847 void CompaniesMonthlyLoop()
    01848 {
    01849   CompaniesGenStatistics();
    01850   if (_settings_game.economy.inflation) AddInflation();
    01851   CompaniesPayInterest();
    01852   /* Reset the _current_company flag */
    01853   _current_company = OWNER_NONE;
    01854   HandleEconomyFluctuations();
    01855   SubsidyMonthlyHandler();
    01856 }
    01857
    01858 static void DoAcquireCompany(Company *c)
    01859 {
    01860   Company *owner;
    01861   int i;
    01862   Money value;
    01863   CompanyID ci = c->index;
    01864
    01865   CompanyNewsInformation *cni = MallocT<CompanyNewsInformation>(1);
    01866   cni->FillData(c, GetCompany(_current_company));
    01867
    01868   SetDParam(0, STR_7059_TRANSPORT_COMPANY_MERGER);
    01869   SetDParam(1, c->bankrupt_value == 0 ? STR_707F_HAS_BEEN_TAKEN_OVER_BY : STR_705A_HAS_BEEN_SOLD_TO_FOR);
    01870   SetDParamStr(2, cni->company_name);
    01871   SetDParamStr(3, cni->other_company_name);
    01872   SetDParam(4, c->bankrupt_value);
    01873   AddNewsItem(STR_02B6, NS_COMPANY_MERGER, 0, 0, cni);
    01874   AI::BroadcastNewEvent(new AIEventCompanyMerger(ci, _current_company));
    01875
    01876   /* original code does this a little bit differently */
    01877   ChangeNetworkOwner(ci, _current_company);
    01878   ChangeOwnershipOfCompanyItems(ci, _current_company);
    01879
    01880   if (c->bankrupt_value == 0) {
    01881     owner = GetCompany(_current_company);
    01882     owner->current_loan += c->current_loan;
    01883   }
    01884
    01885   value = CalculateCompanyValue(c) >> 2;
    01886   CompanyID old_company = _current_company;
    01887   for (i = 0; i != 4; i++) {
    01888     if (c->share_owners[i] != COMPANY_SPECTATOR) {
    01889       _current_company = c->share_owners[i];
    01890       SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, -value));
    01891     }
    01892   }
    01893   _current_company = old_company;
    01894
    01895   if (!IsHumanCompany(c->index)) AI::Stop(c->index);
    01896
    01897   DeleteCompanyWindows(ci);
    01898   InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
    01899   InvalidateWindowClassesData(WC_SHIPS_LIST, 0);
    01900   InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
    01901   InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
    01902
    01903   delete c;
    01904 }
    01905
    01906 extern int GetAmountOwnedBy(const Company *c, Owner owner);
    01907
    01914 CommandCost CmdBuyShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    01915 {
    01916   CommandCost cost(EXPENSES_OTHER);
    01917
    01918   /* Check if buying shares is allowed (protection against modified clients)
    01919    * Cannot buy own shares */
    01920   if (!IsValidCompanyID((CompanyID)p1) || !_settings_game.economy.allow_shares || _current_company == (CompanyID)p1) return CMD_ERROR;
    01921
    01922   Company *c = GetCompany((CompanyID)p1);
    01923
    01924   /* Protect new companies from hostile takeovers */
    01925   if (_cur_year - c->inaugurated_year < 6) return_cmd_error(STR_PROTECTED);
    01926
    01927   /* Those lines are here for network-protection (clients can be slow) */
    01928   if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 0) return cost;
    01929
    01930   /* We can not buy out a real company (temporarily). TODO: well, enable it obviously */
    01931   if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 1 && !c->is_ai) return cost;
    01932
    01933   cost.AddCost(CalculateCompanyValue(c) >> 2);
    01934   if (flags & DC_EXEC) {
    01935     OwnerByte *b = c->share_owners;
    01936     int i;
    01937
    01938     while (*b != COMPANY_SPECTATOR) b++; // share owners is guaranteed to contain at least one COMPANY_SPECTATOR
    01939     *b = _current_company;
    01940
    01941     for (i = 0; c->share_owners[i] == _current_company;) {
    01942       if (++i == 4) {
    01943         c->bankrupt_value = 0;
    01944         DoAcquireCompany(c);
    01945         break;
    01946       }
    01947     }
    01948     InvalidateWindow(WC_COMPANY, p1);
    01949   }
    01950   return cost;
    01951 }
    01952
    01959 CommandCost CmdSellShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    01960 {
    01961   /* Check if selling shares is allowed (protection against modified clients)
    01962    * Cannot sell own shares */
    01963   if (!IsValidCompanyID((CompanyID)p1) || !_settings_game.economy.allow_shares || _current_company == (CompanyID)p1) return CMD_ERROR;
    01964
    01965   Company *c = GetCompany((CompanyID)p1);
    01966
    01967   /* Those lines are here for network-protection (clients can be slow) */
    01968   if (GetAmountOwnedBy(c, _current_company) == 0) return CommandCost();
    01969
    01970   /* adjust it a little to make it less profitable to sell and buy */
    01971   Money cost = CalculateCompanyValue(c) >> 2;
    01972   cost = -(cost - (cost >> 7));
    01973
    01974   if (flags & DC_EXEC) {
    01975     OwnerByte *b = c->share_owners;
    01976     while (*b != _current_company) b++; // share owners is guaranteed to contain company
    01977     *b = COMPANY_SPECTATOR;
    01978     InvalidateWindow(WC_COMPANY, p1);
    01979   }
    01980   return CommandCost(EXPENSES_OTHER, cost);
    01981 }
    01982
    01992 CommandCost CmdBuyCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    01993 {
    01994   CompanyID cid = (CompanyID)p1;
    01995
    01996   /* Disable takeovers in multiplayer games */
    01997   if (!IsValidCompanyID(cid) || _networking) return CMD_ERROR;
    01998
    01999   /* Do not allow companies to take over themselves */
    02000   if (cid == _current_company) return CMD_ERROR;
    02001
    02002   Company *c = GetCompany(cid);
    02003
    02004   if (!c->is_ai) return CMD_ERROR;
    02005
    02006   if (flags & DC_EXEC) {
    02007     DoAcquireCompany(c);
    02008   }
    02009   return CommandCost(EXPENSES_OTHER, c->bankrupt_value);
    02010 }