ai_rail.cpp

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

Generated on Fri Dec 31 17:15:28 2010 for OpenTTD by  doxygen 1.6.1