# ai_tunnel.cpp

Go to the documentation of this file.

    00001 /* $Id: ai_tunnel.cpp 17693 2009-10-04 17:16:41Z 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_tunnel.hpp"
    00013 #include "ai_rail.hpp"
    00014 #include "../ai_instance.hpp"
    00015 #include "../../tunnel_map.h"
    00016 #include "../../command_func.h"
    00017
    00018 /* static */ bool AITunnel::IsTunnelTile(TileIndex tile)
    00019 {
    00020   if (!::IsValidTile(tile)) return false;
    00021   return ::IsTunnelTile(tile);
    00022 }
    00023
    00024 /* static */ TileIndex AITunnel::GetOtherTunnelEnd(TileIndex tile)
    00025 {
    00026   if (!::IsValidTile(tile)) return INVALID_TILE;
    00027
    00028   /* If it's a tunnel alread, take the easy way out! */
    00029   if (IsTunnelTile(tile)) return ::GetOtherTunnelEnd(tile);
    00030
    00031   uint start_z;
    00032   Slope start_tileh = ::GetTileSlope(tile, &start_z);
    00033   DiagDirection direction = ::GetInclinedSlopeDirection(start_tileh);
    00034   if (direction == INVALID_DIAGDIR) return INVALID_TILE;
    00035
    00036   TileIndexDiff delta = ::TileOffsByDiagDir(direction);
    00037   uint end_z;
    00038   do {
    00039     tile += delta;
    00040     if (!::IsValidTile(tile)) return INVALID_TILE;
    00041
    00042 		::GetTileSlope(tile, &end_z);
    00043   } while (start_z != end_z);
    00044
    00045   return tile;
    00046 }
    00047
    00048 static void _DoCommandReturnBuildTunnel2(class AIInstance *instance)
    00049 {
    00050   if (!AITunnel::_BuildTunnelRoad2()) {
    00051     AIInstance::DoCommandReturn(instance);
    00052     return;
    00053   }
    00054
    00055   /* This can never happen, as in test-mode this callback is never executed,
    00056    *  and in execute-mode, the other callback is called. */
    00057   NOT_REACHED();
    00058 }
    00059
    00060 static void _DoCommandReturnBuildTunnel1(class AIInstance *instance)
    00061 {
    00062   if (!AITunnel::_BuildTunnelRoad1()) {
    00063     AIInstance::DoCommandReturn(instance);
    00064     return;
    00065   }
    00066
    00067   /* This can never happen, as in test-mode this callback is never executed,
    00068    *  and in execute-mode, the other callback is called. */
    00069   NOT_REACHED();
    00070 }
    00071
    00072 /* static */ bool AITunnel::BuildTunnel(AIVehicle::VehicleType vehicle_type, TileIndex start)
    00073 {
    00074   EnforcePrecondition(false, ::IsValidTile(start));
    00075   EnforcePrecondition(false, vehicle_type == AIVehicle::VT_RAIL || vehicle_type == AIVehicle::VT_ROAD);
    00076   EnforcePrecondition(false, vehicle_type != AIVehicle::VT_RAIL || AIRail::IsRailTypeAvailable(AIRail::GetCurrentRailType()));
    00077
    00078   uint type = 0;
    00079   if (vehicle_type == AIVehicle::VT_ROAD) {
    00080     type |= (TRANSPORT_ROAD << 9);
    00081     type |= ::RoadTypeToRoadTypes((::RoadType)AIObject::GetRoadType());
    00082   } else {
    00083     type |= (TRANSPORT_RAIL << 9);
    00084     type |= AIRail::GetCurrentRailType();
    00085   }
    00086
    00087   /* For rail we do nothing special */
    00088   if (vehicle_type == AIVehicle::VT_RAIL) {
    00089     return AIObject::DoCommand(start, type, 0, CMD_BUILD_TUNNEL);
    00090   }
    00091
    00092   AIObject::SetCallbackVariable(0, start);
    00093   return AIObject::DoCommand(start, type, 0, CMD_BUILD_TUNNEL, NULL, &_DoCommandReturnBuildTunnel1);
    00094 }
    00095
    00096 /* static */ bool AITunnel::_BuildTunnelRoad1()
    00097 {
    00098   /* Build the piece of road on the 'start' side of the tunnel */
    00099   TileIndex end = AIObject::GetCallbackVariable(0);
    00100   TileIndex start = AITunnel::GetOtherTunnelEnd(end);
    00101
    00102   DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
    00103   DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
    00104
    00105   return AIObject::DoCommand(start + ::TileOffsByDiagDir(dir_1), ::DiagDirToRoadBits(dir_2) | (AIObject::GetRoadType() << 4), 0, CMD_BUILD_ROAD, NULL, &_DoCommandReturnBuildTunnel2);
    00106 }
    00107
    00108 /* static */ bool AITunnel::_BuildTunnelRoad2()
    00109 {
    00110   /* Build the piece of road on the 'end' side of the tunnel */
    00111   TileIndex end = AIObject::GetCallbackVariable(0);
    00112   TileIndex start = AITunnel::GetOtherTunnelEnd(end);
    00113
    00114   DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
    00115   DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
    00116
    00117   return AIObject::DoCommand(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1) | (AIObject::GetRoadType() << 4), 0, CMD_BUILD_ROAD);
    00118 }
    00119
    00120 /* static */ bool AITunnel::RemoveTunnel(TileIndex tile)
    00121 {
    00122   EnforcePrecondition(false, IsTunnelTile(tile));
    00123
    00124   return AIObject::DoCommand(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
    00125 }