ai_rail.cpp

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

Generated on Sat Jul 17 18:43:15 2010 for OpenTTD by  doxygen 1.6.1