mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-09 23:50:25 +00:00
Fix: Try all possible reverse directions when a ship reaches a dead end
This commit is contained in:
parent
207cf7bbdd
commit
cbe00ec651
@ -1211,7 +1211,7 @@ Track NPFShipChooseTrack(const Ship *v, bool &path_found)
|
|||||||
return TrackdirToTrack(ftd.best_trackdir);
|
return TrackdirToTrack(ftd.best_trackdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NPFShipCheckReverse(const Ship *v)
|
bool NPFShipCheckReverse(const Ship *v, Trackdir *best_td)
|
||||||
{
|
{
|
||||||
NPFFindStationOrTileData fstd;
|
NPFFindStationOrTileData fstd;
|
||||||
NPFFoundTargetData ftd;
|
NPFFoundTargetData ftd;
|
||||||
@ -1224,7 +1224,21 @@ bool NPFShipCheckReverse(const Ship *v)
|
|||||||
assert(trackdir_rev != INVALID_TRACKDIR);
|
assert(trackdir_rev != INVALID_TRACKDIR);
|
||||||
|
|
||||||
AyStarUserData user = { v->owner, TRANSPORT_WATER, RAILTYPES_NONE, ROADTYPES_NONE, 0 };
|
AyStarUserData user = { v->owner, TRANSPORT_WATER, RAILTYPES_NONE, ROADTYPES_NONE, 0 };
|
||||||
ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, false, v->tile, trackdir_rev, false, &fstd, &user);
|
if (best_td != nullptr) {
|
||||||
|
TrackdirBits rtds = DiagdirReachesTrackdirs(ReverseDiagDir(VehicleExitDir(v->direction, v->state)));
|
||||||
|
Trackdir best = (Trackdir)FindFirstBit2x64(rtds);
|
||||||
|
for (rtds = KillFirstBit(rtds); rtds != TRACKDIR_BIT_NONE; rtds = KillFirstBit(rtds)) {
|
||||||
|
Trackdir td = (Trackdir)FindFirstBit2x64(rtds);
|
||||||
|
ftd = NPFRouteToStationOrTileTwoWay(v->tile, best, false, v->tile, td, false, &fstd, &user);
|
||||||
|
if (ftd.best_bird_dist == 0 && NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) best = td;
|
||||||
|
}
|
||||||
|
if (ftd.best_bird_dist == 0) {
|
||||||
|
*best_td = best;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, false, v->tile, trackdir_rev, false, &fstd, &user);
|
||||||
|
}
|
||||||
/* If we didn't find anything, just keep on going straight ahead, otherwise take the reverse flag */
|
/* If we didn't find anything, just keep on going straight ahead, otherwise take the reverse flag */
|
||||||
return ftd.best_bird_dist == 0 && NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE);
|
return ftd.best_bird_dist == 0 && NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE);
|
||||||
}
|
}
|
||||||
|
@ -46,9 +46,10 @@ Track NPFShipChooseTrack(const Ship *v, bool &path_found);
|
|||||||
/**
|
/**
|
||||||
* Returns true if it is better to reverse the ship before leaving depot using NPF.
|
* Returns true if it is better to reverse the ship before leaving depot using NPF.
|
||||||
* @param v the ship leaving the depot
|
* @param v the ship leaving the depot
|
||||||
|
* @param trackdir [out] the best of all possible reversed trackdirs
|
||||||
* @return true if reversing is better
|
* @return true if reversing is better
|
||||||
*/
|
*/
|
||||||
bool NPFShipCheckReverse(const Ship *v);
|
bool NPFShipCheckReverse(const Ship *v, Trackdir *trackdir);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used when user sends train to the nearest depot or if train needs servicing using NPF
|
* Used when user sends train to the nearest depot or if train needs servicing using NPF
|
||||||
|
@ -31,9 +31,10 @@ Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir,
|
|||||||
/**
|
/**
|
||||||
* Returns true if it is better to reverse the ship before leaving depot using YAPF.
|
* Returns true if it is better to reverse the ship before leaving depot using YAPF.
|
||||||
* @param v the ship leaving the depot
|
* @param v the ship leaving the depot
|
||||||
|
* @param trackdir [out] the best of all possible reversed trackdirs
|
||||||
* @return true if reversing is better
|
* @return true if reversing is better
|
||||||
*/
|
*/
|
||||||
bool YapfShipCheckReverse(const Ship *v);
|
bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the best path for given road vehicle using YAPF.
|
* Finds the best path for given road vehicle using YAPF.
|
||||||
|
@ -204,14 +204,15 @@ public:
|
|||||||
* @param tile Current position
|
* @param tile Current position
|
||||||
* @param td1 Forward direction
|
* @param td1 Forward direction
|
||||||
* @param td2 Reverse direction
|
* @param td2 Reverse direction
|
||||||
|
* @param trackdir [out] the best of all possible reversed trackdirs
|
||||||
* @return true if the reverse direction is better
|
* @return true if the reverse direction is better
|
||||||
*/
|
*/
|
||||||
static bool CheckShipReverse(const Ship *v, TileIndex tile, Trackdir td1, Trackdir td2)
|
static bool CheckShipReverse(const Ship *v, TileIndex tile, Trackdir td1, Trackdir td2, Trackdir *trackdir)
|
||||||
{
|
{
|
||||||
/* create pathfinder instance */
|
/* create pathfinder instance */
|
||||||
Tpf pf;
|
Tpf pf;
|
||||||
/* set origin and destination nodes */
|
/* set origin and destination nodes */
|
||||||
pf.SetOrigin(tile, TrackdirToTrackdirBits(td1) | TrackdirToTrackdirBits(td2));
|
pf.SetOrigin(tile, trackdir == nullptr ? TrackdirToTrackdirBits(td1) | TrackdirToTrackdirBits(td2) : DiagdirReachesTrackdirs(ReverseDiagDir(VehicleExitDir(v->direction, v->state))));
|
||||||
pf.SetDestination(v);
|
pf.SetDestination(v);
|
||||||
/* find best path */
|
/* find best path */
|
||||||
if (!pf.FindPath(v)) return false;
|
if (!pf.FindPath(v)) return false;
|
||||||
@ -226,8 +227,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Trackdir best_trackdir = pNode->GetTrackdir();
|
Trackdir best_trackdir = pNode->GetTrackdir();
|
||||||
assert(best_trackdir == td1 || best_trackdir == td2);
|
if (trackdir != nullptr) {
|
||||||
return best_trackdir == td2;
|
*trackdir = best_trackdir;
|
||||||
|
} else {
|
||||||
|
assert(best_trackdir == td1 || best_trackdir == td2);
|
||||||
|
}
|
||||||
|
return best_trackdir != td1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -353,13 +358,13 @@ Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir,
|
|||||||
return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : INVALID_TRACK;
|
return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : INVALID_TRACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool YapfShipCheckReverse(const Ship *v)
|
bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir)
|
||||||
{
|
{
|
||||||
Trackdir td = v->GetVehicleTrackdir();
|
Trackdir td = v->GetVehicleTrackdir();
|
||||||
Trackdir td_rev = ReverseTrackdir(td);
|
Trackdir td_rev = ReverseTrackdir(td);
|
||||||
TileIndex tile = v->tile;
|
TileIndex tile = v->tile;
|
||||||
|
|
||||||
typedef bool (*PfnCheckReverseShip)(const Ship*, TileIndex, Trackdir, Trackdir);
|
typedef bool (*PfnCheckReverseShip)(const Ship*, TileIndex, Trackdir, Trackdir, Trackdir*);
|
||||||
PfnCheckReverseShip pfnCheckReverseShip = CYapfShip2::CheckShipReverse; // default: ExitDir
|
PfnCheckReverseShip pfnCheckReverseShip = CYapfShip2::CheckShipReverse; // default: ExitDir
|
||||||
|
|
||||||
/* check if non-default YAPF type needed */
|
/* check if non-default YAPF type needed */
|
||||||
@ -367,7 +372,7 @@ bool YapfShipCheckReverse(const Ship *v)
|
|||||||
pfnCheckReverseShip = &CYapfShip1::CheckShipReverse; // Trackdir
|
pfnCheckReverseShip = &CYapfShip1::CheckShipReverse; // Trackdir
|
||||||
}
|
}
|
||||||
|
|
||||||
bool reverse = pfnCheckReverseShip(v, tile, td, td_rev);
|
bool reverse = pfnCheckReverseShip(v, tile, td, td_rev, trackdir);
|
||||||
|
|
||||||
return reverse;
|
return reverse;
|
||||||
}
|
}
|
||||||
|
@ -335,13 +335,13 @@ static Vehicle *EnsureNoMovingShipProc(Vehicle *v, void *data)
|
|||||||
return v->type == VEH_SHIP && (v->vehstatus & (VS_HIDDEN | VS_STOPPED)) == 0 ? v : nullptr;
|
return v->type == VEH_SHIP && (v->vehstatus & (VS_HIDDEN | VS_STOPPED)) == 0 ? v : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CheckReverseShip(const Ship *v)
|
static bool CheckReverseShip(const Ship *v, Trackdir *trackdir = nullptr)
|
||||||
{
|
{
|
||||||
/* Ask pathfinder for best direction */
|
/* Ask pathfinder for best direction */
|
||||||
bool reverse = false;
|
bool reverse = false;
|
||||||
switch (_settings_game.pf.pathfinder_for_ships) {
|
switch (_settings_game.pf.pathfinder_for_ships) {
|
||||||
case VPF_NPF: reverse = NPFShipCheckReverse(v); break;
|
case VPF_NPF: reverse = NPFShipCheckReverse(v, trackdir); break;
|
||||||
case VPF_YAPF: reverse = YapfShipCheckReverse(v); break;
|
case VPF_YAPF: reverse = YapfShipCheckReverse(v, trackdir); break;
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
}
|
}
|
||||||
return reverse;
|
return reverse;
|
||||||
@ -725,7 +725,19 @@ static void ShipController(Ship *v)
|
|||||||
DiagDirection diagdir = DiagdirBetweenTiles(gp.old_tile, gp.new_tile);
|
DiagDirection diagdir = DiagdirBetweenTiles(gp.old_tile, gp.new_tile);
|
||||||
assert(diagdir != INVALID_DIAGDIR);
|
assert(diagdir != INVALID_DIAGDIR);
|
||||||
tracks = GetAvailShipTracks(gp.new_tile, diagdir);
|
tracks = GetAvailShipTracks(gp.new_tile, diagdir);
|
||||||
if (tracks == TRACK_BIT_NONE) goto reverse_direction;
|
if (tracks == TRACK_BIT_NONE) {
|
||||||
|
Trackdir trackdir = INVALID_TRACKDIR;
|
||||||
|
CheckReverseShip(v, &trackdir);
|
||||||
|
if (trackdir == INVALID_TRACKDIR) goto reverse_direction;
|
||||||
|
static const Direction _trackdir_to_direction[] = {
|
||||||
|
DIR_NE, DIR_SE, DIR_E, DIR_E, DIR_S, DIR_S, INVALID_DIR, INVALID_DIR,
|
||||||
|
DIR_SW, DIR_NW, DIR_W, DIR_W, DIR_N, DIR_N, INVALID_DIR, INVALID_DIR,
|
||||||
|
};
|
||||||
|
v->direction = _trackdir_to_direction[trackdir];
|
||||||
|
assert(v->direction != INVALID_DIR);
|
||||||
|
v->state = TrackdirBitsToTrackBits(TrackdirToTrackdirBits(trackdir));
|
||||||
|
goto direction_changed;
|
||||||
|
}
|
||||||
|
|
||||||
/* Choose a direction, and continue if we find one */
|
/* Choose a direction, and continue if we find one */
|
||||||
track = ChooseShipTrack(v, gp.new_tile, diagdir, tracks);
|
track = ChooseShipTrack(v, gp.new_tile, diagdir, tracks);
|
||||||
@ -796,6 +808,7 @@ getout:
|
|||||||
|
|
||||||
reverse_direction:
|
reverse_direction:
|
||||||
v->direction = ReverseDir(v->direction);
|
v->direction = ReverseDir(v->direction);
|
||||||
|
direction_changed:
|
||||||
/* Remember our current location to avoid movement glitch */
|
/* Remember our current location to avoid movement glitch */
|
||||||
v->rotation_x_pos = v->x_pos;
|
v->rotation_x_pos = v->x_pos;
|
||||||
v->rotation_y_pos = v->y_pos;
|
v->rotation_y_pos = v->y_pos;
|
||||||
|
Loading…
Reference in New Issue
Block a user