00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "../stdafx.h"
00013 #include "../core/bitmath_func.hpp"
00014 #include "../station_func.h"
00015 #include "../engine_base.h"
00016 #include "../vehicle_func.h"
00017 #include "refresh.h"
00018 #include "linkgraph.h"
00019
00025 void LinkRefresher::Run(Vehicle *v, bool allow_merge)
00026 {
00027
00028 if (v->orders.list == NULL) return;
00029
00030
00031 const Order *first = v->orders.list->GetNextDecisionNode(v->GetOrder(v->cur_implicit_order_index), 0);
00032 if (first == NULL) return;
00033
00034 HopSet seen_hops;
00035 LinkRefresher refresher(v, &seen_hops, allow_merge);
00036
00037 refresher.RefreshLinks(first, first, v->last_loading_station != INVALID_STATION ? 1 << HAS_CARGO : 0);
00038 }
00039
00045 bool LinkRefresher::Hop::operator<(const Hop &other) const
00046 {
00047 if (this->from < other.from) {
00048 return true;
00049 } else if (this->from > other.from) {
00050 return false;
00051 }
00052 if (this->to < other.to) {
00053 return true;
00054 } else if (this->to > other.to) {
00055 return false;
00056 }
00057 return this->cargo < other.cargo;
00058 }
00059
00067 LinkRefresher::LinkRefresher(Vehicle *vehicle, HopSet *seen_hops, bool allow_merge) :
00068 vehicle(vehicle), seen_hops(seen_hops), cargo(CT_INVALID), allow_merge(allow_merge)
00069 {
00070
00071 for (Vehicle *v = this->vehicle; v != NULL; v = v->Next()) {
00072 this->refit_capacities.push_back(RefitDesc(v->cargo_type, v->cargo_cap, v->refit_cap));
00073 if (v->refit_cap > 0) this->capacities[v->cargo_type] += v->refit_cap;
00074 }
00075 }
00076
00081 void LinkRefresher::HandleRefit(const Order *next)
00082 {
00083 this->cargo = next->GetRefitCargo();
00084 RefitList::iterator refit_it = this->refit_capacities.begin();
00085 for (Vehicle *v = this->vehicle; v != NULL; v = v->Next()) {
00086 const Engine *e = Engine::Get(v->engine_type);
00087 if (!HasBit(e->info.refit_mask, this->cargo)) {
00088 ++refit_it;
00089 continue;
00090 }
00091
00092
00093 CargoID temp_cid = v->cargo_type;
00094 byte temp_subtype = v->cargo_subtype;
00095 v->cargo_type = this->cargo;
00096 v->cargo_subtype = GetBestFittingSubType(v, v, this->cargo);
00097
00098 uint16 mail_capacity = 0;
00099 uint amount = e->DetermineCapacity(v, &mail_capacity);
00100
00101
00102 v->cargo_type = temp_cid;
00103 v->cargo_subtype = temp_subtype;
00104
00105
00106 if (this->cargo != refit_it->cargo && refit_it->remaining > 0) {
00107 this->capacities[refit_it->cargo] -= refit_it->remaining;
00108 refit_it->remaining = 0;
00109 } else if (amount < refit_it->remaining) {
00110 this->capacities[refit_it->cargo] -= refit_it->remaining - amount;
00111 refit_it->remaining = amount;
00112 }
00113 refit_it->capacity = amount;
00114 refit_it->cargo = this->cargo;
00115
00116 ++refit_it;
00117
00118
00119 if (v->type == VEH_AIRCRAFT) {
00120 if (mail_capacity < refit_it->remaining) {
00121 this->capacities[refit_it->cargo] -= refit_it->remaining - mail_capacity;
00122 refit_it->remaining = mail_capacity;
00123 }
00124 refit_it->capacity = mail_capacity;
00125 break;
00126 }
00127 }
00128 }
00129
00133 void LinkRefresher::ResetRefit()
00134 {
00135 for (RefitList::iterator it(this->refit_capacities.begin()); it != this->refit_capacities.end(); ++it) {
00136 if (it->remaining == it->capacity) continue;
00137 this->capacities[it->cargo] += it->capacity - it->remaining;
00138 it->remaining = it->capacity;
00139 }
00140 }
00141
00151 const Order *LinkRefresher::PredictNextOrder(const Order *cur, const Order *next, uint8 flags, uint num_hops)
00152 {
00153
00154
00155
00156 while (next != NULL && (!HasBit(flags, USE_NEXT) || next->IsType(OT_CONDITIONAL))) {
00157
00158
00159
00160
00161 SetBit(flags, USE_NEXT);
00162
00163 if (next->IsType(OT_CONDITIONAL)) {
00164 const Order *skip_to = this->vehicle->orders.list->GetNextDecisionNode(
00165 this->vehicle->orders.list->GetOrderAt(next->GetConditionSkipToOrder()), num_hops);
00166 if (skip_to != NULL && num_hops < this->vehicle->orders.list->GetNumOrders()) {
00167
00168
00169
00170
00171 LinkRefresher branch(*this);
00172 branch.RefreshLinks(cur, skip_to, flags, num_hops + 1);
00173 }
00174 }
00175
00176
00177
00178 next = this->vehicle->orders.list->GetNextDecisionNode(
00179 this->vehicle->orders.list->GetNext(next), num_hops++);
00180 }
00181 return next;
00182 }
00183
00189 void LinkRefresher::RefreshStats(const Order *cur, const Order *next)
00190 {
00191 StationID next_station = next->GetDestination();
00192 Station *st = Station::GetIfValid(cur->GetDestination());
00193 if (st != NULL && next_station != INVALID_STATION && next_station != st->index) {
00194 for (CapacitiesMap::const_iterator i = this->capacities.begin(); i != this->capacities.end(); ++i) {
00195
00196
00197 if (i->second == 0) continue;
00198 CargoID c = i->first;
00199
00200
00201
00202 if (!this->allow_merge && st->goods[c].link_graph != Station::Get(next_station)->goods[c].link_graph) {
00203 continue;
00204 }
00205
00206
00207
00208 IncreaseStats(st, c, next_station, i->second,
00209 (cur->GetLoadType() & OLFB_NO_LOAD) == 0 ? LinkGraph::REFRESH_UNRESTRICTED : LinkGraph::REFRESH_RESTRICTED);
00210 }
00211 }
00212 }
00213
00225 void LinkRefresher::RefreshLinks(const Order *cur, const Order *next, uint8 flags, uint num_hops)
00226 {
00227 while (next != NULL) {
00228
00229
00230
00231
00232
00233
00234 if ((next->IsType(OT_GOTO_DEPOT) || next->IsType(OT_GOTO_STATION)) &&
00235 next->IsRefit() && !next->IsAutoRefit()) {
00236 SetBit(flags, WAS_REFIT);
00237 this->HandleRefit(next);
00238 }
00239
00240
00241
00242
00243 if (HasBit(flags, WAS_REFIT) && (next->IsType(OT_GOTO_STATION) || next->IsType(OT_IMPLICIT))) {
00244 SetBit(flags, RESET_REFIT);
00245 } else {
00246 ClrBit(flags, RESET_REFIT);
00247 }
00248
00249 next = this->PredictNextOrder(cur, next, flags, num_hops);
00250 if (next == NULL) break;
00251 Hop hop(cur->index, next->index, this->cargo);
00252 if (this->seen_hops->find(hop) != this->seen_hops->end()) {
00253 break;
00254 } else {
00255 this->seen_hops->insert(hop);
00256 }
00257
00258
00259 ClrBit(flags, USE_NEXT);
00260
00261
00262 if (!next->IsType(OT_GOTO_STATION) && !next->IsType(OT_IMPLICIT)) continue;
00263
00264 if (HasBit(flags, RESET_REFIT)) {
00265 this->ResetRefit();
00266 ClrBit(flags, RESET_REFIT);
00267 ClrBit(flags, WAS_REFIT);
00268 }
00269
00270 if (cur->IsType(OT_GOTO_STATION) || cur->IsType(OT_IMPLICIT)) {
00271 if (cur->CanLeaveWithCargo(HasBit(flags, HAS_CARGO))) {
00272 SetBit(flags, HAS_CARGO);
00273 this->RefreshStats(cur, next);
00274 } else {
00275 ClrBit(flags, HAS_CARGO);
00276 }
00277 }
00278
00279
00280
00281 cur = next;
00282 }
00283 }