# ai_road.cpp

Go to the documentation of this file.

    00001 /* $Id: ai_road.cpp 18811 2010-01-15 18:22:57Z 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_map.hpp"
    00013 #include "ai_station.hpp"
    00014 #include "ai_cargo.hpp"
    00015 #include "../../station_base.h"
    00016 #include "../../command_type.h"
    00017 #include "../../company_func.h"
    00018 #include "../../script/squirrel_helper_type.hpp"
    00019
    00020 /* static */ AIRoad::RoadVehicleType AIRoad::GetRoadVehicleTypeForCargo(CargoID cargo_type)
    00021 {
    00022   return AICargo::HasCargoClass(cargo_type, AICargo::CC_PASSENGERS) ? ROADVEHTYPE_BUS : ROADVEHTYPE_TRUCK;
    00023 }
    00024
    00025 /* static */ bool AIRoad::IsRoadTile(TileIndex tile)
    00026 {
    00027   if (!::IsValidTile(tile)) return false;
    00028
    00029   return (::IsTileType(tile, MP_ROAD) && ::GetRoadTileType(tile) != ROAD_TILE_DEPOT) ||
    00030       IsDriveThroughRoadStationTile(tile);
    00031 }
    00032
    00033 /* static */ bool AIRoad::IsRoadDepotTile(TileIndex tile)
    00034 {
    00035   if (!::IsValidTile(tile)) return false;
    00036
    00037   return ::IsTileType(tile, MP_ROAD) && ::GetRoadTileType(tile) == ROAD_TILE_DEPOT &&
    00038       (::RoadTypeToRoadTypes((::RoadType)GetCurrentRoadType()) & ::GetRoadTypes(tile)) != 0;
    00039 }
    00040
    00041 /* static */ bool AIRoad::IsRoadStationTile(TileIndex tile)
    00042 {
    00043   if (!::IsValidTile(tile)) return false;
    00044
    00045   return ::IsRoadStopTile(tile) && (::RoadTypeToRoadTypes((::RoadType)GetCurrentRoadType()) & ::GetRoadTypes(tile)) != 0;
    00046 }
    00047
    00048 /* static */ bool AIRoad::IsDriveThroughRoadStationTile(TileIndex tile)
    00049 {
    00050   if (!::IsValidTile(tile)) return false;
    00051
    00052   return ::IsDriveThroughStopTile(tile) && (::RoadTypeToRoadTypes((::RoadType)GetCurrentRoadType()) & ::GetRoadTypes(tile)) != 0;
    00053 }
    00054
    00055 /* static */ bool AIRoad::IsRoadTypeAvailable(RoadType road_type)
    00056 {
    00057   return ::HasRoadTypesAvail(_current_company, ::RoadTypeToRoadTypes((::RoadType)road_type));
    00058 }
    00059
    00060 /* static */ AIRoad::RoadType AIRoad::GetCurrentRoadType()
    00061 {
    00062   return (RoadType)AIObject::GetRoadType();
    00063 }
    00064
    00065 /* static */ void AIRoad::SetCurrentRoadType(RoadType road_type)
    00066 {
    00067   if (!IsRoadTypeAvailable(road_type)) return;
    00068
    00069   AIObject::SetRoadType((::RoadType)road_type);
    00070 }
    00071
    00072 /* static */ bool AIRoad::HasRoadType(TileIndex tile, RoadType road_type)
    00073 {
    00074   if (!AIMap::IsValidTile(tile)) return false;
    00075   if (!IsRoadTypeAvailable(road_type)) return false;
    00076   return ::GetAnyRoadBits(tile, (::RoadType)road_type, false) != ROAD_NONE;
    00077 }
    00078
    00079 /* static */ bool AIRoad::AreRoadTilesConnected(TileIndex t1, TileIndex t2)
    00080 {
    00081   if (!::IsValidTile(t1)) return false;
    00082   if (!::IsValidTile(t2)) return false;
    00083   if (!IsRoadTypeAvailable(GetCurrentRoadType())) return false;
    00084
    00085   /* Tiles not neighbouring */
    00086   if ((abs((int)::TileX(t1) - (int)::TileX(t2)) + abs((int)::TileY(t1) - (int)::TileY(t2))) != 1) return false;
    00087
    00088   RoadBits r1 = ::GetAnyRoadBits(t1, AIObject::GetRoadType());
    00089   RoadBits r2 = ::GetAnyRoadBits(t2, AIObject::GetRoadType());
    00090
    00091   uint dir_1 = (::TileX(t1) == ::TileX(t2)) ? (::TileY(t1) < ::TileY(t2) ? 2 : 0) : (::TileX(t1) < ::TileX(t2) ? 1 : 3);
    00092   uint dir_2 = 2 ^ dir_1;
    00093
    00094   DisallowedRoadDirections drd2 = IsNormalRoadTile(t2) ? GetDisallowedRoadDirections(t2) : DRD_NONE;
    00095
    00096   return HasBit(r1, dir_1) && HasBit(r2, dir_2) && drd2 != DRD_BOTH && drd2 != (dir_1 > dir_2 ? DRD_SOUTHBOUND : DRD_NORTHBOUND);
    00097 }
    00098
    00099 /* Helper functions for AIRoad::CanBuildConnectedRoadParts(). */
    00100
    00115 static bool CheckAutoExpandedRoadBits(const Array *existing, int32 start, int32 end)
    00116 {
    00117   return (start + end == 0) && (existing->size == 0 || existing->array[0] == start || existing->array[0] == end);
    00118 }
    00119
    00130 static int32 LookupWithoutBuildOnSlopes(::Slope slope, const Array *existing, int32 start, int32 end)
    00131 {
    00132   switch (slope) {
    00133     /* Flat slopes can always be build. */
    00134     case SLOPE_FLAT:
    00135       return 1;
    00136
    00137     /* Only 4 of the slopes can be build upon. Testing the existing bits is
    00138      * necessary because these bits can be something else when the settings
    00139      * in the game have been changed.
    00140      */
    00141     case SLOPE_NE: case SLOPE_SW:
    00142       return (CheckAutoExpandedRoadBits(existing, start, end) && (start == 1 || end == 1)) ? (existing->size == 0 ? 2 : 1) : 0;
    00143     case SLOPE_SE: case SLOPE_NW:
    00144       return (CheckAutoExpandedRoadBits(existing, start, end) && (start != 1 && end != 1)) ? (existing->size == 0 ? 2 : 1) : 0;
    00145
    00146     /* Any other tile cannot be built on. */
    00147     default:
    00148       return 0;
    00149   }
    00150 }
    00151
    00157 static int32 RotateNeighbour(int32 neighbour)
    00158 {
    00159   switch (neighbour) {
    00160     case -2: return -1;
    00161     case -1: return  2;
    00162     case  1: return -2;
    00163     case  2: return  1;
    00164     default: NOT_REACHED();
    00165   }
    00166 }
    00167
    00173 static RoadBits NeighbourToRoadBits(int32 neighbour)
    00174 {
    00175   switch (neighbour) {
    00176     case -2: return ROAD_NW;
    00177     case -1: return ROAD_NE;
    00178     case  2: return ROAD_SE;
    00179     case  1: return ROAD_SW;
    00180     default: NOT_REACHED();
    00181   }
    00182 }
    00183
    00194 static int32 LookupWithBuildOnSlopes(::Slope slope, Array *existing, int32 start, int32 end)
    00195 {
    00196   if (::IsSteepSlope(slope)) {
    00197     switch (slope) {
    00198       /* On steep slopes one can only build straight roads that will be
    00199        * automatically expanded to a straight road. Just check that the existing
    00200        * road parts are in the same direction. */
    00201       case SLOPE_STEEP_S:
    00202       case SLOPE_STEEP_W:
    00203       case SLOPE_STEEP_N:
    00204       case SLOPE_STEEP_E:
    00205         return CheckAutoExpandedRoadBits(existing, start, end) ? (existing->size == 0 ? 2 : 1) : 0;
    00206
    00207       /* All other slopes are invalid slopes!. */
    00208       default:
    00209         return -1;
    00210     }
    00211   }
    00212
    00213   /* The slope is not steep. Furthermore lots of slopes are generally the
    00214    * same but are only rotated. So to reduce the amount of lookup work that
    00215    * needs to be done the data is made uniform. This means rotating the
    00216    * existing parts and updating the slope. */
    00217   static const ::Slope base_slopes[] = {
    00218     SLOPE_FLAT, SLOPE_W,   SLOPE_W,   SLOPE_SW,
    00219     SLOPE_W,    SLOPE_EW,  SLOPE_SW,  SLOPE_WSE,
    00220     SLOPE_W,    SLOPE_SW,  SLOPE_EW,  SLOPE_WSE,
    00221     SLOPE_SW,   SLOPE_WSE, SLOPE_WSE};
    00222   static const byte base_rotates[] = {0, 0, 1, 0, 2, 0, 1, 0, 3, 3, 2, 3, 2, 2, 1};
    00223
    00224   if (slope >= (::Slope)lengthof(base_slopes)) {
    00225     /* This slope is an invalid slope, so ignore it. */
    00226     return -1;
    00227   }
    00228   byte base_rotate = base_rotates[slope];
    00229   slope = base_slopes[slope];
    00230
    00231   /* Some slopes don't need rotating, so return early when we know we do
    00232    * not need to rotate. */
    00233   switch (slope) {
    00234     case SLOPE_FLAT:
    00235       /* Flat slopes can always be build. */
    00236       return 1;
    00237
    00238     case SLOPE_EW:
    00239     case SLOPE_WSE:
    00240       /* A slope similar to a SLOPE_EW or SLOPE_WSE will always cause
    00241        * foundations which makes them accessible from all sides. */
    00242       return 1;
    00243
    00244     case SLOPE_W:
    00245     case SLOPE_SW:
    00246       /* A slope for which we need perform some calculations. */
    00247       break;
    00248
    00249     default:
    00250       /* An invalid slope. */
    00251       return -1;
    00252   }
    00253
    00254   /* Now perform the actual rotation. */
    00255   for (int j = 0; j < base_rotate; j++) {
    00256     for (int i = 0; i < existing->size; i++) {
    00257       existing->array[i] = RotateNeighbour(existing->array[i]);
    00258     }
    00259     start = RotateNeighbour(start);
    00260     end   = RotateNeighbour(end);
    00261   }
    00262
    00263   /* Create roadbits out of the data for easier handling. */
    00264   RoadBits start_roadbits    = NeighbourToRoadBits(start);
    00265   RoadBits new_roadbits      = start_roadbits | NeighbourToRoadBits(end);
    00266   RoadBits existing_roadbits = ROAD_NONE;
    00267   for (int i = 0; i < existing->size; i++) {
    00268     existing_roadbits |= NeighbourToRoadBits(existing->array[i]);
    00269   }
    00270
    00271   switch (slope) {
    00272     case SLOPE_W:
    00273       /* A slope similar to a SLOPE_W. */
    00274       switch (new_roadbits) {
    00275         case ROAD_N:
    00276         case ROAD_E:
    00277         case ROAD_S:
    00278           /* Cannot build anything with a turn from the low side. */
    00279           return 0;
    00280
    00281         case ROAD_X:
    00282         case ROAD_Y:
    00283           /* A 'sloped' tile is going to be build. */
    00284           if ((existing_roadbits | new_roadbits) != new_roadbits) {
    00285             /* There is already a foundation on the tile, or at least
    00286              * another slope that is not compatible with the new one. */
    00287             return 0;
    00288           }
    00289           /* If the start is in the low part, it is automatically
    00290            * building the second part too. */
    00291           return ((start_roadbits & ROAD_E) && !(existing_roadbits & ROAD_W)) ? 2 : 1;
    00292
    00293         default:
    00294           /* Roadbits causing a foundation are going to be build.
    00295            * When the existing roadbits are slopes (the lower bits
    00296            * are used), this cannot be done. */
    00297           if ((existing_roadbits | new_roadbits) == new_roadbits) return 1;
    00298           return (existing_roadbits & ROAD_E) ? 0 : 1;
    00299       }
    00300
    00301     case SLOPE_SW:
    00302       /* A slope similar to a SLOPE_SW. */
    00303       switch (new_roadbits) {
    00304         case ROAD_N:
    00305         case ROAD_E:
    00306           /* Cannot build anything with a turn from the low side. */
    00307           return 0;
    00308
    00309         case ROAD_X:
    00310           /* A 'sloped' tile is going to be build. */
    00311           if ((existing_roadbits | new_roadbits) != new_roadbits) {
    00312             /* There is already a foundation on the tile, or at least
    00313              * another slope that is not compatible with the new one. */
    00314             return 0;
    00315           }
    00316           /* If the start is in the low part, it is automatically
    00317            * building the second part too. */
    00318           return ((start_roadbits & ROAD_NE) && !(existing_roadbits & ROAD_SW)) ? 2 : 1;
    00319
    00320         default:
    00321           /* Roadbits causing a foundation are going to be build.
    00322            * When the existing roadbits are slopes (the lower bits
    00323            * are used), this cannot be done. */
    00324           return (existing_roadbits & ROAD_NE) ? 0 : 1;
    00325       }
    00326
    00327     default:
    00328       NOT_REACHED();
    00329   }
    00330 }
    00331
    00342 static bool NormaliseTileOffset(int32 *tile)
    00343 {
    00344     if (*tile == 1 || *tile == -1) return true;
    00345     if (*tile == ::TileDiffXY(0, -1)) {
    00346       *tile = -2;
    00347       return true;
    00348     }
    00349     if (*tile == ::TileDiffXY(0, 1)) {
    00350       *tile = 2;
    00351       return true;
    00352     }
    00353     return false;
    00354 }
    00355
    00356 /* static */ int32 AIRoad::CanBuildConnectedRoadParts(AITile::Slope slope_, Array *existing, TileIndex start_, TileIndex end_)
    00357 {
    00358 	::Slope slope = (::Slope)slope_;
    00359   int32 start = start_;
    00360   int32 end = end_;
    00361
    00362   /* The start tile and end tile cannot be the same tile either. */
    00363   if (start == end) return -1;
    00364
    00365   for (int i = 0; i < existing->size; i++) {
    00366     if (!NormaliseTileOffset(&existing->array[i])) return -1;
    00367   }
    00368
    00369   if (!NormaliseTileOffset(&start)) return -1;
    00370   if (!NormaliseTileOffset(&end)) return -1;
    00371
    00372   /* Without build on slopes the characteristics are vastly different, so use
    00373    * a different helper function (one that is much simpler). */
    00374   return _settings_game.construction.build_on_slopes ? LookupWithBuildOnSlopes(slope, existing, start, end) : LookupWithoutBuildOnSlopes(slope, existing, start, end);
    00375 }
    00376
    00377 /* static */ int32 AIRoad::CanBuildConnectedRoadPartsHere(TileIndex tile, TileIndex start, TileIndex end)
    00378 {
    00379   if (!::IsValidTile(tile) || !::IsValidTile(start) || !::IsValidTile(end)) return -1;
    00380   if (::DistanceManhattan(tile, start) != 1 || ::DistanceManhattan(tile, end) != 1) return -1;
    00381
    00382   /*                                       ROAD_NW              ROAD_SW             ROAD_SE             ROAD_NE */
    00383   static const TileIndex neighbours[] = {::TileDiffXY(0, -1), ::TileDiffXY(1, 0), ::TileDiffXY(0, 1), ::TileDiffXY(-1, 0)};
    00384   Array *existing = (Array*)alloca(sizeof(Array) + lengthof(neighbours) * sizeof(int32));
    00385   existing->size = 0;
    00386
    00387 	::RoadBits rb = ::ROAD_NONE;
    00388   if (::IsNormalRoadTile(tile)) {
    00389     rb = ::GetAllRoadBits(tile);
    00390   } else {
    00391     for (::RoadType rt = ::ROADTYPE_BEGIN; rt < ::ROADTYPE_END; rt++) rb |= ::GetAnyRoadBits(tile, rt);
    00392   }
    00393   for (uint i = 0; i < lengthof(neighbours); i++) {
    00394     if (HasBit(rb, i)) existing->array[existing->size++] = neighbours[i];
    00395   }
    00396
    00397   return AIRoad::CanBuildConnectedRoadParts(AITile::GetSlope(tile), existing, start - tile, end - tile);
    00398 }
    00399
    00408 static bool NeighbourHasReachableRoad(::RoadTypes rts, TileIndex start_tile, DiagDirection neighbour)
    00409 {
    00410   TileIndex neighbour_tile = ::TileAddByDiagDir(start_tile, neighbour);
    00411   if ((rts & ::GetRoadTypes(neighbour_tile)) == 0) return false;
    00412
    00413   switch (::GetTileType(neighbour_tile)) {
    00414     case MP_ROAD:
    00415       return (::GetRoadTileType(neighbour_tile) != ROAD_TILE_DEPOT);
    00416
    00417     case MP_STATION:
    00418       if (::IsDriveThroughStopTile(neighbour_tile)) {
    00419         return (::DiagDirToAxis(neighbour) == ::DiagDirToAxis(::GetRoadStopDir(neighbour_tile)));
    00420       }
    00421       return false;
    00422
    00423     default:
    00424       return false;
    00425   }
    00426 }
    00427
    00428 /* static */ int32 AIRoad::GetNeighbourRoadCount(TileIndex tile)
    00429 {
    00430   if (!::IsValidTile(tile)) return false;
    00431   if (!IsRoadTypeAvailable(GetCurrentRoadType())) return false;
    00432
    00433 	::RoadTypes rts = ::RoadTypeToRoadTypes((::RoadType)GetCurrentRoadType());
    00434   int32 neighbour = 0;
    00435
    00436   if (TileX(tile) > 0 && NeighbourHasReachableRoad(rts, tile, DIAGDIR_NE)) neighbour++;
    00437   if (NeighbourHasReachableRoad(rts, tile, DIAGDIR_SE)) neighbour++;
    00438   if (NeighbourHasReachableRoad(rts, tile, DIAGDIR_SW)) neighbour++;
    00439   if (TileY(tile) > 0 && NeighbourHasReachableRoad(rts, tile, DIAGDIR_NW)) neighbour++;
    00440
    00441   return neighbour;
    00442 }
    00443
    00444 /* static */ TileIndex AIRoad::GetRoadDepotFrontTile(TileIndex depot)
    00445 {
    00446   if (!IsRoadDepotTile(depot)) return INVALID_TILE;
    00447
    00448   return depot + ::TileOffsByDiagDir(::GetRoadDepotDirection(depot));
    00449 }
    00450
    00451 /* static */ TileIndex AIRoad::GetRoadStationFrontTile(TileIndex station)
    00452 {
    00453   if (!IsRoadStationTile(station)) return INVALID_TILE;
    00454
    00455   return station + ::TileOffsByDiagDir(::GetRoadStopDir(station));
    00456 }
    00457
    00458 /* static */ TileIndex AIRoad::GetDriveThroughBackTile(TileIndex station)
    00459 {
    00460   if (!IsDriveThroughRoadStationTile(station)) return INVALID_TILE;
    00461
    00462   return station + ::TileOffsByDiagDir(::ReverseDiagDir(::GetRoadStopDir(station)));
    00463 }
    00464
    00465 /* static */ bool AIRoad::_BuildRoadInternal(TileIndex start, TileIndex end, bool one_way, bool full)
    00466 {
    00467   EnforcePrecondition(false, start != end);
    00468   EnforcePrecondition(false, ::IsValidTile(start));
    00469   EnforcePrecondition(false, ::IsValidTile(end));
    00470   EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
    00471   EnforcePrecondition(false, !one_way || AIObject::GetRoadType() == ::ROADTYPE_ROAD);
    00472   EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
    00473
    00474   return AIObject::DoCommand(start, end, (::TileY(start) != ::TileY(end) ? 4 : 0) | (((start < end) == !full) ? 1 : 2) | (AIObject::GetRoadType() << 3) | ((one_way ? 1 : 0) << 5), CMD_BUILD_LONG_ROAD);
    00475 }
    00476
    00477 /* static */ bool AIRoad::BuildRoad(TileIndex start, TileIndex end)
    00478 {
    00479   return _BuildRoadInternal(start, end, false, false);
    00480 }
    00481
    00482 /* static */ bool AIRoad::BuildOneWayRoad(TileIndex start, TileIndex end)
    00483 {
    00484   return _BuildRoadInternal(start, end, true, false);
    00485 }
    00486
    00487 /* static */ bool AIRoad::BuildRoadFull(TileIndex start, TileIndex end)
    00488 {
    00489   return _BuildRoadInternal(start, end, false, true);
    00490 }
    00491
    00492 /* static */ bool AIRoad::BuildOneWayRoadFull(TileIndex start, TileIndex end)
    00493 {
    00494   return _BuildRoadInternal(start, end, true, true);
    00495 }
    00496
    00497 /* static */ bool AIRoad::BuildRoadDepot(TileIndex tile, TileIndex front)
    00498 {
    00499   EnforcePrecondition(false, tile != front);
    00500   EnforcePrecondition(false, ::IsValidTile(tile));
    00501   EnforcePrecondition(false, ::IsValidTile(front));
    00502   EnforcePrecondition(false, ::TileX(tile) == ::TileX(front) || ::TileY(tile) == ::TileY(front));
    00503   EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
    00504
    00505   uint entrance_dir = (::TileX(tile) == ::TileX(front)) ? (::TileY(tile) < ::TileY(front) ? 1 : 3) : (::TileX(tile) < ::TileX(front) ? 2 : 0);
    00506
    00507   return AIObject::DoCommand(tile, entrance_dir | (AIObject::GetRoadType() << 2), 0, CMD_BUILD_ROAD_DEPOT);
    00508 }
    00509
    00510 /* static */ bool AIRoad::_BuildRoadStationInternal(TileIndex tile, TileIndex front, RoadVehicleType road_veh_type, bool drive_through, StationID station_id)
    00511 {
    00512   EnforcePrecondition(false, tile != front);
    00513   EnforcePrecondition(false, ::IsValidTile(tile));
    00514   EnforcePrecondition(false, ::IsValidTile(front));
    00515   EnforcePrecondition(false, ::TileX(tile) == ::TileX(front) || ::TileY(tile) == ::TileY(front));
    00516   EnforcePrecondition(false, station_id == AIStation::STATION_NEW || station_id == AIStation::STATION_JOIN_ADJACENT || AIStation::IsValidStation(station_id));
    00517   EnforcePrecondition(false, road_veh_type == ROADVEHTYPE_BUS || road_veh_type == ROADVEHTYPE_TRUCK);
    00518   EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
    00519
    00520   uint entrance_dir;
    00521   if (drive_through) {
    00522     entrance_dir = ::TileY(tile) != ::TileY(front);
    00523   } else {
    00524     entrance_dir = (::TileX(tile) == ::TileX(front)) ? (::TileY(tile) < ::TileY(front) ? 1 : 3) : (::TileX(tile) < ::TileX(front) ? 2 : 0);
    00525   }
    00526
    00527   uint p2 = station_id == AIStation::STATION_JOIN_ADJACENT ? 0 : 32;
    00528   p2 |= drive_through ? 2 : 0;
    00529   p2 |= road_veh_type == ROADVEHTYPE_TRUCK ? 1 : 0;
    00530   p2 |= ::RoadTypeToRoadTypes(AIObject::GetRoadType()) << 2;
    00531   p2 |= (AIStation::IsValidStation(station_id) ? station_id : INVALID_STATION) << 16;
    00532   return AIObject::DoCommand(tile, entrance_dir, p2, CMD_BUILD_ROAD_STOP);
    00533 }
    00534
    00535 /* static */ bool AIRoad::BuildRoadStation(TileIndex tile, TileIndex front, RoadVehicleType road_veh_type, StationID station_id)
    00536 {
    00537   return _BuildRoadStationInternal(tile, front, road_veh_type, false, station_id);
    00538 }
    00539
    00540 /* static */ bool AIRoad::BuildDriveThroughRoadStation(TileIndex tile, TileIndex front, RoadVehicleType road_veh_type, StationID station_id)
    00541 {
    00542   return _BuildRoadStationInternal(tile, front, road_veh_type, true, station_id);
    00543 }
    00544
    00545 /* static */ bool AIRoad::RemoveRoad(TileIndex start, TileIndex end)
    00546 {
    00547   EnforcePrecondition(false, ::IsValidTile(start));
    00548   EnforcePrecondition(false, ::IsValidTile(end));
    00549   EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
    00550   EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
    00551
    00552   return AIObject::DoCommand(end, start, (::TileY(start) != ::TileY(end) ? 4 : 0) | (start < end ? 1 : 2) | (AIObject::GetRoadType() << 3), CMD_REMOVE_LONG_ROAD);
    00553 }
    00554
    00555 /* static */ bool AIRoad::RemoveRoadFull(TileIndex start, TileIndex end)
    00556 {
    00557   EnforcePrecondition(false, ::IsValidTile(start));
    00558   EnforcePrecondition(false, ::IsValidTile(end));
    00559   EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
    00560   EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
    00561
    00562   return AIObject::DoCommand(end, start, (::TileY(start) != ::TileY(end) ? 4 : 0) | (start < end ? 2 : 1) | (AIObject::GetRoadType() << 3), CMD_REMOVE_LONG_ROAD);
    00563 }
    00564
    00565 /* static */ bool AIRoad::RemoveRoadDepot(TileIndex tile)
    00566 {
    00567   EnforcePrecondition(false, ::IsValidTile(tile));
    00568   EnforcePrecondition(false, IsTileType(tile, MP_ROAD))
    00569   EnforcePrecondition(false, GetRoadTileType(tile) == ROAD_TILE_DEPOT);
    00570
    00571   return AIObject::DoCommand(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
    00572 }
    00573
    00574 /* static */ bool AIRoad::RemoveRoadStation(TileIndex tile)
    00575 {
    00576   EnforcePrecondition(false, ::IsValidTile(tile));
    00577   EnforcePrecondition(false, IsTileType(tile, MP_STATION));
    00578   EnforcePrecondition(false, IsRoadStop(tile));
    00579
    00580   return AIObject::DoCommand(tile, 0, GetRoadStopType(tile), CMD_REMOVE_ROAD_STOP);
    00581 }