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 }

Generated on Wed Mar 3 23:32:19 2010 for OpenTTD by  doxygen 1.6.1