(svn r18382) -Codechange: make road vehicles behave more like trains 'around' stations and use pathfinder penalties to determine to which 'part' to go. Note that the pathfinder penalties for drive through stops are currently only looking at the occupation of the first in a row, but this is to change later on.

This commit is contained in:
rubidium 2009-12-02 17:56:02 +00:00
parent 992bc6c345
commit 2f640cb195
3 changed files with 52 additions and 27 deletions

View File

@ -21,6 +21,7 @@
#include "../../roadveh.h" #include "../../roadveh.h"
#include "../../ship.h" #include "../../ship.h"
#include "../../train.h" #include "../../train.h"
#include "../../roadstop_base.h"
#include "../pathfinder_func.h" #include "../pathfinder_func.h"
#include "../pathfinder_type.h" #include "../pathfinder_type.h"
#include "npf.h" #include "npf.h"
@ -104,8 +105,8 @@ static int32 NPFCalcStationOrTileHeuristic(AyStar *as, AyStarNode *current, Open
uint dist; uint dist;
/* for train-stations, we are going to aim for the closest station tile */ /* for train-stations, we are going to aim for the closest station tile */
if (as->user_data[NPF_TYPE] == TRANSPORT_RAIL && fstd->station_index != INVALID_STATION) if (as->user_data[NPF_TYPE] != TRANSPORT_WATER && fstd->station_index != INVALID_STATION)
to = CalcClosestStationTile(fstd->station_index, from, STATION_RAIL); to = CalcClosestStationTile(fstd->station_index, from, fstd->station_type);
if (as->user_data[NPF_TYPE] == TRANSPORT_ROAD) { if (as->user_data[NPF_TYPE] == TRANSPORT_ROAD) {
/* Since roads only have diagonal pieces, we use manhattan distance here */ /* Since roads only have diagonal pieces, we use manhattan distance here */
@ -279,11 +280,13 @@ static int32 NPFRoadPathCost(AyStar *as, AyStarNode *current, OpenListNode *pare
if (IsLevelCrossing(tile)) cost += _settings_game.pf.npf.npf_crossing_penalty; if (IsLevelCrossing(tile)) cost += _settings_game.pf.npf.npf_crossing_penalty;
break; break;
case MP_STATION: case MP_STATION: {
cost = NPF_TILE_LENGTH; cost = NPF_TILE_LENGTH;
/* Increase the cost for drive-through road stops */ /* Increase the cost for drive-through road stops */
if (IsDriveThroughStopTile(tile)) cost += _settings_game.pf.npf.npf_road_drive_through_penalty; if (IsDriveThroughStopTile(tile)) cost += _settings_game.pf.npf.npf_road_drive_through_penalty;
break; RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile));
cost += 8 * NPF_TILE_LENGTH * ((!rs->IsFreeBay(0)) + (!rs->IsFreeBay(1)));
} break;
default: default:
break; break;
@ -447,16 +450,14 @@ static int32 NPFFindStationOrTile(AyStar *as, OpenListNode *current)
AyStarNode *node = &current->path.node; AyStarNode *node = &current->path.node;
TileIndex tile = node->tile; TileIndex tile = node->tile;
/* If GetNeighbours said we could get here, we assume the station type if (fstd->station_index == INVALID_STATION && tile == fstd->dest_coords) return AYSTAR_FOUND_END_NODE;
* is correct */
if ( if (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == fstd->station_index) {
(fstd->station_index == INVALID_STATION && tile == fstd->dest_coords) || // We've found the tile, or if (fstd->station_type == STATION_RAIL) return AYSTAR_FOUND_END_NODE;
(IsTileType(tile, MP_STATION) && GetStationIndex(tile) == fstd->station_index) // the station /* Only if it is a valid station *and* we can stop there */
) { if (GetStationType(tile) == fstd->station_type && (fstd->not_articulated || IsDriveThroughStopTile(tile))) return AYSTAR_FOUND_END_NODE;
return AYSTAR_FOUND_END_NODE;
} else {
return AYSTAR_DONE;
} }
return AYSTAR_DONE;
} }
/** /**
@ -1086,10 +1087,13 @@ void NPFFillWithOrderData(NPFFindStationOrTileData *fstd, const Vehicle *v, bool
* dest_tile, not just any stop of that station. * dest_tile, not just any stop of that station.
* So only for train orders to stations we fill fstd->station_index, for all * So only for train orders to stations we fill fstd->station_index, for all
* others only dest_coords */ * others only dest_coords */
if (v->type == VEH_TRAIN && (v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_WAYPOINT))) { if (v->type != VEH_SHIP && (v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_WAYPOINT))) {
assert(v->type == VEH_TRAIN || v->type == VEH_ROAD);
fstd->station_index = v->current_order.GetDestination(); fstd->station_index = v->current_order.GetDestination();
/* Let's take the closest tile of the station as our target for trains */ fstd->station_type = (v->type == VEH_TRAIN) ? STATION_RAIL : (RoadVehicle::From(v)->IsBus() ? STATION_BUS : STATION_TRUCK);
fstd->dest_coords = CalcClosestStationTile(fstd->station_index, v->tile, STATION_RAIL); fstd->not_articulated = v->type == VEH_ROAD && !RoadVehicle::From(v)->HasArticulatedPart();
/* Let's take the closest tile of the station as our target for vehicles */
fstd->dest_coords = CalcClosestStationTile(fstd->station_index, v->tile, fstd->station_type);
} else { } else {
fstd->dest_coords = v->dest_tile; fstd->dest_coords = v->dest_tile;
fstd->station_index = INVALID_STATION; fstd->station_index = INVALID_STATION;

View File

@ -36,6 +36,8 @@ struct NPFFindStationOrTileData {
TileIndex dest_coords; ///< An indication of where the station is, for heuristic purposes, or the target tile TileIndex dest_coords; ///< An indication of where the station is, for heuristic purposes, or the target tile
StationID station_index; ///< station index we're heading for, or INVALID_STATION when we're heading for a tile StationID station_index; ///< station index we're heading for, or INVALID_STATION when we're heading for a tile
bool reserve_path; ///< Indicates whether the found path should be reserved bool reserve_path; ///< Indicates whether the found path should be reserved
StationType station_type; ///< The type of station we're heading for
bool not_articulated; ///< The (road) vehicle is not articulated
const Vehicle *v; ///< The vehicle we are pathfinding for const Vehicle *v; ///< The vehicle we are pathfinding for
}; };

View File

@ -66,11 +66,11 @@ protected:
} }
break; break;
case MP_STATION: case MP_STATION: {
if (IsDriveThroughStopTile(tile)) { if (IsDriveThroughStopTile(tile)) cost += Yapf().PfGetSettings().road_stop_penalty;
cost += Yapf().PfGetSettings().road_stop_penalty; RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile));
} cost += 8 * YAPF_TILE_LENGTH * ((!rs->IsFreeBay(0)) + (!rs->IsFreeBay(1)));
break; } break;
default: default:
break; break;
@ -268,13 +268,25 @@ public:
protected: protected:
TileIndex m_destTile; TileIndex m_destTile;
TrackdirBits m_destTrackdirs; TrackdirBits m_destTrackdirs;
StationID m_dest_station;
bool m_bus;
bool m_non_artic;
public: public:
void SetDestination(const RoadVehicle *v) void SetDestination(const RoadVehicle *v)
{ {
if (v->current_order.IsType(OT_GOTO_STATION)) {
m_dest_station = v->current_order.GetDestination();
m_bus = v->IsBus();
m_destTile = CalcClosestStationTile(m_dest_station, v->tile, m_bus ? STATION_BUS : STATION_TRUCK);
m_non_artic = !v->HasArticulatedPart();
m_destTrackdirs = INVALID_TRACKDIR_BIT;
} else {
m_dest_station = INVALID_STATION;
m_destTile = v->dest_tile; m_destTile = v->dest_tile;
m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_ROAD, v->compatible_roadtypes)); m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_ROAD, v->compatible_roadtypes));
} }
}
protected: protected:
/** to access inherited path finder */ /** to access inherited path finder */
@ -292,6 +304,13 @@ public:
FORCEINLINE bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir) FORCEINLINE bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir)
{ {
if (m_dest_station != INVALID_STATION) {
return IsTileType(tile, MP_STATION) &&
GetStationIndex(tile) == m_dest_station &&
(m_bus ? IsBusStop(tile) : IsTruckStop(tile)) &&
(m_non_artic || IsDriveThroughStopTile(tile));
}
return tile == m_destTile && ((m_destTrackdirs & TrackdirToTrackdirBits(trackdir)) != TRACKDIR_BIT_NONE); return tile == m_destTile && ((m_destTrackdirs & TrackdirToTrackdirBits(trackdir)) != TRACKDIR_BIT_NONE);
} }