/** * Checks whether the 'next' tile is still part of the road same drive through * stop 'rs' in the same direction for the same vehicle. * @param rs the road stop tile to check against * @param next the 'next' tile to check * @return true if the 'next' tile is part of the road stop at 'next'. */ /* static */ bool RoadStop::IsDriveThroughRoadStopContinuation(TileIndex rs, TileIndex next) { return IsTileType(next, MP_STATION) && GetStationIndex(next) == GetStationIndex(rs) && GetStationType(next) == GetStationType(rs) && GetRoadStopDir(next) == GetRoadStopDir(rs) && IsDriveThroughStopTile(next); }
/* Determine the cost of this node, for road tracks */ static int32 NPFRoadPathCost(AyStar *as, AyStarNode *current, OpenListNode *parent) { TileIndex tile = current->tile; int32 cost = 0; /* Determine base length */ switch (GetTileType(tile)) { case MP_TUNNELBRIDGE: cost = IsTunnel(tile) ? NPFTunnelCost(current) : NPFBridgeCost(current); break; case MP_ROAD: cost = NPF_TILE_LENGTH; /* Increase the cost for level crossings */ if (IsLevelCrossing(tile)) cost += _settings_game.pf.npf.npf_crossing_penalty; break; case MP_STATION: { cost = NPF_TILE_LENGTH; const RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile)); if (IsDriveThroughStopTile(tile)) { /* Increase the cost for drive-through road stops */ cost += _settings_game.pf.npf.npf_road_drive_through_penalty; DiagDirection dir = TrackdirToExitdir(current->direction); if (!RoadStop::IsDriveThroughRoadStopContinuation(tile, tile - TileOffsByDiagDir(dir))) { /* When we're the first road stop in a 'queue' of them we increase * cost based on the fill percentage of the whole queue. */ const RoadStop::Entry *entry = rs->GetEntry(dir); cost += entry->GetOccupied() * _settings_game.pf.npf.npf_road_dt_occupied_penalty / entry->GetLength(); } } else { /* Increase cost for filled road stops */ cost += _settings_game.pf.npf.npf_road_bay_occupied_penalty * (!rs->IsFreeBay(0) + !rs->IsFreeBay(1)) / 2; } break; } default: break; } /* Determine extra costs */ /* Check for slope */ cost += NPFSlopeCost(current); /* Check for turns. Road vehicles only really drive diagonal, turns are * represented by non-diagonal tracks */ if (!IsDiagonalTrackdir(current->direction)) { cost += _settings_game.pf.npf.npf_road_curve_penalty; } NPFMarkTile(tile); DEBUG(npf, 4, "Calculating G for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), cost); return cost; }
inline 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); }
/** * (Re)building of road stop caches after loading a savegame. */ void AfterLoadRoadStops() { /* First construct the drive through entries */ RoadStop *rs; FOR_ALL_ROADSTOPS(rs) { if (IsDriveThroughStopTile(rs->xy)) rs->MakeDriveThrough(); } /* And then rebuild the data in those entries */ FOR_ALL_ROADSTOPS(rs) { if (!HasBit(rs->status, RoadStop::RSSFB_BASE_ENTRY)) continue; rs->GetEntry(DIAGDIR_NE)->Rebuild(rs); rs->GetEntry(DIAGDIR_NW)->Rebuild(rs); } }
/* Will find a station identified using the NPFFindStationOrTileData */ static int32 NPFFindStationOrTile(AyStar *as, OpenListNode *current) { NPFFindStationOrTileData *fstd = (NPFFindStationOrTileData*)as->user_target; AyStarNode *node = ¤t->path.node; TileIndex tile = node->tile; if (fstd->station_index == INVALID_STATION && tile == fstd->dest_coords) return AYSTAR_FOUND_END_NODE; if (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == fstd->station_index) { if (fstd->v->type == VEH_TRAIN) return AYSTAR_FOUND_END_NODE; assert(fstd->v->type == VEH_ROAD); /* 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_DONE; }
/** return one tile cost */ inline int OneTileCost(TileIndex tile, Trackdir trackdir) { int cost = 0; /* set base cost */ if (IsDiagonalTrackdir(trackdir)) { cost += YAPF_TILE_LENGTH; switch (GetTileType(tile)) { case MP_ROAD: /* Increase the cost for level crossings */ if (IsLevelCrossing(tile)) { cost += Yapf().PfGetSettings().road_crossing_penalty; } break; case MP_STATION: { const RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile)); if (IsDriveThroughStopTile(tile)) { /* Increase the cost for drive-through road stops */ cost += Yapf().PfGetSettings().road_stop_penalty; DiagDirection dir = TrackdirToExitdir(trackdir); if (!RoadStop::IsDriveThroughRoadStopContinuation(tile, tile - TileOffsByDiagDir(dir))) { /* When we're the first road stop in a 'queue' of them we increase * cost based on the fill percentage of the whole queue. */ const RoadStop::Entry *entry = rs->GetEntry(dir); cost += entry->GetOccupied() * Yapf().PfGetSettings().road_stop_occupied_penalty / entry->GetLength(); } } else { /* Increase cost for filled road stops */ cost += Yapf().PfGetSettings().road_stop_bay_occupied_penalty * (!rs->IsFreeBay(0) + !rs->IsFreeBay(1)) / 2; } break; } default: break; } } else { /* non-diagonal trackdir */ cost = YAPF_TILE_CORNER_LENGTH + Yapf().PfGetSettings().road_curve_penalty; } return cost; }