cargoaction.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 #include "economy_base.h"
00014 #include "cargoaction.h"
00015 #include "station_base.h"
00016 
00023 template<class Tsource, class Tdest>
00024 CargoPacket *CargoMovement<Tsource, Tdest>::Preprocess(CargoPacket *cp)
00025 {
00026   if (this->max_move < cp->Count()) {
00027     cp = cp->Split(this->max_move);
00028     this->max_move = 0;
00029   } else {
00030     this->max_move -= cp->Count();
00031   }
00032   return cp;
00033 }
00034 
00041 template<class Tsource>
00042 uint CargoRemoval<Tsource>::Preprocess(CargoPacket *cp)
00043 {
00044   if (this->max_move >= cp->Count()) {
00045     this->max_move -= cp->Count();
00046     return cp->Count();
00047   } else {
00048     uint ret = this->max_move;
00049     this->max_move = 0;
00050     return ret;
00051   }
00052 }
00053 
00060 template<class Tsource>
00061 bool CargoRemoval<Tsource>::Postprocess(CargoPacket *cp, uint remove)
00062 {
00063   if (remove == cp->Count()) {
00064     delete cp;
00065     return true;
00066   } else {
00067     cp->Reduce(remove);
00068     return false;
00069   }
00070 }
00071 
00078 template<>
00079 bool CargoRemoval<StationCargoList>::operator()(CargoPacket *cp)
00080 {
00081   uint remove = this->Preprocess(cp);
00082   this->source->RemoveFromCache(cp, remove);
00083   return this->Postprocess(cp, remove);
00084 }
00085 
00092 template<>
00093 bool CargoRemoval<VehicleCargoList>::operator()(CargoPacket *cp)
00094 {
00095   uint remove = this->Preprocess(cp);
00096   this->source->RemoveFromMeta(cp, VehicleCargoList::MTA_KEEP, remove);
00097   return this->Postprocess(cp, remove);
00098 }
00099 
00106 bool CargoDelivery::operator()(CargoPacket *cp)
00107 {
00108   uint remove = this->Preprocess(cp);
00109   this->source->RemoveFromMeta(cp, VehicleCargoList::MTA_DELIVER, remove);
00110   this->payment->PayFinalDelivery(cp, remove);
00111   return this->Postprocess(cp, remove);
00112 }
00113 
00119 bool CargoLoad::operator()(CargoPacket *cp)
00120 {
00121   CargoPacket *cp_new = this->Preprocess(cp);
00122   if (cp_new == NULL) return false;
00123   cp_new->SetLoadPlace(this->load_place);
00124   this->source->RemoveFromCache(cp_new, cp_new->Count());
00125   this->destination->Append(cp_new, VehicleCargoList::MTA_KEEP);
00126   return cp_new == cp;
00127 }
00128 
00134 bool CargoReservation::operator()(CargoPacket *cp)
00135 {
00136   CargoPacket *cp_new = this->Preprocess(cp);
00137   if (cp_new == NULL) return false;
00138   cp_new->SetLoadPlace(this->load_place);
00139   this->source->reserved_count += cp_new->Count();
00140   this->source->RemoveFromCache(cp_new, cp_new->Count());
00141   this->destination->Append(cp_new, VehicleCargoList::MTA_LOAD);
00142   return cp_new == cp;
00143 }
00144 
00150 bool CargoReturn::operator()(CargoPacket *cp)
00151 {
00152   CargoPacket *cp_new = this->Preprocess(cp);
00153   if (cp_new == NULL) cp_new = cp;
00154   assert(cp_new->Count() <= this->destination->reserved_count);
00155   this->source->RemoveFromMeta(cp_new, VehicleCargoList::MTA_LOAD, cp_new->Count());
00156   this->destination->reserved_count -= cp_new->Count();
00157   this->destination->Append(cp_new, this->next);
00158   return cp_new == cp;
00159 }
00160 
00166 bool CargoTransfer::operator()(CargoPacket *cp)
00167 {
00168   CargoPacket *cp_new = this->Preprocess(cp);
00169   if (cp_new == NULL) return false;
00170   this->source->RemoveFromMeta(cp_new, VehicleCargoList::MTA_TRANSFER, cp_new->Count());
00171   this->destination->Append(cp_new, cp_new->NextStation());
00172   return cp_new == cp;
00173 }
00174 
00180 bool CargoShift::operator()(CargoPacket *cp)
00181 {
00182   CargoPacket *cp_new = this->Preprocess(cp);
00183   if (cp_new == NULL) cp_new = cp;
00184   this->source->RemoveFromMeta(cp_new, VehicleCargoList::MTA_KEEP, cp_new->Count());
00185   this->destination->Append(cp_new, VehicleCargoList::MTA_KEEP);
00186   return cp_new == cp;
00187 }
00188 
00194 bool CargoReroute::operator()(CargoPacket *cp)
00195 {
00196   CargoPacket *cp_new = this->Preprocess(cp);
00197   if (cp_new == NULL) cp_new = cp;
00198   StationID next = this->ge->GetVia(cp_new->SourceStation(), this->avoid);
00199   assert(next != this->avoid);
00200   if (this->source != this->destination) {
00201     this->source->RemoveFromCache(cp_new, cp_new->Count());
00202     this->destination->AddToCache(cp_new);
00203   }
00204 
00205   /* Legal, as insert doesn't invalidate iterators in the MultiMap, however
00206    * this might insert the packet between range.first and range.second (which might be end())
00207    * This is why we check for GetKey above to avoid infinite loops. */
00208   this->destination->packets.Insert(next, cp_new);
00209   return cp_new == cp;
00210 }
00211 
00212 template uint CargoRemoval<VehicleCargoList>::Preprocess(CargoPacket *cp);
00213 template uint CargoRemoval<StationCargoList>::Preprocess(CargoPacket *cp);
00214 template bool CargoRemoval<VehicleCargoList>::Postprocess(CargoPacket *cp, uint remove);
00215 template bool CargoRemoval<StationCargoList>::Postprocess(CargoPacket *cp, uint remove);