ai_road.cpp

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

Generated on Mon Dec 14 20:59:57 2009 for OpenTTD by  doxygen 1.5.6