ai_bridge.cpp

Go to the documentation of this file.
00001 /* $Id: ai_bridge.cpp 15490 2009-02-14 21:17:35Z yexo $ */
00002 
00005 #include "ai_bridge.hpp"
00006 #include "ai_rail.hpp"
00007 #include "../ai_instance.hpp"
00008 #include "../../bridge_map.h"
00009 #include "../../strings_func.h"
00010 #include "../../core/alloc_func.hpp"
00011 #include "../../economy_func.h"
00012 #include "../../settings_type.h"
00013 #include "../../date_func.h"
00014 
00015 /* static */ bool AIBridge::IsValidBridge(BridgeID bridge_id)
00016 {
00017   return bridge_id < MAX_BRIDGES && ::GetBridgeSpec(bridge_id)->avail_year <= _cur_year;
00018 }
00019 
00020 /* static */ bool AIBridge::IsBridgeTile(TileIndex tile)
00021 {
00022   if (!::IsValidTile(tile)) return false;
00023   return ::IsBridgeTile(tile);
00024 }
00025 
00026 static void _DoCommandReturnBuildBridge2(class AIInstance *instance)
00027 {
00028   if (!AIBridge::_BuildBridgeRoad2()) {
00029     AIObject::SetLastCommandRes(false);
00030     AIInstance::DoCommandReturn(instance);
00031     return;
00032   }
00033 
00034   /* This can never happen, as in test-mode this callback is never executed,
00035   *  and in execute-mode, the other callback is called. */
00036   NOT_REACHED();
00037 }
00038 
00039 static void _DoCommandReturnBuildBridge1(class AIInstance *instance)
00040 {
00041   if (!AIBridge::_BuildBridgeRoad1()) {
00042     AIObject::SetLastCommandRes(false);
00043     AIInstance::DoCommandReturn(instance);
00044     return;
00045   }
00046 
00047   /* This can never happen, as in test-mode this callback is never executed,
00048   *  and in execute-mode, the other callback is called. */
00049   NOT_REACHED();
00050 }
00051 
00052 /* static */ bool AIBridge::BuildBridge(AIVehicle::VehicleType vehicle_type, BridgeID bridge_id, TileIndex start, TileIndex end)
00053 {
00054   EnforcePrecondition(false, start != end);
00055   EnforcePrecondition(false, ::IsValidTile(start) && ::IsValidTile(end));
00056   EnforcePrecondition(false, TileX(start) == TileX(end) || TileY(start) == TileY(end));
00057   EnforcePrecondition(false, vehicle_type == AIVehicle::VT_ROAD || vehicle_type == AIVehicle::VT_RAIL || vehicle_type == AIVehicle::VT_WATER);
00058   EnforcePrecondition(false, vehicle_type != AIVehicle::VT_RAIL || AIRail::IsRailTypeAvailable(AIRail::GetCurrentRailType()));
00059 
00060   uint type = 0;
00061   switch (vehicle_type) {
00062     case AIVehicle::VT_ROAD:
00063       type |= (TRANSPORT_ROAD << 15);
00064       type |= (RoadTypeToRoadTypes((::RoadType)AIObject::GetRoadType()) << 8);
00065       break;
00066     case AIVehicle::VT_RAIL:
00067       type |= (TRANSPORT_RAIL << 15);
00068       type |= (AIRail::GetCurrentRailType() << 8);
00069       break;
00070     case AIVehicle::VT_WATER:
00071       type |= (TRANSPORT_WATER << 15);
00072       break;
00073     default: NOT_REACHED();
00074   }
00075 
00076   /* For rail and water we do nothing special */
00077   if (vehicle_type == AIVehicle::VT_RAIL || vehicle_type == AIVehicle::VT_WATER) {
00078     return AIObject::DoCommand(end, start, type | bridge_id, CMD_BUILD_BRIDGE);
00079   }
00080 
00081   AIObject::SetCallbackVariable(0, start);
00082   AIObject::SetCallbackVariable(1, end);
00083   if (!AIObject::DoCommand(end, start, type | bridge_id, CMD_BUILD_BRIDGE, NULL, &_DoCommandReturnBuildBridge1)) return false;
00084 
00085   /* In case of test-mode, test if we can build both road pieces */
00086   return _BuildBridgeRoad1();
00087 }
00088 
00089 /* static */ bool AIBridge::_BuildBridgeRoad1()
00090 {
00091   /* Build the piece of road on the 'start' side of the bridge */
00092   TileIndex end = AIObject::GetCallbackVariable(0);
00093   TileIndex start = AIObject::GetCallbackVariable(1);
00094 
00095   DiagDirection dir_1 = (DiagDirection)((::TileX(start) == ::TileX(end)) ? (::TileY(start) < ::TileY(end) ? DIAGDIR_NW : DIAGDIR_SE) : (::TileX(start) < ::TileX(end) ? DIAGDIR_NE : DIAGDIR_SW));
00096   DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
00097 
00098   if (!AIObject::DoCommand(start + ::TileOffsByDiagDir(dir_1), ::DiagDirToRoadBits(dir_2) | (AIObject::GetRoadType() << 4), 0, CMD_BUILD_ROAD, NULL, &_DoCommandReturnBuildBridge2)) return false;
00099 
00100   /* In case of test-mode, test the other road piece too */
00101   return _BuildBridgeRoad2();
00102 }
00103 
00104 /* static */ bool AIBridge::_BuildBridgeRoad2()
00105 {
00106   /* Build the piece of road on the 'end' side of the bridge */
00107   TileIndex end = AIObject::GetCallbackVariable(0);
00108   TileIndex start = AIObject::GetCallbackVariable(1);
00109 
00110   DiagDirection dir_1 = (DiagDirection)((::TileX(start) == ::TileX(end)) ? (::TileY(start) < ::TileY(end) ? DIAGDIR_NW : DIAGDIR_SE) : (::TileX(start) < ::TileX(end) ? DIAGDIR_NE : DIAGDIR_SW));
00111   DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
00112 
00113   return AIObject::DoCommand(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1) | (AIObject::GetRoadType() << 4), 0, CMD_BUILD_ROAD);
00114 }
00115 
00116 /* static */ bool AIBridge::RemoveBridge(TileIndex tile)
00117 {
00118   EnforcePrecondition(false, IsBridgeTile(tile));
00119   return AIObject::DoCommand(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
00120 }
00121 
00122 /* static */ char *AIBridge::GetName(BridgeID bridge_id)
00123 {
00124   if (!IsValidBridge(bridge_id)) return NULL;
00125 
00126   static const int len = 64;
00127   char *bridge_name = MallocT<char>(len);
00128 
00129   ::GetString(bridge_name, ::GetBridgeSpec(bridge_id)->transport_name[0], &bridge_name[len - 1]);
00130   return bridge_name;
00131 }
00132 
00133 /* static */ int32 AIBridge::GetMaxSpeed(BridgeID bridge_id)
00134 {
00135   if (!IsValidBridge(bridge_id)) return -1;
00136 
00137   return ::GetBridgeSpec(bridge_id)->speed; // km-ish/h
00138 }
00139 
00140 /* static */ Money AIBridge::GetPrice(BridgeID bridge_id, uint length)
00141 {
00142   if (!IsValidBridge(bridge_id)) return -1;
00143 
00144   return length * _price.build_bridge * ::GetBridgeSpec(bridge_id)->price >> 8;
00145 }
00146 
00147 /* static */ int32 AIBridge::GetMaxLength(BridgeID bridge_id)
00148 {
00149   if (!IsValidBridge(bridge_id)) return -1;
00150 
00151   uint max = ::GetBridgeSpec(bridge_id)->max_length;
00152   if (max >= 16 && _settings_game.construction.longbridges) max = 100;
00153   return max + 2;
00154 }
00155 
00156 /* static */ int32 AIBridge::GetMinLength(BridgeID bridge_id)
00157 {
00158   if (!IsValidBridge(bridge_id)) return -1;
00159 
00160   return ::GetBridgeSpec(bridge_id)->min_length + 2;
00161 }
00162 
00163 /* static */ TileIndex AIBridge::GetOtherBridgeEnd(TileIndex tile)
00164 {
00165   if (!::IsValidTile(tile)) return INVALID_TILE;
00166   if (!IsBridgeTile(tile)) return INVALID_TILE;
00167 
00168   return ::GetOtherBridgeEnd(tile);
00169 }

Generated on Mon Feb 16 23:12:05 2009 for openttd by  doxygen 1.5.6