economy.cpp

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

Generated on Wed Jul 15 20:35:58 2009 for OpenTTD by  doxygen 1.5.6