1
0
Fork 0

Add: Add and adapt some functions for extended depots.

pull/8480/head
J0anJosep 2021-03-27 13:51:37 +01:00
parent 2ddb3bf2d7
commit 08f4ae4b3d
6 changed files with 139 additions and 3 deletions

View File

@ -112,19 +112,29 @@ void Depot::Disuse()
* Of all the depot parts a depot has, return the best destination for a vehicle. * Of all the depot parts a depot has, return the best destination for a vehicle.
* @param v The vehicle. * @param v The vehicle.
* @param dep The depot vehicle \a v is heading for. * @param dep The depot vehicle \a v is heading for.
* @return The closest part of depot to vehicle v. * @return The free and closest (if none is free, just closest) part of depot to vehicle v.
*/ */
TileIndex Depot::GetBestDepotTile(Vehicle *v) const TileIndex Depot::GetBestDepotTile(Vehicle *v) const
{ {
assert(this->veh_type == v->type); assert(this->veh_type == v->type);
TileIndex best_depot = INVALID_TILE; TileIndex best_depot = INVALID_TILE;
DepotReservation best_found_type = DEPOT_RESERVATION_END;
uint best_distance = UINT_MAX; uint best_distance = UINT_MAX;
for (const auto &tile : this->depot_tiles) { for (const auto &tile : this->depot_tiles) {
bool check_south = v->type == VEH_ROAD;
uint new_distance = DistanceManhattan(v->tile, tile); uint new_distance = DistanceManhattan(v->tile, tile);
if (new_distance < best_distance) { again:
DepotReservation depot_reservation = GetDepotReservation(tile, check_south);
if (((best_found_type == depot_reservation) && new_distance < best_distance) || (depot_reservation < best_found_type)) {
best_depot = tile; best_depot = tile;
best_distance = new_distance; best_distance = new_distance;
best_found_type = depot_reservation;
}
if (check_south) {
/* For road vehicles, check north direction as well. */
check_south = false;
goto again;
} }
} }

View File

@ -83,4 +83,96 @@ inline VehicleType GetDepotVehicleType(Tile t)
} }
} }
/** Return true if a tile belongs to an extended depot. */
static inline bool IsExtendedDepot(Tile tile) {
assert(IsValidTile(tile));
assert(IsDepotTile(tile));
if (IsAirportTile(tile)) return false;
return HasBit(tile.m5(), 5);
}
/** Return true if a tile belongs to an extended depot. */
static inline bool IsExtendedDepotTile(TileIndex tile) {
if (!IsValidTile(tile)) return false;
if (!IsDepotTile(tile)) return false;
return IsExtendedDepot(tile);
}
/**
* Has this depot some vehicle servicing or stopped inside?
* @param tile tile of the depot.
* @param south_dir In case of road transport, return reservation facing south if true.
* @return The type of reservation on this tile (empty, servicing or occupied).
* @pre is a depot tile
*/
static inline DepotReservation GetDepotReservation(Tile t, bool south_dir = false)
{
assert(IsDepotTile(t));
if (!IsExtendedDepot(t)) return DEPOT_RESERVATION_EMPTY;
if (south_dir) {
assert(GetDepotVehicleType(t) == VEH_ROAD);
return (DepotReservation)GB(t.m6(), 4, 2);
}
return (DepotReservation)GB(t.m4(), 6, 2);
}
/**
* Is this a platform/depot tile full with stopped vehicles?
* @param tile tile of the depot.
* @param south_dir In case of road transport, check reservation facing south if true.
* @return the type of reservation of the depot.
* @pre is a depot tile
*/
static inline bool IsDepotFullWithStoppedVehicles(TileIndex t, bool south_dir = false)
{
assert(IsDepotTile(t));
if (!IsExtendedDepot(t)) return false;
return GetDepotReservation(t, south_dir) == DEPOT_RESERVATION_FULL_STOPPED_VEH;
}
/**
* Has this depot tile/platform some vehicle inside?
* @param tile tile of the depot.
* @param south_dir In case of road transport, check reservation facing south if true.
* @return true iff depot tile/platform has no vehicle.
* @pre IsExtendedDepotTile
*/
static inline bool IsExtendedDepotEmpty(TileIndex t, bool south_dir = false)
{
assert(IsExtendedDepotTile(t));
return GetDepotReservation(t, south_dir) == DEPOT_RESERVATION_EMPTY;
}
/**
* Mark whether this depot has a ship inside.
* @param tile of the depot.
* @param reservation type of reservation
* @param south_dir Whether to set south direction reservation.
* @pre tile is an extended ship depot.
*/
static inline void SetDepotReservation(Tile t, DepotReservation reservation, bool south_dir = false)
{
assert(IsDepotTile(t));
if (!IsExtendedDepot(t)) return;
switch (GetTileType(t)) {
default: NOT_REACHED();
case MP_RAILWAY:
break;
case MP_ROAD:
if (south_dir) {
SB(t.m6(), 4, 2, reservation);
return;
}
break;
case MP_WATER:
assert(GetDepotReservation(t) == GetDepotReservation(GetOtherShipDepotTile(t)));
SB(Tile(GetOtherShipDepotTile(t)).m4(), 6, 2, reservation);
break;
case MP_STATION: return;
}
SB(t.m4(), 6, 2, reservation);
}
#endif /* DEPOT_MAP_H */ #endif /* DEPOT_MAP_H */

View File

@ -18,4 +18,12 @@ static const DepotID NEW_DEPOT = INVALID_DEPOT - 1;
static const uint MAX_LENGTH_DEPOT_NAME_CHARS = 32; ///< The maximum length of a depot name in characters including '\0' static const uint MAX_LENGTH_DEPOT_NAME_CHARS = 32; ///< The maximum length of a depot name in characters including '\0'
/** Type of reservation of extended ship depots. */
enum DepotReservation {
DEPOT_RESERVATION_EMPTY = 0, ///< No vehicle servicing/stopped on depot tile/platform.
DEPOT_RESERVATION_IN_USE = 1, ///< At least a vehicle is in the depot, but the depot tile is not full of stopped vehicles.
DEPOT_RESERVATION_FULL_STOPPED_VEH = 2, ///< The depot tile/platform is full with stopped vehicles.
DEPOT_RESERVATION_END
};
#endif /* DEPOT_TYPE_H */ #endif /* DEPOT_TYPE_H */

View File

@ -910,6 +910,7 @@ STR_NEWS_TRAIN_IS_STUCK :{WHITE}{VEHICLE
STR_NEWS_VEHICLE_IS_LOST :{WHITE}{VEHICLE} is lost STR_NEWS_VEHICLE_IS_LOST :{WHITE}{VEHICLE} is lost
STR_NEWS_VEHICLE_UNPROFITABLE_YEAR :{WHITE}{VEHICLE}'s profit last year was {CURRENCY_LONG} STR_NEWS_VEHICLE_UNPROFITABLE_YEAR :{WHITE}{VEHICLE}'s profit last year was {CURRENCY_LONG}
STR_NEWS_VEHICLE_UNPROFITABLE_PERIOD :{WHITE}{VEHICLE}'s profit last period was {CURRENCY_LONG} STR_NEWS_VEHICLE_UNPROFITABLE_PERIOD :{WHITE}{VEHICLE}'s profit last period was {CURRENCY_LONG}
STR_NEWS_VEHICLE_CAN_T_FIND_FREE_DEPOT :{WHITE}{VEHICLE} can't find a free depot
STR_NEWS_AIRCRAFT_DEST_TOO_FAR :{WHITE}{VEHICLE} can't get to the next destination because it is out of range STR_NEWS_AIRCRAFT_DEST_TOO_FAR :{WHITE}{VEHICLE} can't get to the next destination because it is out of range
STR_NEWS_ORDER_REFIT_FAILED :{WHITE}{VEHICLE} stopped because an ordered refit failed STR_NEWS_ORDER_REFIT_FAILED :{WHITE}{VEHICLE} stopped because an ordered refit failed

View File

@ -66,13 +66,22 @@ static inline TileIndex CalcClosestDepotTile(DepotID depot_id, TileIndex tile)
} }
TileIndex best_tile = INVALID_TILE; TileIndex best_tile = INVALID_TILE;
DepotReservation best_found_type = dep->veh_type == VEH_SHIP ? DEPOT_RESERVATION_END : DEPOT_RESERVATION_EMPTY;
uint best_distance = UINT_MAX; uint best_distance = UINT_MAX;
for (auto const &depot_tile : dep->depot_tiles) { for (auto const &depot_tile : dep->depot_tiles) {
uint new_distance = DistanceManhattan(depot_tile, tile); uint new_distance = DistanceManhattan(depot_tile, tile);
if (new_distance < best_distance) { bool check_south_direction = dep->veh_type == VEH_ROAD;
again:
DepotReservation depot_reservation = GetDepotReservation(depot_tile, check_south_direction);
if (((best_found_type == depot_reservation) && new_distance < best_distance) || (depot_reservation < best_found_type)) {
best_tile = depot_tile; best_tile = depot_tile;
best_distance = new_distance; best_distance = new_distance;
best_found_type = depot_reservation;
}
if (check_south_direction) {
check_south_direction = false;
goto again;
} }
} }

View File

@ -790,6 +790,22 @@ void Vehicle::ShiftDates(TimerGameEconomy::Date interval)
*/ */
void Vehicle::HandlePathfindingResult(bool path_found) void Vehicle::HandlePathfindingResult(bool path_found)
{ {
if (this->dest_tile != INVALID_TILE && IsDepotTypeTile(this->dest_tile, (TransportType)this->type) && IsDepotFullWithStoppedVehicles(this->dest_tile)) {
/* Vehicle cannot find a free depot. */
/* Were we already lost? */
if (HasBit(this->vehicle_flags, VF_PATHFINDER_LOST)) return;
/* It is first time the problem occurred, set the "lost" flag. */
SetBit(this->vehicle_flags, VF_PATHFINDER_LOST);
/* Notify user about the event. */
AI::NewEvent(this->owner, new ScriptEventVehicleLost(this->index));
if (_settings_client.gui.lost_vehicle_warn && this->owner == _local_company) {
SetDParam(0, this->index);
AddVehicleAdviceNewsItem(STR_NEWS_VEHICLE_CAN_T_FIND_FREE_DEPOT, this->index);
}
return;
}
if (path_found) { if (path_found) {
/* Route found, is the vehicle marked with "lost" flag? */ /* Route found, is the vehicle marked with "lost" flag? */
if (!HasBit(this->vehicle_flags, VF_PATHFINDER_LOST)) return; if (!HasBit(this->vehicle_flags, VF_PATHFINDER_LOST)) return;