# ai_tilelist.cpp

Go to the documentation of this file.

    00001 /* $Id: ai_tilelist.cpp 16531 2009-06-07 15:26:33Z rubidium $ */
    00002
    00005 #include "ai_tilelist.hpp"
    00006 #include "ai_industry.hpp"
    00007 #include "../../tile_map.h"
    00008 #include "../../industry_map.h"
    00009 #include "../../station_map.h"
    00010 #include "../../settings_type.h"
    00011
    00012 void AITileList::FixRectangleSpan(TileIndex &t1, TileIndex &t2)
    00013 {
    00014   uint x1 = ::TileX(t1);
    00015   uint x2 = ::TileX(t2);
    00016
    00017   uint y1 = ::TileY(t1);
    00018   uint y2 = ::TileY(t2);
    00019
    00020   if (x1 >= x2) ::Swap(x1, x2);
    00021   if (y1 >= y2) ::Swap(y1, y2);
    00022
    00023   t1 = ::TileXY(x1, y1);
    00024   t2 = ::TileXY(x2, y2);
    00025 }
    00026
    00027 void AITileList::AddRectangle(TileIndex t1, TileIndex t2)
    00028 {
    00029   if (!::IsValidTile(t1)) return;
    00030   if (!::IsValidTile(t2)) return;
    00031
    00032   this->FixRectangleSpan(t1, t2);
    00033
    00034   uint w = TileX(t2) - TileX(t1) + 1;
    00035   uint h = TileY(t2) - TileY(t1) + 1;
    00036
    00037   BEGIN_TILE_LOOP(t, w, h, t1) {
    00038     this->AddItem(t);
    00039   } END_TILE_LOOP(t, w, h, t1)
    00040 }
    00041
    00042 void AITileList::AddTile(TileIndex tile)
    00043 {
    00044   if (!::IsValidTile(tile)) return;
    00045
    00046   this->AddItem(tile);
    00047 }
    00048
    00049 void AITileList::RemoveRectangle(TileIndex t1, TileIndex t2)
    00050 {
    00051   if (!::IsValidTile(t1)) return;
    00052   if (!::IsValidTile(t2)) return;
    00053
    00054   this->FixRectangleSpan(t1, t2);
    00055
    00056   uint w = TileX(t2) - TileX(t1) + 1;
    00057   uint h = TileY(t2) - TileY(t1) + 1;
    00058
    00059   BEGIN_TILE_LOOP(t, w, h, t1) {
    00060     this->RemoveItem(t);
    00061   } END_TILE_LOOP(t, w, h, t1)
    00062 }
    00063
    00064 void AITileList::RemoveTile(TileIndex tile)
    00065 {
    00066   if (!::IsValidTile(tile)) return;
    00067
    00068   this->RemoveItem(tile);
    00069 }
    00070
    00071 AITileList_IndustryAccepting::AITileList_IndustryAccepting(IndustryID industry_id, int radius)
    00072 {
    00073   if (!AIIndustry::IsValidIndustry(industry_id) || radius <= 0) return;
    00074
    00075   const Industry *i = ::GetIndustry(industry_id);
    00076
    00077   /* Check if this industry accepts anything */
    00078   {
    00079     bool cargo_accepts = false;
    00080     for (byte j = 0; j < lengthof(i->accepts_cargo); j++) {
    00081       if (i->accepts_cargo[j] != CT_INVALID) cargo_accepts = true;
    00082     }
    00083     if (!cargo_accepts) return;
    00084   }
    00085
    00086   if (!_settings_game.station.modified_catchment) radius = CA_UNMODIFIED;
    00087
    00088   BEGIN_TILE_LOOP(cur_tile, i->width + radius * 2, i->height + radius * 2, i->xy - ::TileDiffXY(radius, radius)) {
    00089     if (!::IsValidTile(cur_tile)) continue;
    00090     /* Exclude all tiles that belong to this industry */
    00091     if (::IsTileType(cur_tile, MP_INDUSTRY) && ::GetIndustryIndex(cur_tile) == industry_id) continue;
    00092
    00093     /* Only add the tile if it accepts the cargo (sometimes just 1 tile of an
    00094      *  industry triggers the acceptance). */
    00095     AcceptedCargo accepts;
    00096 		::GetAcceptanceAroundTiles(accepts, cur_tile, 1, 1, radius);
    00097     {
    00098       bool cargo_accepts = false;
    00099       for (byte j = 0; j < lengthof(i->accepts_cargo); j++) {
    00100         if (i->accepts_cargo[j] != CT_INVALID && accepts[i->accepts_cargo[j]] != 0) cargo_accepts = true;
    00101       }
    00102       if (!cargo_accepts) continue;
    00103     }
    00104
    00105     this->AddTile(cur_tile);
    00106   } END_TILE_LOOP(cur_tile, i->width + radius * 2, i->height + radius * 2, i->xy - ::TileDiffXY(radius, radius))
    00107 }
    00108
    00109 AITileList_IndustryProducing::AITileList_IndustryProducing(IndustryID industry_id, int radius)
    00110 {
    00111   if (!AIIndustry::IsValidIndustry(industry_id) || radius <= 0) return;
    00112
    00113   const Industry *i = ::GetIndustry(industry_id);
    00114
    00115   /* Check if this industry produces anything */
    00116   {
    00117     bool cargo_produces = false;
    00118     for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
    00119       if (i->produced_cargo[j] != CT_INVALID) cargo_produces = true;
    00120     }
    00121     if (!cargo_produces) return;
    00122   }
    00123
    00124   if (!_settings_game.station.modified_catchment) radius = CA_UNMODIFIED;
    00125
    00126   BEGIN_TILE_LOOP(cur_tile, i->width + radius * 2, i->height + radius * 2, i->xy - ::TileDiffXY(radius, radius)) {
    00127     if (!::IsValidTile(cur_tile)) continue;
    00128     /* Exclude all tiles that belong to this industry */
    00129     if (::IsTileType(cur_tile, MP_INDUSTRY) && ::GetIndustryIndex(cur_tile) == industry_id) continue;
    00130
    00131     /* Only add the tile if it produces the cargo (a bug in OpenTTD makes this
    00132      *  inconsitance). */
    00133     AcceptedCargo produces;
    00134 		::GetProductionAroundTiles(produces, cur_tile, 1, 1, radius);
    00135     {
    00136       bool cargo_produces = false;
    00137       for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
    00138         if (i->produced_cargo[j] != CT_INVALID && produces[i->produced_cargo[j]] != 0) cargo_produces = true;
    00139       }
    00140       if (!cargo_produces) continue;
    00141     }
    00142
    00143     this->AddTile(cur_tile);
    00144   } END_TILE_LOOP(cur_tile, i->width + radius * 2, i->height + radius * 2, i->xy - ::TileDiffXY(radius, radius))
    00145 }
    00146
    00147 AITileList_StationType::AITileList_StationType(StationID station_id, AIStation::StationType station_type)
    00148 {
    00149   if (!AIStation::IsValidStation(station_id)) return;
    00150
    00151   const StationRect *rect = &::GetStation(station_id)->rect;
    00152
    00153   uint station_type_value = 0;
    00154   /* Convert AIStation::StationType to ::StationType, but do it in a
    00155    *  bitmask, so we can scan for multiple entries at the same time. */
    00156   if ((station_type & AIStation::STATION_TRAIN) != 0)      station_type_value |= (1 << ::STATION_RAIL);
    00157   if ((station_type & AIStation::STATION_TRUCK_STOP) != 0) station_type_value |= (1 << ::STATION_TRUCK);
    00158   if ((station_type & AIStation::STATION_BUS_STOP) != 0)   station_type_value |= (1 << ::STATION_BUS);
    00159   if ((station_type & AIStation::STATION_AIRPORT) != 0)    station_type_value |= (1 << ::STATION_AIRPORT) | (1 << ::STATION_OILRIG);
    00160   if ((station_type & AIStation::STATION_DOCK) != 0)       station_type_value |= (1 << ::STATION_DOCK)    | (1 << ::STATION_OILRIG);
    00161
    00162   BEGIN_TILE_LOOP(cur_tile, rect->right - rect->left + 1, rect->bottom - rect->top + 1, ::TileXY(rect->left, rect->top)) {
    00163     if (!::IsTileType(cur_tile, MP_STATION)) continue;
    00164     if (::GetStationIndex(cur_tile) != station_id) continue;
    00165     if (!HasBit(station_type_value, ::GetStationType(cur_tile))) continue;
    00166     this->AddTile(cur_tile);
    00167   } END_TILE_LOOP(cur_tile, rect->right - rect->left + 1, rect->bottom - rect->top + 1, ::TileXY(rect->left, rect->top))
    00168 }