# ai_tile.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    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 "../../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 /* static */ 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       /* Tram bits aren't considered buildable */
    00036       if (::GetRoadTypes(tile) != ROADTYPES_ROAD) return false;
    00037       /* Depots and crossings aren't considered buildable */
    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 /* static */ 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 /* static */ bool AITile::IsWaterTile(TileIndex tile)
    00063 {
    00064   if (!::IsValidTile(tile)) return false;
    00065
    00066   return ::IsTileType(tile, MP_WATER) && !::IsCoast(tile);
    00067 }
    00068
    00069 /* static */ 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 /* static */ bool AITile::IsStationTile(TileIndex tile)
    00078 {
    00079   if (!::IsValidTile(tile)) return false;
    00080
    00081   return ::IsTileType(tile, MP_STATION);
    00082 }
    00083
    00084 /* static */ 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 /* static */ 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 /* static */ bool AITile::HasTreeOnTile(TileIndex tile)
    00099 {
    00100   if (!::IsValidTile(tile)) return false;
    00101
    00102   return ::IsTileType(tile, MP_TREES);
    00103 }
    00104
    00105 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ bool AITile::IsSnowTile(TileIndex tile)
    00127 {
    00128   if (!::IsValidTile(tile)) return false;
    00129
    00130   return (::IsTileType(tile, MP_CLEAR) && ::IsSnowTile(tile));
    00131 }
    00132
    00133 /* static */ 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 /* static */ AITile::Slope AITile::GetSlope(TileIndex tile)
    00141 {
    00142   if (!::IsValidTile(tile)) return SLOPE_INVALID;
    00143
    00144   return (Slope)::GetTileSlope(tile, NULL);
    00145 }
    00146
    00147 /* static */ 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 /* static */ int32 AITile::GetMinHeight(TileIndex tile)
    00155 {
    00156   if (!::IsValidTile(tile)) return -1;
    00157
    00158   return ::GetTileZ(tile) / ::TILE_HEIGHT;
    00159 }
    00160
    00161 /* static */ int32 AITile::GetMaxHeight(TileIndex tile)
    00162 {
    00163   if (!::IsValidTile(tile)) return -1;
    00164
    00165   return ::GetTileMaxZ(tile) / ::TILE_HEIGHT;
    00166 }
    00167
    00168 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ int32 AITile::GetDistanceManhattanToTile(TileIndex tile_from, TileIndex tile_to)
    00210 {
    00211   return AIMap::DistanceManhattan(tile_from, tile_to);
    00212 }
    00213
    00214 /* static */ int32 AITile::GetDistanceSquareToTile(TileIndex tile_from, TileIndex tile_to)
    00215 {
    00216   return AIMap::DistanceSquare(tile_from, tile_to);
    00217 }
    00218
    00219 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ 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 /* static */ bool AITile::IsWithinTownInfluence(TileIndex tile, TownID town_id)
    00266 {
    00267   return AITown::IsWithinTownInfluence(town_id, tile);
    00268 }
    00269
    00270 /* static */ TownID AITile::GetClosestTown(TileIndex tile)
    00271 {
    00272   if (!::IsValidTile(tile)) return INVALID_TOWN;
    00273
    00274   return ::ClosestTownFromTile(tile, UINT_MAX)->index;
    00275 }
    00276
    00277 /* static */ 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 }