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