2013-10-22 18:45:55 +00:00
|
|
|
/* $Id$ */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This file is part of OpenTTD.
|
|
|
|
* 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.
|
|
|
|
* 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.
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** @file refresh.h Declaration of link refreshing utility. */
|
|
|
|
|
|
|
|
#ifndef REFRESH_H
|
|
|
|
#define REFRESH_H
|
|
|
|
|
|
|
|
#include "../cargo_type.h"
|
|
|
|
#include "../vehicle_base.h"
|
2016-07-10 11:57:16 +00:00
|
|
|
#include <vector>
|
2013-10-22 18:45:55 +00:00
|
|
|
#include <map>
|
2013-10-22 18:46:20 +00:00
|
|
|
#include <set>
|
2013-10-22 18:45:55 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Utility to refresh links a consist will visit.
|
|
|
|
*/
|
|
|
|
class LinkRefresher {
|
|
|
|
public:
|
2014-05-01 14:50:52 +00:00
|
|
|
static void Run(Vehicle *v, bool allow_merge = true, bool is_full_loading = false);
|
2013-10-22 18:45:55 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
/**
|
|
|
|
* Various flags about properties of the last examined link that might have
|
|
|
|
* an influence on the next one.
|
|
|
|
*/
|
|
|
|
enum RefreshFlags {
|
2014-09-21 14:22:32 +00:00
|
|
|
USE_NEXT, ///< There was a conditional jump. Try to use the given next order when looking for a new one.
|
|
|
|
HAS_CARGO, ///< Consist could leave the last stop where it could interact with cargo carrying cargo (i.e. not an "unload all" + "no loading" order).
|
|
|
|
WAS_REFIT, ///< Consist was refit since the last stop where it could interact with cargo.
|
|
|
|
RESET_REFIT, ///< Consist had a chance to load since the last refit and the refit capacities can be reset.
|
|
|
|
IN_AUTOREFIT, ///< Currently doing an autorefit loop. Ignore the first autorefit order.
|
2013-10-22 18:45:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Simulated cargo type and capacity for prediction of future links.
|
|
|
|
*/
|
|
|
|
struct RefitDesc {
|
|
|
|
CargoID cargo; ///< Cargo type the vehicle will be carrying.
|
|
|
|
uint16 capacity; ///< Capacity the vehicle will have.
|
|
|
|
uint16 remaining; ///< Capacity remaining from before the previous refit.
|
|
|
|
RefitDesc(CargoID cargo, uint16 capacity, uint16 remaining) :
|
|
|
|
cargo(cargo), capacity(capacity), remaining(remaining) {}
|
|
|
|
};
|
|
|
|
|
2013-10-22 18:46:20 +00:00
|
|
|
/**
|
|
|
|
* A hop the refresh algorithm might evaluate. If the same hop is seen again
|
|
|
|
* the evaluation is stopped. This of course is a fairly simple heuristic.
|
|
|
|
* Sequences of refit orders can produce vehicles with all kinds of
|
|
|
|
* different cargoes and remembering only one can lead to early termination
|
|
|
|
* of the algorithm. However, as the order language is Turing complete, we
|
|
|
|
* are facing the halting problem here. At some point we have to draw the
|
|
|
|
* line.
|
|
|
|
*/
|
|
|
|
struct Hop {
|
|
|
|
OrderID from; ///< Last order where vehicle could interact with cargo or absolute first order.
|
|
|
|
OrderID to; ///< Next order to be processed.
|
|
|
|
CargoID cargo; ///< Cargo the consist is probably carrying or CT_INVALID if unknown.
|
2013-10-22 19:25:29 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Default constructor should not be called but has to be visible for
|
|
|
|
* usage in std::set.
|
|
|
|
*/
|
2013-10-22 18:46:20 +00:00
|
|
|
Hop() {NOT_REACHED();}
|
2013-10-22 19:25:29 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Real constructor, only use this one.
|
|
|
|
* @param from First order of the hop.
|
|
|
|
* @param to Second order of the hop.
|
|
|
|
* @param cargo Cargo the consist is probably carrying when passing the hop.
|
|
|
|
*/
|
2013-10-22 18:46:20 +00:00
|
|
|
Hop(OrderID from, OrderID to, CargoID cargo) : from(from), to(to), cargo(cargo) {}
|
|
|
|
bool operator<(const Hop &other) const;
|
|
|
|
};
|
|
|
|
|
2016-07-10 11:57:16 +00:00
|
|
|
typedef std::vector<RefitDesc> RefitList;
|
2013-10-22 18:46:20 +00:00
|
|
|
typedef std::set<Hop> HopSet;
|
2013-10-22 18:45:55 +00:00
|
|
|
|
|
|
|
Vehicle *vehicle; ///< Vehicle for which the links should be refreshed.
|
2016-07-10 12:17:00 +00:00
|
|
|
uint capacities[NUM_CARGO]; ///< Current added capacities per cargo ID in the consist.
|
2013-10-22 18:45:55 +00:00
|
|
|
RefitList refit_capacities; ///< Current state of capacity remaining from previous refits versus overall capacity per vehicle in the consist.
|
2013-10-22 18:46:20 +00:00
|
|
|
HopSet *seen_hops; ///< Hops already seen. If the same hop is seen twice we stop the algorithm. This is shared between all Refreshers of the same run.
|
|
|
|
CargoID cargo; ///< Cargo given in last refit order.
|
2013-11-07 20:50:03 +00:00
|
|
|
bool allow_merge; ///< If the refresher is allowed to merge or extend link graphs.
|
2014-05-01 14:50:52 +00:00
|
|
|
bool is_full_loading; ///< If the vehicle is full loading.
|
2013-10-22 18:46:20 +00:00
|
|
|
|
2014-05-01 14:50:52 +00:00
|
|
|
LinkRefresher(Vehicle *v, HopSet *seen_hops, bool allow_merge, bool is_full_loading);
|
2013-10-22 18:45:55 +00:00
|
|
|
|
2014-09-21 14:22:32 +00:00
|
|
|
bool HandleRefit(CargoID refit_cargo);
|
2013-10-22 18:45:55 +00:00
|
|
|
void ResetRefit();
|
|
|
|
void RefreshStats(const Order *cur, const Order *next);
|
2014-01-28 19:49:43 +00:00
|
|
|
const Order *PredictNextOrder(const Order *cur, const Order *next, uint8 flags, uint num_hops = 0);
|
2013-10-22 18:45:55 +00:00
|
|
|
|
2014-01-28 19:49:43 +00:00
|
|
|
void RefreshLinks(const Order *cur, const Order *next, uint8 flags, uint num_hops = 0);
|
2013-10-22 18:45:55 +00:00
|
|
|
};
|
|
|
|
|
2014-10-15 18:31:37 +00:00
|
|
|
#endif /* REFRESH_H */
|