00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "ai_tile.hpp"
00013 #include "ai_map.hpp"
00014 #include "ai_town.hpp"
00015 #include "../../station_func.h"
00016 #include "../../company_func.h"
00017 #include "../../water_map.h"
00018 #include "../../clear_map.h"
00019 #include "../../tree_map.h"
00020 #include "../../town.h"
00021 #include "../../landscape.h"
00022 #include "../../economy_func.h"
00023
00024 bool AITile::IsBuildable(TileIndex tile)
00025 {
00026 if (!::IsValidTile(tile)) return false;
00027
00028 switch (::GetTileType(tile)) {
00029 default: return false;
00030 case MP_CLEAR: return true;
00031 case MP_TREES: return true;
00032 case MP_WATER: return IsCoast(tile);
00033 case MP_ROAD:
00034
00035 if (::GetRoadTypes(tile) != ROADTYPES_ROAD) return false;
00036
00037 if (::GetRoadTileType(tile) != ROAD_TILE_NORMAL) return false;
00038 if (!HasExactlyOneBit(::GetRoadBits(tile, ROADTYPE_ROAD))) return false;
00039 if (::IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN)) return true;
00040 if (::IsRoadOwner(tile, ROADTYPE_ROAD, _current_company)) return true;
00041 return false;
00042 }
00043 }
00044
00045 bool AITile::IsBuildableRectangle(TileIndex tile, uint width, uint height)
00046 {
00047 uint tx, ty;
00048
00049 tx = AIMap::GetTileX(tile);
00050 ty = AIMap::GetTileY(tile);
00051
00052 for (uint x = tx; x < width + tx; x++) {
00053 for (uint y = ty; y < height + ty; y++) {
00054 if (!IsBuildable(AIMap::GetTileIndex(x, y))) return false;
00055 }
00056 }
00057
00058 return true;
00059 }
00060
00061 bool AITile::IsWaterTile(TileIndex tile)
00062 {
00063 if (!::IsValidTile(tile)) return false;
00064
00065 return ::IsTileType(tile, MP_WATER) && !::IsCoast(tile);
00066 }
00067
00068 bool AITile::IsCoastTile(TileIndex tile)
00069 {
00070 if (!::IsValidTile(tile)) return false;
00071
00072 return (::IsTileType(tile, MP_WATER) && ::IsCoast(tile)) ||
00073 (::IsTileType(tile, MP_TREES) && ::GetTreeGround(tile) == TREE_GROUND_SHORE);
00074 }
00075
00076 bool AITile::IsStationTile(TileIndex tile)
00077 {
00078 if (!::IsValidTile(tile)) return false;
00079
00080 return ::IsTileType(tile, MP_STATION);
00081 }
00082
00083 bool AITile::IsSteepSlope(Slope slope)
00084 {
00085 if ((slope & ~(SLOPE_ELEVATED | SLOPE_STEEP | SLOPE_HALFTILE_MASK)) != 0) return false;
00086
00087 return ::IsSteepSlope((::Slope)slope);
00088 }
00089
00090 bool AITile::IsHalftileSlope(Slope slope)
00091 {
00092 if ((slope & ~(SLOPE_ELEVATED | SLOPE_STEEP | SLOPE_HALFTILE_MASK)) != 0) return false;
00093
00094 return ::IsHalftileSlope((::Slope)slope);
00095 }
00096
00097 bool AITile::HasTreeOnTile(TileIndex tile)
00098 {
00099 if (!::IsValidTile(tile)) return false;
00100
00101 return ::IsTileType(tile, MP_TREES);
00102 }
00103
00104 bool AITile::IsFarmTile(TileIndex tile)
00105 {
00106 if (!::IsValidTile(tile)) return false;
00107
00108 return (::IsTileType(tile, MP_CLEAR) && ::IsClearGround(tile, CLEAR_FIELDS));
00109 }
00110
00111 bool AITile::IsRockTile(TileIndex tile)
00112 {
00113 if (!::IsValidTile(tile)) return false;
00114
00115 return (::IsTileType(tile, MP_CLEAR) && ::GetRawClearGround(tile) == ::CLEAR_ROCKS);
00116 }
00117
00118 bool AITile::IsRoughTile(TileIndex tile)
00119 {
00120 if (!::IsValidTile(tile)) return false;
00121
00122 return (::IsTileType(tile, MP_CLEAR) && ::GetRawClearGround(tile) == ::CLEAR_ROUGH);
00123 }
00124
00125 bool AITile::IsSnowTile(TileIndex tile)
00126 {
00127 if (!::IsValidTile(tile)) return false;
00128
00129 return (::IsTileType(tile, MP_CLEAR) && ::IsSnowTile(tile));
00130 }
00131
00132 bool AITile::IsDesertTile(TileIndex tile)
00133 {
00134 if (!::IsValidTile(tile)) return false;
00135
00136 return (::IsTileType(tile, MP_CLEAR) && ::IsClearGround(tile, CLEAR_DESERT));
00137 }
00138
00139 AITile::Slope AITile::GetSlope(TileIndex tile)
00140 {
00141 if (!::IsValidTile(tile)) return SLOPE_INVALID;
00142
00143 return (Slope)::GetTileSlope(tile, NULL);
00144 }
00145
00146 AITile::Slope AITile::GetComplementSlope(Slope slope)
00147 {
00148 if ((slope & ~SLOPE_ELEVATED) != 0) return SLOPE_INVALID;
00149
00150 return (Slope)::ComplementSlope((::Slope)slope);
00151 }
00152
00153 int32 AITile::GetMinHeight(TileIndex tile)
00154 {
00155 if (!::IsValidTile(tile)) return -1;
00156
00157 return ::GetTileZ(tile) / ::TILE_HEIGHT;
00158 }
00159
00160 int32 AITile::GetMaxHeight(TileIndex tile)
00161 {
00162 if (!::IsValidTile(tile)) return -1;
00163
00164 return ::GetTileMaxZ(tile) / ::TILE_HEIGHT;
00165 }
00166
00167 int32 AITile::GetCornerHeight(TileIndex tile, Corner corner)
00168 {
00169 if (!::IsValidTile(tile) || !::IsValidCorner((::Corner)corner)) return -1;
00170
00171 uint z;
00172 ::Slope slope = ::GetTileSlope(tile, &z);
00173 return (z + ::GetSlopeZInCorner(slope, (::Corner)corner)) / ::TILE_HEIGHT;
00174 }
00175
00176 AICompany::CompanyID AITile::GetOwner(TileIndex tile)
00177 {
00178 if (!::IsValidTile(tile)) return AICompany::COMPANY_INVALID;
00179 if (::IsTileType(tile, MP_HOUSE)) return AICompany::COMPANY_INVALID;
00180 if (::IsTileType(tile, MP_INDUSTRY)) return AICompany::COMPANY_INVALID;
00181
00182 return AICompany::ResolveCompanyID((AICompany::CompanyID)(byte)::GetTileOwner(tile));
00183 }
00184
00185 bool AITile::HasTransportType(TileIndex tile, TransportType transport_type)
00186 {
00187 if (!::IsValidTile(tile)) return false;
00188
00189 return ::TrackStatusToTrackdirBits(::GetTileTrackStatus(tile, (::TransportType)transport_type, UINT32_MAX)) != TRACKDIR_BIT_NONE;
00190 }
00191
00192 int32 AITile::GetCargoAcceptance(TileIndex tile, CargoID cargo_type, int width, int height, int radius)
00193 {
00194 if (!::IsValidTile(tile) || width <= 0 || height <= 0 || radius < 0) return -1;
00195
00196 CargoArray acceptance = ::GetAcceptanceAroundTiles(tile, width, height, _settings_game.station.modified_catchment ? radius : (int)CA_UNMODIFIED);
00197 return acceptance[cargo_type];
00198 }
00199
00200 int32 AITile::GetCargoProduction(TileIndex tile, CargoID cargo_type, int width, int height, int radius)
00201 {
00202 if (!::IsValidTile(tile) || width <= 0 || height <= 0 || radius < 0) return -1;
00203
00204 CargoArray produced = ::GetProductionAroundTiles(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 }
00275
00276 Money AITile::GetBuildCost(BuildType build_type)
00277 {
00278 switch (build_type) {
00279 case BT_FOUNDATION: return ::GetPrice(PR_BUILD_FOUNDATION, 1, NULL);
00280 case BT_TERRAFORM: return ::GetPrice(PR_TERRAFORM, 1, NULL);
00281 case BT_BUILD_TREES: return ::GetPrice(PR_BUILD_TREES, 1, NULL);
00282 case BT_CLEAR_GRASS: return ::GetPrice(PR_CLEAR_GRASS, 1, NULL);
00283 case BT_CLEAR_ROUGH: return ::GetPrice(PR_CLEAR_ROUGH, 1, NULL);
00284 case BT_CLEAR_ROCKY: return ::GetPrice(PR_CLEAR_ROCKS, 1, NULL);
00285 case BT_CLEAR_FIELDS: return ::GetPrice(PR_CLEAR_FIELDS, 1, NULL);
00286 case BT_CLEAR_HOUSE: return ::GetPrice(PR_CLEAR_HOUSE, 1, NULL);
00287 default: return -1;
00288 }
00289 }