town_cmd.cpp

Go to the documentation of this file.
00001 /* $Id: town_cmd.cpp 14933 2009-01-09 14:59:02Z rubidium $ */
00002 
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "tile_cmd.h"
00008 #include "debug.h"
00009 #include "road_map.h"
00010 #include "road_internal.h" /* Cleaning up road bits */
00011 #include "road_cmd.h"
00012 #include "landscape.h"
00013 #include "town_map.h"
00014 #include "tunnel_map.h"
00015 #include "viewport_func.h"
00016 #include "town.h"
00017 #include "command_func.h"
00018 #include "industry.h"
00019 #include "station_base.h"
00020 #include "company_base.h"
00021 #include "news_func.h"
00022 #include "gui.h"
00023 #include "unmovable_map.h"
00024 #include "water_map.h"
00025 #include "variables.h"
00026 #include "bridge.h"
00027 #include "bridge_map.h"
00028 #include "genworld.h"
00029 #include "newgrf.h"
00030 #include "newgrf_callbacks.h"
00031 #include "newgrf_house.h"
00032 #include "newgrf_commons.h"
00033 #include "newgrf_townname.h"
00034 #include "autoslope.h"
00035 #include "waypoint.h"
00036 #include "transparency.h"
00037 #include "tunnelbridge_map.h"
00038 #include "strings_func.h"
00039 #include "window_func.h"
00040 #include "string_func.h"
00041 #include "newgrf_cargo.h"
00042 #include "oldpool_func.h"
00043 #include "sprite.h"
00044 #include "economy_func.h"
00045 #include "station_func.h"
00046 #include "cheat_func.h"
00047 #include "functions.h"
00048 #include "animated_tile_func.h"
00049 #include "date_func.h"
00050 #include "core/smallmap_type.hpp"
00051 
00052 #include "table/strings.h"
00053 #include "table/sprites.h"
00054 #include "table/town_land.h"
00055 
00056 uint _total_towns;
00057 HouseSpec _house_specs[HOUSE_MAX];
00058 
00059 Town *_cleared_town;
00060 int _cleared_town_rating;
00061 
00062 /* Initialize the town-pool */
00063 DEFINE_OLD_POOL_GENERIC(Town, Town)
00064 
00065 Town::Town(TileIndex tile)
00066 {
00067   if (tile != INVALID_TILE) _total_towns++;
00068   this->xy = tile;
00069 }
00070 
00071 Town::~Town()
00072 {
00073   free(this->name);
00074 
00075   if (CleaningPool()) return;
00076 
00077   Industry *i;
00078 
00079   /* Delete town authority window
00080    * and remove from list of sorted towns */
00081   DeleteWindowById(WC_TOWN_VIEW, this->index);
00082   InvalidateWindowData(WC_TOWN_DIRECTORY, 0, 0);
00083   _total_towns--;
00084 
00085   /* Delete all industries belonging to the town */
00086   FOR_ALL_INDUSTRIES(i) if (i->town == this) delete i;
00087 
00088   /* Go through all tiles and delete those belonging to the town */
00089   for (TileIndex tile = 0; tile < MapSize(); ++tile) {
00090     switch (GetTileType(tile)) {
00091       case MP_HOUSE:
00092         if (GetTownByTile(tile) == this) DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
00093         break;
00094 
00095       case MP_ROAD:
00096         /* Cached nearest town is updated later (after this town has been deleted) */
00097         if (HasTownOwnedRoad(tile) && GetTownIndex(tile) == this->index) {
00098           DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
00099         }
00100         break;
00101 
00102       case MP_TUNNELBRIDGE:
00103         if (IsTileOwner(tile, OWNER_TOWN) &&
00104             ClosestTownFromTile(tile, UINT_MAX) == this)
00105           DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
00106         break;
00107 
00108       default:
00109         break;
00110     }
00111   }
00112 
00113   DeleteSubsidyWithTown(this->index);
00114 
00115   MarkWholeScreenDirty();
00116 
00117   this->xy = INVALID_TILE;
00118 
00119   UpdateNearestTownForRoadTiles(false);
00120 }
00121 
00127 void Town::InitializeLayout()
00128 {
00129   this->layout = (TownLayout)(TileHash(TileX(this->xy), TileY(this->xy)) % NUM_TLS);
00130 
00131   /* Set invalid layouts to valid ones */
00132   switch (this->layout) {
00133     default: break;
00134     case TL_RANDOM: this->layout = TL_ORIGINAL; break;
00135     case TL_NO_ROADS: this->layout = TL_BETTER_ROADS; break;
00136   }
00137 }
00138 
00139 Money HouseSpec::GetRemovalCost() const
00140 {
00141   return (_price.remove_house * this->removal_cost) >> 8;
00142 }
00143 
00144 // Local
00145 static int _grow_town_result;
00146 
00147 /* Describe the possible states */
00148 enum TownGrowthResult {
00149   GROWTH_SUCCEED         = -1,
00150   GROWTH_SEARCH_STOPPED  =  0
00151 //  GROWTH_SEARCH_RUNNING >=  1
00152 };
00153 
00154 static bool BuildTownHouse(Town *t, TileIndex tile);
00155 
00156 static void TownDrawHouseLift(const TileInfo *ti)
00157 {
00158   AddChildSpriteScreen(SPR_LIFT, PAL_NONE, 14, 60 - GetLiftPosition(ti->tile));
00159 }
00160 
00161 typedef void TownDrawTileProc(const TileInfo *ti);
00162 static TownDrawTileProc *const _town_draw_tile_procs[1] = {
00163   TownDrawHouseLift
00164 };
00165 
00171 static inline DiagDirection RandomDiagDir()
00172 {
00173   return (DiagDirection)(3 & Random());
00174 }
00175 
00181 static void DrawTile_Town(TileInfo *ti)
00182 {
00183   HouseID house_id = GetHouseType(ti->tile);
00184 
00185   if (house_id >= NEW_HOUSE_OFFSET) {
00186     /* Houses don't necessarily need new graphics. If they don't have a
00187      * spritegroup associated with them, then the sprite for the substitute
00188      * house id is drawn instead. */
00189     if (GetHouseSpecs(house_id)->spritegroup != NULL) {
00190       DrawNewHouseTile(ti, house_id);
00191       return;
00192     } else {
00193       house_id = GetHouseSpecs(house_id)->substitute_id;
00194     }
00195   }
00196 
00197   /* Retrieve pointer to the draw town tile struct */
00198   const DrawBuildingsTileStruct *dcts = &_town_draw_tile_data[house_id << 4 | TileHash2Bit(ti->x, ti->y) << 2 | GetHouseBuildingStage(ti->tile)];
00199 
00200   if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
00201 
00202   DrawGroundSprite(dcts->ground.sprite, dcts->ground.pal);
00203 
00204   /* If houses are invisible, do not draw the upper part */
00205   if (IsInvisibilitySet(TO_HOUSES)) return;
00206 
00207   /* Add a house on top of the ground? */
00208   SpriteID image = dcts->building.sprite;
00209   if (image != 0) {
00210     AddSortableSpriteToDraw(image, dcts->building.pal,
00211       ti->x + dcts->subtile_x,
00212       ti->y + dcts->subtile_y,
00213       dcts->width,
00214       dcts->height,
00215       dcts->dz,
00216       ti->z,
00217       IsTransparencySet(TO_HOUSES)
00218     );
00219 
00220     if (IsTransparencySet(TO_HOUSES)) return;
00221   }
00222 
00223   {
00224     int proc = dcts->draw_proc - 1;
00225 
00226     if (proc >= 0) _town_draw_tile_procs[proc](ti);
00227   }
00228 }
00229 
00230 static uint GetSlopeZ_Town(TileIndex tile, uint x, uint y)
00231 {
00232   return GetTileMaxZ(tile);
00233 }
00234 
00236 static Foundation GetFoundation_Town(TileIndex tile, Slope tileh)
00237 {
00238   return FlatteningFoundation(tileh);
00239 }
00240 
00247 static void AnimateTile_Town(TileIndex tile)
00248 {
00249   if (GetHouseType(tile) >= NEW_HOUSE_OFFSET) {
00250     AnimateNewHouseTile(tile);
00251     return;
00252   }
00253 
00254   if (_tick_counter & 3) return;
00255 
00256   /* If the house is not one with a lift anymore, then stop this animating.
00257    * Not exactly sure when this happens, but probably when a house changes.
00258    * Before this was just a return...so it'd leak animated tiles..
00259    * That bug seems to have been here since day 1?? */
00260   if (!(GetHouseSpecs(GetHouseType(tile))->building_flags & BUILDING_IS_ANIMATED)) {
00261     DeleteAnimatedTile(tile);
00262     return;
00263   }
00264 
00265   if (!LiftHasDestination(tile)) {
00266     uint i;
00267 
00268     /* Building has 6 floors, number 0 .. 6, where 1 is illegal.
00269      * This is due to the fact that the first floor is, in the graphics,
00270      *  the height of 2 'normal' floors.
00271      * Furthermore, there are 6 lift positions from floor N (incl) to floor N + 1 (excl) */
00272     do {
00273       i = RandomRange(7);
00274     } while (i == 1 || i * 6 == GetLiftPosition(tile));
00275 
00276     SetLiftDestination(tile, i);
00277   }
00278 
00279   int pos = GetLiftPosition(tile);
00280   int dest = GetLiftDestination(tile) * 6;
00281   pos += (pos < dest) ? 1 : -1;
00282   SetLiftPosition(tile, pos);
00283 
00284   if (pos == dest) {
00285     HaltLift(tile);
00286     DeleteAnimatedTile(tile);
00287   }
00288 
00289   MarkTileDirtyByTile(tile);
00290 }
00291 
00298 static bool IsCloseToTown(TileIndex tile, uint dist)
00299 {
00300   const Town *t;
00301 
00302   FOR_ALL_TOWNS(t) {
00303     if (DistanceManhattan(tile, t->xy) < dist) return true;
00304   }
00305   return false;
00306 }
00307 
00316 static void MarkTownSignDirty(Town *t)
00317 {
00318   MarkAllViewportsDirty(
00319     t->sign.left - 6,
00320     t->sign.top - 3,
00321     t->sign.left + t->sign.width_1 * 4 + 12,
00322     t->sign.top + 45
00323   );
00324 }
00325 
00331 void UpdateTownVirtCoord(Town *t)
00332 {
00333   MarkTownSignDirty(t);
00334   Point pt = RemapCoords2(TileX(t->xy) * TILE_SIZE, TileY(t->xy) * TILE_SIZE);
00335   SetDParam(0, t->index);
00336   SetDParam(1, t->population);
00337   UpdateViewportSignPos(&t->sign, pt.x, pt.y - 24,
00338     _settings_client.gui.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL);
00339   MarkTownSignDirty(t);
00340 }
00341 
00343 void UpdateAllTownVirtCoords()
00344 {
00345   Town *t;
00346   FOR_ALL_TOWNS(t) {
00347     UpdateTownVirtCoord(t);
00348   }
00349 }
00350 
00356 static void ChangePopulation(Town *t, int mod)
00357 {
00358   t->population += mod;
00359   InvalidateWindow(WC_TOWN_VIEW, t->index);
00360   UpdateTownVirtCoord(t);
00361 
00362   InvalidateWindowData(WC_TOWN_DIRECTORY, 0, 1);
00363 }
00364 
00370 uint32 GetWorldPopulation()
00371 {
00372   uint32 pop = 0;
00373   const Town *t;
00374 
00375   FOR_ALL_TOWNS(t) pop += t->population;
00376   return pop;
00377 }
00378 
00383 static void MakeSingleHouseBigger(TileIndex tile)
00384 {
00385   assert(IsTileType(tile, MP_HOUSE));
00386 
00387   /* means it is completed, get out. */
00388   if (LiftHasDestination(tile)) return;
00389 
00390   /* progress in construction stages */
00391   IncHouseConstructionTick(tile);
00392   if (GetHouseConstructionTick(tile) != 0) return;
00393 
00394   const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
00395 
00396   /* Check and/or  */
00397   if (HasBit(hs->callback_mask, CBM_HOUSE_CONSTRUCTION_STATE_CHANGE)) {
00398     uint16 callback_res = GetHouseCallback(CBID_HOUSE_CONSTRUCTION_STATE_CHANGE, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
00399     if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(hs->grffile, tile, callback_res);
00400   }
00401 
00402   if (IsHouseCompleted(tile)) {
00403     /* Now that construction is complete, we can add the population of the
00404      * building to the town. */
00405     ChangePopulation(GetTownByTile(tile), hs->population);
00406     ResetHouseAge(tile);
00407   }
00408   MarkTileDirtyByTile(tile);
00409 }
00410 
00414 static void MakeTownHouseBigger(TileIndex tile)
00415 {
00416   uint flags = GetHouseSpecs(GetHouseType(tile))->building_flags;
00417   if (flags & BUILDING_HAS_1_TILE)  MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 0));
00418   if (flags & BUILDING_2_TILES_Y)   MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 1));
00419   if (flags & BUILDING_2_TILES_X)   MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 0));
00420   if (flags & BUILDING_HAS_4_TILES) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 1));
00421 }
00422 
00429 static void TileLoop_Town(TileIndex tile)
00430 {
00431   HouseID house_id = GetHouseType(tile);
00432 
00433   /* NewHouseTileLoop returns false if Callback 21 succeeded, i.e. the house
00434    * doesn't exist any more, so don't continue here. */
00435   if (house_id >= NEW_HOUSE_OFFSET && !NewHouseTileLoop(tile)) return;
00436 
00437   if (!IsHouseCompleted(tile)) {
00438     /* Construction is not completed. See if we can go further in construction*/
00439     MakeTownHouseBigger(tile);
00440     return;
00441   }
00442 
00443   const HouseSpec *hs = GetHouseSpecs(house_id);
00444 
00445   /* If the lift has a destination, it is already an animated tile. */
00446   if ((hs->building_flags & BUILDING_IS_ANIMATED) &&
00447       house_id < NEW_HOUSE_OFFSET &&
00448       !LiftHasDestination(tile) &&
00449       Chance16(1, 2)) {
00450     AddAnimatedTile(tile);
00451   }
00452 
00453   Town *t = GetTownByTile(tile);
00454   uint32 r = Random();
00455 
00456   if (HasBit(hs->callback_mask, CBM_HOUSE_PRODUCE_CARGO)) {
00457     for (uint i = 0; i < 256; i++) {
00458       uint16 callback = GetHouseCallback(CBID_HOUSE_PRODUCE_CARGO, i, r, house_id, t, tile);
00459 
00460       if (callback == CALLBACK_FAILED || callback == CALLBACK_HOUSEPRODCARGO_END) break;
00461 
00462       CargoID cargo = GetCargoTranslation(GB(callback, 8, 7), hs->grffile);
00463       if (cargo == CT_INVALID) continue;
00464 
00465       uint amt = GB(callback, 0, 8);
00466       uint moved = MoveGoodsToStation(tile, 1, 1, cargo, amt);
00467 
00468       const CargoSpec *cs = GetCargo(cargo);
00469       switch (cs->town_effect) {
00470         case TE_PASSENGERS:
00471           t->new_max_pass += amt;
00472           t->new_act_pass += moved;
00473           break;
00474 
00475         case TE_MAIL:
00476           t->new_max_mail += amt;
00477           t->new_act_mail += moved;
00478           break;
00479 
00480         default:
00481           break;
00482       }
00483     }
00484   } else {
00485     if (GB(r, 0, 8) < hs->population) {
00486       uint amt = GB(r, 0, 8) / 8 + 1;
00487 
00488       if (_economy.fluct <= 0) amt = (amt + 1) >> 1;
00489       t->new_max_pass += amt;
00490       t->new_act_pass += MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt);
00491     }
00492 
00493     if (GB(r, 8, 8) < hs->mail_generation) {
00494       uint amt = GB(r, 8, 8) / 8 + 1;
00495 
00496       if (_economy.fluct <= 0) amt = (amt + 1) >> 1;
00497       t->new_max_mail += amt;
00498       t->new_act_mail += MoveGoodsToStation(tile, 1, 1, CT_MAIL, amt);
00499     }
00500   }
00501 
00502   _current_company = OWNER_TOWN;
00503 
00504   if (hs->building_flags & BUILDING_HAS_1_TILE &&
00505       HasBit(t->flags12, TOWN_IS_FUNDED) &&
00506       CanDeleteHouse(tile) &&
00507       GetHouseAge(tile) >= hs->minimum_life &&
00508       --t->time_until_rebuild == 0) {
00509     t->time_until_rebuild = GB(r, 16, 8) + 192;
00510 
00511     ClearTownHouse(t, tile);
00512 
00513     /* Rebuild with another house? */
00514     if (GB(r, 24, 8) >= 12) BuildTownHouse(t, tile);
00515   }
00516 
00517   _current_company = OWNER_NONE;
00518 }
00519 
00524 static bool ClickTile_Town(TileIndex tile)
00525 {
00526   /* not used */
00527   return false;
00528 }
00529 
00530 static CommandCost ClearTile_Town(TileIndex tile, byte flags)
00531 {
00532   if ((flags & DC_AUTO) && !(flags & DC_AI_BUILDING)) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED);
00533   if (!CanDeleteHouse(tile)) return CMD_ERROR;
00534 
00535   const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
00536 
00537   CommandCost cost(EXPENSES_CONSTRUCTION);
00538   cost.AddCost(hs->GetRemovalCost());
00539 
00540   int rating = hs->remove_rating_decrease;
00541   _cleared_town_rating += rating;
00542   Town *t = _cleared_town = GetTownByTile(tile);
00543 
00544   if (IsValidCompanyID(_current_company)) {
00545     if (rating > t->ratings[_current_company] && !(flags & DC_NO_TOWN_RATING) && !_cheats.magic_bulldozer.value) {
00546       SetDParam(0, t->index);
00547       return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES);
00548     }
00549   }
00550 
00551   ChangeTownRating(t, -rating, RATING_HOUSE_MINIMUM);
00552   if (flags & DC_EXEC) {
00553     ClearTownHouse(t, tile);
00554   }
00555 
00556   return cost;
00557 }
00558 
00559 static void GetProducedCargo_Town(TileIndex tile, CargoID *b)
00560 {
00561   HouseID house_id = GetHouseType(tile);
00562   const HouseSpec *hs = GetHouseSpecs(house_id);
00563   Town *t = GetTownByTile(tile);
00564 
00565   if (HasBit(hs->callback_mask, CBM_HOUSE_PRODUCE_CARGO)) {
00566     for (uint i = 0; i < 256; i++) {
00567       uint16 callback = GetHouseCallback(CBID_HOUSE_PRODUCE_CARGO, i, 0, house_id, t, tile);
00568 
00569       if (callback == CALLBACK_FAILED || callback == CALLBACK_HOUSEPRODCARGO_END) break;
00570 
00571       CargoID cargo = GetCargoTranslation(GB(callback, 8, 7), hs->grffile);
00572 
00573       if (cargo == CT_INVALID) continue;
00574       *(b++) = cargo;
00575     }
00576   } else {
00577     if (hs->population > 0) {
00578       *(b++) = CT_PASSENGERS;
00579     }
00580     if (hs->mail_generation > 0) {
00581       *(b++) = CT_MAIL;
00582     }
00583   }
00584 }
00585 
00586 static void GetAcceptedCargo_Town(TileIndex tile, AcceptedCargo ac)
00587 {
00588   const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
00589   CargoID accepts[3];
00590 
00591   /* Set the initial accepted cargo types */
00592   for (uint8 i = 0; i < lengthof(accepts); i++) {
00593     accepts[i] = hs->accepts_cargo[i];
00594   }
00595 
00596   /* Check for custom accepted cargo types */
00597   if (HasBit(hs->callback_mask, CBM_HOUSE_ACCEPT_CARGO)) {
00598     uint16 callback = GetHouseCallback(CBID_HOUSE_ACCEPT_CARGO, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
00599     if (callback != CALLBACK_FAILED) {
00600       /* Replace accepted cargo types with translated values from callback */
00601       accepts[0] = GetCargoTranslation(GB(callback,  0, 5), hs->grffile);
00602       accepts[1] = GetCargoTranslation(GB(callback,  5, 5), hs->grffile);
00603       accepts[2] = GetCargoTranslation(GB(callback, 10, 5), hs->grffile);
00604     }
00605   }
00606 
00607   /* Check for custom cargo acceptance */
00608   if (HasBit(hs->callback_mask, CBM_HOUSE_CARGO_ACCEPTANCE)) {
00609     uint16 callback = GetHouseCallback(CBID_HOUSE_CARGO_ACCEPTANCE, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
00610     if (callback != CALLBACK_FAILED) {
00611       if (accepts[0] != CT_INVALID) ac[accepts[0]] = GB(callback, 0, 4);
00612       if (accepts[1] != CT_INVALID) ac[accepts[1]] = GB(callback, 4, 4);
00613       if (_settings_game.game_creation.landscape != LT_TEMPERATE && HasBit(callback, 12)) {
00614         /* The 'S' bit indicates food instead of goods */
00615         ac[CT_FOOD] = GB(callback, 8, 4);
00616       } else {
00617         if (accepts[2] != CT_INVALID) ac[accepts[2]] = GB(callback, 8, 4);
00618       }
00619       return;
00620     }
00621   }
00622 
00623   /* No custom acceptance, so fill in with the default values */
00624   for (uint8 i = 0; i < lengthof(accepts); i++) {
00625     if (accepts[i] != CT_INVALID) ac[accepts[i]] = hs->cargo_acceptance[i];
00626   }
00627 }
00628 
00629 static void GetTileDesc_Town(TileIndex tile, TileDesc *td)
00630 {
00631   const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
00632 
00633   td->str = hs->building_name;
00634   if (!IsHouseCompleted(tile)) {
00635     SetDParamX(td->dparam, 0, td->str);
00636     td->str = STR_2058_UNDER_CONSTRUCTION;
00637   }
00638 
00639   if (hs->grffile != NULL) {
00640     const GRFConfig *gc = GetGRFConfig(hs->grffile->grfid);
00641     td->grf = gc->name;
00642   }
00643 
00644   td->owner[0] = OWNER_TOWN;
00645 }
00646 
00647 static TrackStatus GetTileTrackStatus_Town(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
00648 {
00649   /* not used */
00650   return 0;
00651 }
00652 
00653 static void ChangeTileOwner_Town(TileIndex tile, Owner old_owner, Owner new_owner)
00654 {
00655   /* not used */
00656 }
00657 
00658 static bool GrowTown(Town *t);
00659 
00660 static void TownTickHandler(Town *t)
00661 {
00662   if (HasBit(t->flags12, TOWN_IS_FUNDED)) {
00663     int i = t->grow_counter - 1;
00664     if (i < 0) {
00665       if (GrowTown(t)) {
00666         i = t->growth_rate;
00667       } else {
00668         i = 0;
00669       }
00670     }
00671     t->grow_counter = i;
00672   }
00673 
00674   UpdateTownRadius(t);
00675 }
00676 
00677 void OnTick_Town()
00678 {
00679   if (_game_mode == GM_EDITOR) return;
00680 
00681   /* Make sure each town's tickhandler invocation frequency is about the
00682    * same - TOWN_GROWTH_FREQUENCY - independent on the number of towns. */
00683   for (_cur_town_iter += GetMaxTownIndex() + 1;
00684        _cur_town_iter >= TOWN_GROWTH_FREQUENCY;
00685        _cur_town_iter -= TOWN_GROWTH_FREQUENCY) {
00686     uint32 i = _cur_town_ctr;
00687 
00688     if (++_cur_town_ctr > GetMaxTownIndex())
00689       _cur_town_ctr = 0;
00690 
00691     if (IsValidTownID(i)) TownTickHandler(GetTown(i));
00692   }
00693 }
00694 
00703 static RoadBits GetTownRoadBits(TileIndex tile)
00704 {
00705   TrackBits b = GetAnyRoadTrackBits(tile, ROADTYPE_ROAD);
00706   RoadBits r = ROAD_NONE;
00707 
00708   if (b == TRACK_BIT_NONE) return r;
00709   if (b & TRACK_BIT_X)     r |= ROAD_X;
00710   if (b & TRACK_BIT_Y)     r |= ROAD_Y;
00711   if (b & TRACK_BIT_UPPER) r |= ROAD_NE | ROAD_NW;
00712   if (b & TRACK_BIT_LOWER) r |= ROAD_SE | ROAD_SW;
00713   if (b & TRACK_BIT_LEFT)  r |= ROAD_NW | ROAD_SW;
00714   if (b & TRACK_BIT_RIGHT) r |= ROAD_NE | ROAD_SE;
00715   return r;
00716 }
00717 
00727 static bool IsNeighborRoadTile(TileIndex tile, const DiagDirection dir, uint dist_multi)
00728 {
00729   /* Lookup table for the used diff values */
00730   const TileIndexDiff tid_lt[3] = {
00731     TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90RIGHT)),
00732     TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90LEFT)),
00733     TileOffsByDiagDir(ReverseDiagDir(dir)),
00734   };
00735 
00736   /* We add 1 to the distance because we want to get 1 for
00737    * the min distance multiplyer and not 0.
00738    * Therefore we start at 4. The 4 is used because
00739    * there are 4 tiles per distance step to check. */
00740   dist_multi = (dist_multi + 1) * 4;
00741   for (uint pos = 4; pos < dist_multi; pos++) {
00742     TileIndexDiff cur = 0;
00743     /* For each even value of pos add the right TileIndexDiff
00744      * for each uneven value the left TileIndexDiff
00745      * for each with 2nd bit set (2,3,6,7,..) add the reversed TileIndexDiff */
00746     cur += tid_lt[(pos & 1) ? 0 : 1];
00747     if (pos & 2) cur += tid_lt[2];
00748 
00749     cur = (uint)(pos / 4) * cur; // Multiply for the fitting distance
00750     if (GetTownRoadBits(TILE_ADD(tile, cur)) & DiagDirToRoadBits((pos & 2) ? dir : ReverseDiagDir(dir))) return true;
00751   }
00752   return false;
00753 }
00754 
00763 static bool IsRoadAllowedHere(Town *t, TileIndex tile, DiagDirection dir)
00764 {
00765   if (TileX(tile) < 2 || TileX(tile) >= MapMaxX() || TileY(tile) < 2 || TileY(tile) >= MapMaxY()) return false;
00766 
00767   Slope cur_slope, desired_slope;
00768 
00769   for (;;) {
00770     /* Check if there already is a road at this point? */
00771     if (GetTownRoadBits(tile) == ROAD_NONE) {
00772       /* No, try if we are able to build a road piece there.
00773        * If that fails clear the land, and if that fails exit.
00774        * This is to make sure that we can build a road here later. */
00775       if (CmdFailed(DoCommand(tile, ((dir == DIAGDIR_NW || dir == DIAGDIR_SE) ? ROAD_X : ROAD_Y), 0, DC_AUTO, CMD_BUILD_ROAD)) &&
00776           CmdFailed(DoCommand(tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR)))
00777         return false;
00778     }
00779 
00780     cur_slope = GetTileSlope(tile, NULL);
00781     if (cur_slope == SLOPE_FLAT) {
00782 no_slope:
00783       /* Tile has no slope */
00784       switch (t->GetActiveLayout()) {
00785         default: NOT_REACHED();
00786 
00787         case TL_ORIGINAL: // Disallow the road if any neighboring tile has a road (distance: 1)
00788           return !IsNeighborRoadTile(tile, dir, 1);
00789 
00790         case TL_BETTER_ROADS: // Disallow the road if any neighboring tile has a road (distance: 1 and 2).
00791           return !IsNeighborRoadTile(tile, dir, 2);
00792       }
00793     }
00794 
00795     /* If the tile is not a slope in the right direction, then
00796      * maybe terraform some. */
00797     desired_slope = (dir == DIAGDIR_NW || dir == DIAGDIR_SE) ? SLOPE_NW : SLOPE_NE;
00798     if (desired_slope != cur_slope && ComplementSlope(desired_slope) != cur_slope) {
00799       if (Chance16(1, 8)) {
00800         CommandCost res = CMD_ERROR;
00801         if (!_generating_world && Chance16(1, 10)) {
00802           /* Note: Do not replace "^ SLOPE_ELEVATED" with ComplementSlope(). The slope might be steep. */
00803           res = DoCommand(tile, Chance16(1, 16) ? cur_slope : cur_slope ^ SLOPE_ELEVATED, 0,
00804               DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND);
00805         }
00806         if (CmdFailed(res) && Chance16(1, 3)) {
00807           /* We can consider building on the slope, though. */
00808           goto no_slope;
00809         }
00810       }
00811       return false;
00812     }
00813     return true;
00814   }
00815 }
00816 
00817 static bool TerraformTownTile(TileIndex tile, int edges, int dir)
00818 {
00819   TILE_ASSERT(tile);
00820 
00821   CommandCost r = DoCommand(tile, edges, dir, DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND);
00822   if (CmdFailed(r) || r.GetCost() >= (_price.terraform + 2) * 8) return false;
00823   DoCommand(tile, edges, dir, DC_AUTO | DC_NO_WATER | DC_EXEC, CMD_TERRAFORM_LAND);
00824   return true;
00825 }
00826 
00827 static void LevelTownLand(TileIndex tile)
00828 {
00829   TILE_ASSERT(tile);
00830 
00831   /* Don't terraform if land is plain or if there's a house there. */
00832   if (IsTileType(tile, MP_HOUSE)) return;
00833   Slope tileh = GetTileSlope(tile, NULL);
00834   if (tileh == SLOPE_FLAT) return;
00835 
00836   /* First try up, then down */
00837   if (!TerraformTownTile(tile, ~tileh & SLOPE_ELEVATED, 1)) {
00838     TerraformTownTile(tile, tileh & SLOPE_ELEVATED, 0);
00839   }
00840 }
00841 
00851 static RoadBits GetTownRoadGridElement(Town *t, TileIndex tile, DiagDirection dir)
00852 {
00853   /* align the grid to the downtown */
00854   TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, tile); // Vector from downtown to the tile
00855   RoadBits rcmd = ROAD_NONE;
00856 
00857   switch (t->GetActiveLayout()) {
00858     default: NOT_REACHED();
00859 
00860     case TL_2X2_GRID:
00861       if ((grid_pos.x % 3) == 0) rcmd |= ROAD_Y;
00862       if ((grid_pos.y % 3) == 0) rcmd |= ROAD_X;
00863       break;
00864 
00865     case TL_3X3_GRID:
00866       if ((grid_pos.x % 4) == 0) rcmd |= ROAD_Y;
00867       if ((grid_pos.y % 4) == 0) rcmd |= ROAD_X;
00868       break;
00869   }
00870 
00871   /* Optimise only X-junctions */
00872   if (rcmd != ROAD_ALL) return rcmd;
00873 
00874   RoadBits rb_template;
00875 
00876   switch (GetTileSlope(tile, NULL)) {
00877     default:       rb_template = ROAD_ALL; break;
00878     case SLOPE_W:  rb_template = ROAD_NW | ROAD_SW; break;
00879     case SLOPE_SW: rb_template = ROAD_Y  | ROAD_SW; break;
00880     case SLOPE_S:  rb_template = ROAD_SW | ROAD_SE; break;
00881     case SLOPE_SE: rb_template = ROAD_X  | ROAD_SE; break;
00882     case SLOPE_E:  rb_template = ROAD_SE | ROAD_NE; break;
00883     case SLOPE_NE: rb_template = ROAD_Y  | ROAD_NE; break;
00884     case SLOPE_N:  rb_template = ROAD_NE | ROAD_NW; break;
00885     case SLOPE_NW: rb_template = ROAD_X  | ROAD_NW; break;
00886     case SLOPE_STEEP_W:
00887     case SLOPE_STEEP_S:
00888     case SLOPE_STEEP_E:
00889     case SLOPE_STEEP_N:
00890       rb_template = ROAD_NONE;
00891       break;
00892   }
00893 
00894   /* Stop if the template is compatible to the growth dir */
00895   if (DiagDirToRoadBits(ReverseDiagDir(dir)) & rb_template) return rb_template;
00896   /* If not generate a straight road in the direction of the growth */
00897   return DiagDirToRoadBits(dir) | DiagDirToRoadBits(ReverseDiagDir(dir));
00898 }
00899 
00910 static bool GrowTownWithExtraHouse(Town *t, TileIndex tile)
00911 {
00912   /* We can't look further than that. */
00913   if (TileX(tile) < 2 || TileY(tile) < 2 || MapMaxX() <= TileX(tile) || MapMaxY() <= TileY(tile)) return false;
00914 
00915   uint counter = 0; // counts the house neighbor tiles
00916 
00917   /* Check the tiles E,N,W and S of the current tile for houses */
00918   for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
00919 
00920     if (IsTileType(TileAddByDiagDir(tile, dir), MP_HOUSE)) counter++;
00921 
00922     /* If there are enough neighbors stop here */
00923     if (counter >= 3) {
00924       if (BuildTownHouse(t, tile)) {
00925         _grow_town_result = GROWTH_SUCCEED;
00926         return true;
00927       }
00928       return false;
00929     }
00930   }
00931   return false;
00932 }
00933 
00942 static bool GrowTownWithRoad(const Town *t, TileIndex tile, RoadBits rcmd)
00943 {
00944   if (CmdSucceeded(DoCommand(tile, rcmd, t->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD))) {
00945     _grow_town_result = GROWTH_SUCCEED;
00946     return true;
00947   }
00948   return false;
00949 }
00950 
00961