00001
00002
00005 #include "ai_tile.hpp"
00006 #include "ai_map.hpp"
00007 #include "ai_town.hpp"
00008 #include "../../station_func.h"
00009 #include "../../company_func.h"
00010 #include "../../road_map.h"
00011 #include "../../water_map.h"
00012 #include "../../clear_map.h"
00013 #include "../../town.h"
00014 #include "../../landscape.h"
00015
00016 bool AITile::IsBuildable(TileIndex tile)
00017 {
00018 if (!::IsValidTile(tile)) return false;
00019
00020 switch (::GetTileType(tile)) {
00021 default: return false;
00022 case MP_CLEAR: return true;
00023 case MP_TREES: return true;
00024 case MP_WATER: return IsCoast(tile);
00025 case MP_ROAD:
00026
00027 if (::GetRoadTypes(tile) != ROADTYPES_ROAD) return false;
00028
00029 if (::GetRoadTileType(tile) != ROAD_TILE_NORMAL) return false;
00030 if (CountBits(::GetRoadBits(tile, ROADTYPE_ROAD)) != 1) return false;
00031 if (::IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN)) return true;
00032 if (::IsRoadOwner(tile, ROADTYPE_ROAD, _current_company)) return true;
00033 return false;
00034 }
00035 }
00036
00037 bool AITile::IsBuildableRectangle(TileIndex tile, uint width, uint height)
00038 {
00039 uint tx, ty;
00040
00041 tx = AIMap::GetTileX(tile);
00042 ty = AIMap::GetTileY(tile);
00043
00044 for (uint x = tx; x < width + tx; x++) {
00045 for (uint y = ty; y < height + ty; y++) {
00046 if (!IsBuildable(AIMap::GetTileIndex(x, y))) return false;
00047 }
00048 }
00049
00050 return true;
00051 }
00052
00053 bool AITile::IsWaterTile(TileIndex tile)
00054 {
00055 if (!::IsValidTile(tile)) return false;
00056
00057 return ::IsTileType(tile, MP_WATER) && !::IsCoast(tile);
00058 }
00059
00060 bool AITile::IsCoastTile(TileIndex tile)
00061 {
00062 if (!::IsValidTile(tile)) return false;
00063
00064 return ::IsTileType(tile, MP_WATER) && ::IsCoast(tile);
00065 }
00066
00067 bool AITile::IsStationTile(TileIndex tile)
00068 {
00069 if (!::IsValidTile(tile)) return false;
00070
00071 return ::IsTileType(tile, MP_STATION);
00072 }
00073
00074 bool AITile::IsSteepSlope(Slope slope)
00075 {
00076 if ((slope & ~(SLOPE_ELEVATED | SLOPE_STEEP | SLOPE_HALFTILE_MASK)) != 0) return false;
00077
00078 return ::IsSteepSlope((::Slope)slope);
00079 }
00080
00081 bool AITile::IsHalftileSlope(Slope slope)
00082 {
00083 if ((slope & ~(SLOPE_ELEVATED | SLOPE_STEEP | SLOPE_HALFTILE_MASK)) != 0) return false;
00084
00085 return ::IsHalftileSlope((::Slope)slope);
00086 }
00087
00088 bool AITile::HasTreeOnTile(TileIndex tile)
00089 {
00090 if (!::IsValidTile(tile)) return false;
00091
00092 return ::IsTileType(tile, MP_TREES);
00093 }
00094
00095 bool AITile::IsFarmTile(TileIndex tile)
00096 {
00097 if (!::IsValidTile(tile)) return false;
00098
00099 return (::IsTileType(tile, MP_CLEAR) && ::IsClearGround(tile, CLEAR_FIELDS));
00100 }
00101
00102 bool AITile::IsRockTile(TileIndex tile)
00103 {
00104 if (!::IsValidTile(tile)) return false;
00105
00106 return (::IsTileType(tile, MP_CLEAR) && ::IsClearGround(tile, CLEAR_ROCKS));
00107 }
00108
00109 bool AITile::IsRoughTile(TileIndex tile)
00110 {
00111 if (!::IsValidTile(tile)) return false;
00112
00113 return (::IsTileType(tile, MP_CLEAR) && ::IsClearGround(tile, CLEAR_ROUGH));
00114 }
00115
00116 bool AITile::IsSnowTile(TileIndex tile)
00117 {
00118 if (!::IsValidTile(tile)) return false;
00119
00120 return (::IsTileType(tile, MP_CLEAR) && ::IsClearGround(tile, CLEAR_SNOW));
00121 }
00122
00123 bool AITile::IsDesertTile(TileIndex tile)
00124 {
00125 if (!::IsValidTile(tile)) return false;
00126
00127 return (::IsTileType(tile, MP_CLEAR) && ::IsClearGround(tile, CLEAR_DESERT));
00128 }
00129
00130 AITile::Slope AITile::GetSlope(TileIndex tile)
00131 {
00132 if (!::IsValidTile(tile)) return SLOPE_INVALID;
00133
00134 return (Slope)::GetTileSlope(tile, NULL);
00135 }
00136
00137 AITile::Slope AITile::GetComplementSlope(Slope slope)
00138 {
00139 if ((slope & ~SLOPE_ELEVATED) != 0) return SLOPE_INVALID;
00140
00141 return (Slope)::ComplementSlope((::Slope)slope);
00142 }
00143
00144 int32 AITile::GetHeight(TileIndex tile)
00145 {
00146 if (!::IsValidTile(tile)) return -1;
00147
00148 return ::TileHeight(tile);
00149 }
00150
00151 int32 AITile::GetMinHeight(TileIndex tile)
00152 {
00153 if (!::IsValidTile(tile)) return -1;
00154
00155 return ::GetTileZ(tile) / ::TILE_HEIGHT;
00156 }
00157
00158 int32 AITile::GetMaxHeight(TileIndex tile)
00159 {
00160 if (!::IsValidTile(tile)) return -1;
00161
00162 return ::GetTileMaxZ(tile) / ::TILE_HEIGHT;
00163 }
00164
00165 int32 AITile::GetCornerHeight(TileIndex tile, Corner corner)
00166 {
00167 if (!::IsValidTile(tile) || !::IsValidCorner((::Corner)corner)) return -1;
00168
00169 uint z;
00170 ::Slope slope = ::GetTileSlope(tile, &z);
00171 return (z + ::GetSlopeZInCorner(slope, (::Corner)corner)) / ::TILE_HEIGHT;
00172 }
00173
00174 AICompany::CompanyID AITile::GetOwner(TileIndex tile)
00175 {
00176 if (!::IsValidTile(tile)) return AICompany::COMPANY_INVALID;
00177 if (::IsTileType(tile, MP_HOUSE)) return AICompany::COMPANY_INVALID;
00178 if (::IsTileType(tile, MP_INDUSTRY)) return AICompany::COMPANY_INVALID;
00179
00180 return AICompany::ResolveCompanyID((AICompany::CompanyID)(byte)::GetTileOwner(tile));
00181 }
00182
00183 bool AITile::HasTransportType(TileIndex tile, TransportType transport_type)
00184 {
00185 if (!::IsValidTile(tile)) return false;
00186
00187 return ::TrackStatusToTrackdirBits(::GetTileTrackStatus(tile, (::TransportType)transport_type, UINT32_MAX)) != TRACKDIR_BIT_NONE;
00188 }
00189
00190 int32 AITile::GetCargoAcceptance(TileIndex tile, CargoID cargo_type, int width, int height, int radius)
00191 {
00192 if (!::IsValidTile(tile) || width <= 0 || height <= 0 || radius < 0) return -1;
00193
00194 AcceptedCargo accepts;
00195 ::GetAcceptanceAroundTiles(accepts, tile, width, height, _settings_game.station.modified_catchment ? radius : (int)CA_UNMODIFIED);
00196 return accepts[cargo_type];
00197 }
00198
00199 int32 AITile::GetCargoProduction(TileIndex tile, CargoID cargo_type, int width, int height, int radius)
00200 {
00201 if (!::IsValidTile(tile) || width <= 0 || height <= 0 || radius < 0) return -1;
00202
00203 AcceptedCargo produced;
00204 ::GetProductionAroundTiles(produced, tile, width, height, _settings_game.station.modified_catchment ? radius : (int)CA_UNMODIFIED);
00205 return produced[cargo_type];
00206 }
00207
00208 int32 AITile::GetDistanceManhattanToTile(TileIndex tile_from, TileIndex tile_to)
00209 {
00210 return AIMap::DistanceManhattan(tile_from, tile_to);
00211 }
00212
00213 int32 AITile::GetDistanceSquareToTile(TileIndex tile_from, TileIndex tile_to)
00214 {
00215 return AIMap::DistanceSquare(tile_from, tile_to);
00216 }
00217
00218 bool AITile::RaiseTile(TileIndex tile, int32 slope)
00219 {
00220 EnforcePrecondition(false, tile < ::MapSize());
00221
00222 return AIObject::DoCommand(tile, slope, 1, CMD_TERRAFORM_LAND);
00223 }
00224
00225 bool AITile::LowerTile(TileIndex tile, int32 slope)
00226 {
00227 EnforcePrecondition(false, tile < ::MapSize());
00228
00229 return AIObject::DoCommand(tile, slope, 0, CMD_TERRAFORM_LAND);
00230 }
00231
00232 bool AITile::LevelTiles(TileIndex start_tile, TileIndex end_tile)
00233 {
00234 EnforcePrecondition(false, start_tile < ::MapSize());
00235 EnforcePrecondition(false, end_tile < ::MapSize());
00236
00237 return AIObject::DoCommand(end_tile, start_tile, 0, CMD_LEVEL_LAND);
00238 }
00239
00240 bool AITile::DemolishTile(TileIndex tile)
00241 {
00242 EnforcePrecondition(false, ::IsValidTile(tile));
00243
00244 return AIObject::DoCommand(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
00245 }
00246
00247 bool AITile::PlantTree(TileIndex tile)
00248 {
00249 EnforcePrecondition(false, ::IsValidTile(tile));
00250
00251 return AIObject::DoCommand(tile, UINT_MAX, tile, CMD_PLANT_TREE);
00252 }
00253
00254 bool AITile::PlantTreeRectangle(TileIndex tile, uint width, uint height)
00255 {
00256 EnforcePrecondition(false, ::IsValidTile(tile));
00257 EnforcePrecondition(false, width >= 1 && width <= 20);
00258 EnforcePrecondition(false, height >= 1 && height <= 20);
00259 TileIndex end_tile = tile + ::TileDiffXY(width - 1, height - 1);
00260
00261 return AIObject::DoCommand(tile, UINT_MAX, end_tile, CMD_PLANT_TREE);
00262 }
00263
00264 bool AITile::IsWithinTownInfluence(TileIndex tile, TownID town_id)
00265 {
00266 return AITown::IsWithinTownInfluence(town_id, tile);
00267 }
00268
00269 TownID AITile::GetClosestTown(TileIndex tile)
00270 {
00271 if (!::IsValidTile(tile)) return INVALID_TOWN;
00272
00273 return ::ClosestTownFromTile(tile, UINT_MAX)->index;
00274 }