# ai_tile.cpp

Go to the documentation of this file.

    00001 /* $Id: ai_tile.cpp 18809 2010-01-15 16:41:15Z 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
    00023 /* static */ 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       /* Tram bits aren't considered buildable */
    00034       if (::GetRoadTypes(tile) != ROADTYPES_ROAD) return false;
    00035       /* Depots and crossings aren't considered buildable */
    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 /* static */ 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 /* static */ bool AITile::IsWaterTile(TileIndex tile)
    00061 {
    00062   if (!::IsValidTile(tile)) return false;
    00063
    00064   return ::IsTileType(tile, MP_WATER) && !::IsCoast(tile);
    00065 }
    00066
    00067 /* static */ 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 /* static */ bool AITile::IsStationTile(TileIndex tile)
    00076 {
    00077   if (!::IsValidTile(tile)) return false;
    00078
    00079   return ::IsTileType(tile, MP_STATION);
    00080 }
    00081
    00082 /* static */ 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 /* static */ 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 /* static */ bool AITile::HasTreeOnTile(TileIndex tile)
    00097 {
    00098   if (!::IsValidTile(tile)) return false;
    00099
    00100   return ::IsTileType(tile, MP_TREES);
    00101 }
    00102
    00103 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ bool AITile::IsSnowTile(TileIndex tile)
    00125 {
    00126   if (!::IsValidTile(tile)) return false;
    00127
    00128   return (::IsTileType(tile, MP_CLEAR) && ::IsSnowTile(tile));
    00129 }
    00130
    00131 /* static */ 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 /* static */ AITile::Slope AITile::GetSlope(TileIndex tile)
    00139 {
    00140   if (!::IsValidTile(tile)) return SLOPE_INVALID;
    00141
    00142   return (Slope)::GetTileSlope(tile, NULL);
    00143 }
    00144
    00145 /* static */ 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 /* static */ int32 AITile::GetMinHeight(TileIndex tile)
    00153 {
    00154   if (!::IsValidTile(tile)) return -1;
    00155
    00156   return ::GetTileZ(tile) / ::TILE_HEIGHT;
    00157 }
    00158
    00159 /* static */ int32 AITile::GetMaxHeight(TileIndex tile)
    00160 {
    00161   if (!::IsValidTile(tile)) return -1;
    00162
    00163   return ::GetTileMaxZ(tile) / ::TILE_HEIGHT;
    00164 }
    00165
    00166 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ int32 AITile::GetDistanceManhattanToTile(TileIndex tile_from, TileIndex tile_to)
    00208 {
    00209   return AIMap::DistanceManhattan(tile_from, tile_to);
    00210 }
    00211
    00212 /* static */ int32 AITile::GetDistanceSquareToTile(TileIndex tile_from, TileIndex tile_to)
    00213 {
    00214   return AIMap::DistanceSquare(tile_from, tile_to);
    00215 }
    00216
    00217 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ bool AITile::IsWithinTownInfluence(TileIndex tile, TownID town_id)
    00264 {
    00265   return AITown::IsWithinTownInfluence(town_id, tile);
    00266 }
    00267
    00268 /* static */ TownID AITile::GetClosestTown(TileIndex tile)
    00269 {
    00270   if (!::IsValidTile(tile)) return INVALID_TOWN;
    00271
    00272   return ::ClosestTownFromTile(tile, UINT_MAX)->index;
    00273 }