mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-08-13 09:39:10 +00:00
ai
data
docs
lang
makefiledir
media
music
openttd.xcode
os
scenario
scripts
sound
strgen
table
video
yapf
array.hpp
autocopyptr.hpp
binaryheap.hpp
blob.hpp
countedptr.hpp
crc32.hpp
fixedsizearray.hpp
follow_track.cpp
follow_track.hpp
hashtable.hpp
nodelist.hpp
track_dir.hpp
yapf.h
yapf.hpp
yapf_base.hpp
yapf_common.cpp
yapf_common.hpp
yapf_costbase.hpp
yapf_costcache.hpp
yapf_costrail.hpp
yapf_destrail.hpp
yapf_node.hpp
yapf_node_rail.hpp
yapf_node_road.hpp
yapf_rail.cpp
yapf_road.cpp
yapf_settings.h
yapf_ship.cpp
BUGS
COPYING
Doxyfile
Makefile
aircraft.h
aircraft_cmd.c
aircraft_gui.c
airport.c
airport.h
airport_gui.c
airport_movement.h
aystar.c
aystar.h
bmp.c
bmp.h
bridge.h
bridge_gui.c
bridge_map.c
bridge_map.h
callback_table.c
callback_table.h
changelog.txt
clear_cmd.c
clear_map.h
command.c
command.h
configure
console.c
console.h
console_cmds.c
currency.c
currency.h
date.c
date.h
debug.c
debug.h
dedicated.c
depot.c
depot.h
direction.h
disaster_cmd.c
dock_gui.c
driver.c
driver.h
dummy_land.c
economy.c
economy.h
elrail.c
endian_check.c
engine.c
engine.h
engine_gui.c
fileio.c
fileio.h
fios.c
fios.h
functions.h
genworld.c
genworld.h
genworld_gui.c
gfx.c
gfx.h
gfxinit.c
gfxinit.h
graph_gui.c
gui.h
hal.h
heightmap.c
heightmap.h
industry.h
industry_cmd.c
industry_gui.c
industry_map.h
intro_gui.c
known-bugs.txt
landscape.c
langs.vcproj
langs_vs80.vcproj
lzoconf.h
macros.h
main_gui.c
mainicon.ico
map.c
map.h
masm64.rules
md5.c
md5.h
mersenne.c
minilzo.c
minilzo.h
misc.c
misc_cmd.c
misc_gui.c
mixer.c
mixer.h
music.c
music.h
music_gui.c
namegen.c
namegen.h
network.c
network.h
network_client.c
network_client.h
network_core.h
network_data.c
network_data.h
network_gamelist.c
network_gamelist.h
network_gui.c
network_gui.h
network_server.c
network_server.h
network_udp.c
network_udp.h
newgrf.c
newgrf.h
newgrf_callbacks.h
newgrf_cargo.c
newgrf_cargo.h
newgrf_engine.c
newgrf_engine.h
newgrf_spritegroup.c
newgrf_spritegroup.h
newgrf_station.c
newgrf_station.h
newgrf_text.c
newgrf_text.h
news.h
news_gui.c
npf.c
npf.h
oldloader.c
openttd.c
openttd.h
openttd.ico
openttd.sln
openttd.tgt
openttd.vcproj
openttd_vs80.sln
openttd_vs80.vcproj
order.h
order_cmd.c
order_gui.c
os2.c
os_timer.c
ottdres.rc
pathfind.c
pathfind.h
player.h
player_gui.c
players.c
pool.c
pool.h
queue.c
queue.h
rail.c
rail.h
rail_cmd.c
rail_gui.c
rail_map.h
railtypes.h
readme.txt
resource.h
road.h
road_cmd.c
road_cmd.h
road_gui.c
road_map.c
road_map.h
roadveh.h
roadveh_cmd.c
roadveh_gui.c
saveload.c
saveload.h
screenshot.c
screenshot.h
sdl.c
sdl.h
settings.c
settings.h
settings_gui.c
ship.h
ship_cmd.c
ship_gui.c
signs.c
signs.h
slope.h
smallmap_gui.c
sound.c
sound.h
sprite.h
spritecache.c
spritecache.h
station.h
station_cmd.c
station_gui.c
station_map.c
station_map.h
stdafx.h
string.c
string.h
strings.c
strings.h
subsidy_gui.c
svnup.sh
terraform_gui.c
texteff.c
tgp.c
tgp.h
thread.c
thread.h
tile.c
tile.h
town.h
town_cmd.c
town_gui.c
town_map.h
train.h
train_cmd.c
train_gui.c
tree_cmd.c
tree_map.h
tunnel_map.c
tunnel_map.h
tunnelbridge_cmd.c
unix.c
unmovable.h
unmovable_cmd.c
unmovable_map.h
variables.h
vehicle.c
vehicle.h
vehicle_gui.c
vehicle_gui.h
viewport.c
viewport.h
void_map.h
water_cmd.c
water_map.h
waypoint.c
waypoint.h
widget.c
win32.c
win32.h
win64.asm
window.c
window.h
yapf.txt
DiagDirections, and add TileOffsByDir that handles Directions. -Codechange: Make the treeloop use TileOffsByDir().
177 lines
6.5 KiB
C++
177 lines
6.5 KiB
C++
/* $Id$ */
|
|
|
|
#include "../stdafx.h"
|
|
|
|
#include "yapf.hpp"
|
|
|
|
/** Node Follower module of YAPF for ships */
|
|
template <class Types>
|
|
class CYapfFollowShipT
|
|
{
|
|
public:
|
|
typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
|
|
typedef typename Types::TrackFollower TrackFollower;
|
|
typedef typename Types::NodeList::Titem Node; ///< this will be our node type
|
|
typedef typename Node::Key Key; ///< key to hash tables
|
|
|
|
protected:
|
|
/// to access inherited path finder
|
|
FORCEINLINE Tpf& Yapf() {return *static_cast<Tpf*>(this);}
|
|
|
|
public:
|
|
/** Called by YAPF to move from the given node to the next tile. For each
|
|
* reachable trackdir on the new tile creates new node, initializes it
|
|
* and adds it to the open list by calling Yapf().AddNewNode(n) */
|
|
inline void PfFollowNode(Node& old_node)
|
|
{
|
|
TrackFollower F;
|
|
if (F.Follow(old_node.m_key.m_tile, old_node.m_key.m_td))
|
|
Yapf().AddMultipleNodes(&old_node, F.m_new_tile, F.m_new_td_bits);
|
|
}
|
|
|
|
/// return debug report character to identify the transportation type
|
|
FORCEINLINE char TransportTypeChar() const {return 'w';}
|
|
|
|
static Trackdir ChooseShipTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
|
|
{
|
|
// handle special case - when next tile is destination tile
|
|
if (tile == v->dest_tile) {
|
|
// convert tracks to trackdirs
|
|
TrackdirBits trackdirs = (TrackdirBits)(tracks | ((int)tracks << 8));
|
|
// choose any trackdir reachable from enterdir
|
|
trackdirs &= DiagdirReachesTrackdirs(enterdir);
|
|
return (Trackdir)FindFirstBit2x64(trackdirs);
|
|
}
|
|
|
|
// move back to the old tile/trackdir (where ship is coming from)
|
|
TileIndex src_tile = TILE_ADD(tile, TileOffsByDiagDir(ReverseDiagDir(enterdir)));
|
|
Trackdir trackdir = GetVehicleTrackdir(v);
|
|
assert(IsValidTrackdir(trackdir));
|
|
|
|
// convert origin trackdir to TrackdirBits
|
|
TrackdirBits trackdirs = TrackdirToTrackdirBits(trackdir);
|
|
// get available trackdirs on the destination tile
|
|
TrackdirBits dest_trackdirs = (TrackdirBits)(GetTileTrackStatus(v->dest_tile, TRANSPORT_WATER) & TRACKDIR_BIT_MASK);
|
|
|
|
// create pathfinder instance
|
|
Tpf pf;
|
|
// set origin and destination nodes
|
|
pf.SetOrigin(src_tile, trackdirs);
|
|
pf.SetDestination(v->dest_tile, dest_trackdirs);
|
|
// find best path
|
|
bool bFound = pf.FindPath(v);
|
|
|
|
Trackdir next_trackdir = INVALID_TRACKDIR; // this would mean "path not found"
|
|
if (bFound) {
|
|
// path was found
|
|
// walk through the path back to the origin
|
|
Node* pNode = &pf.GetBestNode();
|
|
Node* pPrevNode = NULL;
|
|
while (pNode->m_parent != NULL) {
|
|
pPrevNode = pNode;
|
|
pNode = pNode->m_parent;
|
|
}
|
|
// return trackdir from the best next node (direct child of origin)
|
|
Node& best_next_node = *pPrevNode;
|
|
assert(best_next_node.GetTile() == tile);
|
|
next_trackdir = best_next_node.GetTrackdir();
|
|
}
|
|
return next_trackdir;
|
|
}
|
|
};
|
|
|
|
/** Cost Provider module of YAPF for ships */
|
|
template <class Types>
|
|
class CYapfCostShipT
|
|
{
|
|
public:
|
|
typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
|
|
typedef typename Types::NodeList::Titem Node; ///< this will be our node type
|
|
typedef typename Node::Key Key; ///< key to hash tables
|
|
|
|
protected:
|
|
/// to access inherited path finder
|
|
Tpf& Yapf() {return *static_cast<Tpf*>(this);}
|
|
|
|
public:
|
|
/** Called by YAPF to calculate the cost from the origin to the given node.
|
|
* Calculates only the cost of given node, adds it to the parent node cost
|
|
* and stores the result into Node::m_cost member */
|
|
FORCEINLINE bool PfCalcCost(Node& n)
|
|
{
|
|
// base tile cost depending on distance
|
|
int c = IsDiagonalTrackdir(n.GetTrackdir()) ? 10 : 7;
|
|
// additional penalty for curves
|
|
if (n.m_parent != NULL && n.GetTrackdir() != n.m_parent->GetTrackdir()) c += 3;
|
|
// apply it
|
|
n.m_cost = n.m_parent->m_cost + c;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
/** Config struct of YAPF for ships.
|
|
* Defines all 6 base YAPF modules as classes providing services for CYapfBaseT.
|
|
*/
|
|
template <class Tpf_, class Ttrack_follower, class Tnode_list>
|
|
struct CYapfShip_TypesT
|
|
{
|
|
/** Types - shortcut for this struct type */
|
|
typedef CYapfShip_TypesT<Tpf_, Ttrack_follower, Tnode_list> Types;
|
|
|
|
/** Tpf - pathfinder type */
|
|
typedef Tpf_ Tpf;
|
|
/** track follower helper class */
|
|
typedef Ttrack_follower TrackFollower;
|
|
/** node list type */
|
|
typedef Tnode_list NodeList;
|
|
/** pathfinder components (modules) */
|
|
typedef CYapfBaseT<Types> PfBase; // base pathfinder class
|
|
typedef CYapfFollowShipT<Types> PfFollow; // node follower
|
|
typedef CYapfOriginTileT<Types> PfOrigin; // origin provider
|
|
typedef CYapfDestinationTileT<Types> PfDestination; // destination/distance provider
|
|
typedef CYapfSegmentCostCacheNoneT<Types> PfCache; // segment cost cache provider
|
|
typedef CYapfCostShipT<Types> PfCost; // cost provider
|
|
};
|
|
|
|
// YAPF type 1 - uses TileIndex/Trackdir as Node key, allows 90-deg turns
|
|
struct CYapfShip1 : CYapfT<CYapfShip_TypesT<CYapfShip1, CFollowTrackWater , CShipNodeListTrackDir> > {};
|
|
// YAPF type 2 - uses TileIndex/DiagDirection as Node key, allows 90-deg turns
|
|
struct CYapfShip2 : CYapfT<CYapfShip_TypesT<CYapfShip2, CFollowTrackWater , CShipNodeListExitDir > > {};
|
|
// YAPF type 3 - uses TileIndex/Trackdir as Node key, forbids 90-deg turns
|
|
struct CYapfShip3 : CYapfT<CYapfShip_TypesT<CYapfShip3, CFollowTrackWaterNo90, CShipNodeListTrackDir> > {};
|
|
|
|
/** Ship controller helper - path finder invoker */
|
|
Trackdir YapfChooseShipTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
|
|
{
|
|
// default is YAPF type 2
|
|
typedef Trackdir (*PfnChooseShipTrack)(Vehicle*, TileIndex, DiagDirection, TrackBits);
|
|
PfnChooseShipTrack pfnChooseShipTrack = CYapfShip2::ChooseShipTrack; // default: ExitDir, allow 90-deg
|
|
|
|
// check if non-default YAPF type needed
|
|
if (_patches.forbid_90_deg)
|
|
pfnChooseShipTrack = &CYapfShip3::ChooseShipTrack; // Trackdir, forbid 90-deg
|
|
else if (_patches.yapf.disable_node_optimization)
|
|
pfnChooseShipTrack = &CYapfShip1::ChooseShipTrack; // Trackdir, allow 90-deg
|
|
|
|
Trackdir td_ret = pfnChooseShipTrack(v, tile, enterdir, tracks);
|
|
return td_ret;
|
|
}
|
|
|
|
/** performance measurement helper */
|
|
void* NpfBeginInterval()
|
|
{
|
|
CPerformanceTimer& perf = *new CPerformanceTimer;
|
|
perf.Start();
|
|
return &perf;
|
|
}
|
|
|
|
/** performance measurement helper */
|
|
int NpfEndInterval(void* vperf)
|
|
{
|
|
CPerformanceTimer& perf = *(CPerformanceTimer*)vperf;
|
|
perf.Stop();
|
|
int t = perf.Get(1000000);
|
|
delete &perf;
|
|
return t;
|
|
}
|