# ai_tunnel.cpp

Go to the documentation of this file.

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