economy.cpp

Go to the documentation of this file.
00001 /* $Id: economy.cpp 17564 2009-09-18 07:00:35Z 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     c->bankrupt_asked = 0;
00473     return;
00474   }
00475 
00476   c->quarters_of_bankrupcy++;
00477 
00478   CompanyNewsInformation *cni = MallocT<CompanyNewsInformation>(1);
00479   cni->FillData(c);
00480 
00481   switch (c->quarters_of_bankrupcy) {
00482     case 0:
00483     case 1:
00484       free(cni);
00485       break;
00486 
00487     case 2:
00488       SetDParam(0, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE);
00489       SetDParam(1, STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED);
00490       SetDParamStr(2, cni->company_name);
00491       AddNewsItem(STR_02B6, NS_COMPANY_TROUBLE, 0, 0, cni);
00492       AI::BroadcastNewEvent(new AIEventCompanyInTrouble(c->index));
00493       break;
00494     case 3: {
00495       /* XXX - In multiplayer, should we ask other companies if it wants to take
00496               over when it is a human company? -- TrueLight */
00497       if (IsHumanCompany(c->index)) {
00498         SetDParam(0, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE);
00499         SetDParam(1, STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED);
00500         SetDParamStr(2, cni->company_name);
00501         AddNewsItem(STR_02B6, NS_COMPANY_TROUBLE, 0, 0, cni);
00502         break;
00503       }
00504 
00505       /* Check if the company has any value.. if not, declare it bankrupt
00506        *  right now */
00507       Money val = CalculateCompanyValue(c);
00508       if (val > 0) {
00509         c->bankrupt_value = val;
00510         c->bankrupt_asked = 1 << c->index; // Don't ask the owner
00511         c->bankrupt_timeout = 0;
00512         free(cni);
00513         break;
00514       }
00515       /* Else, falltrue to case 4... */
00516     }
00517     default:
00518     case 4:
00519       if (!_networking && _local_company == c->index) {
00520         /* If we are in offline mode, leave the company playing. Eg. there
00521          * is no THE-END, otherwise mark the client as spectator to make sure
00522          * he/she is no long in control of this company. However... when you
00523          * join another company (cheat) the "unowned" company can bankrupt. */
00524         c->bankrupt_asked = MAX_UVALUE(CompanyMask);
00525         free(cni);
00526         break;
00527       }
00528 
00529       /* Close everything the owner has open */
00530       DeleteCompanyWindows(c->index);
00531 
00532       /* Show bankrupt news */
00533       SetDParam(0, STR_705C_BANKRUPT);
00534       SetDParam(1, STR_705D_HAS_BEEN_CLOSED_DOWN_BY);
00535       SetDParamStr(2, cni->company_name);
00536       AddNewsItem(STR_02B6, NS_COMPANY_BANKRUPT, 0, 0, cni);
00537 
00538       /* Remove the company */
00539       ChangeNetworkOwner(c->index, COMPANY_SPECTATOR);
00540       ChangeOwnershipOfCompanyItems(c->index, INVALID_OWNER);
00541 
00542       if (!IsHumanCompany(c->index)) AI::Stop(c->index);
00543 
00544       CompanyID c_index = c->index;
00545       delete c;
00546       AI::BroadcastNewEvent(new AIEventCompanyBankrupt(c_index));
00547   }
00548 }
00549 
00550 static void CompaniesGenStatistics()
00551 {
00552   Station *st;
00553   Company *c;
00554 
00555   FOR_ALL_STATIONS(st) {
00556     _current_company = st->owner;
00557     CommandCost cost(EXPENSES_PROPERTY, _price.station_value >> 1);
00558     SubtractMoneyFromCompany(cost);
00559   }
00560 
00561   if (!HasBit(1 << 0 | 1 << 3 | 1 << 6 | 1 << 9, _cur_month))
00562     return;
00563 
00564   FOR_ALL_COMPANIES(c) {
00565     memmove(&c->old_economy[1], &c->old_economy[0], sizeof(c->old_economy) - sizeof(c->old_economy[0]));
00566     c->old_economy[0] = c->cur_economy;
00567     memset(&c->cur_economy, 0, sizeof(c->cur_economy));
00568 
00569     if (c->num_valid_stat_ent != 24) c->num_valid_stat_ent++;
00570 
00571     UpdateCompanyRatingAndValue(c, true);
00572     CompanyCheckBankrupt(c);
00573 
00574     if (c->block_preview != 0) c->block_preview--;
00575   }
00576 
00577   InvalidateWindow(WC_INCOME_GRAPH, 0);
00578   InvalidateWindow(WC_OPERATING_PROFIT, 0);
00579   InvalidateWindow(WC_DELIVERED_CARGO, 0);
00580   InvalidateWindow(WC_PERFORMANCE_HISTORY, 0);
00581   InvalidateWindow(WC_COMPANY_VALUE, 0);
00582   InvalidateWindow(WC_COMPANY_LEAGUE, 0);
00583 }
00584 
00585 static void AddSingleInflation(Money *value, uint16 *frac, int32 amt)
00586 {
00587   /* Is it safe to add inflation ? */
00588   if ((INT64_MAX / amt) < (*value + 1)) {
00589     *value = INT64_MAX / amt;
00590     *frac = 0;
00591   } else {
00592     int64 tmp = (int64)*value * amt + *frac;
00593     *frac   = GB(tmp, 0, 16);
00594     *value += tmp >> 16;
00595   }
00596 }
00597 
00598 static void AddInflation(bool check_year = true)
00599 {
00600   /* The cargo payment inflation differs from the normal inflation, so the
00601    * relative amount of money you make with a transport decreases slowly over
00602    * the 170 years. After a few hundred years we reach a level in which the
00603    * games will become unplayable as the maximum income will be less than
00604    * the minimum running cost.
00605    *
00606    * Furthermore there are a lot of inflation related overflows all over the
00607    * place. Solving them is hardly possible because inflation will always
00608    * reach the overflow threshold some day. So we'll just perform the
00609    * inflation mechanism during the first 170 years (the amount of years that
00610    * one had in the original TTD) and stop doing the inflation after that
00611    * because it only causes problems that can't be solved nicely and the
00612    * inflation doesn't add anything after that either; it even makes playing
00613    * it impossible due to the diverging cost and income rates.
00614    */
00615   if (check_year && (_cur_year - _settings_game.game_creation.starting_year) >= (ORIGINAL_MAX_YEAR - ORIGINAL_BASE_YEAR)) return;
00616 
00617   /* Approximation for (100 + infl_amount)% ** (1 / 12) - 100%
00618    * scaled by 65536
00619    * 12 -> months per year
00620    * This is only a good approxiamtion for small values
00621    */
00622   int32 inf = _economy.infl_amount * 54;
00623 
00624   for (uint i = 0; i != NUM_PRICES; i++) {
00625     AddSingleInflation((Money*)&_price + i, _price_frac + i, inf);
00626   }
00627 
00628   AddSingleInflation(&_economy.max_loan_unround, &_economy.max_loan_unround_fract, inf);
00629 
00630   if (_economy.max_loan + 50000 <= _economy.max_loan_unround) _economy.max_loan += 50000;
00631 
00632   inf = _economy.infl_amount_pr * 54;
00633   for (CargoID i = 0; i < NUM_CARGO; i++) {
00634     AddSingleInflation(
00635       (Money*)_cargo_payment_rates + i,
00636       _cargo_payment_rates_frac + i,
00637       inf
00638     );
00639   }
00640 
00641   InvalidateWindowClasses(WC_BUILD_VEHICLE);
00642   InvalidateWindowClasses(WC_REPLACE_VEHICLE);
00643   InvalidateWindowClasses(WC_VEHICLE_DETAILS);
00644   InvalidateWindow(WC_PAYMENT_RATES, 0);
00645 }
00646 
00647 static void CompaniesPayInterest()
00648 {
00649   const Company *c;
00650 
00651   FOR_ALL_COMPANIES(c) {
00652     _current_company = c->index;
00653 
00654     /* Over a year the paid interest should be "loan * interest percentage",
00655      * but... as that number is likely not dividable by 12 (pay each month),
00656      * one needs to account for that in the monthly fee calculations.
00657      * To easily calculate what one should pay "this" month, you calculate
00658      * what (total) should have been paid up to this month and you substract
00659      * whatever has been paid in the previous months. This will mean one month
00660      * it'll be a bit more and the other it'll be a bit less than the average
00661      * monthly fee, but on average it will be exact. */
00662     Money yearly_fee = c->current_loan * _economy.interest_rate / 100;
00663     Money up_to_previous_month = yearly_fee * _cur_month / 12;
00664     Money up_to_this_month = yearly_fee * (_cur_month + 1) / 12;
00665 
00666     SubtractMoneyFromCompany(CommandCost(EXPENSES_LOAN_INT, up_to_this_month - up_to_previous_month));
00667 
00668     SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, _price.station_value >> 2));
00669   }
00670 }
00671 
00672 static void HandleEconomyFluctuations()
00673 {
00674   if (_settings_game.difficulty.economy != 0) {
00675     /* When economy is Fluctuating, decrease counter */
00676     _economy.fluct--;
00677   } else if (_economy.fluct <= 0) {
00678     /* When it's Steady and we are in recession, end it now */
00679     _economy.fluct = -12;
00680   } else {
00681     /* No need to do anything else in other cases */
00682     return;
00683   }
00684 
00685   if (_economy.fluct == 0) {
00686     _economy.fluct = -(int)GB(Random(), 0, 2);
00687     AddNewsItem(STR_7073_WORLD_RECESSION_FINANCIAL, NS_ECONOMY, 0, 0);
00688   } else if (_economy.fluct == -12) {
00689     _economy.fluct = GB(Random(), 0, 8) + 312;
00690     AddNewsItem(STR_7074_RECESSION_OVER_UPTURN_IN, NS_ECONOMY, 0, 0);
00691   }
00692 }
00693 
00694 static byte _price_category[NUM_PRICES] = {
00695   0, 2, 2, 2, 2, 2, 2, 2,
00696   2, 2, 2, 2, 2, 2, 2, 2,
00697   2, 2, 2, 2, 2, 2, 2, 2,
00698   2, 2, 2, 2, 2, 2, 2, 2,
00699   2, 2, 2, 2, 2, 2, 2, 2,
00700   2, 2, 1, 1, 1, 1, 1, 1,
00701   2,
00702 };
00703 
00704 static const Money _price_base[NUM_PRICES] = {
00705       100, 
00706       100, 
00707        95, 
00708        65, 
00709       275, 
00710       600, 
00711       500, 
00712       700, 
00713       450, 
00714       200, 
00715       180, 
00716       600, 
00717       200, 
00718       200, 
00719       350, 
00720    400000, 
00721      2000, 
00722    700000, 
00723     14000, 
00724     65000, 
00725        20, 
00726       250, 
00727        20, 
00728        40, 
00729       200, 
00730       500, 
00731        20, 
00732       -70, 
00733        10, 
00734        50, 
00735        80, 
00736        80, 
00737        90, 
00738        30, 
00739     10000, 
00740        50, 
00741        30, 
00742        50, 
00743        50, 
00744        55, 
00745      1600, 
00746        40, 
00747      5600, 
00748      5200, 
00749      4800, 
00750      9600, 
00751      1600, 
00752      5600, 
00753   1000000, 
00754 };
00755 
00756 static byte price_base_multiplier[NUM_PRICES];
00757 
00761 void ResetPriceBaseMultipliers()
00762 {
00763   uint i;
00764 
00765   /* 8 means no multiplier. */
00766   for (i = 0; i < NUM_PRICES; i++)
00767     price_base_multiplier[i] = 8;
00768 }
00769 
00777 void SetPriceBaseMultiplier(uint price, byte factor)
00778 {
00779   assert(price < NUM_PRICES);
00780   price_base_multiplier[price] = factor;
00781 }
00782 
00787 void StartupIndustryDailyChanges(bool init_counter)
00788 {
00789   uint map_size = MapLogX() + MapLogY();
00790   /* After getting map size, it needs to be scaled appropriately and divided by 31,
00791    * which stands for the days in a month.
00792    * Using just 31 will make it so that a monthly reset (based on the real number of days of that month)
00793    * would not be needed.
00794    * Since it is based on "fractionnal parts", the leftover days will not make much of a difference
00795    * on the overall total number of changes performed */
00796   _economy.industry_daily_increment = (1 << map_size) / 31;
00797 
00798   if (init_counter) {
00799     /* A new game or a savegame from an older version will require the counter to be initialized */
00800     _economy.industry_daily_change_counter = 0;
00801   }
00802 }
00803 
00804 void StartupEconomy()
00805 {
00806   int i;
00807 
00808   assert(sizeof(_price) == NUM_PRICES * sizeof(Money));
00809 
00810   for (i = 0; i != NUM_PRICES; i++) {
00811     Money price = _price_base[i];
00812     if (_price_category[i] != 0) {
00813       uint mod = _price_category[i] == 1 ? _settings_game.difficulty.vehicle_costs : _settings_game.difficulty.construction_cost;
00814       if (mod < 1) {
00815         price = price * 3 >> 2;
00816       } else if (mod > 1) {
00817         price = price * 9 >> 3;
00818       }
00819     }
00820     if (price_base_multiplier[i] > 8) {
00821       price <<= price_base_multiplier[i] - 8;
00822     } else {
00823       price >>= 8 - price_base_multiplier[i];
00824     }
00825     ((Money*)&_price)[i] = price;
00826     _price_frac[i] = 0;
00827   }
00828 
00829   _economy.interest_rate = _settings_game.difficulty.initial_interest;
00830   _economy.infl_amount = _settings_game.difficulty.initial_interest;
00831   _economy.infl_amount_pr = max(0, _settings_game.difficulty.initial_interest - 1);
00832   _economy.max_loan_unround = _economy.max_loan = _settings_game.difficulty.max_loan;
00833   _economy.fluct = GB(Random(), 0, 8) + 168;
00834 
00835   StartupIndustryDailyChanges(true); // As we are starting a new game, initialize the counter too
00836 
00837 }
00838 
00839 void ResetEconomy()
00840 {
00841   /* Test if resetting the economy is needed. */
00842   bool needed = false;
00843 
00844   for (CargoID c = 0; c < NUM_CARGO; c++) {
00845     const CargoSpec *cs = GetCargo(c);
00846     if (!cs->IsValid()) continue;
00847     if (_cargo_payment_rates[c] == 0) {
00848       needed = true;
00849       break;
00850     }
00851   }
00852 
00853   if (!needed) return;
00854 
00855   /* Remember old unrounded maximum loan value. NewGRF has the ability
00856    * to change all the other inflation affected base costs. */
00857   Money old_value = _economy.max_loan_unround;
00858 
00859   /* Reset the economy */
00860   StartupEconomy();
00861   InitializeLandscapeVariables(false);
00862 
00863   /* Reapply inflation, ignoring the year */
00864   while (old_value > _economy.max_loan_unround) {
00865     AddInflation(false);
00866   }
00867 }
00868 
00869 Money GetPriceByIndex(uint8 index)
00870 {
00871   if (index > NUM_PRICES) return 0;
00872 
00873   return ((Money*)&_price)[index];
00874 }
00875 
00876 
00877 Pair SetupSubsidyDecodeParam(const Subsidy *s, bool mode)
00878 {
00879   TileIndex tile;
00880   TileIndex tile2;
00881   Pair tp;
00882 
00883   /* if mode is false, use the singular form */
00884   const CargoSpec *cs = GetCargo(s->cargo_type);
00885   SetDParam(0, mode ? cs->name : cs->name_single);
00886 
00887   if (s->age < 12) {
00888     if (cs->town_effect != TE_PASSENGERS && cs->town_effect != TE_MAIL) {
00889       SetDParam(1, STR_INDUSTRY);
00890       SetDParam(2, s->from);
00891       tile = GetIndustry(s->from)->xy;
00892 
00893       if (cs->town_effect != TE_GOODS && cs->town_effect != TE_FOOD) {
00894         SetDParam(4, STR_INDUSTRY);
00895         SetDParam(5, s->to);
00896         tile2 = GetIndustry(s->to)->xy;
00897       } else {
00898         SetDParam(4, STR_TOWN);
00899         SetDParam(5, s->to);
00900         tile2 = GetTown(s->to)->xy;
00901       }
00902     } else {
00903       SetDParam(1, STR_TOWN);
00904       SetDParam(2, s->from);
00905       tile = GetTown(s->from)->xy;
00906 
00907       SetDParam(4, STR_TOWN);
00908       SetDParam(5, s->to);
00909       tile2 = GetTown(s->to)->xy;
00910     }
00911   } else {
00912     SetDParam(1, s->from);
00913     tile = GetStation(s->from)->xy;
00914 
00915     SetDParam(2, s->to);
00916     tile2 = GetStation(s->to)->xy;
00917   }
00918 
00919   tp.a = tile;
00920   tp.b = tile2;
00921 
00922   return tp;
00923 }
00924 
00925 void DeleteSubsidyWithTown(TownID index)
00926 {
00927   Subsidy *s;
00928 
00929   for (s = _subsidies; s != endof(_subsidies); s++) {
00930     if (s->cargo_type != CT_INVALID && s->age < 12) {
00931       const CargoSpec *cs = GetCargo(s->cargo_type);
00932       if (((cs->town_effect == TE_PASSENGERS || cs->town_effect == TE_MAIL) && (index == s->from || index == s->to)) ||
00933         ((cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) && index == s->to)) {
00934         s->cargo_type = CT_INVALID;
00935       }
00936     }
00937   }
00938 }
00939 
00940 void DeleteSubsidyWithIndustry(IndustryID index)
00941 {
00942   Subsidy *s;
00943 
00944   for (s = _subsidies; s != endof(_subsidies); s++) {
00945     if (s->cargo_type != CT_INVALID && s->age < 12) {
00946       const CargoSpec *cs = GetCargo(s->cargo_type);
00947       if (cs->town_effect != TE_PASSENGERS && cs->town_effect != TE_MAIL &&
00948         (index == s->from || (cs->town_effect != TE_GOODS && cs->town_effect != TE_FOOD && index == s->to))) {
00949         s->cargo_type = CT_INVALID;
00950       }
00951     }
00952   }
00953 }
00954 
00955 void DeleteSubsidyWithStation(StationID index)
00956 {
00957   Subsidy *s;
00958   bool dirty = false;
00959 
00960   for (s = _subsidies; s != endof(_subsidies); s++) {
00961     if (s->cargo_type != CT_INVALID && s->age >= 12 &&
00962         (s->from == index || s->to == index)) {
00963       s->cargo_type = CT_INVALID;
00964       dirty = true;
00965     }
00966   }
00967 
00968   if (dirty)
00969     InvalidateWindow(WC_SUBSIDIES_LIST, 0);
00970 }
00971 
00972 struct FoundRoute {
00973   uint distance;
00974   CargoID cargo;
00975   void *from;
00976   void *to;
00977 };
00978 
00979 static void FindSubsidyPassengerRoute(FoundRoute *fr)
00980 {
00981   Town *from, *to;
00982 
00983   fr->distance = UINT_MAX;
00984 
00985   fr->from = from = GetRandomTown();
00986   if (from == NULL || from->population < 400) return;
00987 
00988   fr->to = to = GetRandomTown();
00989   if (from == to || to == NULL || to->population < 400 || to->pct_pass_transported > 42)
00990     return;
00991 
00992   fr->distance = DistanceManhattan(from->xy, to->xy);
00993 }
00994 
00995 static void FindSubsidyCargoRoute(FoundRoute *fr)
00996 {
00997   Industry *i;
00998   int trans, total;
00999   CargoID cargo;
01000 
01001   fr->distance = UINT_MAX;
01002 
01003   fr->from = i = GetRandomIndustry();
01004   if (i == NULL) return;
01005 
01006   /* Randomize cargo type */
01007   if (HasBit(Random(), 0) && i->produced_cargo[1] != CT_INVALID) {
01008     cargo = i->produced_cargo[1];
01009     trans = i->last_month_pct_transported[1];
01010     total = i->last_month_production[1];
01011   } else {
01012     cargo = i->produced_cargo[0];
01013     trans = i->last_month_pct_transported[0];
01014     total = i->last_month_production[0];
01015   }
01016 
01017   /* Quit if no production in this industry
01018    * or if the cargo type is passengers
01019    * or if the pct transported is already large enough */
01020   if (total == 0 || trans > 42 || cargo == CT_INVALID) return;
01021 
01022   const CargoSpec *cs = GetCargo(cargo);
01023   if (cs->town_effect == TE_PASSENGERS) return;
01024 
01025   fr->cargo = cargo;
01026 
01027   if (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) {
01028     /*  The destination is a town */
01029     Town *t = GetRandomTown();
01030 
01031     /* Only want big towns */
01032     if (t == NULL || t->population < 900) return;
01033 
01034     fr->distance = DistanceManhattan(i->xy, t->xy);
01035     fr->to = t;
01036   } else {
01037     /* The destination is an industry */
01038     Industry *i2 = GetRandomIndustry();
01039 
01040     /* The industry must accept the cargo */
01041     if (i2 == NULL || i == i2 ||
01042         (cargo != i2->accepts_cargo[0] &&
01043         cargo != i2->accepts_cargo[1] &&
01044         cargo != i2->accepts_cargo[2])) {
01045       return;
01046     }
01047     fr->distance = DistanceManhattan(i->xy, i2->xy);
01048     fr->to = i2;
01049   }
01050 }
01051 
01052 static bool CheckSubsidyDuplicate(Subsidy *s)
01053 {
01054   const Subsidy *ss;
01055 
01056   for (ss = _subsidies; ss != endof(_subsidies); ss++) {
01057     if (s != ss &&
01058         ss->from == s->from &&
01059         ss->to == s->to &&
01060         ss->cargo_type == s->cargo_type) {
01061       s->cargo_type = CT_INVALID;
01062       return true;
01063     }
01064   }
01065   return false;
01066 }
01067 
01068 
01069 static void SubsidyMonthlyHandler()
01070 {
01071   Subsidy *s;
01072   Pair pair;
01073   Station *st;
01074   uint n;
01075   FoundRoute fr;
01076   bool modified = false;
01077 
01078   for (s = _subsidies; s != endof(_subsidies); s++) {
01079     if (s->cargo_type == CT_INVALID) continue;
01080 
01081     if (s->age == 12 - 1) {
01082       pair = SetupSubsidyDecodeParam(s, 1);
01083       AddNewsItem(STR_202E_OFFER_OF_SUBSIDY_EXPIRED, NS_SUBSIDIES, pair.a, pair.b);
01084       s->cargo_type = CT_INVALID;
01085       modified = true;
01086       AI::BroadcastNewEvent(new AIEventSubsidyOfferExpired(s - _subsidies));
01087     } else if (s->age == 2 * 12 - 1) {
01088       st = GetStation(s->to);
01089       if (st->owner == _local_company) {
01090         pair = SetupSubsidyDecodeParam(s, 1);
01091         AddNewsItem(STR_202F_SUBSIDY_WITHDRAWN_SERVICE, NS_SUBSIDIES, pair.a, pair.b);
01092       }
01093       s->cargo_type = CT_INVALID;
01094       modified = true;
01095       AI::BroadcastNewEvent(new AIEventSubsidyExpired(s - _subsidies));
01096     } else {
01097       s->age++;
01098     }
01099   }
01100 
01101   /* 25% chance to go on */
01102   if (Chance16(1, 4)) {
01103     /*  Find a free slot*/
01104     s = _subsidies;
01105     while (s->cargo_type != CT_INVALID) {
01106       if (++s == endof(_subsidies))
01107         goto no_add;
01108     }
01109 
01110     n = 1000;
01111     do {
01112       FindSubsidyPassengerRoute(&fr);
01113       if (fr.distance <= 70) {
01114         s->cargo_type = CT_PASSENGERS;
01115         s->from = ((Town*)fr.from)->index;
01116         s->to = ((Town*)fr.to)->index;
01117         goto add_subsidy;
01118       }
01119       FindSubsidyCargoRoute(&fr);
01120       if (fr.distance <= 70) {
01121         s->cargo_type = fr.cargo;
01122         s->from = ((Industry*)fr.from)->index;
01123         {
01124           const CargoSpec *cs = GetCargo(fr.cargo);
01125           s->to = (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) ? ((Town*)fr.to)->index : ((Industry*)fr.to)->index;
01126         }
01127   add_subsidy:
01128         if (!CheckSubsidyDuplicate(s)) {
01129           s->age = 0;
01130           pair = SetupSubsidyDecodeParam(s, 0);
01131           AddNewsItem(STR_2030_SERVICE_SUBSIDY_OFFERED, NS_SUBSIDIES, pair.a, pair.b);
01132           AI::BroadcastNewEvent(new AIEventSubsidyOffer(s - _subsidies));
01133           modified = true;
01134           break;
01135         }
01136       }
01137     } while (n--);
01138   }
01139 no_add:;
01140   if (modified)
01141     InvalidateWindow(WC_SUBSIDIES_LIST, 0);
01142 }
01143 
01144 Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type)
01145 {
01146   const CargoSpec *cs = GetCargo(cargo_type);
01147 
01148   /* Use callback to calculate cargo profit, if available */
01149   if (HasBit(cs->callback_mask, CBM_CARGO_PROFIT_CALC)) {
01150     uint32 var18 = min(dist, 0xFFFF) | (min(num_pieces, 0xFF) << 16) | (transit_days << 24);
01151     uint16 callback = GetCargoCallback(CBID_CARGO_PROFIT_CALC, 0, var18, cs);
01152     if (callback != CALLBACK_FAILED) {
01153       int result = GB(callback, 0, 14);
01154 
01155       /* Simulate a 15 bit signed value */
01156       if (HasBit(callback, 14)) result -= 0x4000;
01157 
01158       /* "The result should be a signed multiplier that gets multiplied
01159        * by the amount of cargo moved and the price factor, then gets
01160        * divided by 8192." */
01161       return result * num_pieces * _cargo_payment_rates[cargo_type] / 8192;
01162     }
01163   }
01164 
01165   /* zero the distance (thus income) if it's the bank and very short transport. */
01166   if (_settings_game.game_creation.landscape == LT_TEMPERATE && cs->label == 'VALU' && dist < 10) return 0;
01167 
01168 
01169   static const int MIN_TIME_FACTOR = 31;
01170   static const int MAX_TIME_FACTOR = 255;
01171 
01172   const int days1 = cs->transit_days[0];
01173   const int days2 = cs->transit_days[1];
01174   const int days_over_days1 = max(   transit_days - days1, 0);
01175   const int days_over_days2 = max(days_over_days1 - days2, 0);
01176 
01177   /*
01178    * The time factor is calculated based on the time it took
01179    * (transit_days) compared two cargo-depending values. The
01180    * range is divided into three parts:
01181    *
01182    *  - constant for fast transits
01183    *  - linear decreasing with time with a slope of -1 for medium transports
01184    *  - linear decreasing with time with a slope of -2 for slow transports
01185    *
01186    */
01187   const int time_factor = max(MAX_TIME_FACTOR - days_over_days1 - days_over_days2, MIN_TIME_FACTOR);
01188 
01189   return BigMulS(dist * time_factor * num_pieces, _cargo_payment_rates[cargo_type], 21);
01190 }
01191 
01192 
01193 struct FindIndustryToDeliverData {
01194   const Rect *rect;            
01195   CargoID cargo_type;          
01196 
01197   Industry *ind;               
01198   const IndustrySpec *indspec; 
01199   uint cargo_index;            
01200 };
01201 
01202 static bool FindIndustryToDeliver(TileIndex ind_tile, void *user_data)
01203 {
01204   FindIndustryToDeliverData *callback_data = (FindIndustryToDeliverData *)user_data;
01205   const Rect *rect = callback_data->rect;
01206   CargoID cargo_type = callback_data->cargo_type;
01207 
01208   /* Only process industry tiles */
01209   if (!IsTileType(ind_tile, MP_INDUSTRY)) return false;
01210 
01211   /* Only process tiles in the station acceptance rectangle */
01212   int x = TileX(ind_tile);
01213   int y = TileY(ind_tile);
01214   if (x < rect->left || x > rect->right || y < rect->top || y > rect->bottom) return false;
01215 
01216   Industry *ind = GetIndustryByTile(ind_tile);
01217   const IndustrySpec *indspec = GetIndustrySpec(ind->type);
01218 
01219   uint cargo_index;
01220   for (cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
01221     if (cargo_type == ind->accepts_cargo[cargo_index]) break;
01222   }
01223   /* Check if matching cargo has been found */
01224   if (cargo_index >= lengthof(ind->accepts_cargo)) return false;
01225 
01226   /* Check if industry temporarly refuses acceptance */
01227   if (HasBit(indspec->callback_flags, CBM_IND_REFUSE_CARGO)) {
01228     uint16 res = GetIndustryCallback(CBID_INDUSTRY_REFUSE_CARGO, 0, GetReverseCargoTranslation(cargo_type, indspec->grf_prop.grffile), ind, ind->type, ind->xy);
01229     if (res == 0) return false;
01230   }
01231 
01232   /* Found industry accepting the cargo */
01233   callback_data->ind = ind;
01234   callback_data->indspec = indspec;
01235   callback_data->cargo_index = cargo_index;
01236   return true;
01237 }
01238 
01240 static SmallIndustryList _cargo_delivery_destinations;
01241 
01249 static void DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, int num_pieces)
01250 {
01251   if (st->rect.IsEmpty()) return;
01252 
01253   /* Compute acceptance rectangle */
01254   int catchment_radius = st->GetCatchmentRadius();
01255   Rect rect = {
01256     max<int>(st->rect.left   - catchment_radius, 0),
01257     max<int>(st->rect.top    - catchment_radius, 0),
01258     min<int>(st->rect.right  + catchment_radius, MapMaxX()),
01259     min<int>(st->rect.bottom + catchment_radius, MapMaxY())
01260   };
01261 
01262   /* Compute maximum extent of acceptance rectangle wrt. station sign */
01263   TileIndex start_tile = st->xy;
01264   uint max_radius = max(
01265     max(DistanceManhattan(start_tile, TileXY(rect.left , rect.top)), DistanceManhattan(start_tile, TileXY(rect.left , rect.bottom))),
01266     max(DistanceManhattan(start_tile, TileXY(rect.right, rect.top)), DistanceManhattan(start_tile, TileXY(rect.right, rect.bottom)))
01267   );
01268 
01269   FindIndustryToDeliverData callback_data;
01270   callback_data.rect = &rect;
01271   callback_data.cargo_type = cargo_type;
01272   callback_data.ind = NULL;
01273   callback_data.indspec = NULL;
01274   callback_data.cargo_index = 0;
01275 
01276   /* Find the nearest industrytile to the station sign inside the catchment area, whose industry accepts the cargo.
01277    * This fails in three cases:
01278    *  1) The station accepts the cargo because there are enough houses around it accepting the cargo.
01279    *  2) The industries in the catchment area temporarily reject the cargo, and the daily station loop has not yet updated station acceptance.
01280    *  3) The results of callbacks CBID_INDUSTRY_REFUSE_CARGO and CBID_INDTILE_CARGO_ACCEPTANCE are inconsistent. (documented behaviour)
01281    */
01282   if (CircularTileSearch(&start_tile, 2 * max_radius + 1, FindIndustryToDeliver, &callback_data)) {
01283     Industry *best = callback_data.ind;
01284     uint accepted_cargo_index = callback_data.cargo_index;
01285     assert(best != NULL);
01286 
01287     /* Insert the industry into industry_set, if not yet contained */
01288     _cargo_delivery_destinations.Include(best);
01289 
01290     best->incoming_cargo_waiting[accepted_cargo_index] = min(num_pieces + best->incoming_cargo_waiting[accepted_cargo_index], 0xFFFF);
01291   }
01292 }
01293 
01294 
01295 static bool CheckSubsidised(Station *from, Station *to, CargoID cargo_type, CompanyID company)
01296 {
01297   Subsidy *s;
01298   TileIndex xy;
01299   Pair pair;
01300 
01301   /* check if there is an already existing subsidy that applies to us */
01302   for (s = _subsidies; s != endof(_subsidies); s++) {
01303     if (s->cargo_type == cargo_type &&
01304         s->age >= 12 &&
01305         s->from == from->index &&
01306         s->to == to->index) {
01307       return true;
01308     }
01309   }
01310 
01311   /* check if there's a new subsidy that applies.. */
01312   for (s = _subsidies; s != endof(_subsidies); s++) {
01313     if (s->cargo_type == cargo_type && s->age < 12) {
01314       /* Check distance from source */
01315       const CargoSpec *cs = GetCargo(cargo_type);
01316       if (cs->town_effect == TE_PASSENGERS || cs->town_effect == TE_MAIL) {
01317         xy = GetTown(s->from)->xy;
01318       } else {
01319         xy = GetIndustry(s->from)->xy;
01320       }
01321       if (DistanceMax(xy, from->xy) > 9) continue;
01322 
01323       /* Check distance from dest */
01324       switch (cs->town_effect) {
01325         case TE_PASSENGERS:
01326         case TE_MAIL:
01327         case TE_GOODS:
01328         case TE_FOOD:
01329           xy = GetTown(s->to)->xy;
01330           break;
01331 
01332         default:
01333           xy = GetIndustry(s->to)->xy;
01334           break;
01335       }
01336       if (DistanceMax(xy, to->xy) > 9) continue;
01337 
01338       /* Found a subsidy, change the values to indicate that it's in use */
01339       s->age = 12;
01340       s->from = from->index;
01341       s->to = to->index;
01342 
01343       /* Add a news item */
01344       pair = SetupSubsidyDecodeParam(s, 0);
01345       InjectDParam(1);
01346 
01347       SetDParam(0, company);
01348       AddNewsItem(
01349         STR_2031_SERVICE_SUBSIDY_AWARDED + _settings_game.difficulty.subsidy_multiplier,
01350         NS_SUBSIDIES,
01351         pair.a, pair.b
01352       );
01353       AI::BroadcastNewEvent(new AIEventSubsidyAwarded(s - _subsidies));
01354 
01355       InvalidateWindow(WC_SUBSIDIES_LIST, 0);
01356       return true;
01357     }
01358   }
01359   return false;
01360 }
01361 
01372 static Money DeliverGoods(int num_pieces, CargoID cargo_type, StationID source, StationID dest, TileIndex source_tile, byte days_in_transit, Company *company)
01373 {
01374   bool subsidised;
01375   Station *s_from, *s_to;
01376   Money profit;
01377 
01378   assert(num_pieces > 0);
01379 
01380   /* Update company statistics */
01381   company->cur_economy.delivered_cargo += num_pieces;
01382   SetBit(company->cargo_types, cargo_type);
01383 
01384   /* Get station pointers. */
01385   s_from = IsValidStationID(source) ? GetStation(source) : NULL;
01386   s_to = GetStation(dest);
01387 
01388   /* Check if a subsidy applies. */
01389   subsidised = s_from != NULL && CheckSubsidised(s_from, s_to, cargo_type, company->index);
01390 
01391   /* Increase town's counter for some special goods types */
01392   const CargoSpec *cs = GetCargo(cargo_type);
01393   if (cs->town_effect == TE_FOOD) s_to->town->new_act_food += num_pieces;
01394   if (cs->town_effect == TE_WATER) s_to->town->new_act_water += num_pieces;
01395 
01396   /* Give the goods to the industry. */
01397   DeliverGoodsToIndustry(s_to, cargo_type, num_pieces);
01398 
01399   /* Determine profit */
01400   profit = GetTransportedGoodsIncome(num_pieces, DistanceManhattan(source_tile, s_to->xy), days_in_transit, cargo_type);
01401 
01402   /* Modify profit if a subsidy is in effect */
01403   if (subsidised) {
01404     switch (_settings_game.difficulty.subsidy_multiplier) {
01405       case 0:  profit += profit >> 1; break;
01406       case 1:  profit *= 2; break;
01407       case 2:  profit *= 3; break;
01408       default: profit *= 4; break;
01409     }
01410   }
01411 
01412   return profit;
01413 }
01414 
01420 static void TriggerIndustryProduction(Industry *i)
01421 {
01422   const IndustrySpec *indspec = GetIndustrySpec(i->type);
01423   uint16 callback = indspec->callback_flags;
01424 
01425   i->was_cargo_delivered = true;
01426   i->last_cargo_accepted_at = _date;
01427 
01428   if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(callback, CBM_IND_PRODUCTION_256_TICKS)) {
01429     if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) {
01430       IndustryProductionCallback(i, 0);
01431     } else {
01432       InvalidateWindow(WC_INDUSTRY_VIEW, i->index);
01433     }
01434   } else {
01435     for (uint cargo_index = 0; cargo_index < lengthof(i->incoming_cargo_waiting); cargo_index++) {
01436       uint cargo_waiting = i->incoming_cargo_waiting[cargo_index];
01437       if (cargo_waiting == 0) continue;
01438 
01439       i->produced_cargo_waiting[0] = min(i->produced_cargo_waiting[0] + (cargo_waiting * indspec->input_cargo_multiplier[cargo_index][0] / 256), 0xFFFF);
01440       i->produced_cargo_waiting[1] = min(i->produced_cargo_waiting[1] + (cargo_waiting * indspec->input_cargo_multiplier[cargo_index][1] / 256), 0xFFFF);
01441 
01442       i->incoming_cargo_waiting[cargo_index] = 0;
01443     }
01444   }
01445 
01446   TriggerIndustry(i, INDUSTRY_TRIGGER_RECEIVED_CARGO);
01447   StartStopIndustryTileAnimation(i, IAT_INDUSTRY_RECEIVED_CARGO);
01448 }
01449 
01455 CargoPayment::CargoPayment(Vehicle *front) :
01456   front(front),
01457   current_station(front->last_station_visited)
01458 {
01459 }
01460 
01461 CargoPayment::~CargoPayment()
01462 {
01463   if (this->CleaningPool()) return;
01464 
01465   this->front->cargo_payment = NULL;
01466 
01467   if (this->visual_profit == 0) {
01468     this->front = NULL;
01469     return;
01470   }
01471 
01472   CompanyID old_company = _current_company;
01473   _current_company = this->front->owner;
01474 
01475   SubtractMoneyFromCompany(CommandCost(this->front->GetExpenseType(true), -this->route_profit));
01476   this->front->profit_this_year += this->visual_profit << 8;
01477 
01478   if (this->route_profit != 0) {
01479     if (IsLocalCompany() && !PlayVehicleSound(this->front, VSE_LOAD_UNLOAD)) {
01480       SndPlayVehicleFx(SND_14_CASHTILL, this->front);
01481     }
01482 
01483     ShowCostOrIncomeAnimation(this->front->x_pos, this->front->y_pos, this->front->z_pos, -this->visual_profit);
01484   } else {
01485     ShowFeederIncomeAnimation(this->front->x_pos, this->front->y_pos, this->front->z_pos, this->visual_profit);
01486   }
01487 
01488   _current_company = old_company;
01489 
01490   this->front = NULL;
01491 }
01492 
01498 void CargoPayment::PayFinalDelivery(CargoPacket *cp, uint count)
01499 {
01500   if (this->owner == NULL) {
01501     this->owner = GetCompany(this->front->owner);
01502   }
01503 
01504   /* Handle end of route payment */
01505   Money profit = DeliverGoods(count, this->ct, cp->source, this->current_station, cp->source_xy, cp->days_in_transit, this->owner);
01506   this->route_profit += profit;
01507 
01508   /* The vehicle's profit is whatever route profit there is minus feeder shares. */
01509   this->visual_profit += profit - cp->feeder_share;
01510 }
01511 
01517 void CargoPayment::PayTransfer(CargoPacket *cp, uint count)
01518 {
01519   Money profit = GetTransportedGoodsIncome(
01520     count,
01521     /* pay transfer vehicle for only the part of transfer it has done: ie. cargo_loaded_at_xy to here */
01522     DistanceManhattan(cp->loaded_at_xy, GetStation(this->current_station)->xy),
01523     cp->days_in_transit,
01524     this->ct);
01525 
01526   this->visual_profit += profit; // accumulate transfer profits for whole vehicle
01527   cp->feeder_share    += profit; // account for the (virtual) profit already made for the cargo packet
01528 }
01529 
01534 void PrepareUnload(Vehicle *front_v)
01535 {
01536   /* At this moment loading cannot be finished */
01537   ClrBit(front_v->vehicle_flags, VF_LOADING_FINISHED);
01538 
01539   /* Start unloading in at the first possible moment */
01540   front_v->load_unload_time_rem = 1;
01541 
01542   if ((front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
01543     for (Vehicle *v = front_v; v != NULL; v = v->Next()) {
01544       if (v->cargo_cap > 0 && !v->cargo.Empty()) {
01545         SetBit(v->vehicle_flags, VF_CARGO_UNLOADING);
01546       }
01547     }
01548   }
01549 
01550   assert(front_v->cargo_payment == NULL);
01551   front_v->cargo_payment = new CargoPayment(front_v);
01552 }
01553 
01562 static void LoadUnloadVehicle(Vehicle *v, int *cargo_left)
01563 {
01564   assert(v->current_order.IsType(OT_LOADING));
01565 
01566   assert(v->load_unload_time_rem != 0);
01567 
01568   /* We have not waited enough time till the next round of loading/unloading */
01569   if (--v->load_unload_time_rem != 0) {
01570     if (_settings_game.order.improved_load && (v->current_order.GetLoadType() & OLFB_FULL_LOAD)) {
01571       /* 'Reserve' this cargo for this vehicle, because we were first. */
01572       for (; v != NULL; v = v->Next()) {
01573         int cap_left = v->cargo_cap - v->cargo.Count();
01574         if (cap_left > 0) cargo_left[v->cargo_type] -= cap_left;
01575       }
01576     }
01577     return;
01578   }
01579 
01580   StationID last_visited = v->last_station_visited;
01581   Station *st = GetStation(last_visited);
01582 
01583   if (v->type == VEH_TRAIN && (!IsTileType(v->tile, MP_STATION) || GetStationIndex(v->tile) != st->index)) {
01584     /* The train reversed in the station. Take the "easy" way
01585      * out and let the train just leave as it always did. */
01586     SetBit(v->vehicle_flags, VF_LOADING_FINISHED);
01587     v->load_unload_time_rem = 1;
01588     return;
01589   }
01590 
01591   int unloading_time = 0;
01592   Vehicle *u = v;
01593   int result = 0;
01594 
01595   bool completely_emptied = true;
01596   bool anything_unloaded = false;
01597   bool anything_loaded   = false;
01598   uint32 cargo_not_full  = 0;
01599   uint32 cargo_full      = 0;
01600 
01601   v->cur_speed = 0;
01602 
01603   CargoPayment *payment = v->cargo_payment;
01604 
01605   for (; v != NULL; v = v->Next()) {
01606     if (v->cargo_cap == 0) continue;
01607 
01608     byte load_amount = EngInfo(v->engine_type)->load_amount;
01609 
01610     /* The default loadamount for mail is 1/4 of the load amount for passengers */
01611     if (v->type == VEH_AIRCRAFT && !IsNormalAircraft(v)) load_amount = (load_amount + 3) / 4;
01612 
01613     if (_settings_game.order.gradual_loading && HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_LOAD_AMOUNT)) {
01614       uint16 cb_load_amount = GetVehicleCallback(CBID_VEHICLE_LOAD_AMOUNT, 0, 0, v->engine_type, v);
01615       if (cb_load_amount != CALLBACK_FAILED && GB(cb_load_amount, 0, 8) != 0) load_amount = GB(cb_load_amount, 0, 8);
01616     }
01617 
01618     GoodsEntry *ge = &st->goods[v->cargo_type];
01619 
01620     if (HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) && (u->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
01621       uint cargo_count = v->cargo.Count();
01622       uint amount_unloaded = _settings_game.order.gradual_loading ? min(cargo_count, load_amount) : cargo_count;
01623       bool remaining = false; // Are there cargo entities in this vehicle that can still be unloaded here?
01624       bool accepted  = false; // Is the cargo accepted by the station?
01625 
01626       payment->SetCargo(v->cargo_type);
01627 
01628       if (HasBit(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && !(u->current_order.GetUnloadType() & OUFB_TRANSFER)) {
01629         /* The cargo has reached it's final destination, the packets may now be destroyed */
01630         remaining = v->cargo.MoveTo(NULL, amount_unloaded, CargoList::MTA_FINAL_DELIVERY, payment, last_visited);
01631 
01632         result |= 1;
01633         accepted = true;
01634       }
01635 
01636       /* The !accepted || v->cargo.Count == cargo_count clause is there
01637        * to make it possible to force unload vehicles at the station where
01638        * they were loaded, but to not force unload the vehicle when the
01639        * station is still accepting the cargo in the vehicle. It doesn't
01640        * accept cargo that was loaded at the same station. */
01641       if (u->current_order.GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER) && (!accepted || v->cargo.Count() == cargo_count)) {
01642         remaining = v->cargo.MoveTo(&ge->cargo, amount_unloaded, u->current_order.GetUnloadType() & OUFB_TRANSFER ? CargoList::MTA_TRANSFER : CargoList::MTA_UNLOAD, payment);
01643         SetBit(ge->acceptance_pickup, GoodsEntry::PICKUP);
01644 
01645         result |= 2;
01646       } else if (!accepted) {
01647         /* The order changed while unloading (unset unload/transfer) or the
01648          * station does not accept our goods. */
01649         ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING);
01650 
01651         /* Say we loaded something, otherwise we'll think we didn't unload
01652          * something and we didn't load something, so we must be finished
01653          * at this station. Setting the unloaded means that we will get a
01654          * retry for loading in the next cycle. */
01655         anything_unloaded = true;
01656         continue;
01657       }
01658 
01659       /* Deliver goods to the station */
01660       st->time_since_unload = 0;
01661 
01662       unloading_time += amount_unloaded;
01663 
01664       anything_unloaded = true;
01665       if (_settings_game.order.gradual_loading && remaining) {
01666         completely_emptied = false;
01667       } else {
01668         /* We have finished unloading (cargo count == 0) */
01669         ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING);
01670       }
01671 
01672       continue;
01673     }
01674 
01675     /* Do not pick up goods when we have no-load set. */
01676     if (u->current_order.GetLoadType() & OLFB_NO_LOAD) continue;
01677 
01678     /* update stats */
01679     int t;
01680     switch (u->type) {
01681       case VEH_TRAIN:    t = u->u.rail.cached_max_speed; break;
01682       case VEH_ROAD:     t = u->max_speed / 2;           break;
01683       case VEH_SHIP:     t = u->max_speed;               break;
01684       case VEH_AIRCRAFT: t = u->max_speed * 10 / 129;    break; // convert to old units
01685       default: NOT_REACHED();
01686     }
01687 
01688     /* if last speed is 0, we treat that as if no vehicle has ever visited the station. */
01689     ge->last_speed = min(t, 255);
01690     ge->last_age = _cur_year - u->build_year;
01691     ge->days_since_pickup = 0;
01692 
01693     /* If there's goods waiting at the station, and the vehicle
01694      * has capacity for it, load it on the vehicle. */
01695     int cap_left = v->cargo_cap - v->cargo.Count();
01696     if (!ge->cargo.Empty() && cap_left > 0) {
01697       uint cap = cap_left;
01698       uint count = ge->cargo.Count();
01699 
01700       /* Skip loading this vehicle if another train/vehicle is already handling
01701        * the same cargo type at this station */
01702       if (_settings_game.order.improved_load && cargo_left[v->cargo_type] <= 0) {
01703         SetBit(cargo_not_full, v->cargo_type);
01704         continue;
01705       }
01706 
01707       if (cap > count) cap = count;
01708       if (_settings_game.order.gradual_loading) cap = min(cap, load_amount);
01709       if (_settings_game.order.improved_load) {
01710         /* Don't load stuff that is already 'reserved' for other vehicles */
01711         cap = min((uint)cargo_left[v->cargo_type], cap);
01712         cargo_left[v->cargo_type] -= cap;
01713       }
01714 
01715       if (v->cargo.Empty()) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
01716 
01717       /* TODO: Regarding this, when we do gradual loading, we
01718        * should first unload all vehicles and then start
01719        * loading them. Since this will cause
01720        * VEHICLE_TRIGGER_EMPTY to be called at the time when
01721        * the whole vehicle chain is really totally empty, the
01722        * completely_emptied assignment can then be safely
01723        * removed; that's how TTDPatch behaves too. --pasky */
01724       completely_emptied = false;
01725       anything_loaded = true;
01726 
01727       ge->cargo.MoveTo(&v->cargo, cap, CargoList::MTA_CARGO_LOAD, NULL, st->xy);
01728 
01729       st->time_since_load = 0;
01730       st->last_vehicle_type = v->type;
01731 
01732       StationAnimationTrigger(st, st->xy, STAT_ANIM_CARGO_TAKEN, v->cargo_type);
01733 
01734       unloading_time += cap;
01735 
01736       result |= 2;
01737     }
01738 
01739     if (v->cargo.Count() >= v->cargo_cap) {
01740       SetBit(cargo_full, v->cargo_type);
01741     } else {
01742       SetBit(cargo_not_full, v->cargo_type);
01743     }
01744   }
01745 
01746   /* Only set completly_emptied, if we just unloaded all remaining cargo */
01747   completely_emptied &= anything_unloaded;
01748 
01749   /* We update these variables here, so gradual loading still fills
01750    * all wagons at the same time instead of using the same 'improved'
01751    * loading algorithm for the wagons (only fill wagon when there is
01752    * enough to fill the previous wagons) */
01753   if (_settings_game.order.improved_load && (u->current_order.GetLoadType() & OLFB_FULL_LOAD)) {
01754     /* Update left cargo */
01755     for (v = u; v != NULL; v = v->Next()) {
01756       int cap_left = v->cargo_cap - v->cargo.Count();
01757       if (cap_left > 0) cargo_left[v->cargo_type] -= cap_left;
01758     }
01759   }
01760 
01761   v = u;
01762 
01763   if (!anything_unloaded) delete payment;
01764 
01765   if (anything_loaded || anything_unloaded) {
01766     if (_settings_game.order.gradual_loading) {
01767       /* The time it takes to load one 'slice' of cargo or passengers depends
01768        * on the vehicle type - the values here are those found in TTDPatch */
01769       const uint gradual_loading_wait_time[] = { 40, 20, 10, 20 };
01770 
01771       unloading_time = gradual_loading_wait_time[v->type];
01772     }
01773   } else {
01774     bool finished_loading = true;
01775     if (v->current_order.GetLoadType() & OLFB_FULL_LOAD) {
01776       if (v->current_order.GetLoadType() == OLF_FULL_LOAD_ANY) {
01777         /* if the aircraft carries passengers and is NOT full, then
01778          * continue loading, no matter how much mail is in */
01779         if ((v->type == VEH_AIRCRAFT && IsCargoInClass(v->cargo_type, CC_PASSENGERS) && v->cargo_cap > v->cargo.Count()) ||
01780             (cargo_not_full && (cargo_full & ~cargo_not_full) == 0)) { // There are stull non-full cargos
01781           finished_loading = false;
01782         }
01783       } else if (cargo_not_full != 0) {
01784         finished_loading = false;
01785       }
01786     }
01787     unloading_time = 20;
01788 
01789     SB(v->vehicle_flags, VF_LOADING_FINISHED, 1, finished_loading);
01790   }
01791 
01792   if (v->type == VEH_TRAIN) {
01793     /* Each platform tile is worth 2 rail vehicles. */
01794     int overhang = v->u.rail.cached_total_length - st->GetPlatformLength(v->tile) * TILE_SIZE;
01795     if (overhang > 0) {
01796       unloading_time <<= 1;
01797       unloading_time += (overhang * unloading_time) / 8;
01798     }
01799   }
01800 
01801   /* Calculate the loading indicator fill percent and display
01802    * In the Game Menu do not display indicators
01803    * If _settings_client.gui.loading_indicators == 2, show indicators (bool can be promoted to int as 0 or 1 - results in 2 > 0,1 )
01804    * if _settings_client.gui.loading_indicators == 1, _local_company must be the owner or must be a spectator to show ind., so 1 > 0
01805    * if _settings_client.gui.loading_indicators == 0, do not display indicators ... 0 is never greater than anything
01806    */
01807   if (_game_mode != GM_MENU && (_settings_client.gui.loading_indicators > (uint)(v->owner != _local_company && _local_company != COMPANY_SPECTATOR))) {
01808     StringID percent_up_down = STR_NULL;
01809     int percent = CalcPercentVehicleFilled(v, &percent_up_down);
01810     if (v->fill_percent_te_id == INVALID_TE_ID) {
01811       v->fill_percent_te_id = ShowFillingPercent(v->x_pos, v->y_pos, v->z_pos + 20, percent, percent_up_down);
01812     } else {
01813       UpdateFillingPercent(v->fill_percent_te_id, percent, percent_up_down);
01814     }
01815   }
01816 
01817   /* Always wait at least 1, otherwise we'll wait 'infinitively' long. */
01818   v->load_unload_time_rem = max(1, unloading_time);
01819 
01820   if (completely_emptied) {
01821     TriggerVehicle(v, VEHICLE_TRIGGER_EMPTY);
01822   }
01823 
01824   if (result != 0) {
01825     InvalidateWindow(GetWindowClassForVehicleType(v->type), v->owner);
01826     InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
01827 
01828     st->MarkTilesDirty(true);
01829     v->MarkDirty();
01830 
01831     if (result & 2) InvalidateWindow(WC_STATION_VIEW, last_visited);
01832   }
01833 }
01834 
01840 void LoadUnloadStation(Station *st)
01841 {
01842   /* No vehicle is here... */
01843   if (st->loading_vehicles.empty()) return;
01844 
01845   int cargo_left[NUM_CARGO];
01846 
01847   for (uint i = 0; i < NUM_CARGO; i++) cargo_left[i] = st->goods[i].cargo.Count();
01848 
01849   std::list<Vehicle *>::iterator iter;
01850   for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
01851     Vehicle *v = *iter;
01852     if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED))) LoadUnloadVehicle(v, cargo_left);
01853   }
01854 
01855   /* Call the production machinery of industries */
01856   const Industry * const *isend = _cargo_delivery_destinations.End();
01857   for (Industry **iid = _cargo_delivery_destinations.Begin(); iid != isend; iid++) {
01858     TriggerIndustryProduction(*iid);
01859   }
01860   _cargo_delivery_destinations.Clear();
01861 }
01862 
01863 void CompaniesMonthlyLoop()
01864 {
01865   CompaniesGenStatistics();
01866   if (_settings_game.economy.inflation) AddInflation();
01867   CompaniesPayInterest();
01868   /* Reset the _current_company flag */
01869   _current_company = OWNER_NONE;
01870   HandleEconomyFluctuations();
01871   SubsidyMonthlyHandler();
01872 }
01873 
01874 static void DoAcquireCompany(Company *c)
01875 {
01876   Company *owner;
01877   int i;
01878   Money value;
01879   CompanyID ci = c->index;
01880 
01881   CompanyNewsInformation *cni = MallocT<CompanyNewsInformation>(1);
01882   cni->FillData(c, GetCompany(_current_company));
01883 
01884   SetDParam(0, STR_7059_TRANSPORT_COMPANY_MERGER);
01885   SetDParam(1, c->bankrupt_value == 0 ? STR_707F_HAS_BEEN_TAKEN_OVER_BY : STR_705A_HAS_BEEN_SOLD_TO_FOR);
01886   SetDParamStr(2, cni->company_name);
01887   SetDParamStr(3, cni->other_company_name);
01888   SetDParam(4, c->bankrupt_value);
01889   AddNewsItem(STR_02B6, NS_COMPANY_MERGER, 0, 0, cni);
01890   AI::BroadcastNewEvent(new AIEventCompanyMerger(ci, _current_company));
01891 
01892   /* original code does this a little bit differently */
01893   ChangeNetworkOwner(ci, _current_company);
01894   ChangeOwnershipOfCompanyItems(ci, _current_company);
01895 
01896   if (c->bankrupt_value == 0) {
01897     owner = GetCompany(_current_company);
01898     owner->current_loan += c->current_loan;
01899   }
01900 
01901   value = CalculateCompanyValue(c) >> 2;
01902   CompanyID old_company = _current_company;
01903   for (i = 0; i != 4; i++) {
01904     if (c->share_owners[i] != COMPANY_SPECTATOR) {
01905       _current_company = c->share_owners[i];
01906       SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, -value));
01907     }
01908   }
01909   _current_company = old_company;
01910 
01911   if (!IsHumanCompany(c->index)) AI::Stop(c->index);
01912 
01913   DeleteCompanyWindows(ci);
01914   InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
01915   InvalidateWindowClassesData(WC_SHIPS_LIST, 0);
01916   InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
01917   InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
01918 
01919   delete c;
01920 }
01921 
01922 extern int GetAmountOwnedBy(const Company *c, Owner owner);
01923 
01930 CommandCost CmdBuyShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
01931 {
01932   CommandCost cost(EXPENSES_OTHER);
01933 
01934   /* Check if buying shares is allowed (protection against modified clients)
01935    * Cannot buy own shares */
01936   if (!IsValidCompanyID((CompanyID)p1) || !_settings_game.economy.allow_shares || _current_company == (CompanyID)p1) return CMD_ERROR;
01937 
01938   Company *c = GetCompany((CompanyID)p1);
01939 
01940   /* Protect new companies from hostile takeovers */
01941   if (_cur_year - c->inaugurated_year < 6) return_cmd_error(STR_PROTECTED);
01942 
01943   /* Those lines are here for network-protection (clients can be slow) */
01944   if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 0) return cost;
01945 
01946   /* We can not buy out a real company (temporarily). TODO: well, enable it obviously */
01947   if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 1 && !c->is_ai) return cost;
01948 
01949   cost.AddCost(CalculateCompanyValue(c) >> 2);
01950   if (flags & DC_EXEC) {
01951     OwnerByte *b = c->share_owners;
01952     int i;
01953 
01954     while (*b != COMPANY_SPECTATOR) b++; // share owners is guaranteed to contain at least one COMPANY_SPECTATOR
01955     *b = _current_company;
01956 
01957     for (i = 0; c->share_owners[i] == _current_company;) {
01958       if (++i == 4) {
01959         c->bankrupt_value = 0;
01960         DoAcquireCompany(c);
01961         break;
01962       }
01963     }
01964     InvalidateWindow(WC_COMPANY, p1);
01965   }
01966   return cost;
01967 }
01968 
01975 CommandCost CmdSellShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
01976 {
01977   /* Check if selling shares is allowed (protection against modified clients)
01978    * Cannot sell own shares */
01979   if (!IsValidCompanyID((CompanyID)p1) || !_settings_game.economy.allow_shares || _current_company == (CompanyID)p1) return CMD_ERROR;
01980 
01981   Company *c = GetCompany((CompanyID)p1);
01982 
01983   /* Those lines are here for network-protection (clients can be slow) */
01984   if (GetAmountOwnedBy(c, _current_company) == 0) return CommandCost();
01985 
01986   /* adjust it a little to make it less profitable to sell and buy */
01987   Money cost = CalculateCompanyValue(c) >> 2;
01988   cost = -(cost - (cost >> 7));
01989 
01990   if (flags & DC_EXEC) {
01991     OwnerByte *b = c->share_owners;
01992     while (*b != _current_company) b++; // share owners is guaranteed to contain company
01993     *b = COMPANY_SPECTATOR;
01994     InvalidateWindow(WC_COMPANY, p1);
01995   }
01996   return CommandCost(EXPENSES_OTHER, cost);
01997 }
01998 
02008 CommandCost CmdBuyCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
02009 {
02010   CompanyID cid = (CompanyID)p1;
02011 
02012   /* Disable takeovers in multiplayer games */
02013   if (!IsValidCompanyID(cid) || _networking) return CMD_ERROR;
02014 
02015   /* Do not allow companies to take over themselves */
02016   if (cid == _current_company) return CMD_ERROR;
02017 
02018   Company *c = GetCompany(cid);
02019 
02020   if (!c->is_ai) return CMD_ERROR;
02021 
02022   if (flags & DC_EXEC) {
02023     DoAcquireCompany(c);
02024   }
02025   return CommandCost(EXPENSES_OTHER, c->bankrupt_value);
02026 }

Generated on Thu Sep 24 19:35:01 2009 for OpenTTD by  doxygen 1.5.6