From bff850128c2b9ad737a212d1091fa092bcb1e79d Mon Sep 17 00:00:00 2001 From: Kuhnovic <68320206+Kuhnovic@users.noreply.github.com> Date: Sat, 20 Sep 2025 21:42:06 +0200 Subject: [PATCH] Codechange: Use YAPF for river builder pathfinder. (#14606) --- src/landscape.cpp | 100 +----------- src/pathfinder/CMakeLists.txt | 2 - src/pathfinder/aystar.cpp | 168 -------------------- src/pathfinder/aystar.h | 98 ------------ src/pathfinder/yapf/CMakeLists.txt | 2 + src/pathfinder/yapf/yapf_river_builder.cpp | 152 ++++++++++++++++++ src/pathfinder/yapf/yapf_river_builder.h | 17 ++ src/settings_table.cpp | 1 - src/table/settings/pathfinding_settings.ini | 2 +- src/water.h | 2 + 10 files changed, 179 insertions(+), 365 deletions(-) delete mode 100644 src/pathfinder/aystar.cpp delete mode 100644 src/pathfinder/aystar.h create mode 100644 src/pathfinder/yapf/yapf_river_builder.cpp create mode 100644 src/pathfinder/yapf/yapf_river_builder.h diff --git a/src/landscape.cpp b/src/landscape.cpp index 39d5a563bb..61aa649874 100644 --- a/src/landscape.cpp +++ b/src/landscape.cpp @@ -32,13 +32,13 @@ #include "object_base.h" #include "company_func.h" #include "company_gui.h" -#include "pathfinder/aystar.h" #include "saveload/saveload.h" #include "framerate_type.h" #include "landscape_cmd.h" #include "terraform_cmd.h" #include "station_func.h" #include "pathfinder/water_regions.h" +#include "pathfinder/yapf/yapf_river_builder.h" #include "table/strings.h" #include "table/sprites.h" @@ -1037,7 +1037,7 @@ static void MakeLake(TileIndex tile, uint height_lake) * @param tile The tile to try expanding the river into. * @param origin_tile The tile to try surrounding the river around. */ -static void RiverMakeWider(TileIndex tile, TileIndex origin_tile) +void RiverMakeWider(TileIndex tile, TileIndex origin_tile) { /* Don't expand into void tiles. */ if (!IsValidTile(tile)) return; @@ -1180,7 +1180,7 @@ static void RiverMakeWider(TileIndex tile, TileIndex origin_tile) * @param end The destination of the flow. * @return True iff the water can be flowing down. */ -static bool FlowsDown(TileIndex begin, TileIndex end) +bool RiverFlowsDown(TileIndex begin, TileIndex end) { assert(DistanceManhattan(begin, end) == 1); @@ -1201,96 +1201,6 @@ static bool FlowsDown(TileIndex begin, TileIndex end) return slope_end == SLOPE_FLAT || slope_begin == SLOPE_FLAT; } -/** Search path and build river */ -class RiverBuilder : public AyStar { -protected: - AyStarStatus EndNodeCheck(const PathNode ¤t) const override - { - return current.GetTile() == this->end ? AyStarStatus::FoundEndNode : AyStarStatus::Done; - } - - int32_t CalculateG(const AyStarNode &, const PathNode &) const override - { - return 1 + RandomRange(_settings_game.game_creation.river_route_random); - } - - int32_t CalculateH(const AyStarNode ¤t, const PathNode &) const override - { - return DistanceManhattan(this->end, current.tile); - } - - void GetNeighbours(const PathNode ¤t, std::vector &neighbours) const override - { - TileIndex tile = current.GetTile(); - - neighbours.clear(); - for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) { - TileIndex t = tile + TileOffsByDiagDir(d); - if (IsValidTile(t) && FlowsDown(tile, t)) { - auto &neighbour = neighbours.emplace_back(); - neighbour.tile = t; - neighbour.td = INVALID_TRACKDIR; - } - } - } - - void FoundEndNode(const PathNode ¤t) override - { - /* First, build the river without worrying about its width. */ - for (PathNode *path = current.parent; path != nullptr; path = path->parent) { - TileIndex tile = path->GetTile(); - if (!IsWaterTile(tile)) { - MakeRiverAndModifyDesertZoneAround(tile); - } - } - - /* If the river is a main river, go back along the path to widen it. - * Don't make wide rivers if we're using the original landscape generator. - */ - if (_settings_game.game_creation.land_generator != LG_ORIGINAL && this->main_river) { - const uint long_river_length = _settings_game.game_creation.min_river_length * 4; - - for (PathNode *path = current.parent; path != nullptr; path = path->parent) { - TileIndex origin_tile = path->GetTile(); - - /* Check if we should widen river depending on how far we are away from the source. */ - uint current_river_length = DistanceManhattan(this->spring, origin_tile); - uint diameter = std::min(3u, (current_river_length / (long_river_length / 3u)) + 1u); - if (diameter <= 1) continue; - - for (auto tile : SpiralTileSequence(origin_tile, diameter)) { - RiverMakeWider(tile, origin_tile); - } - } - } - } - - RiverBuilder(TileIndex end, TileIndex spring, bool main_river) : end(end), spring(spring), main_river(main_river) {} - -private: - TileIndex end; ///< Destination for the river. - TileIndex spring; ///< The current spring during river generation. - bool main_river; ///< Whether the current river is a big river that others flow into. - -public: - /** - * Actually build the river between the begin and end tiles using AyStar. - * @param begin The begin of the river. - * @param end The end of the river. - * @param spring The springing point of the river. - * @param main_river Whether the current river is a big river that others flow into. - */ - static void Exec(TileIndex begin, TileIndex end, TileIndex spring, bool main_river) - { - RiverBuilder builder(end, spring, main_river); - AyStarNode start; - start.tile = begin; - start.td = INVALID_TRACKDIR; - builder.AddStartNode(&start, 0); - builder.Main(); - } -}; - /** * Try to flow the river down from a given begin. * @param spring The springing point of the river. @@ -1328,7 +1238,7 @@ static std::tuple FlowRiver(TileIndex spring, TileIndex begin, uint for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) { TileIndex t = end + TileOffsByDiagDir(d); - if (IsValidTile(t) && !marks.contains(t) && FlowsDown(end, t)) { + if (IsValidTile(t) && !marks.contains(t) && RiverFlowsDown(end, t)) { marks.insert(t); count++; queue.push_back(t); @@ -1373,7 +1283,7 @@ static std::tuple FlowRiver(TileIndex spring, TileIndex begin, uint } marks.clear(); - if (found) RiverBuilder::Exec(begin, end, spring, main_river); + if (found) YapfBuildRiver(begin, end, spring, main_river); return { found, main_river }; } diff --git a/src/pathfinder/CMakeLists.txt b/src/pathfinder/CMakeLists.txt index dd6d63bb4d..aa6b032965 100644 --- a/src/pathfinder/CMakeLists.txt +++ b/src/pathfinder/CMakeLists.txt @@ -1,8 +1,6 @@ add_subdirectory(yapf) add_files( - aystar.h - aystar.cpp follow_track.hpp pathfinder_func.h pathfinder_type.h diff --git a/src/pathfinder/aystar.cpp b/src/pathfinder/aystar.cpp deleted file mode 100644 index b885c76c43..0000000000 --- a/src/pathfinder/aystar.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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 . - */ - -/** @file aystar.cpp Implementation of A*. - * - * This file has the core function for %AyStar. - * %AyStar is a fast path finding routine and is used for things like AI path finding and Train path finding. - * For more information about %AyStar (A* Algorithm), you can look at - * http://en.wikipedia.org/wiki/A-star_search_algorithm. - */ - -#include "../../stdafx.h" -#include "aystar.h" - -#include "../../safeguards.h" - -/** - * Adds a node to the open list. - * It makes a copy of node, and puts the pointer of parent in the struct. - */ -void AyStar::OpenListAdd(PathNode *parent, const AyStarNode *node, int f, int g) -{ - /* Add a new Node to the OpenList */ - PathNode &new_node = this->nodes.CreateNewNode(); - new_node.Set(parent, node->tile, node->td, true); - new_node.estimate = f; - new_node.cost = g; - this->nodes.InsertOpenNode(new_node); -} - -/** - * Checks one tile and calculate its f-value - */ -void AyStar::CheckTile(AyStarNode *current, PathNode *parent) -{ - /* Check the new node against the ClosedList */ - if (this->nodes.FindClosedNode(*current) != nullptr) return; - - /* Calculate the G-value for this node */ - int new_g = this->CalculateG(*current, *parent); - /* If the value was INVALID_NODE, we don't do anything with this node */ - if (new_g == AYSTAR_INVALID_NODE) return; - - /* There should not be given any other error-code.. */ - assert(new_g >= 0); - /* Add the parent g-value to the new g-value */ - new_g += parent->cost; - - /* Calculate the h-value */ - int new_h = this->CalculateH(*current, *parent); - /* There should not be given any error-code.. */ - assert(new_h >= 0); - - /* The f-value if g + h */ - int new_f = new_g + new_h; - - /* Get the pointer to the parent in the ClosedList (the current one is to a copy of the one in the OpenList) */ - PathNode *closedlist_parent = this->nodes.FindClosedNode(parent->key); - - /* Check if this item is already in the OpenList */ - PathNode *check = this->nodes.FindOpenNode(*current); - if (check != nullptr) { - /* Yes, check if this g value is lower.. */ - if (new_g > check->cost) return; - this->nodes.PopOpenNode(check->key); - /* It is lower, so change it to this item */ - check->estimate = new_f; - check->cost = new_g; - check->parent = closedlist_parent; - /* Re-add it in the openlist_queue. */ - this->nodes.InsertOpenNode(*check); - } else { - /* A new node, add it to the OpenList */ - this->OpenListAdd(closedlist_parent, current, new_f, new_g); - } -} - -/** - * This function is the core of %AyStar. It handles one item and checks - * its neighbour items. If they are valid, they are added to be checked too. - * @return Possible values: - * - #AyStarStatus::EmptyOpenList - * - #AyStarStatus::LimitReached - * - #AyStarStatus::FoundEndNode - * - #AyStarStatus::StillBusy - */ -AyStarStatus AyStar::Loop() -{ - /* Get the best node from OpenList */ - PathNode *current = this->nodes.PopBestOpenNode(); - /* If empty, drop an error */ - if (current == nullptr) return AyStarStatus::EmptyOpenList; - - /* Check for end node and if found, return that code */ - if (this->EndNodeCheck(*current) == AyStarStatus::FoundEndNode && current->parent != nullptr) { - this->FoundEndNode(*current); - return AyStarStatus::FoundEndNode; - } - - /* Add the node to the ClosedList */ - this->nodes.InsertClosedNode(*current); - - /* Load the neighbours */ - this->GetNeighbours(*current, this->neighbours); - - /* Go through all neighbours */ - for (auto &neighbour : this->neighbours) { - /* Check and add them to the OpenList if needed */ - this->CheckTile(&neighbour, current); - } - - if (this->nodes.ClosedCount() >= AYSTAR_DEF_MAX_SEARCH_NODES) { - /* We've expanded enough nodes */ - return AyStarStatus::LimitReached; - } else { - /* Return that we are still busy */ - return AyStarStatus::StillBusy; - } -} - -/** - * This is the function you call to run AyStar. - * @return Possible values: - * - #AyStarStatus::FoundEndNode - * - #AyStarStatus::NoPath - * - #AyStarStatus::StillBusy - */ -AyStarStatus AyStar::Main() -{ - AyStarStatus r; - do { - r = this->Loop(); - } while (r == AyStarStatus::StillBusy); -#ifdef AYSTAR_DEBUG - switch (r) { - case AyStarStatus::FoundEndNode: Debug(misc, 0, "[AyStar] Found path!"); break; - case AyStarStatus::EmptyOpenList: Debug(misc, 0, "[AyStar] OpenList run dry, no path found"); break; - case AyStarStatus::LimitReached: Debug(misc, 0, "[AyStar] Exceeded search_nodes, no path found"); break; - default: break; - } -#endif - - switch (r) { - case AyStarStatus::FoundEndNode: return AyStarStatus::FoundEndNode; - case AyStarStatus::EmptyOpenList: - case AyStarStatus::LimitReached: return AyStarStatus::NoPath; - default: return AyStarStatus::StillBusy; - } -} - -/** - * Adds a node from where to start an algorithm. Multiple nodes can be added - * if wanted. - * @param start_node Node to start with. - * @param g the cost for starting with this node. - */ -void AyStar::AddStartNode(AyStarNode *start_node, int g) -{ -#ifdef AYSTAR_DEBUG - Debug(misc, 0, "[AyStar] Starting A* Algorithm from node ({}, {}, {})\n", - TileX(start_node->tile), TileY(start_node->tile), start_node->direction); -#endif - this->OpenListAdd(nullptr, start_node, 0, g); -} diff --git a/src/pathfinder/aystar.h b/src/pathfinder/aystar.h deleted file mode 100644 index e74d1f3476..0000000000 --- a/src/pathfinder/aystar.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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 . - */ - -/** - * @file aystar.h - * This file has the header for %AyStar. - * %AyStar is a fast path finding routine and is used for things like AI path finding and Train path finding. - * For more information about AyStar (A* Algorithm), you can look at - * http://en.wikipedia.org/wiki/A-star_search_algorithm. - */ - -#ifndef AYSTAR_H -#define AYSTAR_H - -#include "yapf/nodelist.hpp" -#include "yapf/yapf_node.hpp" - -static const int AYSTAR_DEF_MAX_SEARCH_NODES = 10000; ///< Reference limit for #AyStar::max_search_nodes - -/** Return status of #AyStar methods. */ -enum class AyStarStatus : uint8_t { - FoundEndNode, ///< An end node was found. - EmptyOpenList, ///< All items are tested, and no path has been found. - StillBusy, ///< Some checking was done, but no path found yet, and there are still items left to try. - NoPath, ///< No path to the goal was found. - LimitReached, ///< The AYSTAR_DEF_MAX_SEARCH_NODES limit has been reached, aborting search. - Done, ///< Not an end-tile, or wrong direction. -}; - -static const int AYSTAR_INVALID_NODE = -1; ///< Item is not valid (for example, not walkable). - -using AyStarNode = CYapfNodeKeyTrackDir; - -struct PathNode : CYapfNodeT { -}; - -/** - * %AyStar search algorithm struct. - */ -class AyStar { -protected: - /** - * Calculate the G-value for the %AyStar algorithm. - * @return G value of the node: - * - #AYSTAR_INVALID_NODE : indicates an item is not valid (e.g.: unwalkable) - * - Any value >= 0 : the g-value for this tile - */ - virtual int32_t CalculateG(const AyStarNode ¤t, const PathNode &parent) const = 0; - - /** - * Calculate the H-value for the %AyStar algorithm. - * Mostly, this must return the distance (Manhattan way) between the current point and the end point. - * @return The h-value for this tile (any value >= 0) - */ - virtual int32_t CalculateH(const AyStarNode ¤t, const PathNode &parent) const = 0; - - /** - * This function requests the tiles around the current tile. - * #neighbours is never reset, so if you are not using directions, just leave it alone. - */ - virtual void GetNeighbours(const PathNode ¤t, std::vector &neighours) const = 0; - - /** - * Check whether the end-tile is found. - * @param current Node to exam. - * @return Status of the node: - * - #AyStarStatus::FoundEndNode : indicates this is the end tile - * - #AyStarStatus::Done : indicates this is not the end tile (or direction was wrong) - */ - virtual AyStarStatus EndNodeCheck(const PathNode ¤t) const = 0; - - /** - * If the End Node is found, this function is called. - * It can do, for example, calculate the route and put that in an array. - */ - virtual void FoundEndNode(const PathNode ¤t) = 0; - - void AddStartNode(AyStarNode *start_node, int g); - - AyStarStatus Main(); - -public: - virtual ~AyStar() = default; - -private: - NodeList nodes; - mutable std::vector neighbours; - - AyStarStatus Loop(); - void OpenListAdd(PathNode *parent, const AyStarNode *node, int f, int g); - void CheckTile(AyStarNode *current, PathNode *parent); -}; - -#endif /* AYSTAR_H */ diff --git a/src/pathfinder/yapf/CMakeLists.txt b/src/pathfinder/yapf/CMakeLists.txt index 6717233352..2ab0ec5b51 100644 --- a/src/pathfinder/yapf/CMakeLists.txt +++ b/src/pathfinder/yapf/CMakeLists.txt @@ -14,6 +14,8 @@ add_files( yapf_node_road.hpp yapf_node_ship.hpp yapf_rail.cpp + yapf_river_builder.h + yapf_river_builder.cpp yapf_road.cpp yapf_ship.cpp yapf_ship_regions.h diff --git a/src/pathfinder/yapf/yapf_river_builder.cpp b/src/pathfinder/yapf/yapf_river_builder.cpp new file mode 100644 index 0000000000..697ddd2e8f --- /dev/null +++ b/src/pathfinder/yapf/yapf_river_builder.cpp @@ -0,0 +1,152 @@ +/* + * 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 . + */ + +/** @file yapf_river_builder.cpp Pathfinder for river building. */ + +#include "../../stdafx.h" + +#include "../../water.h" +#include "../../genworld.h" +#include "yapf.hpp" + +#include "../../safeguards.h" + +/* River builder pathfinder node. */ +struct YapfRiverBuilderNode : CYapfNodeT {}; + +/* River builder pathfinder node list. */ +using RiverBuilderNodeList = NodeList; + +/* We don't need a follower but YAPF requires one. */ +struct DummyFollower {}; + +/* We don't need a vehicle but YAPF requires one. */ +struct DummyVehicle : Vehicle {}; + +class YapfRiverBuilder; + +/* Types struct required for YAPF components. */ +struct RiverBuilderTypes { + using Tpf = YapfRiverBuilder; + using TrackFollower = DummyFollower; + using NodeList = RiverBuilderNodeList; + using VehicleType = DummyVehicle; +}; + +/* River builder pathfinder implementation. */ +class YapfRiverBuilder + : public CYapfBaseT + , public CYapfSegmentCostCacheNoneT +{ +public: + using Node = RiverBuilderTypes::NodeList::Item; + using Key = Node::Key; + +protected: + TileIndex start_tile; ///< Start tile of the river + TileIndex end_tile; ///< End tile of the river + + inline YapfRiverBuilder &Yapf() + { + return *static_cast(this); + } + +public: + YapfRiverBuilder(TileIndex start_tile, TileIndex end_tile) + { + this->start_tile = start_tile; + this->end_tile = end_tile; + } + + void PfSetStartupNodes() + { + Node &node = Yapf().CreateNewNode(); + node.Set(nullptr, this->start_tile, INVALID_TRACKDIR, false); + Yapf().AddStartupNode(node); + } + + inline bool PfDetectDestination(Node &n) const + { + return n.GetTile() == this->end_tile; + } + + inline bool PfCalcCost(Node &n, const DummyFollower *) + { + n.cost = n.parent->cost + 1 + RandomRange(_settings_game.game_creation.river_route_random); + return true; + } + + inline bool PfCalcEstimate(Node &n) + { + n.estimate = n.cost + DistanceManhattan(this->end_tile, n.GetTile()); + assert(n.estimate >= n.parent->estimate); + return true; + } + + inline void PfFollowNode(Node &old_node) + { + for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; ++d) { + const TileIndex t = old_node.GetTile() + TileOffsByDiagDir(d); + if (IsValidTile(t) && RiverFlowsDown(old_node.GetTile(), t)) { + Node &node = Yapf().CreateNewNode(); + node.Set(&old_node, t, INVALID_TRACKDIR, true); + Yapf().AddNewNode(node, DummyFollower{}); + } + } + } + + inline char TransportTypeChar() const + { + return '~'; + } + + static void BuildRiver(TileIndex start_tile, TileIndex end_tile, TileIndex spring_tile, bool main_river) + { + YapfRiverBuilder pf(start_tile, end_tile); + if (pf.FindPath(nullptr) == false) return; // No path found + + /* First, build the river without worrying about its width. */ + for (Node *node = pf.GetBestNode(); node != nullptr; node = node->parent) { + TileIndex tile = node->GetTile(); + if (!IsWaterTile(tile)) { + MakeRiverAndModifyDesertZoneAround(tile); + } + } + + /* If the river is a main river, go back along the path to widen it. + * Don't make wide rivers if we're using the original landscape generator. + */ + if (_settings_game.game_creation.land_generator != LG_ORIGINAL && main_river) { + const uint long_river_length = _settings_game.game_creation.min_river_length * 4; + + for (Node *node = pf.GetBestNode(); node != nullptr; node = node->parent) { + const TileIndex center_tile = node->GetTile(); + + /* Check if we should widen river depending on how far we are away from the source. */ + uint current_river_length = DistanceManhattan(spring_tile, center_tile); + uint diameter = std::min(3u, (current_river_length / (long_river_length / 3u)) + 1u); + if (diameter <= 1) continue; + + for (auto tile : SpiralTileSequence(center_tile, diameter)) { + RiverMakeWider(tile, center_tile); + } + } + } + } +}; + +/** + * Builds a river from the start tile to the end tile. + * @param start_tile Start tile of the river. + * @param end_tile End tile of the river. + * @param spring_tile spring_tile Tile in which the spring of the river is located. + * @param main_river Whether it is a main river. Main rivers can get wider than one tile. + */ +void YapfBuildRiver(TileIndex start_tile, TileIndex end_tile, TileIndex spring_tile, bool main_river) +{ + YapfRiverBuilder::BuildRiver(start_tile, end_tile, spring_tile, main_river); +} diff --git a/src/pathfinder/yapf/yapf_river_builder.h b/src/pathfinder/yapf/yapf_river_builder.h new file mode 100644 index 0000000000..6417770cc0 --- /dev/null +++ b/src/pathfinder/yapf/yapf_river_builder.h @@ -0,0 +1,17 @@ +/* + * 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 . + */ + +/** @file yapf_river_builder.h Pathfinder for river building. */ + +#ifndef YAPF_RIVER_BUILDER_H +#define YAPF_RIVER_BUILDER_H + +#include "../../tile_type.h" + +void YapfBuildRiver(TileIndex start_tile, TileIndex end_tile, TileIndex spring_tile, bool main_river); + +#endif /* YAPF_RIVER_BUILDER_H */ diff --git a/src/settings_table.cpp b/src/settings_table.cpp index 8eeccf90ea..b75bd3afb6 100644 --- a/src/settings_table.cpp +++ b/src/settings_table.cpp @@ -17,7 +17,6 @@ #include "network/network_func.h" #include "network/core/config.h" #include "pathfinder/pathfinder_type.h" -#include "pathfinder/aystar.h" #include "linkgraph/linkgraphschedule.h" #include "genworld.h" #include "train.h" diff --git a/src/table/settings/pathfinding_settings.ini b/src/table/settings/pathfinding_settings.ini index 1bf6efac3a..63c17d1a8d 100644 --- a/src/table/settings/pathfinding_settings.ini +++ b/src/table/settings/pathfinding_settings.ini @@ -102,7 +102,7 @@ cat = SC_EXPERT var = pf.yapf.max_search_nodes type = SLE_UINT from = SLV_28 -def = AYSTAR_DEF_MAX_SEARCH_NODES +def = 10000 min = 500 max = 1000000 cat = SC_EXPERT diff --git a/src/water.h b/src/water.h index 3bad4fba5a..f6c48bcf97 100644 --- a/src/water.h +++ b/src/water.h @@ -39,6 +39,8 @@ void MakeWaterKeepingClass(TileIndex tile, Owner o); void CheckForDockingTile(TileIndex t); void MakeRiverAndModifyDesertZoneAround(TileIndex tile); +void RiverMakeWider(TileIndex tile, TileIndex origin_tile); +bool RiverFlowsDown(TileIndex begin, TileIndex end); static const uint RIVER_OFFSET_DESERT_DISTANCE = 5; ///< Circular tile search diameter to create non-desert around a river tile. bool IsWateredTile(TileIndex tile, Direction from);