diff -r ca3fd1fbe311 -r 5a9dc001e1ad src/economy.cpp --- a/src/economy.cpp Sat Oct 06 21:16:00 2007 +0000 +++ b/src/economy.cpp Mon Dec 03 23:39:38 2007 +0000 @@ -43,6 +43,38 @@ #include "player_face.h" #include "group.h" +/** + * Multiply two integer values and shift the results to right. + * + * This function multiplies two integer values. The result is + * shifted by the amount of shift to right. + * + * @param a The first integer + * @param b The second integer + * @param shift The amount to shift the value to right. + * @return The shifted result + */ +static inline int32 BigMulS(const int32 a, const int32 b, const uint8 shift) +{ + return (int32)((int64)a * (int64)b >> shift); +} + +/** + * Multiply two unsigned integers and shift the results to right. + * + * This function multiplies two unsigned integers. The result is + * shifted by the amount of shift to right. + * + * @param a The first unsigned integer + * @param b The second unsigned integer + * @param shift The amount to shift the value to right. + * @return The shifted result + */ +static inline uint32 BigMulSU(const uint32 a, const uint32 b, const uint8 shift) +{ + return (uint32)((uint64)a * (uint64)b >> shift); +} + /* Score info */ const ScoreInfo _score_info[] = { { SCORE_VEHICLES, 120, 100 }, @@ -63,39 +95,34 @@ { PlayerID owner = p->index; /* Do a little nasty by using CommandCost, so we can use the "overflow" protection of CommandCost */ - CommandCost value; + Money value = 0; - { - Station *st; - uint num = 0; + Station *st; + uint num = 0; - FOR_ALL_STATIONS(st) { - if (st->owner == owner) num += COUNTBITS(st->facilities); - } - - value.AddCost(num * _price.station_value * 25); + FOR_ALL_STATIONS(st) { + if (st->owner == owner) num += CountBits(st->facilities); } - { - Vehicle *v; - - FOR_ALL_VEHICLES(v) { - if (v->owner != owner) continue; + value += num * _price.station_value * 25; - if (v->type == VEH_TRAIN || - v->type == VEH_ROAD || - (v->type == VEH_AIRCRAFT && IsNormalAircraft(v)) || - v->type == VEH_SHIP) { - value.AddCost(v->value * 3 >> 1); - } + Vehicle *v; + FOR_ALL_VEHICLES(v) { + if (v->owner != owner) continue; + + if (v->type == VEH_TRAIN || + v->type == VEH_ROAD || + (v->type == VEH_AIRCRAFT && IsNormalAircraft(v)) || + v->type == VEH_SHIP) { + value += v->value * 3 >> 1; } } /* Add real money value */ - value.AddCost(-p->current_loan); - value.AddCost(p->player_money); + value -= p->current_loan; + value += p->player_money; - return max(value.GetCost(), 1LL); + return max(value, (Money)1); } /** if update is set to true, the economy is updated with this score @@ -146,7 +173,7 @@ const Station* st; FOR_ALL_STATIONS(st) { - if (st->owner == owner) num += COUNTBITS(st->facilities); + if (st->owner == owner) num += CountBits(st->facilities); } _score_part[owner][SCORE_STATIONS] = num; } @@ -191,7 +218,7 @@ /* Generate score for variety of cargo */ { - uint num = COUNTBITS(p->cargo_types); + uint num = CountBits(p->cargo_types); _score_part[owner][SCORE_CARGO] = num; if (update) p->cargo_types = 0; } @@ -217,7 +244,7 @@ /* Skip the total */ if (i == SCORE_TOTAL) continue; /* Check the score */ - s = clamp(_score_part[owner][i], 0, _score_info[i].needed) * _score_info[i].score / _score_info[i].needed; + s = Clamp(_score_part[owner][i], 0, _score_info[i].needed) * _score_info[i].score / _score_info[i].needed; score += s; total_score += _score_info[i].score; } @@ -301,12 +328,12 @@ FOR_ALL_TOWNS(t) { /* If a player takes over, give the ratings to that player. */ if (new_player != PLAYER_SPECTATOR) { - if (HASBIT(t->have_ratings, old_player)) { - if (HASBIT(t->have_ratings, new_player)) { + if (HasBit(t->have_ratings, old_player)) { + if (HasBit(t->have_ratings, new_player)) { // use max of the two ratings. t->ratings[new_player] = max(t->ratings[new_player], t->ratings[old_player]); } else { - SETBIT(t->have_ratings, new_player); + SetBit(t->have_ratings, new_player); t->ratings[new_player] = t->ratings[old_player]; } } @@ -314,7 +341,7 @@ /* Reset the ratings for the old player */ t->ratings[old_player] = 500; - CLRBIT(t->have_ratings, old_player); + ClrBit(t->have_ratings, old_player); } { @@ -338,7 +365,7 @@ } FOR_ALL_VEHICLES(v) { - if (v->owner == old_player && IS_BYTE_INSIDE(v->type, VEH_TRAIN, VEH_AIRCRAFT + 1)) { + if (v->owner == old_player && IsInsideMM(v->type, VEH_TRAIN, VEH_AIRCRAFT + 1)) { if (new_player == PLAYER_SPECTATOR) { DeleteWindowById(WC_VEHICLE_VIEW, v->index); DeleteWindowById(WC_VEHICLE_DETAILS, v->index); @@ -519,7 +546,7 @@ switch (ni->string_id & 0xF0) { case NB_BTROUBLE: - DrawStringCentered(w->width >> 1, 1, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE, 0); + DrawStringCentered(w->width >> 1, 1, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE, TC_FROMSTRING); SetDParam(0, p->index); @@ -531,7 +558,7 @@ break; case NB_BMERGER: - DrawStringCentered(w->width >> 1, 1, STR_7059_TRANSPORT_COMPANY_MERGER, 0); + DrawStringCentered(w->width >> 1, 1, STR_7059_TRANSPORT_COMPANY_MERGER, TC_FROMSTRING); SetDParam(0, ni->params[0]); SetDParam(1, p->index); SetDParam(2, ni->params[1]); @@ -543,7 +570,7 @@ break; case NB_BBANKRUPT: - DrawStringCentered(w->width >> 1, 1, STR_705C_BANKRUPT, 0); + DrawStringCentered(w->width >> 1, 1, STR_705C_BANKRUPT, TC_FROMSTRING); SetDParam(0, ni->params[0]); DrawStringMultiCenter( ((w->width - 101) >> 1) + 98, @@ -553,7 +580,7 @@ break; case NB_BNEWCOMPANY: - DrawStringCentered(w->width >> 1, 1, STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED, 0); + DrawStringCentered(w->width >> 1, 1, STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED, TC_FROMSTRING); SetDParam(0, p->index); SetDParam(1, ni->params[0]); DrawStringMultiCenter( @@ -612,7 +639,7 @@ SubtractMoneyFromPlayer(_price.station_value >> 1); } - if (!HASBIT(1<<0|1<<3|1<<6|1<<9, _cur_month)) + if (!HasBit(1<<0|1<<3|1<<6|1<<9, _cur_month)) return; FOR_ALL_PLAYERS(p) { @@ -711,7 +738,7 @@ _current_player = p->index; SET_EXPENSES_TYPE(EXPENSES_LOAN_INT); - SubtractMoneyFromPlayer(CommandCost((Money)BIGMULUS(p->current_loan, interest, 16))); + SubtractMoneyFromPlayer(CommandCost((Money)BigMulSU(p->current_loan, interest, 16))); SET_EXPENSES_TYPE(EXPENSES_OTHER); SubtractMoneyFromPlayer(_price.station_value >> 2); @@ -764,10 +791,10 @@ 65000, ///< ship_base 20, ///< build_trees 250, ///< terraform - 20, ///< clear_1 - 40, ///< purchase_land - 200, ///< clear_2 - 500, ///< clear_3 + 20, ///< clear_grass + 40, ///< clear_roughland + 200, ///< clear_rocks + 500, ///< clear_fields 20, ///< remove_trees -70, ///< remove_rail 10, ///< remove_signals @@ -982,7 +1009,7 @@ if (i == NULL) return; /* Randomize cargo type */ - if (HASBIT(Random(), 0) && i->produced_cargo[1] != CT_INVALID) { + if (HasBit(Random(), 0) && i->produced_cargo[1] != CT_INVALID) { cargo = i->produced_cargo[1]; trans = i->last_month_pct_transported[1]; total = i->last_month_production[1]; @@ -1075,7 +1102,7 @@ } /* 25% chance to go on */ - if (CHANCE16(1,4)) { + if (Chance16(1,4)) { /* Find a free slot*/ s = _subsidies; while (s->cargo_type != CT_INVALID) { @@ -1152,14 +1179,14 @@ const CargoSpec *cs = GetCargo(cargo_type); /* Use callback to calculate cargo profit, if available */ - if (HASBIT(cs->callback_mask, CBM_CARGO_PROFIT_CALC)) { + if (HasBit(cs->callback_mask, CBM_CARGO_PROFIT_CALC)) { uint32 var18 = min(dist, 0xFFFF) | (min(num_pieces, 0xFF) << 16) | (transit_days << 24); uint16 callback = GetCargoCallback(CBID_CARGO_PROFIT_CALC, 0, var18, cs); if (callback != CALLBACK_FAILED) { int result = GB(callback, 0, 14); /* Simulate a 15 bit signed value */ - if (HASBIT(callback, 14)) result = 0x4000 - result; + if (HasBit(callback, 14)) result = 0x4000 - result; /* "The result should be a signed multiplier that gets multiplied * by the amount of cargo moved and the price factor, then gets @@ -1200,7 +1227,7 @@ if (time_factor < MIN_TIME_FACTOR) time_factor = MIN_TIME_FACTOR; - return BIGMULSS(dist * time_factor * num_pieces, _cargo_payment_rates[cargo_type], 21); + return BigMulS(dist * time_factor * num_pieces, _cargo_payment_rates[cargo_type], 21); } static void DeliverGoodsToIndustry(TileIndex xy, CargoID cargo_type, int num_pieces) @@ -1227,7 +1254,7 @@ /* Check if matching cargo has been found */ if (i == lengthof(ind->accepts_cargo)) continue; - if (HASBIT(indspec->callback_flags, CBM_IND_REFUSE_CARGO)) { + if (HasBit(indspec->callback_flags, CBM_IND_REFUSE_CARGO)) { uint16 res = GetIndustryCallback(CBID_INDUSTRY_REFUSE_CARGO, 0, GetReverseCargoTranslation(cargo_type, indspec->grf_prop.grffile), ind, ind->type, ind->xy); if (res == 0) continue; } @@ -1249,9 +1276,9 @@ best->was_cargo_delivered = true; best->last_cargo_accepted_at = _date; - if (HASBIT(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HASBIT(callback, CBM_IND_PRODUCTION_256_TICKS)) { + if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(callback, CBM_IND_PRODUCTION_256_TICKS)) { best->incoming_cargo_waiting[accepted_cargo_index] = min(num_pieces + best->incoming_cargo_waiting[accepted_cargo_index], 0xFFFF); - if (HASBIT(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) { + if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) { IndustryProductionCallback(best, 0); } else { InvalidateWindow(WC_INDUSTRY_VIEW, best->index); @@ -1261,6 +1288,7 @@ best->produced_cargo_waiting[1] = min(best->produced_cargo_waiting[1] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][1] / 256), 0xFFFF); } + TriggerIndustry(best, INDUSTRY_TRIGGER_RECEIVED_CARGO); StartStopIndustryTileAnimation(best, IAT_INDUSTRY_RECEIVED_CARGO); } } @@ -1343,7 +1371,7 @@ { Player *p = GetPlayer(_current_player); p->cur_economy.delivered_cargo += num_pieces; - SETBIT(p->cargo_types, cargo_type); + SetBit(p->cargo_types, cargo_type); } /* Get station pointers. */ @@ -1397,7 +1425,7 @@ _current_player = front_v->owner; /* At this moment loading cannot be finished */ - CLRBIT(front_v->vehicle_flags, VF_LOADING_FINISHED); + ClrBit(front_v->vehicle_flags, VF_LOADING_FINISHED); /* Start unloading in at the first possible moment */ front_v->load_unload_time_rem = 1; @@ -1408,7 +1436,7 @@ /* All cargo has already been paid for, no need to pay again */ if (!v->cargo.UnpaidCargo()) { - SETBIT(v->vehicle_flags, VF_CARGO_UNLOADING); + SetBit(v->vehicle_flags, VF_CARGO_UNLOADING); continue; } @@ -1419,7 +1447,7 @@ CargoPacket *cp = *it; if (!cp->paid_for && cp->source != last_visited && - HASBIT(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && + HasBit(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && (front_v->current_order.flags & OF_TRANSFER) == 0) { /* Deliver goods to the station */ st->time_since_unload = 0; @@ -1432,7 +1460,7 @@ result |= 1; - SETBIT(v->vehicle_flags, VF_CARGO_UNLOADING); + SetBit(v->vehicle_flags, VF_CARGO_UNLOADING); } else if (front_v->current_order.flags & (OF_UNLOAD | OF_TRANSFER)) { if (!cp->paid_for && (front_v->current_order.flags & OF_TRANSFER) != 0) { Money profit = GetTransportedGoodsIncome( @@ -1449,7 +1477,7 @@ } result |= 2; - SETBIT(v->vehicle_flags, VF_CARGO_UNLOADING); + SetBit(v->vehicle_flags, VF_CARGO_UNLOADING); } } v->cargo.InvalidateCache(); @@ -1487,7 +1515,7 @@ /* We have not waited enough time till the next round of loading/unloading */ if (--v->load_unload_time_rem != 0) { - if (_patches.improved_load && HASBIT(v->current_order.flags, OFB_FULL_LOAD)) { + if (_patches.improved_load && HasBit(v->current_order.flags, OFB_FULL_LOAD)) { /* 'Reserve' this cargo for this vehicle, because we were first. */ for (; v != NULL; v = v->Next()) { if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo.Count(); @@ -1499,7 +1527,7 @@ if (v->type == VEH_TRAIN && !IsTileType(v->tile, MP_STATION)) { /* The train reversed in the station. Take the "easy" way * out and let the train just leave as it always did. */ - SETBIT(v->vehicle_flags, VF_LOADING_FINISHED); + SetBit(v->vehicle_flags, VF_LOADING_FINISHED); return; } @@ -1523,32 +1551,32 @@ if (v->cargo_cap == 0) continue; byte load_amount = EngInfo(v->engine_type)->load_amount; - if (_patches.gradual_loading && HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_LOAD_AMOUNT)) { + if (_patches.gradual_loading && HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_LOAD_AMOUNT)) { uint16 cb_load_amount = GetVehicleCallback(CBID_VEHICLE_LOAD_AMOUNT, 0, 0, v->engine_type, v); - if (cb_load_amount != CALLBACK_FAILED) load_amount = cb_load_amount & 0xFF; + if (cb_load_amount != CALLBACK_FAILED && cb_load_amount != 0) load_amount = cb_load_amount & 0xFF; } GoodsEntry *ge = &st->goods[v->cargo_type]; - if (HASBIT(v->vehicle_flags, VF_CARGO_UNLOADING)) { + if (HasBit(v->vehicle_flags, VF_CARGO_UNLOADING)) { uint cargo_count = v->cargo.Count(); uint amount_unloaded = _patches.gradual_loading ? min(cargo_count, load_amount) : cargo_count; bool remaining; // Are there cargo entities in this vehicle that can still be unloaded here? - if (HASBIT(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && !(u->current_order.flags & OF_TRANSFER)) { + if (HasBit(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && !(u->current_order.flags & OF_TRANSFER)) { /* The cargo has reached it's final destination, the packets may now be destroyed */ remaining = v->cargo.MoveTo(NULL, amount_unloaded, CargoList::MTA_FINAL_DELIVERY, last_visited); result |= 1; } else if (u->current_order.flags & (OF_UNLOAD | OF_TRANSFER)) { remaining = v->cargo.MoveTo(&ge->cargo, amount_unloaded); - SETBIT(ge->acceptance_pickup, GoodsEntry::PICKUP); + SetBit(ge->acceptance_pickup, GoodsEntry::PICKUP); result |= 2; } else { /* The order changed while unloading (unset unload/transfer) or the * station does not accept goods anymore. */ - CLRBIT(v->vehicle_flags, VF_CARGO_UNLOADING); + ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING); continue; } @@ -1562,7 +1590,7 @@ completely_empty = false; } else { /* We have finished unloading (cargo count == 0) */ - CLRBIT(v->vehicle_flags, VF_CARGO_UNLOADING); + ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING); } continue; @@ -1593,7 +1621,7 @@ /* Skip loading this vehicle if another train/vehicle is already handling * the same cargo type at this station */ if (_patches.improved_load && cargo_left[v->cargo_type] <= 0) { - SETBIT(cargo_not_full, v->cargo_type); + SetBit(cargo_not_full, v->cargo_type); continue; } @@ -1628,9 +1656,9 @@ } if (v->cargo.Count() == v->cargo_cap) { - SETBIT(cargo_full, v->cargo_type); + SetBit(cargo_full, v->cargo_type); } else { - SETBIT(cargo_not_full, v->cargo_type); + SetBit(cargo_not_full, v->cargo_type); } } @@ -1638,7 +1666,7 @@ * all wagons at the same time instead of using the same 'improved' * loading algorithm for the wagons (only fill wagon when there is * enough to fill the previous wagons) */ - if (_patches.improved_load && HASBIT(u->current_order.flags, OFB_FULL_LOAD)) { + if (_patches.improved_load && HasBit(u->current_order.flags, OFB_FULL_LOAD)) { /* Update left cargo */ for (v = u; v != NULL; v = v->Next()) { if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo.Count(); @@ -1657,7 +1685,7 @@ } } else { bool finished_loading = true; - if (HASBIT(v->current_order.flags, OFB_FULL_LOAD)) { + if (HasBit(v->current_order.flags, OFB_FULL_LOAD)) { if (_patches.full_load_any) { /* if the aircraft carries passengers and is NOT full, then * continue loading, no matter how much mail is in */