Change: Add path cache for ships.

save_ext
Peter Nelson 5 years ago committed by PeterN
parent 1c725fce47
commit 81330b8d6e

@ -2041,13 +2041,13 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool
{
if (conditional_depth > v->GetNumOrders()) {
v->current_order.Free();
v->dest_tile = 0;
v->SetDestTile(0);
return false;
}
switch (order->GetType()) {
case OT_GOTO_STATION:
v->dest_tile = v->GetOrderStationLocation(order->GetDestination());
v->SetDestTile(v->GetOrderStationLocation(order->GetDestination()));
return true;
case OT_GOTO_DEPOT:
@ -2068,7 +2068,7 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool
/* PBS reservations cannot reverse */
if (pbs_look_ahead && reverse) return false;
v->dest_tile = location;
v->SetDestTile(location);
v->current_order.MakeGoToDepot(destination, v->current_order.GetDepotOrderType(), v->current_order.GetNonStopType(), (OrderDepotActionFlags)(v->current_order.GetDepotActionType() & ~ODATFB_NEAREST_DEPOT), v->current_order.GetRefitCargo());
/* If there is no depot in front, reverse automatically (trains only) */
@ -2092,14 +2092,14 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool
v->IncrementRealOrderIndex();
} else {
if (v->type != VEH_AIRCRAFT) {
v->dest_tile = Depot::Get(order->GetDestination())->xy;
v->SetDestTile(Depot::Get(order->GetDestination())->xy);
}
return true;
}
break;
case OT_GOTO_WAYPOINT:
v->dest_tile = Waypoint::Get(order->GetDestination())->xy;
v->SetDestTile(Waypoint::Get(order->GetDestination())->xy);
return true;
case OT_CONDITIONAL: {
@ -2127,7 +2127,7 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool
}
default:
v->dest_tile = 0;
v->SetDestTile(0);
return false;
}
@ -2143,7 +2143,7 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool
if (order == NULL) {
v->current_order.Free();
v->dest_tile = 0;
v->SetDestTile(0);
return false;
}
@ -2219,7 +2219,7 @@ bool ProcessOrders(Vehicle *v)
}
v->current_order.Free();
v->dest_tile = 0;
v->SetDestTile(0);
return false;
}

@ -40,6 +40,9 @@ static const int YAPF_TILE_CORNER_LENGTH = 71;
*/
static const int YAPF_INFINITE_PENALTY = 1000 * YAPF_TILE_LENGTH;
/** Maximum length of ship path cache */
static const int YAPF_SHIP_PATH_CACHE_LENGTH = 32;
/**
* Helper container to find a depot
*/

@ -15,6 +15,7 @@
#include "../../direction_type.h"
#include "../../track_type.h"
#include "../../vehicle_type.h"
#include "../../ship.h"
#include "../pathfinder_type.h"
/**
@ -26,7 +27,7 @@
* @param path_found [out] Whether a path has been found (true) or has been guessed (false)
* @return the best trackdir for next turn or INVALID_TRACK if the path could not be found
*/
Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found);
Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found, ShipPathCache &path_cache);
/**
* Returns true if it is better to reverse the ship before leaving depot using YAPF.

@ -54,7 +54,7 @@ public:
return 'w';
}
static Trackdir ChooseShipTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found)
static Trackdir ChooseShipTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found, ShipPathCache &path_cache)
{
/* handle special case - when next tile is destination tile */
if (tile == v->dest_tile) {
@ -90,9 +90,17 @@ public:
Node *pNode = pf.GetBestNode();
if (pNode != NULL) {
uint steps = 0;
for (Node *n = pNode; n->m_parent != NULL; n = n->m_parent) steps++;
/* walk through the path back to the origin */
Node *pPrevNode = NULL;
while (pNode->m_parent != NULL) {
if (steps > 1 && --steps < YAPF_SHIP_PATH_CACHE_LENGTH) {
TrackdirByte td;
td = pNode->GetTrackdir();
path_cache.push_front(td);
}
pPrevNode = pNode;
pNode = pNode->m_parent;
}
@ -100,6 +108,8 @@ public:
Node &best_next_node = *pPrevNode;
assert(best_next_node.GetTile() == tile);
next_trackdir = best_next_node.GetTrackdir();
/* remove last element for the special case when tile == dest_tile */
if (path_found && !path_cache.empty()) path_cache.pop_back();
}
return next_trackdir;
}
@ -222,10 +232,10 @@ struct CYapfShip2 : CYapfT<CYapfShip_TypesT<CYapfShip2, CFollowTrackWater , C
struct CYapfShip3 : CYapfT<CYapfShip_TypesT<CYapfShip3, CFollowTrackWaterNo90, CShipNodeListTrackDir> > {};
/** Ship controller helper - path finder invoker */
Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found)
Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found, ShipPathCache &path_cache)
{
/* default is YAPF type 2 */
typedef Trackdir (*PfnChooseShipTrack)(const Ship*, TileIndex, DiagDirection, TrackBits, bool &path_found);
typedef Trackdir (*PfnChooseShipTrack)(const Ship*, TileIndex, DiagDirection, TrackBits, bool &path_found, ShipPathCache &path_cache);
PfnChooseShipTrack pfnChooseShipTrack = CYapfShip2::ChooseShipTrack; // default: ExitDir, allow 90-deg
/* check if non-default YAPF type needed */
@ -235,7 +245,7 @@ Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir,
pfnChooseShipTrack = &CYapfShip1::ChooseShipTrack; // Trackdir, allow 90-deg
}
Trackdir td_ret = pfnChooseShipTrack(v, tile, enterdir, tracks, path_found);
Trackdir td_ret = pfnChooseShipTrack(v, tile, enterdir, tracks, path_found, path_cache);
return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : INVALID_TRACK;
}

@ -1639,7 +1639,7 @@ static void CheckIfRoadVehNeedsService(RoadVehicle *v)
SetBit(v->gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
v->current_order.MakeGoToDepot(depot, ODTFB_SERVICE);
v->dest_tile = rfdd.tile;
v->SetDestTile(rfdd.tile);
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
}

@ -272,8 +272,9 @@
* 200 #6805 Extend railtypes to 64, adding uint16 to map array.
* 201 #6885 Extend NewGRF persistant storages.
* 202 #6867 Increase industry cargo slots to 16 in, 16 out
* 203 #7072 Add path cache for ships
*/
extern const uint16 SAVEGAME_VERSION = 202; ///< Current savegame version of OpenTTD.
extern const uint16 SAVEGAME_VERSION = 203; ///< Current savegame version of OpenTTD.
SavegameType _savegame_type; ///< type of savegame we are loading
FileToSaveLoad _file_to_saveload; ///< File to save or load in the openttd loop.

@ -753,7 +753,8 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
static const SaveLoad _ship_desc[] = {
SLE_WRITEBYTE(Vehicle, type, VEH_SHIP),
SLE_VEH_INCLUDE(),
SLE_VAR(Ship, state, SLE_UINT8),
SLE_VAR(Ship, state, SLE_UINT8),
SLE_CONDDEQUE(Ship, path, SLE_UINT8, 203, SL_MAX_VERSION),
SLE_CONDNULL(16, 2, 143), // old reserved space

@ -12,17 +12,22 @@
#ifndef SHIP_H
#define SHIP_H
#include <deque>
#include "vehicle_base.h"
#include "water_map.h"
void GetShipSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type);
WaterClass GetEffectiveWaterClass(TileIndex tile);
typedef std::deque<TrackdirByte> ShipPathCache;
/**
* All ships have this type.
*/
struct Ship FINAL : public SpecializedVehicle<Ship, VEH_SHIP> {
TrackBitsByte state; ///< The "track" the ship is following.
ShipPathCache path; ///< Cached path.
/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
Ship() : SpecializedVehicleBase() {}
@ -46,6 +51,7 @@ struct Ship FINAL : public SpecializedVehicle<Ship, VEH_SHIP> {
TileIndex GetOrderStationLocation(StationID station);
bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
void UpdateCache();
void SetDestTile(TileIndex tile);
};
static const uint SHIP_MAX_ORDER_DISTANCE = 130;

@ -193,7 +193,7 @@ static void CheckIfShipNeedsService(Vehicle *v)
}
v->current_order.MakeGoToDepot(depot->index, ODTFB_SERVICE);
v->dest_tile = depot->xy;
v->SetDestTile(depot->xy);
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
}
@ -473,10 +473,24 @@ static Track ChooseShipTrack(Ship *v, TileIndex tile, DiagDirection enterdir, Tr
}
path_found = false;
} else {
/* Attempt to follow cached path. */
if (!v->path.empty()) {
track = TrackdirToTrack(v->path.front());
if (HasBit(tracks, track)) {
v->path.pop_front();
/* HandlePathfindResult() is not called here because this is not a new pathfinder result. */
return track;
}
/* Cached path is invalid so continue with pathfinder. */
}
v->path.clear();
switch (_settings_game.pf.pathfinder_for_ships) {
case VPF_OPF: track = OPFShipChooseTrack(v, tile, enterdir, tracks, path_found); break;
case VPF_NPF: track = NPFShipChooseTrack(v, tile, enterdir, tracks, path_found); break;
case VPF_YAPF: track = YapfShipChooseTrack(v, tile, enterdir, tracks, path_found); break;
case VPF_YAPF: track = YapfShipChooseTrack(v, tile, enterdir, tracks, path_found, v->path); break;
default: NOT_REACHED();
}
}
@ -665,6 +679,7 @@ getout:
reverse_direction:
dir = ReverseDir(v->direction);
v->direction = dir;
v->path.clear();
goto getout;
}
@ -679,6 +694,13 @@ bool Ship::Tick()
return true;
}
void Ship::SetDestTile(TileIndex tile)
{
if (tile == this->dest_tile) return;
this->path.clear();
this->dest_tile = tile;
}
/**
* Build a ship.
* @param tile tile of the depot where ship is built.

@ -1980,7 +1980,7 @@ static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags)
FOR_ALL_ROADVEHICLES(v) {
if (v->First() == v && v->current_order.IsType(OT_GOTO_STATION) &&
v->dest_tile == tile) {
v->dest_tile = v->GetOrderStationLocation(st->index);
v->SetDestTile(v->GetOrderStationLocation(st->index));
}
}
@ -2604,7 +2604,7 @@ static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags)
}
if (s->dest_tile == docking_location) {
s->dest_tile = 0;
s->SetDestTile(0);
s->current_order.Free();
}
}

@ -2337,7 +2337,7 @@ CommandCost Vehicle::SendToDepot(DoCommandFlag flags, DepotCommand command)
SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
}
this->dest_tile = location;
this->SetDestTile(location);
this->current_order.MakeGoToDepot(destination, ODTF_MANUAL);
if (!(command & DEPOT_SERVICE)) this->current_order.SetDepotActionType(ODATFB_HALT);
SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP);

@ -749,6 +749,8 @@ public:
*/
virtual bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse) { return false; }
virtual void SetDestTile(TileIndex tile) { this->dest_tile = tile; }
CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command);
void UpdateVisualEffect(bool allow_power_change = true);

Loading…
Cancel
Save