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