/* $Id$ */
/** @file ai_road.cpp Implementation of AIRoad. */
#include "ai_road.hpp"
#include "ai_map.hpp"
#include "../../openttd.h"
#include "../../road_map.h"
#include "../../station_map.h"
#include "../../command_type.h"
#include "../../player_func.h"
/* static */ bool AIRoad::IsRoadTile(TileIndex tile)
{
if (!::IsValidTile(tile)) return false;
return (::IsTileType(tile, MP_ROAD) && ::GetRoadTileType(tile) != ROAD_TILE_DEPOT) ||
IsDriveThroughRoadStationTile(tile);
}
/* static */ bool AIRoad::IsRoadDepotTile(TileIndex tile)
{
if (!::IsValidTile(tile)) return false;
return ::IsTileType(tile, MP_ROAD) && ::GetRoadTileType(tile) == ROAD_TILE_DEPOT;
}
/* static */ bool AIRoad::IsRoadStationTile(TileIndex tile)
{
if (!::IsValidTile(tile)) return false;
return ::IsRoadStopTile(tile);
}
/* static */ bool AIRoad::IsDriveThroughRoadStationTile(TileIndex tile)
{
if (!::IsValidTile(tile)) return false;
return ::IsDriveThroughStopTile(tile);
}
/* static */ bool AIRoad::IsRoadTypeAvailable(RoadType road_type)
{
return ::HasRoadTypesAvail(_current_player, ::RoadTypeToRoadTypes((::RoadType)road_type));
}
/* static */ AIRoad::RoadType AIRoad::GetCurrentRoadType()
{
return (RoadType)AIObject::GetRoadType();
}
/* static */ void AIRoad::SetCurrentRoadType(RoadType road_type)
{
if (!IsRoadTypeAvailable(road_type)) return;
AIObject::SetRoadType((::RoadType)road_type);
}
/* static */ bool AIRoad::HasRoadType(TileIndex tile, RoadType road_type)
{
if (!AIMap::IsValidTile(tile)) return false;
if (!IsRoadTypeAvailable(road_type)) return false;
return ::GetAnyRoadBits(tile, (::RoadType)road_type, false) != ROAD_NONE;
}
/* static */ bool AIRoad::AreRoadTilesConnected(TileIndex t1, TileIndex t2)
{
if (!::IsValidTile(t1)) return false;
if (!::IsValidTile(t2)) return false;
/* Tiles not neighbouring */
if ((abs((int)::TileX(t1) - (int)::TileX(t2)) + abs((int)::TileY(t1) - (int)::TileY(t2))) != 1) return false;
RoadBits r1 = ::GetAnyRoadBits(t1, AIObject::GetRoadType());
RoadBits r2 = ::GetAnyRoadBits(t2, AIObject::GetRoadType());
DiagDirection dir_1 = (DiagDirection)((::TileX(t1) == ::TileX(t2)) ? (::TileY(t1) < ::TileY(t2) ? 2 : 0) : (::TileX(t1) < ::TileX(t2) ? 1 : 3));
DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
return HasBit(r1, dir_1) && HasBit(r2, dir_2);
}
/* static */ int32 AIRoad::GetNeighbourRoadCount(TileIndex tile)
{
if (!::IsValidTile(tile)) return false;
int32 neighbour = 0;
if (::IsTileType(tile + ::TileDiffXY(-1, 0), MP_ROAD) && ::GetRoadTileType(tile + ::TileDiffXY(-1, 0)) != ROAD_TILE_DEPOT) neighbour++;
if (::IsTileType(tile + ::TileDiffXY( 1, 0), MP_ROAD) && ::GetRoadTileType(tile + ::TileDiffXY( 1, 0)) != ROAD_TILE_DEPOT) neighbour++;
if (::IsTileType(tile + ::TileDiffXY( 0,-1), MP_ROAD) && ::GetRoadTileType(tile + ::TileDiffXY( 0,-1)) != ROAD_TILE_DEPOT) neighbour++;
if (::IsTileType(tile + ::TileDiffXY( 0, 1), MP_ROAD) && ::GetRoadTileType(tile + ::TileDiffXY( 0, 1)) != ROAD_TILE_DEPOT) neighbour++;
return neighbour;
}
/* static */ TileIndex AIRoad::GetRoadDepotFrontTile(TileIndex depot)
{
if (!IsRoadDepotTile(depot)) return INVALID_TILE;
return depot + ::TileOffsByDiagDir(::GetRoadDepotDirection(depot));
}
/* static */ TileIndex AIRoad::GetRoadStationFrontTile(TileIndex station)
{
if (!IsRoadStationTile(station)) return INVALID_TILE;
return station + ::TileOffsByDiagDir(::GetRoadStopDir(station));
}
/* static */ TileIndex AIRoad::GetDriveThroughBackTile(TileIndex station)
{
if (!IsDriveThroughRoadStationTile(station)) return INVALID_TILE;
return station + ::TileOffsByDiagDir(::ReverseDiagDir(::GetRoadStopDir(station)));
}
/* static */ bool AIRoad::BuildRoad(TileIndex start, TileIndex end)
{
EnforcePrecondition(false, start != end);
EnforcePrecondition(false, ::IsValidTile(start));
EnforcePrecondition(false, ::IsValidTile(end));
EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
return AIObject::DoCommand(end, start, (::TileY(start) != ::TileY(end) ? 4 : 0) | (start < end ? 1 : 2) | (AIObject::GetRoadType() << 3), CMD_BUILD_LONG_ROAD);
}
/* static */ bool AIRoad::BuildRoadFull(TileIndex start, TileIndex end)
{
EnforcePrecondition(false, start != end);
EnforcePrecondition(false, ::IsValidTile(start));
EnforcePrecondition(false, ::IsValidTile(end));
EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
return AIObject::DoCommand(end, start, (::TileY(start) != ::TileY(end) ? 4 : 0) | (start < end ? 2 : 1) | (AIObject::GetRoadType() << 3), CMD_BUILD_LONG_ROAD);
}
/* static */ bool AIRoad::BuildRoadDepot(TileIndex tile, TileIndex front)
{
EnforcePrecondition(false, tile != front);
EnforcePrecondition(false, ::IsValidTile(tile));
EnforcePrecondition(false, ::IsValidTile(front));
EnforcePrecondition(false, ::TileX(tile) == ::TileX(front) || ::TileY(tile) == ::TileY(front));
uint entrance_dir = (::TileX(tile) == ::TileX(front)) ? (::TileY(tile) < ::TileY(front) ? 1 : 3) : (::TileX(tile) < ::TileX(front) ? 2 : 0);
return AIObject::DoCommand(tile, entrance_dir | (AIObject::GetRoadType() << 2), 0, CMD_BUILD_ROAD_DEPOT);
}
/* static */ bool AIRoad::BuildRoadStation(TileIndex tile, TileIndex front, bool truck, bool drive_through)
{
EnforcePrecondition(false, tile != front);
EnforcePrecondition(false, ::IsValidTile(tile));
EnforcePrecondition(false, ::IsValidTile(front));
EnforcePrecondition(false, ::TileX(tile) == ::TileX(front) || ::TileY(tile) == ::TileY(front));
uint entrance_dir;
if (drive_through) {
entrance_dir = ::TileY(tile) != ::TileY(front);
} else {
entrance_dir = (::TileX(tile) == ::TileX(front)) ? (::TileY(tile) < ::TileY(front) ? 1 : 3) : (::TileX(tile) < ::TileX(front) ? 2 : 0);
}
return AIObject::DoCommand(tile, entrance_dir, (drive_through ? 2 : 0) | (truck ? 1 : 0) | (::RoadTypeToRoadTypes(AIObject::GetRoadType()) << 2), CMD_BUILD_ROAD_STOP);
}
/* static */ bool AIRoad::RemoveRoad(TileIndex start, TileIndex end)
{
EnforcePrecondition(false, ::IsValidTile(start));
EnforcePrecondition(false, ::IsValidTile(end));
EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
return AIObject::DoCommand(end, start, (::TileY(start) != ::TileY(end) ? 4 : 0) | (start < end ? 1 : 2) | (AIObject::GetRoadType() << 3), CMD_REMOVE_LONG_ROAD);
}
/* static */ bool AIRoad::RemoveRoadFull(TileIndex start, TileIndex end)
{
EnforcePrecondition(false, ::IsValidTile(start));
EnforcePrecondition(false, ::IsValidTile(end));
EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
return AIObject::DoCommand(end, start, (::TileY(start) != ::TileY(end) ? 4 : 0) | (start < end ? 2 : 1) | (AIObject::GetRoadType() << 3), CMD_REMOVE_LONG_ROAD);
}
/* static */ bool AIRoad::RemoveRoadDepot(TileIndex tile)
{
EnforcePrecondition(false, ::IsValidTile(tile));
EnforcePrecondition(false, IsTileType(tile, MP_ROAD))
EnforcePrecondition(false, GetRoadTileType(tile) == ROAD_TILE_DEPOT);
return AIObject::DoCommand(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
}
/* static */ bool AIRoad::RemoveRoadStation(TileIndex tile)
{
EnforcePrecondition(false, ::IsValidTile(tile));
EnforcePrecondition(false, IsTileType(tile, MP_STATION));
EnforcePrecondition(false, IsRoadStop(tile));
return AIObject::DoCommand(tile, 0, GetRoadStopType(tile), CMD_REMOVE_ROAD_STOP);
}