economy.cpp

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

Generated on Tue Jul 21 18:48:23 2009 for OpenTTD by  doxygen 1.5.6