# economy.cpp

Go to the documentation of this file.

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