ai_rail.cpp

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

Generated on Sat Dec 26 20:05:59 2009 for OpenTTD by  doxygen 1.5.6