# ai_tile.cpp

Go to the documentation of this file.

    00001 /* $Id: ai_tile.cpp 19646 2010-04-16 22:02:33Z rubidium $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    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 /* static */ 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       /* Tram bits aren't considered buildable */
    00035       if (::GetRoadTypes(tile) != ROADTYPES_ROAD) return false;
    00036       /* Depots and crossings aren't considered buildable */
    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 /* static */ 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 /* static */ bool AITile::IsWaterTile(TileIndex tile)
    00062 {
    00063   if (!::IsValidTile(tile)) return false;
    00064
    00065   return ::IsTileType(tile, MP_WATER) && !::IsCoast(tile);
    00066 }
    00067
    00068 /* static */ 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 /* static */ bool AITile::IsStationTile(TileIndex tile)
    00077 {
    00078   if (!::IsValidTile(tile)) return false;
    00079
    00080   return ::IsTileType(tile, MP_STATION);
    00081 }
    00082
    00083 /* static */ 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 /* static */ 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 /* static */ bool AITile::HasTreeOnTile(TileIndex tile)
    00098 {
    00099   if (!::IsValidTile(tile)) return false;
    00100
    00101   return ::IsTileType(tile, MP_TREES);
    00102 }
    00103
    00104 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ bool AITile::IsSnowTile(TileIndex tile)
    00126 {
    00127   if (!::IsValidTile(tile)) return false;
    00128
    00129   return (::IsTileType(tile, MP_CLEAR) && ::IsSnowTile(tile));
    00130 }
    00131
    00132 /* static */ 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 /* static */ AITile::Slope AITile::GetSlope(TileIndex tile)
    00140 {
    00141   if (!::IsValidTile(tile)) return SLOPE_INVALID;
    00142
    00143   return (Slope)::GetTileSlope(tile, NULL);
    00144 }
    00145
    00146 /* static */ 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 /* static */ int32 AITile::GetMinHeight(TileIndex tile)
    00154 {
    00155   if (!::IsValidTile(tile)) return -1;
    00156
    00157   return ::GetTileZ(tile) / ::TILE_HEIGHT;
    00158 }
    00159
    00160 /* static */ int32 AITile::GetMaxHeight(TileIndex tile)
    00161 {
    00162   if (!::IsValidTile(tile)) return -1;
    00163
    00164   return ::GetTileMaxZ(tile) / ::TILE_HEIGHT;
    00165 }
    00166
    00167 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ int32 AITile::GetDistanceManhattanToTile(TileIndex tile_from, TileIndex tile_to)
    00209 {
    00210   return AIMap::DistanceManhattan(tile_from, tile_to);
    00211 }
    00212
    00213 /* static */ int32 AITile::GetDistanceSquareToTile(TileIndex tile_from, TileIndex tile_to)
    00214 {
    00215   return AIMap::DistanceSquare(tile_from, tile_to);
    00216 }
    00217
    00218 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ bool AITile::PlantTree(TileIndex tile)
    00248 {
    00249   EnforcePrecondition(false, ::IsValidTile(tile));
    00250
    00251   return AIObject::DoCommand(tile, TREE_INVALID, tile, CMD_PLANT_TREE);
    00252 }
    00253
    00254 /* static */ 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, TREE_INVALID, end_tile, CMD_PLANT_TREE);
    00262 }
    00263
    00264 /* static */ bool AITile::IsWithinTownInfluence(TileIndex tile, TownID town_id)
    00265 {
    00266   return AITown::IsWithinTownInfluence(town_id, tile);
    00267 }
    00268
    00269 /* static */ TownID AITile::GetClosestTown(TileIndex tile)
    00270 {
    00271   if (!::IsValidTile(tile)) return INVALID_TOWN;
    00272
    00273   return ::ClosestTownFromTile(tile, UINT_MAX)->index;
    00274 }
    00275
    00276 /* static */ 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 }