00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "ai_rail.hpp"
00013 #include "ai_map.hpp"
00014 #include "ai_station.hpp"
00015 #include "ai_industrytype.hpp"
00016 #include "../../debug.h"
00017 #include "../../station_base.h"
00018 #include "../../company_func.h"
00019 #include "../../newgrf.h"
00020 #include "../../newgrf_generic.h"
00021 #include "../../newgrf_station.h"
00022
00023 bool AIRail::IsRailTile(TileIndex tile)
00024 {
00025 if (!::IsValidTile(tile)) return false;
00026
00027 return (::IsTileType(tile, MP_RAILWAY) && !::IsRailDepot(tile)) ||
00028 (::HasStationTileRail(tile) && !::IsStationTileBlocked(tile)) || ::IsLevelCrossingTile(tile);
00029 }
00030
00031 bool AIRail::IsLevelCrossingTile(TileIndex tile)
00032 {
00033 if (!::IsValidTile(tile)) return false;
00034
00035 return ::IsLevelCrossingTile(tile);
00036 }
00037
00038 bool AIRail::IsRailDepotTile(TileIndex tile)
00039 {
00040 if (!::IsValidTile(tile)) return false;
00041
00042 return ::IsRailDepotTile(tile);
00043 }
00044
00045 bool AIRail::IsRailStationTile(TileIndex tile)
00046 {
00047 if (!::IsValidTile(tile)) return false;
00048
00049 return ::IsRailStationTile(tile);
00050 }
00051
00052 bool AIRail::IsRailWaypointTile(TileIndex tile)
00053 {
00054 if (!::IsValidTile(tile)) return false;
00055
00056 return ::IsRailWaypointTile(tile);
00057 }
00058
00059 bool AIRail::IsRailTypeAvailable(RailType rail_type)
00060 {
00061 if ((::RailType)rail_type < RAILTYPE_BEGIN || (::RailType)rail_type >= RAILTYPE_END) return false;
00062
00063 return ::HasRailtypeAvail(_current_company, (::RailType)rail_type);
00064 }
00065
00066 AIRail::RailType AIRail::GetCurrentRailType()
00067 {
00068 return (RailType)AIObject::GetRailType();
00069 }
00070
00071 void AIRail::SetCurrentRailType(RailType rail_type)
00072 {
00073 if (!IsRailTypeAvailable(rail_type)) return;
00074
00075 AIObject::SetRailType((::RailType)rail_type);
00076 }
00077
00078 bool AIRail::TrainCanRunOnRail(AIRail::RailType engine_rail_type, AIRail::RailType track_rail_type)
00079 {
00080 if (!AIRail::IsRailTypeAvailable(engine_rail_type)) return false;
00081 if (!AIRail::IsRailTypeAvailable(track_rail_type)) return false;
00082
00083 return ::IsCompatibleRail((::RailType)engine_rail_type, (::RailType)track_rail_type);
00084 }
00085
00086 bool AIRail::TrainHasPowerOnRail(AIRail::RailType engine_rail_type, AIRail::RailType track_rail_type)
00087 {\
00088 if (!AIRail::IsRailTypeAvailable(engine_rail_type)) return false;
00089 if (!AIRail::IsRailTypeAvailable(track_rail_type)) return false;
00090
00091 return ::HasPowerOnRail((::RailType)engine_rail_type, (::RailType)track_rail_type);
00092 }
00093
00094 AIRail::RailType AIRail::GetRailType(TileIndex tile)
00095 {
00096 if (!AITile::HasTransportType(tile, AITile::TRANSPORT_RAIL)) return RAILTYPE_INVALID;
00097
00098 return (RailType)::GetRailType(tile);
00099 }
00100
00101 bool AIRail::ConvertRailType(TileIndex start_tile, TileIndex end_tile, AIRail::RailType convert_to)
00102 {
00103 EnforcePrecondition(false, ::IsValidTile(start_tile));
00104 EnforcePrecondition(false, ::IsValidTile(end_tile));
00105 EnforcePrecondition(false, IsRailTypeAvailable(convert_to));
00106
00107 return AIObject::DoCommand(start_tile, end_tile, convert_to, CMD_CONVERT_RAIL);
00108 }
00109
00110 TileIndex AIRail::GetRailDepotFrontTile(TileIndex depot)
00111 {
00112 if (!IsRailDepotTile(depot)) return INVALID_TILE;
00113
00114 return depot + ::TileOffsByDiagDir(::GetRailDepotDirection(depot));
00115 }
00116
00117 AIRail::RailTrack AIRail::GetRailStationDirection(TileIndex tile)
00118 {
00119 if (!IsRailStationTile(tile)) return RAILTRACK_INVALID;
00120
00121 return (RailTrack)::GetRailStationTrackBits(tile);
00122 }
00123
00124 bool AIRail::BuildRailDepot(TileIndex tile, TileIndex front)
00125 {
00126 EnforcePrecondition(false, tile != front);
00127 EnforcePrecondition(false, ::IsValidTile(tile));
00128 EnforcePrecondition(false, ::IsValidTile(front));
00129 EnforcePrecondition(false, ::TileX(tile) == ::TileX(front) || ::TileY(tile) == ::TileY(front));
00130 EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType()));
00131
00132 uint entrance_dir = (::TileX(tile) == ::TileX(front)) ? (::TileY(tile) < ::TileY(front) ? 1 : 3) : (::TileX(tile) < ::TileX(front) ? 2 : 0);
00133
00134 return AIObject::DoCommand(tile, AIObject::GetRailType(), entrance_dir, CMD_BUILD_TRAIN_DEPOT);
00135 }
00136
00137 bool AIRail::BuildRailStation(TileIndex tile, RailTrack direction, uint num_platforms, uint platform_length, StationID station_id)
00138 {
00139 EnforcePrecondition(false, ::IsValidTile(tile));
00140 EnforcePrecondition(false, direction == RAILTRACK_NW_SE || direction == RAILTRACK_NE_SW);
00141 EnforcePrecondition(false, num_platforms > 0 && num_platforms <= 0xFF);
00142 EnforcePrecondition(false, platform_length > 0 && platform_length <= 0xFF);
00143 EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType()));
00144 EnforcePrecondition(false, station_id == AIStation::STATION_NEW || station_id == AIStation::STATION_JOIN_ADJACENT || AIStation::IsValidStation(station_id));
00145
00146 uint32 p1 = GetCurrentRailType() | (platform_length << 16) | (num_platforms << 8);
00147 if (direction == RAILTRACK_NW_SE) p1 |= (1 << 4);
00148 if (station_id != AIStation::STATION_JOIN_ADJACENT) p1 |= (1 << 24);
00149 return AIObject::DoCommand(tile, p1, (AIStation::IsValidStation(station_id) ? station_id : INVALID_STATION) << 16, CMD_BUILD_RAIL_STATION);
00150 }
00151
00152 bool AIRail::BuildNewGRFRailStation(TileIndex tile, RailTrack direction, uint num_platforms, uint platform_length, StationID station_id, CargoID cargo_id, IndustryType source_industry, IndustryType goal_industry, int distance, bool source_station)
00153 {
00154 EnforcePrecondition(false, ::IsValidTile(tile));
00155 EnforcePrecondition(false, direction == RAILTRACK_NW_SE || direction == RAILTRACK_NE_SW);
00156 EnforcePrecondition(false, num_platforms > 0 && num_platforms <= 0xFF);
00157 EnforcePrecondition(false, platform_length > 0 && platform_length <= 0xFF);
00158 EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType()));
00159 EnforcePrecondition(false, station_id == AIStation::STATION_NEW || station_id == AIStation::STATION_JOIN_ADJACENT || AIStation::IsValidStation(station_id));
00160 EnforcePrecondition(false, source_industry == AIIndustryType::INDUSTRYTYPE_UNKNOWN || source_industry == AIIndustryType::INDUSTRYTYPE_TOWN || AIIndustryType::IsValidIndustryType(source_industry));
00161 EnforcePrecondition(false, goal_industry == AIIndustryType::INDUSTRYTYPE_UNKNOWN || goal_industry == AIIndustryType::INDUSTRYTYPE_TOWN || AIIndustryType::IsValidIndustryType(goal_industry));
00162
00163 uint32 p1 = GetCurrentRailType() | (platform_length << 16) | (num_platforms << 8);
00164 if (direction == RAILTRACK_NW_SE) p1 |= 1 << 4;
00165 if (station_id != AIStation::STATION_JOIN_ADJACENT) p1 |= (1 << 24);
00166
00167 const GRFFile *file;
00168 uint16 res = GetAiPurchaseCallbackResult(GSF_STATIONS, cargo_id, 0, source_industry, goal_industry, min(255, distance / 2), AICE_STATION_GET_STATION_ID, source_station ? 0 : 1, min(15, num_platforms) << 4 | min(15, platform_length), &file);
00169 uint32 p2 = (AIStation::IsValidStation(station_id) ? station_id : INVALID_STATION) << 16;
00170 if (res != CALLBACK_FAILED) {
00171 int index = 0;
00172 const StationSpec *spec = StationClass::GetByGrf(file->grfid, res, &index);
00173 if (spec == NULL) {
00174 DEBUG(grf, 1, "%s returned an invalid station ID for 'AI construction/purchase selection (18)' callback", file->filename);
00175 } else {
00176 p2 |= spec->cls_id | index << 8;
00177 }
00178
00179 }
00180 return AIObject::DoCommand(tile, p1, p2, CMD_BUILD_RAIL_STATION);
00181 }
00182
00183 bool AIRail::BuildRailWaypoint(TileIndex tile)
00184 {
00185 EnforcePrecondition(false, ::IsValidTile(tile));
00186 EnforcePrecondition(false, IsRailTile(tile));
00187 EnforcePrecondition(false, GetRailTracks(tile) == RAILTRACK_NE_SW || GetRailTracks(tile) == RAILTRACK_NW_SE);
00188 EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType()));
00189
00190 return AIObject::DoCommand(tile, GetCurrentRailType() | (GetRailTracks(tile) == RAILTRACK_NE_SW ? AXIS_X : AXIS_Y) << 4 | 1 << 8 | 1 << 16, STAT_CLASS_WAYP | INVALID_STATION << 16, CMD_BUILD_RAIL_WAYPOINT);
00191 }
00192
00193 bool AIRail::RemoveRailWaypointTileRectangle(TileIndex tile, TileIndex tile2, bool keep_rail)
00194 {
00195 EnforcePrecondition(false, ::IsValidTile(tile));
00196 EnforcePrecondition(false, ::IsValidTile(tile2));
00197
00198 return AIObject::DoCommand(tile, tile2, keep_rail ? 1 : 0, CMD_REMOVE_FROM_RAIL_WAYPOINT);
00199 }
00200
00201 bool AIRail::RemoveRailStationTileRectangle(TileIndex tile, TileIndex tile2, bool keep_rail)
00202 {
00203 EnforcePrecondition(false, ::IsValidTile(tile));
00204 EnforcePrecondition(false, ::IsValidTile(tile2));
00205
00206 return AIObject::DoCommand(tile, tile2, keep_rail ? 1 : 0, CMD_REMOVE_FROM_RAIL_STATION);
00207 }
00208
00209 uint AIRail::GetRailTracks(TileIndex tile)
00210 {
00211 if (!IsRailTile(tile)) return RAILTRACK_INVALID;
00212
00213 if (IsRailStationTile(tile) || IsRailWaypointTile(tile)) return ::TrackToTrackBits(::GetRailStationTrack(tile));
00214 if (IsLevelCrossingTile(tile)) return ::GetCrossingRailBits(tile);
00215 if (IsRailDepotTile(tile)) return ::TRACK_BIT_NONE;
00216 return ::GetTrackBits(tile);
00217 }
00218
00219 bool AIRail::BuildRailTrack(TileIndex tile, RailTrack rail_track)
00220 {
00221 EnforcePrecondition(false, ::IsValidTile(tile));
00222 EnforcePrecondition(false, rail_track != 0);
00223 EnforcePrecondition(false, (rail_track & ~::TRACK_BIT_ALL) == 0);
00224 EnforcePrecondition(false, KillFirstBit((uint)rail_track) == 0);
00225 EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType()));
00226
00227 return AIObject::DoCommand(tile, tile, GetCurrentRailType() | (FindFirstTrack((::TrackBits)rail_track) << 4), CMD_BUILD_RAILROAD_TRACK);
00228 }
00229
00230 bool AIRail::RemoveRailTrack(TileIndex tile, RailTrack rail_track)
00231 {
00232 EnforcePrecondition(false, ::IsValidTile(tile));
00233 EnforcePrecondition(false, ::IsPlainRailTile(tile) || ::IsLevelCrossingTile(tile));
00234 EnforcePrecondition(false, GetRailTracks(tile) & rail_track);
00235 EnforcePrecondition(false, KillFirstBit((uint)rail_track) == 0);
00236
00237 return AIObject::DoCommand(tile, tile, GetCurrentRailType() | (FindFirstTrack((::TrackBits)rail_track) << 4), CMD_REMOVE_RAILROAD_TRACK);
00238 }
00239
00240 bool AIRail::AreTilesConnected(TileIndex from, TileIndex tile, TileIndex to)
00241 {
00242 if (!IsRailTile(tile)) return false;
00243 if (from == to || AIMap::DistanceManhattan(from, tile) != 1 || AIMap::DistanceManhattan(tile, to) != 1) return false;
00244
00245 if (to < from) ::Swap(from, to);
00246
00247 if (tile - from == 1) {
00248 if (to - tile == 1) return (GetRailTracks(tile) & RAILTRACK_NE_SW) != 0;
00249 if (to - tile == ::MapSizeX()) return (GetRailTracks(tile) & RAILTRACK_NE_SE) != 0;
00250 } else if (tile - from == ::MapSizeX()) {
00251 if (tile - to == 1) return (GetRailTracks(tile) & RAILTRACK_NW_NE) != 0;
00252 if (to - tile == 1) return (GetRailTracks(tile) & RAILTRACK_NW_SW) != 0;
00253 if (to - tile == ::MapSizeX()) return (GetRailTracks(tile) & RAILTRACK_NW_SE) != 0;
00254 } else {
00255 return (GetRailTracks(tile) & RAILTRACK_SW_SE) != 0;
00256 }
00257
00258 NOT_REACHED();
00259 }
00260
00265 static uint32 SimulateDrag(TileIndex from, TileIndex tile, TileIndex *to)
00266 {
00267 int diag_offset = abs(abs((int)::TileX(*to) - (int)::TileX(tile)) - abs((int)::TileY(*to) - (int)::TileY(tile)));
00268 uint32 p2 = AIRail::GetCurrentRailType();
00269 if (::TileY(from) == ::TileY(*to)) {
00270 p2 |= (TRACK_X << 4);
00271 *to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1);
00272 } else if (::TileX(from) == ::TileX(*to)) {
00273 p2 |= (TRACK_Y << 4);
00274 *to -= ::MapSizeX() * Clamp((int)::TileY(*to) - (int)::TileY(tile), -1, 1);
00275 } else if (::TileY(from) < ::TileY(tile)) {
00276 if (::TileX(*to) < ::TileX(tile)) {
00277 p2 |= (TRACK_UPPER << 4);
00278 } else {
00279 p2 |= (TRACK_LEFT << 4);
00280 }
00281 if (diag_offset) {
00282 *to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1);
00283 } else {
00284 *to -= ::MapSizeX() * Clamp((int)::TileY(*to) - (int)::TileY(tile), -1, 1);
00285 }
00286 } else if (::TileY(from) > ::TileY(tile)) {
00287 if (::TileX(*to) < ::TileX(tile)) {
00288 p2 |= (TRACK_RIGHT << 4);
00289 } else {
00290 p2 |= (TRACK_LOWER << 4);
00291 }
00292 if (diag_offset) {
00293 *to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1);
00294 } else {
00295 *to -= ::MapSizeX() * Clamp((int)::TileY(*to) - (int)::TileY(tile), -1, 1);
00296 }
00297 } else if (::TileX(from) < ::TileX(tile)) {
00298 if (::TileY(*to) < ::TileY(tile)) {
00299 p2 |= (TRACK_UPPER << 4);
00300 } else {
00301 p2 |= (TRACK_RIGHT << 4);
00302 }
00303 if (!diag_offset) {
00304 *to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1);
00305 } else {
00306 *to -= ::MapSizeX() * Clamp((int)::TileY(*to) - (int)::TileY(tile), -1, 1);
00307 }
00308 } else if (::TileX(from) > ::TileX(tile)) {
00309 if (::TileY(*to) < ::TileY(tile)) {
00310 p2 |= (TRACK_LEFT << 4);
00311 } else {
00312 p2 |= (TRACK_LOWER << 4);
00313 }
00314 if (!diag_offset) {
00315 *to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1);
00316 } else {
00317 *to -= ::MapSizeX() * Clamp((int)::TileY(*to) - (int)::TileY(tile), -1, 1);
00318 }
00319 }
00320 return p2;
00321 }
00322
00323 bool AIRail::BuildRail(TileIndex from, TileIndex tile, TileIndex to)
00324 {
00325 EnforcePrecondition(false, ::IsValidTile(from));
00326 EnforcePrecondition(false, ::IsValidTile(tile));
00327 EnforcePrecondition(false, ::IsValidTile(to));
00328 EnforcePrecondition(false, ::DistanceManhattan(from, tile) == 1);
00329 EnforcePrecondition(false, ::DistanceManhattan(tile, to) >= 1);
00330 EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType()));
00331 int diag_offset = abs(abs((int)::TileX(to) - (int)::TileX(tile)) - abs((int)::TileY(to) - (int)::TileY(tile)));
00332 EnforcePrecondition(false, diag_offset <= 1 ||
00333 (::TileX(from) == ::TileX(tile) && ::TileX(tile) == ::TileX(to)) ||
00334 (::TileY(from) == ::TileY(tile) && ::TileY(tile) == ::TileY(to)));
00335
00336 uint32 p2 = SimulateDrag(from, tile, &to) | 1 << 8;
00337 return AIObject::DoCommand(tile, to, p2, CMD_BUILD_RAILROAD_TRACK);
00338 }
00339
00340 bool AIRail::RemoveRail(TileIndex from, TileIndex tile, TileIndex to)
00341 {
00342 EnforcePrecondition(false, ::IsValidTile(from));
00343 EnforcePrecondition(false, ::IsValidTile(tile));
00344 EnforcePrecondition(false, ::IsValidTile(to));
00345 EnforcePrecondition(false, ::DistanceManhattan(from, tile) == 1);
00346 EnforcePrecondition(false, ::DistanceManhattan(tile, to) >= 1);
00347 int diag_offset = abs(abs((int)::TileX(to) - (int)::TileX(tile)) - abs((int)::TileY(to) - (int)::TileY(tile)));
00348 EnforcePrecondition(false, diag_offset <= 1 ||
00349 (::TileX(from) == ::TileX(tile) && ::TileX(tile) == ::TileX(to)) ||
00350 (::TileY(from) == ::TileY(tile) && ::TileY(tile) == ::TileY(to)));
00351
00352 if (!IsRailTypeAvailable(GetCurrentRailType())) SetCurrentRailType(GetRailType(tile));
00353 uint32 p2 = SimulateDrag(from, tile, &to);
00354 return AIObject::DoCommand(tile, to, p2, CMD_REMOVE_RAILROAD_TRACK);
00355 }
00356
00361 struct AIRailSignalData {
00362 Track track;
00363 Trackdir trackdir;
00364 uint signal_cycles;
00365 };
00366
00367 static const int NUM_TRACK_DIRECTIONS = 3;
00368
00375 static const AIRailSignalData _possible_trackdirs[5][NUM_TRACK_DIRECTIONS] = {
00376 {{TRACK_UPPER, TRACKDIR_UPPER_E, 0}, {TRACK_Y, TRACKDIR_Y_SE, 0}, {TRACK_LEFT, TRACKDIR_LEFT_S, 1}},
00377 {{TRACK_RIGHT, TRACKDIR_RIGHT_S, 1}, {TRACK_X, TRACKDIR_X_SW, 1}, {TRACK_UPPER, TRACKDIR_UPPER_W, 1}},
00378 {{INVALID_TRACK, INVALID_TRACKDIR, 0}, {INVALID_TRACK, INVALID_TRACKDIR, 0}, {INVALID_TRACK, INVALID_TRACKDIR, 0}},
00379 {{TRACK_LOWER, TRACKDIR_LOWER_E, 0}, {TRACK_X, TRACKDIR_X_NE, 0}, {TRACK_LEFT, TRACKDIR_LEFT_N, 0}},
00380 {{TRACK_RIGHT, TRACKDIR_RIGHT_N, 0}, {TRACK_Y, TRACKDIR_Y_NW, 1}, {TRACK_LOWER, TRACKDIR_LOWER_W, 1}}
00381 };
00382
00383 AIRail::SignalType AIRail::GetSignalType(TileIndex tile, TileIndex front)
00384 {
00385 if (AIMap::DistanceManhattan(tile, front) != 1) return SIGNALTYPE_NONE;
00386 if (!::IsTileType(tile, MP_RAILWAY) || !::HasSignals(tile)) return SIGNALTYPE_NONE;
00387
00388 int data_index = 2 + (::TileX(front) - ::TileX(tile)) + 2 * (::TileY(front) - ::TileY(tile));
00389
00390 for (int i = 0; i < NUM_TRACK_DIRECTIONS; i++) {
00391 const Track &track = _possible_trackdirs[data_index][i].track;
00392 if (!(::TrackToTrackBits(track) & GetRailTracks(tile))) continue;
00393 if (!HasSignalOnTrack(tile, track)) continue;
00394 if (!HasSignalOnTrackdir(tile, _possible_trackdirs[data_index][i].trackdir)) continue;
00395 SignalType st = (SignalType)::GetSignalType(tile, track);
00396 if (HasSignalOnTrackdir(tile, ::ReverseTrackdir(_possible_trackdirs[data_index][i].trackdir))) st = (SignalType)(st | SIGNALTYPE_TWOWAY);
00397 return st;
00398 }
00399
00400 return SIGNALTYPE_NONE;
00401 }
00402
00406 static bool IsValidSignalType(int signal_type)
00407 {
00408 if (signal_type < AIRail::SIGNALTYPE_NORMAL || signal_type > AIRail::SIGNALTYPE_COMBO_TWOWAY) return false;
00409 if (signal_type > AIRail::SIGNALTYPE_PBS_ONEWAY && signal_type < AIRail::SIGNALTYPE_NORMAL_TWOWAY) return false;
00410 return true;
00411 }
00412
00413 bool AIRail::BuildSignal(TileIndex tile, TileIndex front, SignalType signal)
00414 {
00415 EnforcePrecondition(false, AIMap::DistanceManhattan(tile, front) == 1)
00416 EnforcePrecondition(false, ::IsPlainRailTile(tile));
00417 EnforcePrecondition(false, ::IsValidSignalType(signal));
00418
00419 Track track = INVALID_TRACK;
00420 uint signal_cycles;
00421
00422 int data_index = 2 + (::TileX(front) - ::TileX(tile)) + 2 * (::TileY(front) - ::TileY(tile));
00423 for (int i = 0; i < NUM_TRACK_DIRECTIONS; i++) {
00424 const Track &t = _possible_trackdirs[data_index][i].track;
00425 if (!(::TrackToTrackBits(t) & GetRailTracks(tile))) continue;
00426 track = t;
00427 signal_cycles = _possible_trackdirs[data_index][i].signal_cycles;
00428 break;
00429 }
00430 EnforcePrecondition(false, track != INVALID_TRACK);
00431
00432 uint p1 = track;
00433 if (signal < SIGNALTYPE_TWOWAY) {
00434 if (signal != SIGNALTYPE_PBS && signal != SIGNALTYPE_PBS_ONEWAY) signal_cycles++;
00435 p1 |= (signal_cycles << 15);
00436 }
00437 p1 |= ((signal >= SIGNALTYPE_TWOWAY ? signal ^ SIGNALTYPE_TWOWAY : signal) << 5);
00438
00439 return AIObject::DoCommand(tile, p1, 0, CMD_BUILD_SIGNALS);
00440 }
00441
00442 bool AIRail::RemoveSignal(TileIndex tile, TileIndex front)
00443 {
00444 EnforcePrecondition(false, AIMap::DistanceManhattan(tile, front) == 1)
00445 EnforcePrecondition(false, GetSignalType(tile, front) != SIGNALTYPE_NONE);
00446
00447 Track track = INVALID_TRACK;
00448 int data_index = 2 + (::TileX(front) - ::TileX(tile)) + 2 * (::TileY(front) - ::TileY(tile));
00449 for (int i = 0; i < NUM_TRACK_DIRECTIONS; i++) {
00450 const Track &t = _possible_trackdirs[data_index][i].track;
00451 if (!(::TrackToTrackBits(t) & GetRailTracks(tile))) continue;
00452 track = t;
00453 break;
00454 }
00455 EnforcePrecondition(false, track != INVALID_TRACK);
00456
00457 return AIObject::DoCommand(tile, track, 0, CMD_REMOVE_SIGNALS);
00458 }
00459
00460 Money AIRail::GetBuildCost(RailType railtype, BuildType build_type)
00461 {
00462 if (!AIRail::IsRailTypeAvailable(railtype)) return -1;
00463
00464 switch (build_type) {
00465 case BT_TRACK: return ::RailBuildCost((::RailType)railtype);
00466 case BT_SIGNAL: return ::GetPrice(PR_BUILD_SIGNALS, 1, NULL);
00467 case BT_DEPOT: return ::GetPrice(PR_BUILD_DEPOT_TRAIN, 1, NULL);
00468 case BT_STATION: return ::GetPrice(PR_BUILD_STATION_RAIL, 1, NULL) + ::GetPrice(PR_BUILD_STATION_RAIL_LENGTH, 1, NULL);
00469 case BT_WAYPOINT: return ::GetPrice(PR_BUILD_WAYPOINT_RAIL, 1, NULL);
00470 default: return -1;
00471 }
00472 }
00473
00474 int32 AIRail::GetMaxSpeed(RailType railtype)
00475 {
00476 if (!AIRail::IsRailTypeAvailable(railtype)) return -1;
00477
00478 return ::GetRailTypeInfo((::RailType)railtype)->max_speed;
00479 }