# ai_tile.cpp

Go to the documentation of this file.

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