# 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
    00053 static void _DoCommandReturnBuildTunnel2(class AIInstance *instance)
    00054 {
    00055   if (!AITunnel::_BuildTunnelRoad2()) {
    00056     AIInstance::DoCommandReturn(instance);
    00057     return;
    00058   }
    00059
    00060   /* This can never happen, as in test-mode this callback is never executed,
    00061    *  and in execute-mode, the other callback is called. */
    00062   NOT_REACHED();
    00063 }
    00064
    00069 static void _DoCommandReturnBuildTunnel1(class AIInstance *instance)
    00070 {
    00071   if (!AITunnel::_BuildTunnelRoad1()) {
    00072     AIInstance::DoCommandReturn(instance);
    00073     return;
    00074   }
    00075
    00076   /* This can never happen, as in test-mode this callback is never executed,
    00077    *  and in execute-mode, the other callback is called. */
    00078   NOT_REACHED();
    00079 }
    00080
    00081 /* static */ bool AITunnel::BuildTunnel(AIVehicle::VehicleType vehicle_type, TileIndex start)
    00082 {
    00083   EnforcePrecondition(false, ::IsValidTile(start));
    00084   EnforcePrecondition(false, vehicle_type == AIVehicle::VT_RAIL || vehicle_type == AIVehicle::VT_ROAD);
    00085   EnforcePrecondition(false, vehicle_type != AIVehicle::VT_RAIL || AIRail::IsRailTypeAvailable(AIRail::GetCurrentRailType()));
    00086
    00087   uint type = 0;
    00088   if (vehicle_type == AIVehicle::VT_ROAD) {
    00089     type |= (TRANSPORT_ROAD << 8);
    00090     type |= ::RoadTypeToRoadTypes((::RoadType)AIObject::GetRoadType());
    00091   } else {
    00092     type |= (TRANSPORT_RAIL << 8);
    00093     type |= AIRail::GetCurrentRailType();
    00094   }
    00095
    00096   /* For rail we do nothing special */
    00097   if (vehicle_type == AIVehicle::VT_RAIL) {
    00098     return AIObject::DoCommand(start, type, 0, CMD_BUILD_TUNNEL);
    00099   }
    00100
    00101   AIObject::SetCallbackVariable(0, start);
    00102   return AIObject::DoCommand(start, type, 0, CMD_BUILD_TUNNEL, NULL, &::_DoCommandReturnBuildTunnel1);
    00103 }
    00104
    00105 /* static */ bool AITunnel::_BuildTunnelRoad1()
    00106 {
    00107   /* Build the piece of road on the 'start' side of the tunnel */
    00108   TileIndex end = AIObject::GetCallbackVariable(0);
    00109   TileIndex start = AITunnel::GetOtherTunnelEnd(end);
    00110
    00111   DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
    00112   DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
    00113
    00114   return AIObject::DoCommand(start + ::TileOffsByDiagDir(dir_1), ::DiagDirToRoadBits(dir_2) | (AIObject::GetRoadType() << 4), 0, CMD_BUILD_ROAD, NULL, &::_DoCommandReturnBuildTunnel2);
    00115 }
    00116
    00117 /* static */ bool AITunnel::_BuildTunnelRoad2()
    00118 {
    00119   /* Build the piece of road on the 'end' side of the tunnel */
    00120   TileIndex end = AIObject::GetCallbackVariable(0);
    00121   TileIndex start = AITunnel::GetOtherTunnelEnd(end);
    00122
    00123   DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
    00124   DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
    00125
    00126   return AIObject::DoCommand(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1) | (AIObject::GetRoadType() << 4), 0, CMD_BUILD_ROAD);
    00127 }
    00128
    00129 /* static */ bool AITunnel::RemoveTunnel(TileIndex tile)
    00130 {
    00131   EnforcePrecondition(false, IsTunnelTile(tile));
    00132
    00133   return AIObject::DoCommand(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
    00134 }