10#include "../../stdafx.h"
11#include "../../ship.h"
15#include "../water_regions.h"
17#include "../../safeguards.h"
19static constexpr int DIRECT_NEIGHBOUR_COST = 100;
20static constexpr int NODES_PER_REGION = 4;
21static constexpr int MAX_NUMBER_OF_NODES = 65536;
23static constexpr int NODE_LIST_HASH_BITS_OPEN = 12;
24static constexpr int NODE_LIST_HASH_BITS_CLOSED = 12;
32 this->water_region_patch = water_region_patch;
36 inline bool operator==(
const WaterRegionPatchKey &other)
const {
return this->CalcHash() == other.CalcHash(); }
41 return (std::abs(a.water_region_patch.
x - b.water_region_patch.
x) + std::abs(a.water_region_patch.
y - b.water_region_patch.
y)) * DIRECT_NEIGHBOUR_COST;
51 this->key.Set(water_region_patch);
52 this->hash_next =
nullptr;
53 this->parent = parent;
58 inline void Set(
Node *parent,
const Key &key)
60 this->Set(parent, key.water_region_patch);
66 const int dx = this->key.water_region_patch.
x - this->parent->key.water_region_patch.
x;
67 const int dy = this->key.water_region_patch.
y - this->parent->key.water_region_patch.
y;
97 using Node =
typename WaterRegionTypes::NodeList::Item;
99 std::vector<WaterRegionPatchKey> origin_keys;
115 if (water_region_patch.
label == INVALID_WATER_REGION_PATCH)
return;
116 if (!HasOrigin(water_region_patch)) {
117 this->origin_keys.emplace_back(water_region_patch);
119 node.Set(
nullptr, water_region_patch);
126 return std::ranges::find(this->origin_keys,
WaterRegionPatchKey{ water_region_patch }) != this->origin_keys.end();
131 this->dest.Set(water_region_patch);
134 inline void PfFollowNode(Node &old_node)
136 VisitWaterRegionPatchCallback visit_func = [&](
const WaterRegionPatchDesc &water_region_patch) {
138 node.Set(&old_node, water_region_patch);
144 inline bool PfDetectDestination(Node &n)
const
146 return n.key == this->dest;
149 inline bool PfCalcCost(Node &n,
const TrackFollower *)
151 n.cost = n.parent->cost + ManhattanDistance(n.key, n.parent->key);
154 Node *grandparent = n.parent->parent;
155 if (grandparent !=
nullptr) {
163 inline bool PfCalcEstimate(Node &n)
165 if (this->PfDetectDestination(n)) {
170 n.estimate = n.cost + ManhattanDistance(n.key, this->dest);
175 inline char TransportTypeChar()
const {
return '^'; }
177 static std::vector<WaterRegionPatchDesc> FindWaterRegionPath(
const Ship *v,
TileIndex start_tile,
int max_returned_path_length)
183 const int node_limit = std::min(
static_cast<int>(
Map::Size() * NODES_PER_REGION) / WATER_REGION_NUMBER_OF_TILES, MAX_NUMBER_OF_NODES);
185 pf.SetDestination(start_water_region_patch);
190 for (
const auto &tile : station->
GetTileArea(StationType::Dock)) {
201 std::vector<WaterRegionPatchDesc> path = { start_water_region_patch };
202 path.reserve(max_returned_path_length);
203 if (pf.HasOrigin(start_water_region_patch))
return path;
209 for (
int i = 0; i < max_returned_path_length - 1; ++i) {
210 if (node !=
nullptr) {
212 if (node !=
nullptr) path.push_back(node->key.water_region_patch);
216 assert(!path.empty());
230 return YapfShipRegions::FindWaterRegionPath(v, start_tile, max_returned_path_length);
CYapfBaseT - A-star type path finder base class.
void AddNewNode(Node &n, const TrackFollower &follower)
AddNewNode() - called by Tderived::PfFollowNode() for each child node.
int max_search_nodes
maximum number of nodes we are allowed to visit before we give up
Node * GetBestNode()
If path was found return the best node that has reached the destination.
bool FindPath(const VehicleType *v)
Main pathfinder routine:
Node & CreateNewNode()
Calls NodeList::CreateNewNode() - allocates new node that can be filled and used as argument for AddS...
void AddStartupNode(Node &n)
Add new node (created by CreateNewNode and filled with data) into open list.
CYapfSegmentCostCacheNoneT - the formal only yapf cost cache provider that implements PfNodeCacheFetc...
Hash table based node list multi-container class.
Water region based YAPF implementation for ships.
DiagDirDiff DiagDirDifference(DiagDirection d0, DiagDirection d1)
Calculate the difference between two DiagDirection values.
DiagDirDiff
Enumeration for the difference between to DiagDirection.
@ DIAGDIRDIFF_90RIGHT
90 degrees right
@ DIAGDIRDIFF_90LEFT
90 degrees left
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_NE
Northeast, upper right on your monitor.
@ INVALID_DIAGDIR
Flag for an invalid DiagDirection.
bool IsShipDestinationTile(TileIndex tile, StationID station)
Test if a tile is a docking tile for the given station.
Base class for all station-ish types.
virtual TileArea GetTileArea(StationType type) const =0
Get the tile area for a given station type.
Track follower helper template class (can serve pathfinders and vehicle controllers).
static debug_inline uint Size()
Get the size of the map.
DestinationID GetDestination() const
Gets the destination of this order.
bool IsType(OrderType type) const
Check whether this order is of the given type.
static Titem * Get(auto index)
Returns Titem with given index.
All ships have this type.
Order current_order
The current order (+ status, like: loading)
TileIndex dest_tile
Heading for this tile.
Yapf Node for water regions.
Describes a single interconnected patch of water within a particular water region.
int y
The Y coordinate of the water region, i.e. Y=2 is the 3rd water region along the Y-axis.
int x
The X coordinate of the water region, i.e. X=2 is the 3rd water region along the X-axis.
WaterRegionPatchLabel label
Unique label identifying the patch within the region.
Yapf Node Key that represents a single patch of interconnected water within a water region.
bool IsDockingTile(Tile t)
Checks whether the tile is marked as a dockling tile.
WaterRegionPatchDesc GetWaterRegionPatchInfo(TileIndex tile)
Returns basic water region patch information for the provided tile.
int CalculateWaterRegionPatchHash(const WaterRegionPatchDesc &water_region_patch)
Calculates a number that uniquely identifies the provided water region patch.
void VisitWaterRegionPatchNeighbours(const WaterRegionPatchDesc &water_region_patch, VisitWaterRegionPatchCallback &callback)
Calls the provided callback function on all accessible water region patches in each cardinal directio...
Base includes/functions for YAPF.
std::vector< WaterRegionPatchDesc > YapfShipFindWaterRegionPath(const Ship *v, TileIndex start_tile, int max_returned_path_length)
Finds a path at the water region level.
Implementation of YAPF for water regions, which are used for finding intermediate ship destinations.