# ai_road.cpp

Go to the documentation of this file.

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