54 #include "table/strings.h"
75 static inline int32
BigMulS(const int32 a, const int32 b, const uint8 shift)
77 return (int32)((int64)a * (int64)b >> shift);
101 Money _additional_cash_required;
102 static PriceMultipliers _price_base_multiplier;
120 FOR_ALL_STATIONS(st) {
124 Money value = num * _price[PR_STATION_VALUE] * 25;
128 if (v->
owner != owner)
continue;
134 value += v->
value * 3 >> 1;
158 memset(_score_part[owner], 0,
sizeof(_score_part[owner]));
163 Money min_profit = 0;
164 bool min_profit_first =
true;
168 if (v->
owner != owner)
continue;
175 min_profit_first =
false;
183 _score_part[owner][SCORE_VEHICLES] = num;
185 if (min_profit > 0) {
186 _score_part[owner][SCORE_MIN_PROFIT] =
ClampToI32(min_profit);
195 FOR_ALL_STATIONS(st) {
197 if (st->
owner == owner && (st->time_since_load <= 20 || st->time_since_unload <= 20)) num +=
CountBits((byte)st->
facilities);
199 _score_part[owner][SCORE_STATIONS] = num;
213 }
while (++cee, --numec);
215 if (min_income > 0) {
216 _score_part[owner][SCORE_MIN_INCOME] =
ClampToI32(min_income);
219 _score_part[owner][SCORE_MAX_INCOME] =
ClampToI32(max_income);
231 }
while (++cee, --numec);
233 _score_part[owner][SCORE_DELIVERED] =
ClampToI32(total_delivered);
263 s =
Clamp(_score_part[owner][i], 0, _score_info[i].needed) * _score_info[i].
score / _score_info[i].
needed;
265 total_score += _score_info[i].
score;
295 #ifdef ENABLE_NETWORK
305 FOR_ALL_COMPANIES(c) {
306 if (c->
index != old_owner) {
317 assert(old_owner != new_owner);
324 FOR_ALL_COMPANIES(c) {
325 for (i = 0; i < 4; i++) {
339 for (i = 0; i < 4; i++) {
360 FOR_ALL_SUBSIDIES(s) {
406 if (v->
Previous() == NULL)
delete v;
420 RemoveAllGroupsForCompany(old_owner);
424 if (g->
owner == old_owner) g->
owner = new_owner;
439 v->
owner = new_owner;
497 FOR_ALL_STATIONS(st) {
498 if (st->
owner == old_owner) {
508 if (wp->
owner == old_owner) {
521 if (g->
company == old_owner)
delete g;
528 FOR_ALL_STORY_PAGES(sp) {
529 if (sp->
company == old_owner)
delete sp;
573 SetDParam(0, STR_NEWS_COMPANY_IN_TROUBLE_TITLE);
574 SetDParam(1, STR_NEWS_COMPANY_IN_TROUBLE_DESCRIPTION);
576 AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, cni);
587 c->bankrupt_value = val;
592 assert(c->bankrupt_value > 0);
636 FOR_ALL_STATIONS(st) {
643 FOR_ALL_COMPANIES(c) {
665 FOR_ALL_COMPANIES(c) {
672 FOR_ALL_COMPANIES(c) {
740 for (
Price i = PR_BEGIN; i < PR_END; i++) {
745 switch (_price_base_specs[i].category) {
757 case 0: price *= 6;
break;
758 case 1: price *= 8;
break;
759 case 2: price *= 9;
break;
760 default: NOT_REACHED();
767 int shift = _price_base_multiplier[i] - 16 - 3;
780 price =
Clamp(_price_base_specs[i].start_price, -1, 1);
790 FOR_ALL_CARGOSPECS(cs) {
791 cs->current_payment = ((int64)cs->initial_payment * _economy.
inflation_payment) >> 16;
807 FOR_ALL_COMPANIES(c) {
835 static void HandleEconomyFluctuations()
842 _economy.
fluct = -12;
848 if (_economy.
fluct == 0) {
849 _economy.
fluct = -(int)
GB(Random(), 0, 2);
851 }
else if (_economy.
fluct == -12) {
852 _economy.
fluct =
GB(Random(), 0, 8) + 312;
863 memset(_price_base_multiplier, 0,
sizeof(_price_base_multiplier));
875 assert(price < PR_END);
900 void StartupEconomy()
905 _economy.
fluct =
GB(Random(), 0, 8) + 168;
934 if (index >= PR_END)
return 0;
936 Money cost = _price[index] * cost_factor;
948 Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days,
CargoID cargo_type)
958 uint32 var18 =
min(dist, 0xFFFF) | (
min(num_pieces, 0xFF) << 16) | (transit_days << 24);
961 int result =
GB(callback, 0, 14);
964 if (
HasBit(callback, 14)) result -= 0x4000;
969 return result * num_pieces * cs->current_payment / 8192;
973 static const int MIN_TIME_FACTOR = 31;
974 static const int MAX_TIME_FACTOR = 255;
976 const int days1 = cs->transit_days[0];
977 const int days2 = cs->transit_days[1];
978 const int days_over_days1 =
max( transit_days - days1, 0);
979 const int days_over_days2 =
max(days_over_days1 - days2, 0);
991 const int time_factor =
max(MAX_TIME_FACTOR - days_over_days1 - days_over_days2, MIN_TIME_FACTOR);
993 return BigMulS(dist * time_factor * num_pieces, cs->current_payment, 21);
1021 if (ind->
index == source)
continue;
1034 _cargo_delivery_destinations.
Include(ind);
1038 num_pieces -= amount;
1060 assert(num_pieces > 0);
1085 Money profit = GetTransportedGoodsIncome(accepted,
DistanceManhattan(source_tile, st->
xy), days_in_transit, cargo_type);
1093 case 0: profit += profit >> 1;
break;
1094 case 1: profit *= 2;
break;
1095 case 2: profit *= 3;
break;
1096 default: profit *= 4;
break;
1125 if (cargo_waiting == 0)
continue;
1144 current_station(front->last_station_visited)
1148 CargoPayment::~CargoPayment()
1162 SndPlayVehicleFx(SND_14_CASHTILL, this->
front);
1167 this->front->z_pos, this->visual_transfer, -this->visual_profit);
1170 this->front->z_pos, -this->visual_profit);
1173 cur_company.Restore();
1183 if (this->
owner == NULL) {
1203 Money profit = GetTransportedGoodsIncome(
1224 curr_station->loading_vehicles.push_back(front_v);
1242 for (
Vehicle *v = front_v; v != NULL; v = v->
Next()) {
1244 if (v->cargo_cap > 0 && v->cargo.TotalCount() > 0) {
1265 uint load_amount = e->info.load_amount;
1269 if (air_mail) load_amount =
CeilDiv(load_amount, 4);
1273 if (e->
GetGRF() != NULL && e->
GetGRF()->grf_version >= 8) {
1281 if (e->
GetGRF()->grf_version < 8) cb_load_amount =
GB(cb_load_amount, 0, 8);
1282 if (cb_load_amount >= 0x100) {
1284 }
else if (cb_load_amount != 0) {
1285 load_amount = cb_load_amount;
1305 template<
class Taction>
1308 for (
Vehicle *w = v; w != NULL;
1310 if (!action(w))
return false;
1313 if (train->
IsMultiheaded() && !action(train->other_multiheaded_part))
return false;
1350 consist_capleft(consist_capleft), refit_mask(refit_mask) {}
1411 consist_capleft(consist_capleft), st(st), next_station(next_station), do_reserve(do_reserve) {}
1445 uint32 refit_mask = v->
GetEngine()->info.refit_mask;
1451 if (is_auto_refit) {
1455 FOR_EACH_SET_CARGO_ID(cid, refit_mask) {
1467 (consist_capleft[cid] == consist_capleft[new_cid] &&
1476 if (new_cid < NUM_CARGO && new_cid != v_start->cargo_type) {
1498 st(st), next_station(next_station) {}
1504 &v->
cargo, st->
xy, *next_station);
1527 assert(v->cargo_cap >= v->cargo.RemainingCount());
1532 if (!v->IsArticulatedPart() &&
1538 if (consist_capleft == NULL || v->cargo_cap == 0)
continue;
1539 (*consist_capleft)[v->cargo_type] += v->cargo_cap - v->cargo.RemainingCount();
1557 ticks += (overhang * ticks) / 8;
1596 int new_load_unload_ticks = 0;
1597 bool dirty_vehicle =
false;
1598 bool dirty_station =
false;
1600 bool completely_emptied =
true;
1601 bool anything_unloaded =
false;
1602 bool anything_loaded =
false;
1603 uint32 full_load_amount = 0;
1604 uint32 cargo_not_full = 0;
1605 uint32 cargo_full = 0;
1606 uint32 reservation_left = 0;
1612 uint artic_part = 0;
1613 for (
Vehicle *v = front; v != NULL; v = v->
Next()) {
1615 if (v->cargo_cap == 0)
continue;
1623 uint cargo_count = v->
cargo.UnloadCount();
1625 bool remaining =
false;
1637 if (v->cargo_cap < new_remaining) {
1639 v->cargo.Return(new_remaining - v->cargo_cap, &ge->
cargo, INVALID_STATION);
1650 anything_unloaded =
true;
1656 dirty_station =
true;
1666 amount_unloaded = v->cargo.Unload(amount_unloaded, &ge->
cargo, payment);
1667 remaining = v->cargo.UnloadCount() > 0;
1668 if (amount_unloaded > 0) {
1669 dirty_vehicle =
true;
1670 anything_unloaded =
true;
1671 new_load_unload_ticks += amount_unloaded;
1674 st->time_since_unload = 0;
1678 completely_emptied =
false;
1693 ge = &st->
goods[v->cargo_type];
1697 v->refit_cap = v->cargo_cap;
1701 switch (front->
type) {
1715 default: NOT_REACHED();
1723 assert(v->cargo_cap >= v->cargo.StoredCount());
1726 uint cap_left = v->cargo_cap - v->cargo.StoredCount();
1729 if (v->cargo.StoredCount() == 0) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
1731 uint loaded = ge->
cargo.
Load(cap_left, &v->cargo, st->
xy, next_station);
1735 SetBit(reservation_left, v->cargo_type);
1739 if (loaded == cap_left) {
1740 SetBit(full_load_amount, v->cargo_type);
1742 ClrBit(full_load_amount, v->cargo_type);
1753 completely_emptied =
false;
1754 anything_loaded =
true;
1756 st->time_since_load = 0;
1757 st->last_vehicle_type = v->type;
1765 new_load_unload_ticks += loaded;
1767 dirty_vehicle = dirty_station =
true;
1771 if (v->cargo.StoredCount() >= v->cargo_cap) {
1772 SetBit(cargo_full, v->cargo_type);
1774 SetBit(cargo_not_full, v->cargo_type);
1778 if (anything_loaded || anything_unloaded) {
1786 completely_emptied &= anything_unloaded;
1788 if (!anything_unloaded)
delete payment;
1791 if (anything_loaded || anything_unloaded) {
1795 const uint gradual_loading_wait_time[] = { 40, 20, 10, 20 };
1797 new_load_unload_ticks = gradual_loading_wait_time[front->
type];
1809 bool finished_loading =
true;
1815 (cargo_not_full && (cargo_full & ~cargo_not_full) == 0)) {
1816 finished_loading =
false;
1818 }
else if (cargo_not_full != 0) {
1819 finished_loading =
false;
1840 StringID percent_up_down = STR_NULL;
1849 if (completely_emptied) {
1852 dirty_vehicle =
true;
1853 TriggerVehicle(front, VEHICLE_TRIGGER_EMPTY);
1856 if (dirty_vehicle) {
1861 if (dirty_station) {
1876 if (st->loading_vehicles.empty())
return;
1879 std::list<Vehicle *>::iterator iter;
1882 for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
1898 if (last_loading == NULL)
return;
1900 for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
1903 if (v == last_loading)
break;
1907 const Industry *
const *isend = _cargo_delivery_destinations.
End();
1908 for (
Industry **iid = _cargo_delivery_destinations.
Begin(); iid != isend; iid++) {
1911 _cargo_delivery_destinations.
Clear();
1925 HandleEconomyFluctuations();
1928 static void DoAcquireCompany(
Company *c)
1935 SetDParam(0, STR_NEWS_COMPANY_MERGER_TITLE);
1936 SetDParam(1, c->bankrupt_value == 0 ? STR_NEWS_MERGER_TAKEOVER_TITLE : STR_NEWS_COMPANY_MERGER_DESCRIPTION);
1940 AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, cni);
1946 if (c->bankrupt_value == 0) {
1962 extern int GetAmountOwnedBy(
const Company *c,
Owner owner);
1990 if (!c->
is_ai)
return cost;
2005 c->bankrupt_value = 0;
2006 DoAcquireCompany(c);
2042 cost = -(cost - (cost >> 7));
2088 DoAcquireCompany(c);