# town.h

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 #ifndef TOWN_H
    00013 #define TOWN_H
    00014
    00015 #include "core/pool_type.hpp"
    00016 #include "viewport_type.h"
    00017 #include "command_type.h"
    00018 #include "town_map.h"
    00019 #include "subsidy_type.h"
    00020 #include "openttd.h"
    00021 #include "table/strings.h"
    00022 #include "company_func.h"
    00023 #include "landscape.h"
    00024 #include "landscape_type.h"
    00025
    00026 template <typename T>
    00027 struct BuildingCounts {
    00028   T id_count[HOUSE_MAX];
    00029   T class_count[HOUSE_CLASS_MAX];
    00030 };
    00031
    00032 static const uint CUSTOM_TOWN_NUMBER_DIFFICULTY  = 4;
    00033 static const uint CUSTOM_TOWN_MAX_NUMBER = 5000;
    00034
    00035 static const uint INVALID_TOWN = 0xFFFF;
    00036
    00037 typedef Pool<Town, TownID, 64, 64000> TownPool;
    00038 extern TownPool _town_pool;
    00039
    00044 static const uint8 _difficulty_town_needed_for_growth[] = {
    00045   2,   // Off (@note: this value is never used but if defined as zero the game will crash !!).
    00046   2,   // Very Easy.
    00047   3,   // Easy.
    00048   4,   // Average.
    00049   5,   // Hard.
    00050   6,   // very hard.
    00051   10,  // Drive me nuts please.
    00052 };
    00053
    00055 enum TownNeededForGrowth {
    00056   GROWTH_STANDARD,
    00057   GROWTH_NEED_STATION,
    00058   GROWTH_NEED_MORE_PASS,
    00059   GROWTH_NEED_MORE_MAIL,
    00060   GROWTH_NEED_MORE_FOOD,
    00061   GROWTH_NEED_MORE_WATER,
    00062   GROWTH_NEED_MORE_GOODS,
    00063   GROWTH_NEED_PASS,
    00064   GROWTH_NEED_MAIL,
    00065   GROWTH_NEED_FOOD,
    00066   GROWTH_NEED_WATER,
    00067   GROWTH_NEED_GOODS,
    00068   GROWTH_SATISFIED,
    00069 };
    00070
    00072 struct Town : TownPool::PoolItem<&_town_pool> {
    00073   TileIndex xy;
    00074
    00075   /* Current population of people and amount of houses. */
    00076   uint32 num_houses;
    00077   uint32 population;
    00078
    00079   /* Town name */
    00080   uint32 townnamegrfid;
    00081   uint16 townnametype;
    00082   uint32 townnameparts;
    00083   char *name;
    00084
    00085   /* NOSAVE: Location of name sign, UpdateVirtCoord updates this. */
    00086   ViewportSign sign;
    00087
    00088   /* Makes sure we don't build certain house types twice.
    00089    * bit 0 = Building funds received
    00090    * bit 1 = CHURCH
    00091    * bit 2 = STADIUM */
    00092   byte flags;
    00093
    00094   /* level of noise that all the airports are generating */
    00095   uint16 noise_reached;
    00096
    00097   /* Which companies have a statue? */
    00098   CompanyMask statues;
    00099
    00100   /* Company ratings as well as a mask that determines which companies have a rating. */
    00101   CompanyMask have_ratings;
    00102   uint8 unwanted[MAX_COMPANIES];
    00103   CompanyByte exclusivity;
    00104   uint16 exclusive_counter;
    00105   int16 ratings[MAX_COMPANIES];
    00106   StringID town_label;
    00107
    00108   /* Monthly generated town cargo. */
    00109   uint32 gen_act_pass;
    00110   uint32 gen_act_mail;
    00111   uint32 gen_max_pass;
    00112   uint32 gen_max_mail;
    00113   uint32 new_gen_max_pass;
    00114   uint32 new_gen_max_mail;
    00115   uint16 new_gen_act_pass;
    00116   uint16 new_gen_act_mail;
    00117
    00118   /* Minimum amount of cargo that has to be transported to have 100 % growth ratio. */
    00119   uint32 max_pass;
    00120   uint32 max_mail;
    00121   uint32 max_food;
    00122   uint32 max_water;
    00123   uint32 max_goods;
    00124   uint32 new_max_pass;
    00125   uint32 new_max_mail;
    00126   uint32 new_max_food;
    00127   uint32 new_max_water;
    00128   uint32 new_max_goods;
    00129
    00130   /* Amount of cargo that has been transported this month. */
    00131   byte pct_pass_transported;
    00132   byte pct_mail_transported;
    00133   byte pct_food_transported;
    00134   byte pct_water_transported;
    00135   byte pct_goods_transported;
    00136
    00137   /* Amount of cargo that is currently being transported. */
    00138   uint16 act_pass;
    00139   uint16 act_mail;
    00140   uint16 act_food;
    00141   uint16 act_water;
    00142   uint16 act_goods;
    00143   uint16 new_act_pass;
    00144   uint16 new_act_mail;
    00145   uint16 new_act_food;
    00146   uint16 new_act_water;
    00147   uint16 new_act_goods;
    00148
    00149   /* Time until we rebuild a house. */
    00150   uint16 time_until_rebuild;
    00151
    00152   /* When to grow town next time. */
    00153   uint16 grow_counter;
    00154   int16 growth_rate;
    00155
    00156   /* Ratio of transported vs required cargo,
    00157    * used for calculating towngrowth rate. */
    00158   uint32 ratio;
    00159
    00160   /* Fund buildings program in action? */
    00161   byte fund_buildings_months;
    00162
    00163   /* Fund road reconstruction in action? */
    00164   byte road_build_months;
    00165
    00166   /* If this is a larger town, and should grow more quickly. */
    00167   bool larger_town;
    00168   TownLayoutByte layout;
    00169
    00170   PartOfSubsidyByte part_of_subsidy;
    00171
    00172   /* NOSAVE: UpdateTownRadius updates this given the house count. */
    00173   uint32 squared_town_zone_radius[HZB_END];
    00174
    00175   BuildingCounts<uint16> building_counts;
    00176
    00180   Town(TileIndex tile = INVALID_TILE) : xy(tile) { }
    00181
    00183   ~Town();
    00184
    00185   void InitializeLayout(TownLayout layout);
    00186
    00187   void UpdateLabel();
    00188
    00192   FORCEINLINE StringID Label() const{
    00193     if (!(_game_mode == GM_EDITOR) && (_local_company < MAX_COMPANIES)) {
    00200       if (_settings_client.gui.population_in_label) {
    00201         if (!_settings_client.gui.population_in_label_coloured) {
    00202           return STR_VIEWPORT_TOWN_POP;
    00203         } else {
    00204           return STR_VIEWPORT_TOWN_POP_VERY_POOR_RATING + this->town_label;
    00205         }
    00206       } else {
    00207         return STR_VIEWPORT_TOWN;
    00208       }
    00209     } else {
    00210       return STR_VIEWPORT_TOWN;
    00211     }
    00212   }
    00213
    00217   FORCEINLINE StringID SmallLabel() const{
    00218     if (!(_game_mode == GM_EDITOR) && (_local_company < MAX_COMPANIES)) {
    00226       if (_settings_client.gui.population_in_label_coloured && _settings_client.gui.population_in_label) {
    00227         return STR_VIEWPORT_TOWN_TINY_VERY_POOR_RATING + this->town_label;
    00228       } else {
    00229         return STR_VIEWPORT_TOWN_TINY_WHITE;
    00230       }
    00231     } else {
    00232       return STR_VIEWPORT_TOWN_TINY_WHITE;
    00233     }
    00234   }
    00235
    00242   inline uint16 MaxTownNoise() const
    00243   {
    00244     if (this->population == 0) return 0; // no population? no noise
    00245
    00246     /* 3 is added (the noise of the lowest airport), so the  user can at least build a small airfield. */
    00247     return (this->population / _settings_game.economy.town_noise_population[_settings_game.difficulty.town_council_tolerance]) + 3;
    00248   }
    00249
    00250   void UpdateVirtCoord();
    00251
    00252   static FORCEINLINE Town *GetByTile(TileIndex tile)
    00253   {
    00254     return Town::Get(GetTownIndex(tile));
    00255   }
    00256
    00257   static Town *GetRandom();
    00258   static void PostDestructor(size_t index);
    00259
    00260   /* Growthrate displayed in the gui.
    00261    * 100% is normal growth rate. */
    00262   inline uint16 GrowthRatePercent() const {
    00263     int16 default_growth_rate = 320;
    00264     uint growth_multiplier = _settings_game.economy.town_growth_rate != 0 ? _settings_game.economy.town_growth_rate - 1 : 1;
    00265     default_growth_rate >>= growth_multiplier;
    00266     default_growth_rate /= (num_houses / 50 + 1);
    00267     if (larger_town) default_growth_rate /= 2;
    00268     /* If some required cargotypes are not transported return 1.
    00269      * If growth patch is off or town is too small to demand goods calculate normally. */
    00270     if (((!larger_town && _settings_game.economy.town_growth_cargo) || (larger_town && _settings_game.economy.larger_town_growth_cargo))&&
    00271         ((!larger_town && population > _settings_game.economy.town_pop_need_goods) ||
    00272         (larger_town && population > _settings_game.economy.larger_town_pop_need_goods))) {
    00273       if ((_settings_game.game_creation.landscape == LT_TEMPERATE ||
    00274           _settings_game.game_creation.landscape == LT_TOYLAND ||
    00275           (_settings_game.game_creation.landscape == LT_ARCTIC && TilePixelHeight(this->xy) < GetSnowLine()) ||
    00276           (_settings_game.game_creation.landscape == LT_TROPIC && GetTropicZone(this->xy) == TROPICZONE_DESERT)) &&
    00277           (act_pass == 0 || act_mail == 0 || act_goods == 0)) {
    00278         return 1;
    00279       } else if (_settings_game.game_creation.landscape == LT_ARCTIC &&
    00280           TilePixelHeight(this->xy) >= GetSnowLine() &&
    00281           (act_pass == 0 || act_mail == 0 || act_goods == 0 || act_food == 0)) {
    00282         return 1;
    00283       } else if (_settings_game.game_creation.landscape == LT_TROPIC &&
    00284           GetTropicZone(this->xy) == TROPICZONE_DESERT &&
    00285           (act_pass == 0 || act_mail == 0 || act_goods == 0  || act_food == 0|| act_water == 0)) {
    00286         return 1;
    00287       } else {
    00288         return 320 * this->transported_goods_percent / 100;
    00289       }
    00290     } else {
    00291       return (uint16)((1 / (double)growth_rate) * default_growth_rate * 320);
    00292     }
    00293   }
    00294
    00295   byte transported_goods_percent;
    00296   byte needed_for_growth;
    00297 };
    00298
    00299 uint32 GetWorldPopulation();
    00300
    00301 void UpdateAllTownVirtCoords();
    00302 void ShowTownViewWindow(TownID town);
    00303 void ExpandTown(Town *t);
    00304
    00309 enum TownRatingCheckType {
    00310   ROAD_REMOVE         = 0,
    00311   TUNNELBRIDGE_REMOVE = 1,
    00312   TOWN_RATING_CHECK_TYPE_COUNT,
    00313 };
    00314
    00322 enum TownFlags {
    00323   TOWN_IS_FUNDED      = 0,
    00324   TOWN_HAS_CHURCH     = 1,
    00325   TOWN_HAS_STADIUM    = 2
    00326 };
    00327
    00328 CommandCost CheckforTownRating(DoCommandFlag flags, Town *t, TownRatingCheckType type);
    00329
    00330
    00331 TileIndexDiff GetHouseNorthPart(HouseID &house);
    00332
    00333 Town *CalcClosestTownFromTile(TileIndex tile, uint threshold = UINT_MAX);
    00334
    00335 #define FOR_ALL_TOWNS_FROM(var, start) FOR_ALL_ITEMS_FROM(Town, town_index, var, start)
    00336 #define FOR_ALL_TOWNS(var) FOR_ALL_TOWNS_FROM(var, 0)
    00337
    00338 void ResetHouses();
    00339
    00340 void ClearTownHouse(Town *t, TileIndex tile);
    00341 void UpdateTownGenCargo(Town *t);
    00342 void UpdateTownDemands(Town *t);
    00343 void UpdateTownRadius(Town *t);
    00344 CommandCost CheckIfAuthorityAllowsNewStation(TileIndex tile, DoCommandFlag flags);
    00345 Town *ClosestTownFromTile(TileIndex tile, uint threshold);
    00346 void ChangeTownRating(Town *t, int add, int max, DoCommandFlag flags);
    00347 HouseZonesBits GetTownRadiusGroup(const Town *t, TileIndex tile);
    00348 void SetTownRatingTestMode(bool mode);
    00349 uint GetMaskOfTownActions(int *nump, CompanyID cid, const Town *t);
    00350 bool GenerateTowns(TownLayout layout);
    00351
    00353 enum TownActions {
    00354   TACT_NONE             = 0x00,
    00355
    00356   TACT_ADVERTISE_SMALL  = 0x01,
    00357   TACT_ADVERTISE_MEDIUM = 0x02,
    00358   TACT_ADVERTISE_LARGE  = 0x04,
    00359   TACT_ROAD_REBUILD     = 0x08,
    00360   TACT_BUILD_STATUE     = 0x10,
    00361   TACT_FOUND_BUILDINGS  = 0x20,
    00362   TACT_BUY_RIGHTS       = 0x40,
    00363   TACT_BRIBE            = 0x80,
    00364
    00365   TACT_COUNT            = 8,
    00366
    00367   TACT_ADVERTISE        = TACT_ADVERTISE_SMALL | TACT_ADVERTISE_MEDIUM | TACT_ADVERTISE_LARGE,
    00368   TACT_CONSTRUCTION     = TACT_ROAD_REBUILD | TACT_BUILD_STATUE | TACT_FOUND_BUILDINGS,
    00369   TACT_FUNDS            = TACT_BUY_RIGHTS | TACT_BRIBE,
    00370   TACT_ALL              = TACT_ADVERTISE | TACT_CONSTRUCTION | TACT_FUNDS,
    00371 };
    00372 DECLARE_ENUM_AS_BIT_SET(TownActions)
    00373
    00374 extern const byte _town_action_costs[TACT_COUNT];
    00375 extern TownID _new_town_id;
    00376
    00382 template <class T>
    00383 void MakeDefaultName(T *obj)
    00384 {
    00385   /* We only want to set names if it hasn't been set before, or when we're calling from afterload. */
    00386   assert(obj->name == NULL || obj->town_cn == UINT16_MAX);
    00387
    00388   obj->town = ClosestTownFromTile(obj->xy, UINT_MAX);
    00389
    00390   /* Find first unused number belonging to this town. This can never fail,
    00391    * as long as there can be at most 65535 waypoints/depots in total.
    00392    *
    00393    * This does 'n * m' search, but with 32bit 'used' bitmap, it needs at
    00394    * most 'n * (1 + ceil(m / 32))' steps (n - number of waypoints in pool,
    00395    * m - number of waypoints near this town).
    00396    * Usually, it needs only 'n' steps.
    00397    *
    00398    * If it wasn't using 'used' and 'idx', it would just search for increasing 'next',
    00399    * but this way it is faster */
    00400
    00401   uint32 used = 0; // bitmap of used waypoint numbers, sliding window with 'next' as base
    00402   uint32 next = 0; // first number in the bitmap
    00403   uint32 idx  = 0; // index where we will stop
    00404   uint32 cid  = 0; // current index, goes to T::GetPoolSize()-1, then wraps to 0
    00405
    00406   do {
    00407     T *lobj = T::GetIfValid(cid);
    00408
    00409     /* check only valid waypoints... */
    00410     if (lobj != NULL && obj != lobj) {
    00411       /* only objects within the same city and with the same type */
    00412       if (lobj->town == obj->town && lobj->IsOfType(obj)) {
    00413         /* if lobj->town_cn < next, uint will overflow to '+inf' */
    00414         uint i = (uint)lobj->town_cn - next;
    00415
    00416         if (i < 32) {
    00417           SetBit(used, i); // update bitmap
    00418           if (i == 0) {
    00419             /* shift bitmap while the lowest bit is '1';
    00420              * increase the base of the bitmap too */
    00421             do {
    00422               used >>= 1;
    00423               next++;
    00424             } while (HasBit(used, 0));
    00425             /* when we are at 'idx' again at end of the loop and
    00426              * 'next' hasn't changed, then no object had town_cn == next,
    00427              * so we can safely use it */
    00428             idx = cid;
    00429           }
    00430         }
    00431       }
    00432     }
    00433
    00434     cid++;
    00435     if (cid == T::GetPoolSize()) cid = 0; // wrap to zero...
    00436   } while (cid != idx);
    00437
    00438   obj->town_cn = (uint16)next; // set index...
    00439 }
    00440
    00441 #endif /* TOWN_H */