Factor out OnClick dispatching in Window::HandleEditBoxKey
[openttd/fttd.git] / src / town_cmd.cpp
blob91734ef2ff008b31170ab7b4e5e4a781b6a07956
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
10 /** @file town_cmd.cpp Handling of town tiles. */
12 #include "stdafx.h"
14 #include <bitset>
16 #include "road_internal.h" /* Cleaning up road bits */
17 #include "road_cmd.h"
18 #include "landscape.h"
19 #include "viewport_func.h"
20 #include "cmd_helper.h"
21 #include "command_func.h"
22 #include "industry.h"
23 #include "station_base.h"
24 #include "company_base.h"
25 #include "news_func.h"
26 #include "error.h"
27 #include "object.h"
28 #include "genworld.h"
29 #include "newgrf_debug.h"
30 #include "newgrf_house.h"
31 #include "newgrf_text.h"
32 #include "autoslope.h"
33 #include "map/zoneheight.h"
34 #include "map/road.h"
35 #include "map/tunnelbridge.h"
36 #include "strings_func.h"
37 #include "window_func.h"
38 #include "string.h"
39 #include "newgrf_cargo.h"
40 #include "cheat_type.h"
41 #include "animated_tile_func.h"
42 #include "date_func.h"
43 #include "subsidy_func.h"
44 #include "core/pool_func.hpp"
45 #include "town.h"
46 #include "townnamegen.h"
47 #include "townname_func.h"
48 #include "core/random_func.hpp"
49 #include "core/backup_type.hpp"
50 #include "depot_base.h"
51 #include "map/object.h"
52 #include "object_base.h"
53 #include "ai/ai.hpp"
54 #include "game/game.hpp"
55 #include "bridge.h"
56 #include "map/util.h"
57 #include "zoom_func.h"
59 #include "table/strings.h"
60 #include "table/town_land.h"
62 TownID _new_town_id;
63 uint32 _town_cargoes_accepted; ///< Bitmap of all cargoes accepted by houses.
65 /* Initialize the town-pool */
66 template<> Town::Pool Town::PoolItem::pool ("Town");
67 INSTANTIATE_POOL_METHODS(Town)
69 Town::~Town()
71 free(this->name);
72 free(this->text);
74 if (CleaningPool()) return;
76 /* Delete town authority window
77 * and remove from list of sorted towns */
78 DeleteWindowById(WC_TOWN_VIEW, this->index);
80 /* Delete from town set */
81 this->remove_from_tileset();
83 /* Check no industry is related to us. */
84 const Industry *i;
85 FOR_ALL_INDUSTRIES(i) assert(i->town != this);
87 /* ... and no object is related to us. */
88 const Object *o;
89 FOR_ALL_OBJECTS(o) assert(o->town != this);
91 /* Check no tile is related to us. */
92 for (TileIndex tile = 0; tile < MapSize(); ++tile) {
93 if (IsHouseTile(tile)) {
94 assert(GetTownIndex(tile) != this->index);
95 } else {
96 switch (GetTileType(tile)) {
97 case TT_MISC:
98 if (IsTunnelTile(tile)) {
99 assert(!IsTileOwner(tile, OWNER_TOWN) || ClosestTownFromTile(tile) != this);
100 break;
102 if (!IsLevelCrossingTile(tile)) break;
103 /* fall through */
104 case TT_ROAD:
105 assert(!HasTownOwnedRoad(tile) || GetTownIndex(tile) != this->index);
106 break;
108 default:
109 break;
114 /* Clear the persistent storage list. */
115 this->psa_list.clear();
117 DeleteSubsidyWith(ST_TOWN, this->index);
118 DeleteNewGRFInspectWindow(GSF_FAKE_TOWNS, this->index);
119 CargoPacket::InvalidateAllFrom(ST_TOWN, this->index);
120 MarkWholeScreenDirty();
125 * Invalidating of the "nearest town cache" has to be done
126 * after removing item from the pool.
127 * @param index index of deleted item
129 void Town::PostDestructor(size_t index)
131 InvalidateWindowData(WC_TOWN_DIRECTORY, 0, 0);
132 InvalidateWindowData(WC_SELECT_TOWN, 0);
133 UpdateNearestTownForRoadTiles(false);
135 /* Give objects a new home! */
136 Object *o;
137 FOR_ALL_OBJECTS(o) {
138 if (o->town == NULL) o->town = CalcClosestTownFromTile(o->location.tile);
143 * Return a random valid town.
144 * @return random town, NULL if there are no towns
146 /* static */ Town *Town::GetRandom()
148 if (Town::GetNumItems() == 0) return NULL;
149 int num = RandomRange((uint16)Town::GetNumItems());
150 size_t index = MAX_UVALUE(size_t);
152 while (num >= 0) {
153 num--;
154 index++;
156 /* Make sure we have a valid town */
157 while (!Town::IsValidID(index)) {
158 index++;
159 assert(index < Town::GetPoolSize());
163 return Town::Get(index);
167 * Get the cost for removing this house
168 * @return the cost (inflation corrected etc)
170 Money HouseSpec::GetRemovalCost() const
172 return (_price[PR_CLEAR_HOUSE] * this->removal_cost) >> 8;
175 static bool BuildTownHouse(Town *t, TileIndex tile);
176 static Town *CreateRandomTown(uint attempts, uint32 townnameparts, TownSize size, bool city, TownLayout layout);
179 * Return a random direction
181 * @return a random direction
183 static inline DiagDirection RandomDiagDir()
185 return (DiagDirection)(3 & Random());
189 * House Tile drawing handler.
190 * Part of the tile loop process
191 * @param ti TileInfo of the tile to draw
193 static void DrawTile_Town(TileInfo *ti)
195 HouseID house_id = GetHouseType(ti->tile);
197 if (house_id >= NEW_HOUSE_OFFSET) {
198 /* Houses don't necessarily need new graphics. If they don't have a
199 * spritegroup associated with them, then the sprite for the substitute
200 * house id is drawn instead. */
201 if (HouseSpec::Get(house_id)->grf_prop.spritegroup != NULL) {
202 DrawNewHouseTile(ti, house_id);
203 return;
204 } else {
205 house_id = HouseSpec::Get(house_id)->grf_prop.subst_id;
209 /* Retrieve draw town tile data. */
210 const uint64 dcts = town_draw_tile_data[house_id][TileHash2Bit(ti->x, ti->y)][GetHouseBuildingStage(ti->tile)];
212 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
214 DrawGroundSprite (ti, dcts & 0x1fff, PAL_NONE);
216 /* If houses are invisible, do not draw the upper part */
217 if (IsInvisibilitySet(TO_HOUSES)) return;
219 /* Add a house on top of the ground? */
220 SpriteID image = (dcts >> 32) & 0x1fff;
221 if (image != 0) {
222 AddSortableSpriteToDraw (ti->vd, image, GB(dcts, 45, 11),
223 ti->x + GB(dcts, 21, 3), ti->y + GB(dcts, 29, 3),
224 GB(dcts, 16, 5), GB(dcts, 24, 5), GB(dcts, 56, 7),
225 ti->z,
226 IsTransparencySet(TO_HOUSES)
229 /* Draw the lift */
230 if (!IsTransparencySet(TO_HOUSES) && HasBit(dcts, 14)) {
231 AddChildSpriteScreen (ti->vd, SPR_LIFT, PAL_NONE, 14,
232 60 - GetLiftPosition (ti->tile));
237 static void DrawOldHouseTileInGUI (BlitArea *dpi, int x, int y,
238 HouseID house_id, bool ground)
240 /* Retrieve draw town tile data. */
241 const uint64 dcts = town_draw_tile_data[house_id][0][TOWN_HOUSE_COMPLETED];
242 if (ground) {
243 /* Draw the ground sprite */
244 DrawSprite (dpi, dcts & 0x1fff, PAL_NONE, x, y);
245 } else {
246 /* Add a house on top of the ground? */
247 SpriteID image = (dcts >> 32) & 0x1fff;
248 if (image != 0) {
249 uint sx = GB(dcts, 21, 3);
250 uint sy = GB(dcts, 29, 3);
251 DrawSprite (dpi, image, GB(dcts, 45, 11),
252 x + ScaleGUITrad (2 * (sy - sx)),
253 y + ScaleGUITrad (sx + sy));
254 /* Draw the lift */
255 if (HasBit(dcts, 14)) {
256 DrawSprite (dpi, SPR_LIFT, PAL_NONE, x - 18, y + 7);
263 * Draw image of a house. Image will be centered between the \c left and the \c right and verticaly aligned to the \c bottom.
265 * @param house_id house type
266 * @param dpi area to draw on
267 * @param left left bound of the drawing area
268 * @param top top bound of the drawing area
269 * @param right right bound of the drawing area
270 * @param bottom bottom bound of the drawing area
272 void DrawHouseImage (HouseID house_id, BlitArea *dpi,
273 int left, int top, int right, int bottom)
275 BlitArea tmp_dpi;
276 if (!InitBlitArea (dpi, &tmp_dpi, left, top, right - left + 1, bottom - top + 1)) return;
278 const HouseSpec *hs = HouseSpec::Get(house_id);
280 /* sprites are relative to the topmost pixel of the ground tile */
281 uint x = (right - left + 1) / 2 - ScaleGUITrad (1);
282 uint y = bottom - top + 1 - ScaleGUITrad (TILE_PIXELS - 1);
283 uint half_tile_offset = ScaleGUITrad (TILE_PIXELS / 2);
284 if (hs->building_flags & TILE_SIZE_1x2) x -= half_tile_offset;
285 if (hs->building_flags & TILE_SIZE_2x1) x += half_tile_offset;
286 if (hs->building_flags & BUILDING_HAS_2_TILES) y -= half_tile_offset;
287 if (hs->building_flags & BUILDING_HAS_4_TILES) y -= half_tile_offset;
289 bool new_house = false;
290 if (house_id >= NEW_HOUSE_OFFSET) {
291 /* Houses don't necessarily need new graphics. If they don't
292 * have a spritegroup associated with them, then the sprite
293 * for the substitute house id is drawn instead. */
294 if (hs->grf_prop.spritegroup != NULL) {
295 new_house = true;
296 } else {
297 house_id = hs->grf_prop.subst_id;
301 uint num_row = (hs->building_flags & BUILDING_2_TILES_X) ? 2 : 1;
302 uint num_col = (hs->building_flags & BUILDING_2_TILES_Y) ? 2 : 1;
304 Point pt[4];
305 uint n = 0;
306 for (uint row = 0; row < num_row; row++) {
307 for (uint col = 0; col < num_col; col++) {
308 Point offset = RemapCoords (row * TILE_SIZE, col * TILE_SIZE, 0); // offset for current tile
309 pt[n].x = x + UnScaleByZoom (offset.x, ZOOM_LVL_GUI);
310 pt[n].y = y + UnScaleByZoom (offset.y, ZOOM_LVL_GUI);
311 n++;
315 for (bool ground = true; ; ground = !ground) {
316 for (uint i = 0; i < n; i++) {
317 HouseID hid = house_id + i;
318 if (new_house) {
319 DrawNewHouseTileInGUI (&tmp_dpi, pt[i].x, pt[i].y, hid, ground);
320 } else {
321 DrawOldHouseTileInGUI (&tmp_dpi, pt[i].x, pt[i].y, hid, ground);
324 if (!ground) break;
328 static int GetSlopePixelZ_Town(TileIndex tile, uint x, uint y)
330 return GetTileMaxPixelZ(tile);
333 /** Tile callback routine */
334 static Foundation GetFoundation_Town(TileIndex tile, Slope tileh)
336 HouseID hid = GetHouseType(tile);
338 /* For NewGRF house tiles we might not be drawing a foundation. We need to
339 * account for this, as other structures should
340 * draw the wall of the foundation in this case.
342 if (hid >= NEW_HOUSE_OFFSET) {
343 const HouseSpec *hs = HouseSpec::Get(hid);
344 if (hs->grf_prop.spritegroup != NULL && HasBit(hs->callback_mask, CBM_HOUSE_DRAW_FOUNDATIONS)) {
345 uint32 callback_res = GetHouseCallback(CBID_HOUSE_DRAW_FOUNDATIONS, 0, 0, hid, Town::GetByTile(tile), tile);
346 if (callback_res != CALLBACK_FAILED && !ConvertBooleanCallback(hs->grf_prop.grffile, CBID_HOUSE_DRAW_FOUNDATIONS, callback_res)) return FOUNDATION_NONE;
349 return FlatteningFoundation(tileh);
353 * Animate a tile for a town
354 * Only certain houses can be animated
355 * The newhouses animation supersedes regular ones
356 * @param tile TileIndex of the house to animate
358 static void AnimateTile_Town(TileIndex tile)
360 if (GetHouseType(tile) >= NEW_HOUSE_OFFSET) {
361 AnimateNewHouseTile(tile);
362 return;
365 if (_tick_counter & 3) return;
367 /* If the house is not one with a lift anymore, then stop this animating.
368 * Not exactly sure when this happens, but probably when a house changes.
369 * Before this was just a return...so it'd leak animated tiles..
370 * That bug seems to have been here since day 1?? */
371 if (!(HouseSpec::Get(GetHouseType(tile))->building_flags & BUILDING_IS_ANIMATED)) {
372 DeleteAnimatedTile(tile);
373 return;
376 if (!LiftHasDestination(tile)) {
377 uint i;
379 /* Building has 6 floors, number 0 .. 6, where 1 is illegal.
380 * This is due to the fact that the first floor is, in the graphics,
381 * the height of 2 'normal' floors.
382 * Furthermore, there are 6 lift positions from floor N (incl) to floor N + 1 (excl) */
383 do {
384 i = RandomRange(7);
385 } while (i == 1 || i * 6 == GetLiftPosition(tile));
387 SetLiftDestination(tile, i);
390 int pos = GetLiftPosition(tile);
391 int dest = GetLiftDestination(tile) * 6;
392 pos += (pos < dest) ? 1 : -1;
393 SetLiftPosition(tile, pos);
395 if (pos == dest) {
396 HaltLift(tile);
397 DeleteAnimatedTile(tile);
400 MarkTileDirtyByTile(tile);
404 * Resize the sign(label) of the town after changes in
405 * population (creation or growth or else)
407 void Town::UpdateVirtCoord()
409 Point pt = RemapCoords2(TileX(this->xy) * TILE_SIZE, TileY(this->xy) * TILE_SIZE);
410 SetDParam(0, this->index);
411 SetDParam(1, this->cache.population);
412 this->cache.sign.UpdatePosition(pt.x, pt.y - 24 * ZOOM_LVL_BASE,
413 _settings_client.gui.population_in_label ? STR_VIEWPORT_TOWN_POP : STR_VIEWPORT_TOWN,
414 STR_VIEWPORT_TOWN);
416 SetWindowDirty(WC_TOWN_VIEW, this->index);
419 /** Update the virtual coords needed to draw the town sign for all towns. */
420 void UpdateAllTownVirtCoords()
422 Town *t;
424 FOR_ALL_TOWNS(t) {
425 t->UpdateVirtCoord();
430 * Change the towns population
431 * @param t Town which population has changed
432 * @param mod population change (can be positive or negative)
434 static void ChangePopulation(Town *t, int mod)
436 t->cache.population += mod;
437 InvalidateWindowData(WC_TOWN_VIEW, t->index); // Cargo requirements may appear/vanish for small populations
438 t->UpdateVirtCoord();
440 InvalidateWindowData(WC_TOWN_DIRECTORY, 0, 1);
444 * Determines the world population
445 * Basically, count population of all towns, one by one
446 * @return uint32 the calculated population of the world
448 uint32 GetWorldPopulation()
450 uint32 pop = 0;
451 const Town *t;
453 FOR_ALL_TOWNS(t) pop += t->cache.population;
454 return pop;
458 * Helper function for house completion stages progression
459 * @param tile TileIndex of the house (or parts of it) to "grow"
461 static void MakeSingleHouseBigger(TileIndex tile)
463 assert(IsHouseTile(tile));
465 /* progress in construction stages */
466 IncHouseConstructionTick(tile);
467 if (GetHouseConstructionTick(tile) != 0) return;
469 AnimateNewHouseConstruction(tile);
471 if (IsHouseCompleted(tile)) {
472 /* Now that construction is complete, we can add the population of the
473 * building to the town. */
474 ChangePopulation(Town::GetByTile(tile), HouseSpec::Get(GetHouseType(tile))->population);
475 ResetHouseAge(tile);
477 MarkTileDirtyByTile(tile);
481 * Make the house advance in its construction stages until completion
482 * @param tile TileIndex of house
484 static void MakeTownHouseBigger(TileIndex tile)
486 uint flags = HouseSpec::Get(GetHouseType(tile))->building_flags;
487 if (flags & BUILDING_HAS_1_TILE) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 0));
488 if (flags & BUILDING_2_TILES_Y) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 1));
489 if (flags & BUILDING_2_TILES_X) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 0));
490 if (flags & BUILDING_HAS_4_TILES) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 1));
494 * Tile callback function.
496 * Periodic tic handler for houses and town
497 * @param tile been asked to do its stuff
499 static void TileLoop_Town(TileIndex tile)
501 HouseID house_id = GetHouseType(tile);
503 /* NewHouseTileLoop returns false if Callback 21 succeeded, i.e. the house
504 * doesn't exist any more, so don't continue here. */
505 if (house_id >= NEW_HOUSE_OFFSET && !NewHouseTileLoop(tile)) return;
507 if (!IsHouseCompleted(tile)) {
508 /* Construction is not completed. See if we can go further in construction*/
509 MakeTownHouseBigger(tile);
510 return;
513 const HouseSpec *hs = HouseSpec::Get(house_id);
515 /* If the lift has a destination, it is already an animated tile. */
516 if ((hs->building_flags & BUILDING_IS_ANIMATED) &&
517 house_id < NEW_HOUSE_OFFSET &&
518 !LiftHasDestination(tile) &&
519 Chance16(1, 2)) {
520 AddAnimatedTile(tile);
523 Town *t = Town::GetByTile(tile);
524 uint32 r = Random();
526 StationFinder stations(TileArea(tile, 1, 1));
528 if (HasBit(hs->callback_mask, CBM_HOUSE_PRODUCE_CARGO)) {
529 for (uint i = 0; i < 256; i++) {
530 uint16 callback = GetHouseCallback(CBID_HOUSE_PRODUCE_CARGO, i, r, house_id, t, tile);
532 if (callback == CALLBACK_FAILED || callback == CALLBACK_HOUSEPRODCARGO_END) break;
534 CargoID cargo = GetCargoTranslation(GB(callback, 8, 7), hs->grf_prop.grffile);
535 if (cargo == CT_INVALID) continue;
537 uint amt = GB(callback, 0, 8);
538 if (amt == 0) continue;
540 uint moved = MoveGoodsToStation(cargo, amt, ST_TOWN, t->index, stations.GetStations());
542 const CargoSpec *cs = CargoSpec::Get(cargo);
543 t->supplied[cs->Index()].new_max += amt;
544 t->supplied[cs->Index()].new_act += moved;
546 } else {
547 if (GB(r, 0, 8) < hs->population) {
548 uint amt = GB(r, 0, 8) / 8 + 1;
550 if (EconomyIsInRecession()) amt = (amt + 1) >> 1;
551 t->supplied[CT_PASSENGERS].new_max += amt;
552 t->supplied[CT_PASSENGERS].new_act += MoveGoodsToStation(CT_PASSENGERS, amt, ST_TOWN, t->index, stations.GetStations());
555 if (GB(r, 8, 8) < hs->mail_generation) {
556 uint amt = GB(r, 8, 8) / 8 + 1;
558 if (EconomyIsInRecession()) amt = (amt + 1) >> 1;
559 t->supplied[CT_MAIL].new_max += amt;
560 t->supplied[CT_MAIL].new_act += MoveGoodsToStation(CT_MAIL, amt, ST_TOWN, t->index, stations.GetStations());
564 Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
566 if ((hs->building_flags & BUILDING_HAS_1_TILE) &&
567 HasBit(t->flags, TOWN_IS_GROWING) &&
568 CanDeleteHouse(tile) &&
569 GetHouseAge(tile) >= hs->minimum_life &&
570 --t->time_until_rebuild == 0) {
571 t->time_until_rebuild = GB(r, 16, 8) + 192;
573 ClearTownHouse(t, tile);
575 /* Rebuild with another house? */
576 if (GB(r, 24, 8) >= 12) BuildTownHouse(t, tile);
579 cur_company.Restore();
582 static CommandCost ClearTile_Town(TileIndex tile, DoCommandFlag flags)
584 if (flags & DC_AUTO) return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
585 if (!CanDeleteHouse(tile)) return CMD_ERROR;
587 const HouseSpec *hs = HouseSpec::Get(GetHouseType(tile));
589 CommandCost cost(EXPENSES_CONSTRUCTION);
590 cost.AddCost(hs->GetRemovalCost());
592 int rating = hs->remove_rating_decrease;
593 Town *t = Town::GetByTile(tile);
595 if (Company::IsValidID(_current_company)) {
596 if (rating > t->ratings[_current_company] && !(flags & DC_NO_TEST_TOWN_RATING) && !_cheats.magic_bulldozer.value) {
597 SetDParam(0, t->index);
598 return_cmd_error(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS);
602 ChangeTownRating(t, -rating, RATING_HOUSE_MINIMUM, flags);
603 if (flags & DC_EXEC) {
604 ClearTownHouse(t, tile);
607 return cost;
610 static void AddProducedCargo_Town(TileIndex tile, CargoArray &produced)
612 HouseID house_id = GetHouseType(tile);
613 const HouseSpec *hs = HouseSpec::Get(house_id);
614 Town *t = Town::GetByTile(tile);
616 if (HasBit(hs->callback_mask, CBM_HOUSE_PRODUCE_CARGO)) {
617 for (uint i = 0; i < 256; i++) {
618 uint16 callback = GetHouseCallback(CBID_HOUSE_PRODUCE_CARGO, i, 0, house_id, t, tile);
620 if (callback == CALLBACK_FAILED || callback == CALLBACK_HOUSEPRODCARGO_END) break;
622 CargoID cargo = GetCargoTranslation(GB(callback, 8, 7), hs->grf_prop.grffile);
624 if (cargo == CT_INVALID) continue;
625 produced[cargo]++;
627 } else {
628 if (hs->population > 0) {
629 produced[CT_PASSENGERS]++;
631 if (hs->mail_generation > 0) {
632 produced[CT_MAIL]++;
637 static inline void AddAcceptedCargoSetMask(CargoID cargo, uint amount, CargoArray &acceptance, uint32 *always_accepted)
639 if (cargo == CT_INVALID || amount == 0) return;
640 acceptance[cargo] += amount;
641 SetBit(*always_accepted, cargo);
644 static void AddAcceptedCargo_Town(TileIndex tile, CargoArray &acceptance, uint32 *always_accepted)
646 const HouseSpec *hs = HouseSpec::Get(GetHouseType(tile));
647 CargoID accepts[3];
649 /* Set the initial accepted cargo types */
650 for (uint8 i = 0; i < lengthof(accepts); i++) {
651 accepts[i] = hs->accepts_cargo[i];
654 /* Check for custom accepted cargo types */
655 if (HasBit(hs->callback_mask, CBM_HOUSE_ACCEPT_CARGO)) {
656 uint16 callback = GetHouseCallback(CBID_HOUSE_ACCEPT_CARGO, 0, 0, GetHouseType(tile), Town::GetByTile(tile), tile);
657 if (callback != CALLBACK_FAILED) {
658 /* Replace accepted cargo types with translated values from callback */
659 accepts[0] = GetCargoTranslation(GB(callback, 0, 5), hs->grf_prop.grffile);
660 accepts[1] = GetCargoTranslation(GB(callback, 5, 5), hs->grf_prop.grffile);
661 accepts[2] = GetCargoTranslation(GB(callback, 10, 5), hs->grf_prop.grffile);
665 /* Check for custom cargo acceptance */
666 if (HasBit(hs->callback_mask, CBM_HOUSE_CARGO_ACCEPTANCE)) {
667 uint16 callback = GetHouseCallback(CBID_HOUSE_CARGO_ACCEPTANCE, 0, 0, GetHouseType(tile), Town::GetByTile(tile), tile);
668 if (callback != CALLBACK_FAILED) {
669 AddAcceptedCargoSetMask(accepts[0], GB(callback, 0, 4), acceptance, always_accepted);
670 AddAcceptedCargoSetMask(accepts[1], GB(callback, 4, 4), acceptance, always_accepted);
671 if (_settings_game.game_creation.landscape != LT_TEMPERATE && HasBit(callback, 12)) {
672 /* The 'S' bit indicates food instead of goods */
673 AddAcceptedCargoSetMask(CT_FOOD, GB(callback, 8, 4), acceptance, always_accepted);
674 } else {
675 AddAcceptedCargoSetMask(accepts[2], GB(callback, 8, 4), acceptance, always_accepted);
677 return;
681 /* No custom acceptance, so fill in with the default values */
682 for (uint8 i = 0; i < lengthof(accepts); i++) {
683 AddAcceptedCargoSetMask(accepts[i], hs->cargo_acceptance[i], acceptance, always_accepted);
687 static void GetTileDesc_Town(TileIndex tile, TileDesc *td)
689 const HouseID house = GetHouseType(tile);
690 const HouseSpec *hs = HouseSpec::Get(house);
691 bool house_completed = IsHouseCompleted(tile);
693 td->str = hs->building_name;
695 uint16 callback_res = GetHouseCallback(CBID_HOUSE_CUSTOM_NAME, house_completed ? 1 : 0, 0, house, Town::GetByTile(tile), tile);
696 if (callback_res != CALLBACK_FAILED && callback_res != 0x400) {
697 if (callback_res > 0x400) {
698 ErrorUnknownCallbackResult(hs->grf_prop.grffile->grfid, CBID_HOUSE_CUSTOM_NAME, callback_res);
699 } else {
700 StringID new_name = GetGRFStringID(hs->grf_prop.grffile->grfid, 0xD000 + callback_res);
701 if (new_name != STR_NULL && new_name != STR_UNDEFINED) {
702 td->str = new_name;
707 if (!house_completed) {
708 td->dparam = td->str;
709 td->str = STR_LAI_TOWN_INDUSTRY_DESCRIPTION_UNDER_CONSTRUCTION;
712 if (hs->grf_prop.grffile != NULL) {
713 const GRFConfig *gc = GetGRFConfig(hs->grf_prop.grffile->grfid);
714 td->grf = gc->GetName();
717 td->owner[0] = OWNER_TOWN;
720 static void ChangeTileOwner_Town(TileIndex tile, Owner old_owner, Owner new_owner)
722 /* not used */
725 /** Update the total cargo acceptance of the whole town.
726 * @param t The town to update.
728 void UpdateTownCargoTotal(Town *t)
730 t->cargo_accepted_total = 0;
732 const TileArea &area = t->cargo_accepted.GetArea();
733 TILE_AREA_LOOP(tile, area) {
734 if (TileX(tile) % AcceptanceMatrix::GRID == 0 && TileY(tile) % AcceptanceMatrix::GRID == 0) {
735 t->cargo_accepted_total |= t->cargo_accepted[tile];
741 * Update accepted town cargoes around a specific tile.
742 * @param t The town to update.
743 * @param start Update the values around this tile.
744 * @param update_total Set to true if the total cargo acceptance should be updated.
746 static void UpdateTownCargoes(Town *t, TileIndex start, bool update_total = true)
748 CargoArray accepted, produced;
749 uint32 dummy;
751 /* Gather acceptance for all houses in an area around the start tile.
752 * The area is composed of the square the tile is in, extended one square in all
753 * directions as the coverage area of a single station is bigger than just one square. */
754 TileArea area = AcceptanceMatrix::GetAreaForTile(start, 1);
755 TILE_AREA_LOOP(tile, area) {
756 if (!IsHouseTile(tile) || GetTownIndex(tile) != t->index) continue;
758 AddAcceptedCargo_Town(tile, accepted, &dummy);
759 AddProducedCargo_Town(tile, produced);
762 /* Create bitmap of produced and accepted cargoes. */
763 uint32 acc = 0;
764 for (uint cid = 0; cid < NUM_CARGO; cid++) {
765 if (accepted[cid] >= 8) SetBit(acc, cid);
766 if (produced[cid] > 0) SetBit(t->cargo_produced, cid);
768 t->cargo_accepted[start] = acc;
770 if (update_total) UpdateTownCargoTotal(t);
773 /** Update cargo acceptance for the complete town.
774 * @param t The town to update.
776 void UpdateTownCargoes(Town *t)
778 t->cargo_produced = 0;
780 const TileArea &area = t->cargo_accepted.GetArea();
781 if (area.tile == INVALID_TILE) return;
783 /* Update acceptance for each grid square. */
784 TILE_AREA_LOOP(tile, area) {
785 if (TileX(tile) % AcceptanceMatrix::GRID == 0 && TileY(tile) % AcceptanceMatrix::GRID == 0) {
786 UpdateTownCargoes(t, tile, false);
790 /* Update the total acceptance. */
791 UpdateTownCargoTotal(t);
794 /** Updates the bitmap of all cargoes accepted by houses. */
795 void UpdateTownCargoBitmap()
797 Town *town;
798 _town_cargoes_accepted = 0;
800 FOR_ALL_TOWNS(town) {
801 _town_cargoes_accepted |= town->cargo_accepted_total;
805 static bool GrowTown(Town *t);
807 void OnTick_Town()
809 if (_game_mode == GM_EDITOR) return;
811 Town *t;
812 FOR_ALL_TOWNS(t) {
813 /* Run town tick at regular intervals, but not all at once. */
814 if ((_tick_counter + t->index) % TOWN_GROWTH_TICKS == 0
815 && HasBit(t->flags, TOWN_IS_GROWING)) {
816 if (t->grow_counter > 0) {
817 t->grow_counter--;
818 } else if (GrowTown(t)) {
819 t->grow_counter = t->growth_rate & (~TOWN_GROW_RATE_CUSTOM);
826 * Return the RoadBits of a tile
828 * @note There are many other functions doing things like that.
829 * @note Needs to be checked for needlessness.
830 * @param tile The tile we want to analyse
831 * @return The roadbits of the given tile
833 static RoadBits GetTownRoadBits(TileIndex tile)
835 if (IsRoadDepotTile(tile) || IsStandardRoadStopTile(tile)) return ROAD_NONE;
837 return GetAnyRoadBits(tile, ROADTYPE_ROAD, true);
841 * Check for parallel road inside a given distance.
842 * Assuming a road from (tile - TileOffsByDiagDir(dir)) to tile,
843 * is there a parallel road left or right of it within distance dist_multi?
845 * @param tile current tile
846 * @param dir target direction
847 * @param dist_multi distance multiplayer
848 * @return true if there is a parallel road
850 static bool IsNeighborRoadTile(TileIndex tile, const DiagDirection dir, uint dist_multi)
852 if (!IsValidTile(tile)) return false;
854 /* Lookup table for the used diff values */
855 const TileIndexDiff tid_lt[3] = {
856 TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90RIGHT)),
857 TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90LEFT)),
858 TileOffsByDiagDir(ReverseDiagDir(dir)),
861 dist_multi = (dist_multi + 1) * 4;
862 for (uint pos = 4; pos < dist_multi; pos++) {
863 /* Go (pos / 4) tiles to the left or the right */
864 TileIndexDiff cur = tid_lt[(pos & 1) ? 0 : 1] * (pos / 4);
866 /* Use the current tile as origin, or go one tile backwards */
867 if (pos & 2) cur += tid_lt[2];
869 /* Test for roadbit parallel to dir and facing towards the middle axis */
870 if (IsValidTile(tile + cur) &&
871 GetTownRoadBits(TILE_ADD(tile, cur)) & DiagDirToRoadBits((pos & 2) ? dir : ReverseDiagDir(dir))) return true;
873 return false;
877 * Check if a Road is allowed on a given tile
879 * @param t The current town
880 * @param tile The target tile
881 * @param dir The direction in which we want to extend the town
882 * @return true if it is allowed else false
884 static bool IsRoadAllowedHere(Town *t, TileIndex tile, DiagDirection dir)
886 if (DistanceFromEdge(tile) == 0) return false;
888 /* Prevent towns from building roads under bridges along the bridge. Looks silly. */
889 if (HasBridgeAbove(tile) && GetBridgeAxis(tile) == DiagDirToAxis(dir)) return false;
891 /* Check if there already is a road at this point? */
892 if (GetTownRoadBits(tile) == ROAD_NONE) {
893 /* No, try if we are able to build a road piece there.
894 * If that fails clear the land, and if that fails exit.
895 * This is to make sure that we can build a road here later. */
896 if (DoCommand(tile, ((dir == DIAGDIR_NW || dir == DIAGDIR_SE) ? ROAD_Y : ROAD_X), 0, DC_AUTO, CMD_BUILD_ROAD).Failed() &&
897 DoCommand(tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR).Failed()) {
898 return false;
902 Slope cur_slope = _settings_game.construction.build_on_slopes ? GetFoundationSlope(tile) : GetTileSlope(tile);
903 bool ret = !IsNeighborRoadTile(tile, dir, t->layout == TL_ORIGINAL ? 1 : 2);
904 if (cur_slope == SLOPE_FLAT) return ret;
906 Slope desired_slope = (dir == DIAGDIR_NW || dir == DIAGDIR_SE) ? SLOPE_NW : SLOPE_NE;
907 if (desired_slope == cur_slope || ComplementSlope(desired_slope) == cur_slope) return ret;
909 /* If the tile is not a slope in the right direction, then
910 * maybe terraform some. */
911 if (Chance16(1, 8)) {
912 /* Note: Do not replace "^ SLOPE_ELEVATED" with ComplementSlope(). The slope might be steep. */
913 bool terraform = !_generating_world && Chance16(1, 10) &&
914 DoCommand(tile, Chance16(1, 16) ? cur_slope : cur_slope ^ SLOPE_ELEVATED, 0,
915 DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND).Succeeded();
916 if (!terraform && Chance16(1, 3)) {
917 /* We can consider building on the slope, though. */
918 return ret;
921 return false;
924 static bool TerraformTownTile(TileIndex tile, int edges, int dir)
926 assert(tile < MapSize());
928 CommandCost r = DoCommand(tile, edges, dir, DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND);
929 if (r.Failed() || r.GetCost() >= (_price[PR_TERRAFORM] + 2) * 8) return false;
930 DoCommand(tile, edges, dir, DC_AUTO | DC_NO_WATER | DC_EXEC, CMD_TERRAFORM_LAND);
931 return true;
934 static void LevelTownLand(TileIndex tile)
936 assert(tile < MapSize());
938 /* Don't terraform if land is plain or if there's a house there. */
939 if (IsHouseTile(tile)) return;
940 Slope tileh = GetTileSlope(tile);
941 if (tileh == SLOPE_FLAT) return;
943 /* First try up, then down */
944 if (!TerraformTownTile(tile, ~tileh & SLOPE_ELEVATED, 1)) {
945 TerraformTownTile(tile, tileh & SLOPE_ELEVATED, 0);
950 * Generate the RoadBits of a grid tile
952 * @param t current town
953 * @param tile tile in reference to the town
954 * @param dir The direction to which we are growing ATM
955 * @return the RoadBit of the current tile regarding
956 * the selected town layout
958 static RoadBits GetTownRoadGridElement(Town *t, TileIndex tile, DiagDirection dir)
960 /* align the grid to the downtown */
961 CoordDiff grid_pos = TileCoordDiff(t->xy, tile); // Vector from downtown to the tile
962 RoadBits rcmd = ROAD_NONE;
964 switch (t->layout) {
965 default: NOT_REACHED();
967 case TL_2X2_GRID:
968 if ((grid_pos.x % 3) == 0) rcmd |= ROAD_Y;
969 if ((grid_pos.y % 3) == 0) rcmd |= ROAD_X;
970 break;
972 case TL_3X3_GRID:
973 if ((grid_pos.x % 4) == 0) rcmd |= ROAD_Y;
974 if ((grid_pos.y % 4) == 0) rcmd |= ROAD_X;
975 break;
978 /* Optimise only X-junctions */
979 if (rcmd != ROAD_ALL) return rcmd;
981 RoadBits rb_template;
983 switch (GetTileSlope(tile)) {
984 default: rb_template = ROAD_ALL; break;
985 case SLOPE_W: rb_template = ROAD_NW | ROAD_SW; break;
986 case SLOPE_SW: rb_template = ROAD_Y | ROAD_SW; break;
987 case SLOPE_S: rb_template = ROAD_SW | ROAD_SE; break;
988 case SLOPE_SE: rb_template = ROAD_X | ROAD_SE; break;
989 case SLOPE_E: rb_template = ROAD_SE | ROAD_NE; break;
990 case SLOPE_NE: rb_template = ROAD_Y | ROAD_NE; break;
991 case SLOPE_N: rb_template = ROAD_NE | ROAD_NW; break;
992 case SLOPE_NW: rb_template = ROAD_X | ROAD_NW; break;
993 case SLOPE_STEEP_W:
994 case SLOPE_STEEP_S:
995 case SLOPE_STEEP_E:
996 case SLOPE_STEEP_N:
997 rb_template = ROAD_NONE;
998 break;
1001 /* Stop if the template is compatible to the growth dir */
1002 if (DiagDirToRoadBits(ReverseDiagDir(dir)) & rb_template) return rb_template;
1003 /* If not generate a straight road in the direction of the growth */
1004 return DiagDirToRoadBits(dir) | DiagDirToRoadBits(ReverseDiagDir(dir));
1008 * Grows the town with an extra house.
1009 * Check if there are enough neighbor house tiles
1010 * next to the current tile. If there are enough
1011 * add another house.
1013 * @param t The current town
1014 * @param tile The target tile for the extra house
1015 * @return true if an extra house has been added
1017 static bool GrowTownWithExtraHouse(Town *t, TileIndex tile)
1019 /* We can't look further than that. */
1020 if (DistanceFromEdge(tile) == 0) return false;
1022 uint counter = 0; // counts the house neighbor tiles
1024 /* Check the tiles E,N,W and S of the current tile for houses */
1025 for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
1026 /* Count both void and house tiles for checking whether there
1027 * are enough houses in the area. This to make it likely that
1028 * houses get build up to the edge of the map. */
1029 TileIndex tt = TileAddByDiagDir(tile, dir);
1030 if (IsHouseTile(tt) || IsVoidTile(tt)) {
1031 counter++;
1034 /* If there are enough neighbors stop here */
1035 if (counter >= 3) {
1036 return BuildTownHouse (t, tile);
1039 return false;
1043 * Grows the town with a bridge.
1044 * At first we check if a bridge is reasonable.
1045 * If so we check if we are able to build it.
1047 * @param t The current town
1048 * @param tile The current tile
1049 * @param bridge_dir The valid direction in which to grow a bridge
1050 * @return true if a bridge has been build else false
1052 static bool GrowTownWithBridge(const Town *t, const TileIndex tile, const DiagDirection bridge_dir)
1054 assert(bridge_dir < DIAGDIR_END);
1056 const Slope slope = GetTileSlope(tile);
1058 /* Assure that the bridge is connectable to the start side */
1059 if (!(GetTownRoadBits(TileAddByDiagDir(tile, ReverseDiagDir(bridge_dir))) & DiagDirToRoadBits(bridge_dir))) return false;
1061 /* We are in the right direction */
1062 const int delta = TileOffsByDiagDir(bridge_dir);
1064 uint bridge_length = 0; // This value stores the length of the possible bridge
1065 TileIndex bridge_tile = tile + delta; // Used to store the other waterside
1067 if (slope == SLOPE_FLAT) {
1068 /* Bridges starting on flat tiles are only allowed when crossing rivers. */
1069 while (IsValidTile(bridge_tile) && IsPlainWaterTile(bridge_tile) && !IsSea(bridge_tile)) {
1070 /* Allow to cross rivers, not big lakes. */
1071 if (bridge_length >= 3) return false;
1072 bridge_length++;
1073 bridge_tile += delta;
1075 } else {
1076 /* Make sure the direction is compatible with the slope.
1077 * Well we check if the slope has an up bit set in the
1078 * reverse direction. */
1079 if (slope & InclinedSlope(bridge_dir)) return false;
1081 while (IsValidTile(bridge_tile) && IsPlainWaterTile(bridge_tile)) {
1082 /* Max 10-tile long bridges */
1083 if (bridge_length >= 10) return false;
1084 bridge_length++;
1085 bridge_tile += delta;
1089 /* no water tiles in between? */
1090 if (bridge_length == 0) return false;
1092 std::bitset <MAX_BRIDGES> tried;
1093 uint n = MAX_BRIDGES;
1094 byte bridge_type = RandomRange (n);
1096 for (;;) {
1097 /* Can we actually build the bridge? */
1098 if (DoCommand(tile, bridge_tile, bridge_type | ROADTYPES_ROAD << 8 | TRANSPORT_ROAD << 12 | t->index << 16, CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)), CMD_BUILD_BRIDGE).Succeeded()) {
1099 DoCommand(tile, bridge_tile, bridge_type | ROADTYPES_ROAD << 8 | TRANSPORT_ROAD << 12 | t->index << 16, DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)), CMD_BUILD_BRIDGE);
1100 return true;
1103 /* Try a different bridge. */
1104 tried[bridge_type] = true;
1105 n--;
1106 assert (n + tried.count() == MAX_BRIDGES);
1107 if (n == 0) break;
1109 bridge_type = 0;
1110 uint i = RandomRange (n);
1111 while (tried[bridge_type] || (i-- > 0)) {
1112 bridge_type++;
1113 assert (bridge_type < MAX_BRIDGES);
1117 /* Quit if no bridge can be built. */
1118 return false;
1122 * Grows the town with either a bridge or a road piece.
1124 * @param t The current town
1125 * @param tile The current tile
1126 * @param target_dir The target road dir
1127 * @param rcmd The RoadBits we want to build on the tile
1128 * @return true if the RoadBits have been added else false
1130 static bool GrowTownWithRoad(const Town *t, TileIndex tile, DiagDirection target_dir, RoadBits rcmd)
1132 /* Make the roads look nicer */
1133 rcmd = CleanUpRoadBits(tile, rcmd);
1134 if (rcmd == ROAD_NONE) return false;
1136 /* Only use the target direction for bridges to ensure they're connected.
1137 * The target_dir is as computed previously according to town layout, so
1138 * it will match it perfectly. */
1139 return GrowTownWithBridge (t, tile, target_dir)
1140 || DoCommand (tile, rcmd, t->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD).Succeeded();
1144 * Grows the given town at a tile where there are no roads.
1145 * @param t The current town
1146 * @param tile The current tile
1147 * @param target_dir The target road dir
1148 * @return Whether a road was built
1150 static bool GrowTown_NewRoad (Town *t, TileIndex tile, DiagDirection target_dir)
1152 if (!_settings_game.economy.allow_town_roads && !_generating_world) return false;
1153 if (!_settings_game.economy.allow_town_level_crossings && IsRailwayTile(tile)) return false;
1155 /* Remove hills etc */
1156 if (!_settings_game.construction.build_on_slopes || Chance16(1, 6)) LevelTownLand(tile);
1158 RoadBits rcmd = ROAD_NONE; // RoadBits for the road construction command
1160 /* Is a road allowed here? */
1161 switch (t->layout) {
1162 default: NOT_REACHED();
1164 case TL_3X3_GRID:
1165 case TL_2X2_GRID:
1166 rcmd = GetTownRoadGridElement (t, tile, target_dir);
1167 if (rcmd == ROAD_NONE) return false;
1168 break;
1170 case TL_BETTER_ROADS:
1171 case TL_ORIGINAL:
1172 if (!IsRoadAllowedHere (t, tile, target_dir)) return false;
1174 DiagDirection source_dir = ReverseDiagDir(target_dir);
1176 if (Chance16(1, 6)) {
1177 /* Randomize a new target dir */
1178 target_dir = ChangeDiagDir (target_dir, Chance16(1, 2) ? DIAGDIRDIFF_90RIGHT : DIAGDIRDIFF_90LEFT);
1181 if (!IsRoadAllowedHere (t, TileAddByDiagDir(tile, target_dir), target_dir)) {
1182 /* A road is not allowed to continue the randomized road,
1183 * return if the road we're trying to build is curved. */
1184 if (target_dir != ReverseDiagDir(source_dir)) return false;
1186 /* Return if neither side of the new road is a house */
1187 if (!IsHouseTile(TileAddByDiagDir(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90RIGHT))) &&
1188 !IsHouseTile(TileAddByDiagDir(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90LEFT)))) {
1189 return false;
1192 /* That means that the road is only allowed if there is a house
1193 * at any side of the new road. */
1196 rcmd = DiagDirToRoadBits(target_dir) | DiagDirToRoadBits(source_dir);
1197 break;
1200 /* Return if a water tile */
1201 if (HasTileWaterGround(tile)) return false;
1203 return GrowTownWithRoad (t, tile, target_dir, rcmd);
1207 * Grows the given town at a tile where there is an unconnected road.
1208 * @param t The current town
1209 * @param tile The current tile
1210 * @param target_dir The target road dir
1211 * @param cur_rb The current tile RoadBits
1212 * @return Whether a road piece was built
1214 static bool GrowTown_UnconnectedRoad (Town *t, TileIndex tile, DiagDirection target_dir, RoadBits cur_rb)
1216 /* Continue building on a partial road.
1217 * Should be always OK, so we only generate
1218 * the fitting RoadBits */
1220 if (!_settings_game.economy.allow_town_roads && !_generating_world) return false;
1222 RoadBits rcmd = ROAD_NONE; // RoadBits for the road construction command
1224 switch (t->layout) {
1225 default: NOT_REACHED();
1227 case TL_3X3_GRID:
1228 case TL_2X2_GRID:
1229 rcmd = GetTownRoadGridElement (t, tile, target_dir);
1230 break;
1232 case TL_BETTER_ROADS:
1233 case TL_ORIGINAL:
1234 rcmd = DiagDirToRoadBits(ReverseDiagDir(target_dir));
1235 break;
1238 return GrowTownWithRoad (t, tile, target_dir, rcmd);
1241 /* Describe the possible results of GrowTown_ConnectedRoad. */
1242 enum TownGrowthResult {
1243 GROWTH_CONTINUE, ///< continue searching
1244 GROWTH_FAILURE, ///< growth failed, stop searching
1245 GROWTH_SUCCESS, ///< growth succeeded, stop searching
1249 * Grows the given town at a tile where there is a connected road.
1250 * @param t The current town
1251 * @param tile The current tile
1252 * @param target_dir The target road dir
1253 * @param cur_rb The current tile RoadBits
1254 * @return The result of the growth attempt
1256 static TownGrowthResult GrowTown_ConnectedRoad (Town *t, TileIndex tile, DiagDirection target_dir, RoadBits cur_rb)
1258 /* Possibly extend the road in a direction.
1259 * Randomize a direction and if it has a road, bail out. */
1260 target_dir = RandomDiagDir();
1261 if (cur_rb & DiagDirToRoadBits(target_dir)) return GROWTH_CONTINUE;
1263 /* This is the tile we will reach if we extend to this direction. */
1264 TileIndex house_tile = TileAddByDiagDir(tile, target_dir); // position of a possible house
1266 /* Don't walk into water. */
1267 if (HasTileWaterGround(house_tile)) return GROWTH_CONTINUE;
1269 if (!IsValidTile(house_tile)) return GROWTH_CONTINUE;
1271 bool allow_house = true; // Value which decides if we want to construct a house
1272 RoadBits rcmd = ROAD_NONE; // RoadBits for the road construction command
1273 bool house_built = false; // Whether a house has been built
1275 if (_settings_game.economy.allow_town_roads || _generating_world) {
1276 switch (t->layout) {
1277 default: NOT_REACHED();
1279 case TL_3X3_GRID: // Use 2x2 grid afterwards!
1280 house_built = GrowTownWithExtraHouse (t, TileAddByDiagDir(house_tile, target_dir));
1281 /* fall through */
1282 case TL_2X2_GRID:
1283 rcmd = GetTownRoadGridElement (t, house_tile, target_dir);
1284 allow_house = (rcmd == ROAD_NONE);
1285 break;
1287 case TL_BETTER_ROADS: // Use original afterwards!
1288 house_built = GrowTownWithExtraHouse (t, TileAddByDiagDir(house_tile, target_dir));
1289 /* fall through */
1290 case TL_ORIGINAL:
1291 /* Allow a house at the edge. 60% chance or
1292 * always ok if no road allowed. */
1293 rcmd = DiagDirToRoadBits(target_dir);
1294 allow_house = (!IsRoadAllowedHere (t, house_tile, target_dir) || Chance16(6, 10));
1295 break;
1299 if (allow_house) {
1300 /* Build a house, but not if there already is a house there. */
1301 if (!IsHouseTile(house_tile)) {
1302 /* Level the land if possible */
1303 if (Chance16(1, 6)) LevelTownLand(house_tile);
1305 /* And build a house.
1306 * Set result to -1 if we managed to build it. */
1307 if (BuildTownHouse (t, house_tile)) house_built = true;
1309 return house_built ? GROWTH_SUCCESS : GROWTH_CONTINUE;
1312 return GrowTownWithRoad (t, tile, target_dir, rcmd) ? GROWTH_SUCCESS : GROWTH_FAILURE;
1316 * Simple heuristic to check if a tile may be usable for town growth.
1317 * @param tile The tile to check.
1318 * @return Whether the tile is usable.
1320 static bool GrowTownTileUsable (TileIndex tile)
1322 assert (tile < MapSize());
1324 switch (GetTileType (tile)) {
1325 case TT_GROUND:
1326 return !IsTileSubtype (tile, TT_GROUND_VOID);
1328 case TT_WATER:
1329 return IsCoast (tile);
1331 case TT_RAILWAY:
1332 case TT_ROAD:
1333 return true;
1335 case TT_MISC:
1336 switch (GetTileSubtype(tile)) {
1337 case TT_MISC_CROSSING: return true;
1338 case TT_MISC_TUNNEL: return GetTunnelTransportType(tile) == TRANSPORT_ROAD;
1339 default: return false;
1341 break;
1343 case TT_STATION:
1344 return IsDriveThroughStopTile (tile);
1347 default: return false;
1352 * Returns "growth" if a house was built, or no if the build failed.
1353 * @param t town to inquiry
1354 * @param tile to inquiry
1355 * @return whether expansion was possible
1357 static bool GrowTownFromTile (Town *t, TileIndex tile)
1359 DiagDirection target_dir = DIAGDIR_END; // The direction in which we want to extend the town
1361 assert(tile < MapSize());
1363 /* Number of times to search.
1364 * Better roads, 2X2 and 3X3 grid grow quite fast so we give
1365 * them a little handicap. */
1366 uint iterations;
1367 switch (t->layout) {
1368 case TL_BETTER_ROADS:
1369 iterations = 10 + t->cache.num_houses * 2 / 9;
1370 break;
1372 case TL_3X3_GRID:
1373 case TL_2X2_GRID:
1374 iterations = 10 + t->cache.num_houses * 1 / 9;
1375 break;
1377 default:
1378 iterations = 10 + t->cache.num_houses * 4 / 9;
1379 break;
1382 while (iterations-- > 0) {
1383 RoadBits cur_rb = GetTownRoadBits(tile); // The RoadBits of the current tile
1385 /* Try to grow the town from this point */
1386 assert(tile < MapSize());
1387 assert((cur_rb == ROAD_NONE) || !HasTileWaterGround(tile));
1389 if (cur_rb == ROAD_NONE) {
1390 assert (IsValidDiagDirection(target_dir));
1391 return GrowTown_NewRoad (t, tile, target_dir);
1393 } else if (target_dir != DIAGDIR_END && !(cur_rb & DiagDirToRoadBits(ReverseDiagDir(target_dir)))) {
1394 return GrowTown_UnconnectedRoad (t, tile, target_dir, cur_rb);
1396 } else if (!IsRoadBridgeTile(tile) && !IsTunnelTile(tile)) {
1397 switch (GrowTown_ConnectedRoad (t, tile, target_dir, cur_rb)) {
1398 case GROWTH_CONTINUE: break;
1399 case GROWTH_FAILURE: return false;
1400 case GROWTH_SUCCESS: return true;
1404 if (IsTunnelTile(tile)) {
1405 /* Reached a tunnel. Continue at the other end if this
1406 * is not the first tile, or half of the times if it is. */
1407 assert (maptile_is_road_tunnel(tile));
1409 if (target_dir == DIAGDIR_END) {
1410 if (Chance16(1, 2)) tile = GetOtherTunnelEnd (tile);
1411 target_dir = ReverseDiagDir (GetTunnelBridgeDirection(tile));
1412 } else {
1413 if (GetTunnelBridgeDirection(tile) != target_dir) return false;
1414 tile = GetOtherTunnelEnd (tile);
1417 tile = TileAddByDiagDir (tile, target_dir);
1418 if ((IsRoadBridgeTile(tile) || IsTunnelTile(tile))
1419 && GetTunnelBridgeDirection(tile) == (ReverseDiagDir(target_dir))) {
1420 return false;
1422 } else {
1423 /* Exclude the source position from the bitmask
1424 * and return if no more road blocks available */
1425 if (target_dir != DIAGDIR_END) cur_rb &= ~DiagDirToRoadBits(ReverseDiagDir(target_dir));
1427 /* Select a random bit from the blockmask, walk a step
1428 * and continue the search from there. */
1429 TileIndex target_tile;
1430 for (;;) {
1431 if (cur_rb == ROAD_NONE) return false;
1433 RoadBits connect_rb;
1434 do {
1435 target_dir = RandomDiagDir();
1436 connect_rb = DiagDirToRoadBits (target_dir);
1437 } while (!(cur_rb & connect_rb));
1438 cur_rb ^= connect_rb;
1440 if (IsRoadBridgeTile(tile) && target_dir == GetTunnelBridgeDirection(tile)) {
1441 target_tile = GetOtherBridgeEnd (tile);
1442 break;
1445 target_tile = TileAddByDiagDir (tile, target_dir);
1446 if ((IsRoadBridgeTile (target_tile) || IsTunnelTile (target_tile))
1447 && GetTunnelBridgeDirection (target_tile) == (ReverseDiagDir (target_dir))) {
1448 continue;
1451 if (_settings_game.economy.allow_town_roads || _generating_world) {
1452 if (GrowTownTileUsable (target_tile)) break;
1453 } else {
1454 connect_rb = MirrorRoadBits (connect_rb);
1455 RoadBits target_rb = GetTownRoadBits (target_tile);
1456 if ((target_rb & connect_rb) != 0 && (target_rb != connect_rb)) break;
1459 tile = target_tile;
1462 if ((IsRoadTile(tile) || IsLevelCrossingTile(tile)) && HasTileRoadType(tile, ROADTYPE_ROAD)) {
1463 /* Don't allow building over roads of other cities */
1464 if (IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN) && Town::GetByTile(tile) != t) {
1465 return true;
1466 } else if (IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_NONE) && _game_mode == GM_EDITOR) {
1467 /* If we are in the SE, and this road-piece has no town owner yet, it just found an
1468 * owner :) (happy happy happy road now) */
1469 SetRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN);
1470 SetTownIndex(tile, t->index);
1475 return false;
1479 * Generate a random road block.
1480 * The probability of a straight road
1481 * is somewhat higher than a curved.
1483 * @return A RoadBits value with 2 bits set
1485 static RoadBits GenRandomRoadBits()
1487 uint32 r = Random();
1488 uint a = GB(r, 0, 2);
1489 uint b = GB(r, 8, 2);
1490 if (a == b) b ^= 2;
1491 return (RoadBits)((ROAD_NW << a) + (ROAD_NW << b));
1495 * Grow the town
1496 * @param t town to grow
1497 * @return true iff a house was built
1499 static bool GrowTown(Town *t)
1501 static const CoordDiff _town_coord_mod[] = {
1502 {-1, 0},
1503 { 1, 1},
1504 { 1, -1},
1505 {-1, -1},
1506 {-1, 0},
1507 { 0, 2},
1508 { 2, 0},
1509 { 0, -2},
1510 {-1, -1},
1511 {-2, 2},
1512 { 2, 2},
1513 { 2, -2},
1514 { 0, 0}
1517 /* Current "company" is a town */
1518 Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1520 TileIndex tile = t->xy; // The tile we are working with ATM
1522 /* Find a road that we can base the construction on. */
1523 const CoordDiff *ptr;
1524 for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) {
1525 if (GetTownRoadBits(tile) != ROAD_NONE) {
1526 bool r = GrowTownFromTile (t, tile);
1527 cur_company.Restore();
1528 return r;
1530 tile = TILE_ADD(tile, ToTileIndexDiff(*ptr));
1533 /* No road available, try to build a random road block by
1534 * clearing some land and then building a road there. */
1535 if (_settings_game.economy.allow_town_roads || _generating_world) {
1536 tile = t->xy;
1537 for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) {
1538 /* Only work with plain land that not already has a house */
1539 if (!IsHouseTile(tile) && IsTileFlat(tile)) {
1540 if (DoCommand(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR).Succeeded()) {
1541 DoCommand(tile, GenRandomRoadBits(), t->index, DC_EXEC | DC_AUTO, CMD_BUILD_ROAD);
1542 cur_company.Restore();
1543 return true;
1546 tile = TILE_ADD(tile, ToTileIndexDiff(*ptr));
1550 cur_company.Restore();
1551 return false;
1554 void UpdateTownRadius(Town *t)
1556 static const uint32 _town_squared_town_zone_radius_data[23][5] = {
1557 { 4, 0, 0, 0, 0}, // 0
1558 { 16, 0, 0, 0, 0},
1559 { 25, 0, 0, 0, 0},
1560 { 36, 0, 0, 0, 0},
1561 { 49, 0, 4, 0, 0},
1562 { 64, 0, 4, 0, 0}, // 20
1563 { 64, 0, 9, 0, 1},
1564 { 64, 0, 9, 0, 4},
1565 { 64, 0, 16, 0, 4},
1566 { 81, 0, 16, 0, 4},
1567 { 81, 0, 16, 0, 4}, // 40
1568 { 81, 0, 25, 0, 9},
1569 { 81, 36, 25, 0, 9},
1570 { 81, 36, 25, 16, 9},
1571 { 81, 49, 0, 25, 9},
1572 { 81, 64, 0, 25, 9}, // 60
1573 { 81, 64, 0, 36, 9},
1574 { 81, 64, 0, 36, 16},
1575 {100, 81, 0, 49, 16},
1576 {100, 81, 0, 49, 25},
1577 {121, 81, 0, 49, 25}, // 80
1578 {121, 81, 0, 49, 25},
1579 {121, 81, 0, 49, 36}, // 88
1582 if (t->cache.num_houses < 92) {
1583 memcpy(t->cache.squared_town_zone_radius, _town_squared_town_zone_radius_data[t->cache.num_houses / 4], sizeof(t->cache.squared_town_zone_radius));
1584 } else {
1585 int mass = t->cache.num_houses / 8;
1586 /* Actually we are proportional to sqrt() but that's right because we are covering an area.
1587 * The offsets are to make sure the radii do not decrease in size when going from the table
1588 * to the calculated value.*/
1589 t->cache.squared_town_zone_radius[0] = mass * 15 - 40;
1590 t->cache.squared_town_zone_radius[1] = mass * 9 - 15;
1591 t->cache.squared_town_zone_radius[2] = 0;
1592 t->cache.squared_town_zone_radius[3] = mass * 5 - 5;
1593 t->cache.squared_town_zone_radius[4] = mass * 3 + 5;
1597 void UpdateTownMaxPass(Town *t)
1599 t->supplied[CT_PASSENGERS].old_max = t->cache.population >> 3;
1600 t->supplied[CT_MAIL].old_max = t->cache.population >> 4;
1604 * Town constructor.
1605 * @param tile Center tile of the town.
1606 * @param townnameparts Town name.
1607 * @param city Whether the town is a city.
1608 * @param layout Road layout of the town.
1610 Town::Town (TileIndex tile, uint32 townnameparts, bool city, TownLayout layout) :
1611 xy (tile), townnameparams (_settings_game.game_creation.town_name),
1612 townnameparts (townnameparts), name (NULL), flags (0),
1613 noise_reached (0), statues (0), have_ratings (0), text (NULL),
1614 time_until_rebuild (10), grow_counter (0), growth_rate (250),
1615 fund_buildings_months (0), larger_town (city)
1617 add_to_tileset();
1619 this->cache.num_houses = 0;
1620 this->cache.population = 0;
1621 UpdateTownRadius (this);
1623 this->exclusivity = INVALID_COMPANY;
1624 this->exclusive_counter = 0;
1626 for (uint i = 0; i != MAX_COMPANIES; i++) this->ratings[i] = RATING_INITIAL;
1628 /* Set the default cargo requirement for town growth */
1629 switch (_settings_game.game_creation.landscape) {
1630 case LT_ARCTIC:
1631 if (FindFirstCargoWithTownEffect(TE_FOOD) != NULL) this->goal[TE_FOOD] = TOWN_GROWTH_WINTER;
1632 break;
1634 case LT_TROPIC:
1635 if (FindFirstCargoWithTownEffect(TE_FOOD) != NULL) this->goal[TE_FOOD] = TOWN_GROWTH_DESERT;
1636 if (FindFirstCargoWithTownEffect(TE_WATER) != NULL) this->goal[TE_WATER] = TOWN_GROWTH_DESERT;
1637 break;
1640 this->layout = (layout != TL_RANDOM) ? layout :
1641 (TownLayout) (TileHash (TileX(tile), TileY(tile)) % (NUM_TLS - 1));
1645 * Does the actual town creation.
1646 * @param tile Where to put it
1647 * @param townnameparts The town name
1648 * @param size Parameter for size determination
1649 * @param city whether to build a city or town
1650 * @param layout the (road) layout of the town
1651 * @param manual was the town placed manually?
1652 * @return The created town
1654 static Town *DoCreateTown (TileIndex tile, uint32 townnameparts,
1655 TownSize size, bool city, TownLayout layout, bool manual)
1657 Town *t = new Town (tile, townnameparts, city, layout);
1659 int x = (int)size * 16 + 3;
1660 if (size == TSZ_RANDOM) x = (Random() & 0xF) + 8;
1661 /* Don't create huge cities when founding town in-game */
1662 if (city && (!manual || _game_mode == GM_EDITOR)) x *= _settings_game.economy.initial_city_size;
1664 t->cache.num_houses += x;
1665 UpdateTownRadius(t);
1667 int i = x * 4;
1668 do {
1669 GrowTown(t);
1670 } while (--i);
1672 t->cache.num_houses -= x;
1673 UpdateTownRadius(t);
1674 UpdateTownMaxPass(t);
1675 UpdateAirportsNoise();
1677 t->UpdateVirtCoord();
1678 InvalidateWindowData(WC_TOWN_DIRECTORY, 0, 0);
1679 InvalidateWindowData(WC_SELECT_TOWN, 0);
1681 return t;
1685 * Checks if it's possible to place a town at given tile
1686 * @param tile tile to check
1687 * @return error string or STR_NULL on success
1689 static StringID TownCanBePlacedHere (TileIndex tile)
1691 /* Check if too close to the edge of map */
1692 if (DistanceFromEdge(tile) < 12) {
1693 return STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB;
1696 /* Check distance to all other towns. */
1697 if (Town::find_any<DistanceManhattan> (tile, 19)) {
1698 return STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN;
1701 /* Can only build on clear flat areas, possibly with trees. */
1702 if (!IsGroundTile(tile) || !IsTileFlat(tile)) {
1703 return STR_ERROR_SITE_UNSUITABLE;
1706 return STR_NULL;
1710 * Verifies this custom name is unique. Only custom names are checked.
1711 * @param name name to check
1712 * @return is this name unique?
1714 static bool IsUniqueTownName(const char *name)
1716 const Town *t;
1718 FOR_ALL_TOWNS(t) {
1719 if (t->name != NULL && strcmp(t->name, name) == 0) return false;
1722 return true;
1726 * Create a new town.
1727 * @param tile coordinates where town is built
1728 * @param flags type of operation
1729 * @param p1 0..1 size of the town (@see TownSize)
1730 * 2 true iff it should be a city
1731 * 3..5 town road layout (@see TownLayout)
1732 * 6 use random location (randomize \c tile )
1733 * @param p2 town name parts
1734 * @param text Custom name for the town. If empty, the town name parts will be used.
1735 * @return the cost of this operation or an error
1737 CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1739 TownSize size = Extract<TownSize, 0, 2>(p1);
1740 bool city = HasBit(p1, 2);
1741 TownLayout layout = Extract<TownLayout, 3, 3>(p1);
1742 TownNameParams par(_settings_game.game_creation.town_name);
1743 bool random = HasBit(p1, 6);
1744 uint32 townnameparts = p2;
1746 if (size >= TSZ_END) return CMD_ERROR;
1747 if (layout >= NUM_TLS) return CMD_ERROR;
1749 /* Some things are allowed only in the scenario editor and for game scripts. */
1750 if (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY) {
1751 if (_settings_game.economy.found_town == TF_FORBIDDEN) return CMD_ERROR;
1752 if (size == TSZ_LARGE) return CMD_ERROR;
1753 if (random) return CMD_ERROR;
1754 if (_settings_game.economy.found_town != TF_CUSTOM_LAYOUT && layout != _settings_game.economy.town_layout) {
1755 return CMD_ERROR;
1757 } else if (_current_company == OWNER_DEITY && random) {
1758 /* Random parameter is not allowed for Game Scripts. */
1759 return CMD_ERROR;
1762 if (StrEmpty(text)) {
1763 /* If supplied name is empty, townnameparts has to generate unique automatic name */
1764 if (!VerifyTownName(townnameparts, &par)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
1765 } else {
1766 /* If name is not empty, it has to be unique custom name */
1767 if (Utf8StringLength(text) >= MAX_LENGTH_TOWN_NAME_CHARS) return CMD_ERROR;
1768 if (!IsUniqueTownName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
1771 /* Allocate town struct */
1772 if (!Town::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_TOWNS);
1774 if (!random) {
1775 StringID str = TownCanBePlacedHere (tile);
1776 if (str != STR_NULL) return_cmd_error(str);
1779 static const byte price_mult[][TSZ_RANDOM + 1] = {{ 15, 25, 40, 25 }, { 20, 35, 55, 35 }};
1780 /* multidimensional arrays have to have defined length of non-first dimension */
1781 assert_compile(lengthof(price_mult[0]) == 4);
1783 CommandCost cost(EXPENSES_OTHER, _price[PR_BUILD_TOWN]);
1784 byte mult = price_mult[city][size];
1786 cost.MultiplyCost(mult);
1788 /* Create the town */
1789 if (flags & DC_EXEC) {
1790 if (cost.GetCost() > GetAvailableMoneyForCommand()) {
1791 _additional_cash_required = cost.GetCost();
1792 return CommandCost(EXPENSES_OTHER);
1795 Backup<bool> old_generating_world(_generating_world, true, FILE_LINE);
1796 UpdateNearestTownForRoadTiles(true);
1797 Town *t;
1798 if (random) {
1799 t = CreateRandomTown(20, townnameparts, size, city, layout);
1800 if (t == NULL) {
1801 cost = CommandCost(STR_ERROR_NO_SPACE_FOR_TOWN);
1802 } else {
1803 _new_town_id = t->index;
1805 } else {
1806 t = DoCreateTown (tile, townnameparts, size, city, layout, true);
1808 UpdateNearestTownForRoadTiles(false);
1809 old_generating_world.Restore();
1811 if (t != NULL && !StrEmpty(text)) {
1812 t->name = xstrdup(text);
1813 t->UpdateVirtCoord();
1816 if (_game_mode != GM_EDITOR) {
1817 /* 't' can't be NULL since 'random' is false outside scenedit */
1818 assert(!random);
1820 AddNewsItem<FoundTownNewsItem> (t->index, tile, _current_company);
1821 AI::BroadcastNewEvent(new ScriptEventTownFounded(t->index));
1822 Game::NewEvent(new ScriptEventTownFounded(t->index));
1825 return cost;
1829 * Towns must all be placed on the same grid or when they eventually
1830 * interpenetrate their road networks will not mesh nicely; this
1831 * function adjusts a tile so that it aligns properly.
1833 * @param tile the tile to start at
1834 * @param layout which town layout algo is in effect
1835 * @return the adjusted tile
1837 static TileIndex AlignTileToGrid(TileIndex tile, TownLayout layout)
1839 switch (layout) {
1840 case TL_2X2_GRID: return TileXY(TileX(tile) - TileX(tile) % 3, TileY(tile) - TileY(tile) % 3);
1841 case TL_3X3_GRID: return TileXY(TileX(tile) & ~3, TileY(tile) & ~3);
1842 default: return tile;
1847 * Towns must all be placed on the same grid or when they eventually
1848 * interpenetrate their road networks will not mesh nicely; this
1849 * function tells you if a tile is properly aligned.
1851 * @param tile the tile to start at
1852 * @param layout which town layout algo is in effect
1853 * @return true if the tile is in the correct location
1855 static bool IsTileAlignedToGrid(TileIndex tile, TownLayout layout)
1857 switch (layout) {
1858 case TL_2X2_GRID: return TileX(tile) % 3 == 0 && TileY(tile) % 3 == 0;
1859 case TL_3X3_GRID: return TileX(tile) % 4 == 0 && TileY(tile) % 4 == 0;
1860 default: return true;
1865 * Given a spot on the map (presumed to be a water tile), find a good
1866 * coastal spot to build a city. We don't want to build too close to
1867 * the edge if we can help it (since that retards city growth) hence
1868 * the search within a search within a search. O(n*m^2), where n is
1869 * how far to search for land, and m is how far inland to look for a
1870 * flat spot.
1872 * @param tile Start looking from this spot.
1873 * @param layout the road layout to search for
1874 * @return tile that was found
1876 static TileIndex FindNearestGoodCoastalTownSpot(TileIndex tile, TownLayout layout)
1878 CircularTileIterator iter (tile, 40);
1879 for (TileIndex coast = iter; coast != INVALID_TILE; coast = ++iter) {
1880 if (IsGroundTile (coast)) {
1881 /* Search for a good inland spot for a town. */
1882 TileIndex spot_tile = INVALID_TILE;
1883 uint spot_dist = 0;
1885 CircularTileIterator iter (coast, 10);
1886 for (TileIndex t = iter; t != INVALID_TILE; t = ++iter) {
1887 if (!IsGroundTile(t)) continue;
1888 if (!IsTileFlat(t)) continue;
1889 if (!IsTileAlignedToGrid (t, layout)) continue;
1891 uint dist = GetClosestWaterDistance (t, true);
1892 if (dist > spot_dist) {
1893 spot_tile = t;
1894 spot_dist = dist;
1897 return spot_tile;
1901 /* if we get here just give up */
1902 return INVALID_TILE;
1905 static Town *CreateRandomTown(uint attempts, uint32 townnameparts, TownSize size, bool city, TownLayout layout)
1907 assert(_game_mode == GM_EDITOR || _generating_world); // These are the preconditions for CMD_DELETE_TOWN
1909 if (!Town::CanAllocateItem()) return NULL;
1911 do {
1912 /* Generate a tile index not too close from the edge */
1913 TileIndex tile = AlignTileToGrid(RandomTile(), layout);
1915 /* if we tried to place the town on water, slide it over onto
1916 * the nearest likely-looking spot */
1917 if (IsWaterTile(tile)) {
1918 tile = FindNearestGoodCoastalTownSpot(tile, layout);
1919 if (tile == INVALID_TILE) continue;
1922 /* Make sure town can be placed here */
1923 if (TownCanBePlacedHere (tile) != STR_NULL) continue;
1925 /* Allocate a town struct */
1926 Town *t = DoCreateTown (tile, townnameparts, size, city, layout, false);
1928 /* if the population is still 0 at the point, then the
1929 * placement is so bad it couldn't grow at all */
1930 if (t->cache.population > 0) return t;
1932 Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1933 CommandCost rc = DoCommand(t->xy, t->index, 0, DC_EXEC, CMD_DELETE_TOWN);
1934 cur_company.Restore();
1935 assert(rc.Succeeded());
1937 /* We already know that we can allocate a single town when
1938 * entering this function. However, we create and delete
1939 * a town which "resets" the allocation checks. As such we
1940 * need to check again when assertions are enabled. */
1941 assert(Town::CanAllocateItem());
1942 } while (--attempts != 0);
1944 return NULL;
1947 static const byte _num_initial_towns[4] = {5, 11, 23, 46}; // very low, low, normal, high
1950 * This function will generate a certain amount of towns, with a certain layout
1951 * It can be called from the scenario editor (i.e.: generate Random Towns)
1952 * as well as from world creation.
1953 * @param layout which towns will be set to, when created
1954 * @return true if towns have been successfully created
1956 bool GenerateTowns(TownLayout layout)
1958 uint current_number = 0;
1959 uint difficulty = (_game_mode != GM_EDITOR) ? _settings_game.difficulty.number_towns : 0;
1960 uint total = (difficulty == (uint)CUSTOM_TOWN_NUMBER_DIFFICULTY) ? _settings_game.game_creation.custom_town_number : ScaleByMapSize(_num_initial_towns[difficulty] + (Random() & 7));
1961 total = min(Town::Pool::MAX_SIZE, total);
1962 uint32 townnameparts;
1963 TownNames town_names;
1965 SetGeneratingWorldProgress(GWP_TOWN, total);
1967 /* First attempt will be made at creating the suggested number of towns.
1968 * Note that this is really a suggested value, not a required one.
1969 * We would not like the system to lock up just because the user wanted 100 cities on a 64*64 map, would we? */
1970 do {
1971 bool city = (_settings_game.economy.larger_towns != 0 && Chance16(1, _settings_game.economy.larger_towns));
1972 IncreaseGeneratingWorldProgress(GWP_TOWN);
1973 /* Get a unique name for the town. */
1974 if (!GenerateTownName(&townnameparts, &town_names)) continue;
1975 /* try 20 times to create a random-sized town for the first loop. */
1976 if (CreateRandomTown(20, townnameparts, TSZ_RANDOM, city, layout) != NULL) current_number++; // If creation was successful, raise a flag.
1977 } while (--total);
1979 town_names.clear();
1981 if (current_number != 0) return true;
1983 /* If current_number is still zero at this point, it means that not a single town has been created.
1984 * So give it a last try, but now more aggressive */
1985 if (GenerateTownName(&townnameparts) &&
1986 CreateRandomTown(10000, townnameparts, TSZ_RANDOM, _settings_game.economy.larger_towns != 0, layout) != NULL) {
1987 return true;
1990 /* If there are no towns at all and we are generating new game, bail out */
1991 if (Town::GetNumItems() == 0 && _game_mode != GM_EDITOR) {
1992 ShowErrorMessage(STR_ERROR_COULD_NOT_CREATE_TOWN, INVALID_STRING_ID, WL_CRITICAL);
1995 return false; // we are still without a town? we failed, simply
2000 * Returns the bit corresponding to the town zone of the specified tile
2001 * @param t Town on which town zone is to be found
2002 * @param tile TileIndex where town zone needs to be found
2003 * @return the bit position of the given zone, as defined in HouseZones
2005 HouseZonesBits GetTownRadiusGroup(const Town *t, TileIndex tile)
2007 uint dist = DistanceSquare(tile, t->xy);
2009 if (t->fund_buildings_months && dist <= 25) return HZB_TOWN_CENTRE;
2011 HouseZonesBits smallest = HZB_TOWN_EDGE;
2012 for (HouseZonesBits i = HZB_BEGIN; i < HZB_END; i++) {
2013 if (dist < t->cache.squared_town_zone_radius[i]) smallest = i;
2016 return smallest;
2020 * Clears tile and builds a house or house part.
2021 * @param tile tile index
2022 * @param t The town to clear the house for
2023 * @param counter of construction step
2024 * @param stage of construction (used for drawing)
2025 * @param type of house. Index into house specs array
2026 * @param random_bits required for newgrf houses
2027 * @pre house can be built here
2029 static inline void ClearMakeHouseTile(TileIndex tile, Town *t, byte counter, byte stage, HouseID type, byte random_bits)
2031 CommandCost cc = DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR);
2033 assert(cc.Succeeded());
2035 assert(IsGroundTile(tile));
2037 IncreaseBuildingCount(t, type);
2038 MakeHouseTile(tile, t->index, counter, stage, type, random_bits, HouseSpec::Get(type)->processing_time);
2039 if (HouseSpec::Get(type)->building_flags & BUILDING_IS_ANIMATED) AddAnimatedTile(tile);
2041 MarkTileDirtyByTile(tile);
2046 * Write house information into the map. For houses > 1 tile, all tiles are marked.
2047 * @param t tile index
2048 * @param town The town related to this house
2049 * @param counter of construction step
2050 * @param stage of construction (used for drawing)
2051 * @param type of house. Index into house specs array
2052 * @param random_bits required for newgrf houses
2053 * @pre house can be built here
2055 static void MakeTownHouse(TileIndex t, Town *town, byte counter, byte stage, HouseID type, byte random_bits)
2057 BuildingFlags size = HouseSpec::Get(type)->building_flags;
2059 ClearMakeHouseTile(t, town, counter, stage, type, random_bits);
2060 if (size & BUILDING_2_TILES_Y) ClearMakeHouseTile(t + TileDiffXY(0, 1), town, counter, stage, ++type, random_bits);
2061 if (size & BUILDING_2_TILES_X) ClearMakeHouseTile(t + TileDiffXY(1, 0), town, counter, stage, ++type, random_bits);
2062 if (size & BUILDING_HAS_4_TILES) ClearMakeHouseTile(t + TileDiffXY(1, 1), town, counter, stage, ++type, random_bits);
2067 * Checks if a house can be built here. Important is slope, bridge above
2068 * and ability to clear the land.
2069 * @param tile tile to check
2070 * @param noslope are slopes (foundations) allowed?
2071 * @return true iff house can be built here
2073 static inline bool CanBuildHouseHere(TileIndex tile, bool noslope)
2075 /* cannot build on these slopes... */
2076 Slope slope = GetTileSlope(tile);
2077 if ((noslope && slope != SLOPE_FLAT) || IsSteepSlope(slope)) return false;
2079 /* building under a bridge? */
2080 if (HasBridgeAbove(tile)) return false;
2082 /* can we clear the land? */
2083 return DoCommand(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR).Succeeded();
2088 * Checks if a house can be built at this tile, must have the same max z as parameter.
2089 * @param tile tile to check
2090 * @param z max z of this tile so more parts of a house are at the same height (with foundation)
2091 * @param noslope are slopes (foundations) allowed?
2092 * @return true iff house can be built here
2093 * @see CanBuildHouseHere()
2095 static inline bool CheckBuildHouseSameZ(TileIndex tile, int z, bool noslope)
2097 if (!CanBuildHouseHere(tile, noslope)) return false;
2099 /* if building on slopes is allowed, there will be flattening foundation (to tile max z) */
2100 if (GetTileMaxZ(tile) != z) return false;
2102 return true;
2107 * Checks if a house of size 2x2 can be built at this tile
2108 * @param tile tile, N corner
2109 * @param z maximum tile z so all tile have the same max z
2110 * @param noslope are slopes (foundations) allowed?
2111 * @return true iff house can be built
2112 * @see CheckBuildHouseSameZ()
2114 static bool CheckFree2x2Area(TileIndex tile, int z, bool noslope)
2116 /* we need to check this tile too because we can be at different tile now */
2117 if (!CheckBuildHouseSameZ(tile, z, noslope)) return false;
2119 for (DiagDirection d = DIAGDIR_SE; d < DIAGDIR_END; d++) {
2120 tile += TileOffsByDiagDir(d);
2121 if (!CheckBuildHouseSameZ(tile, z, noslope)) return false;
2124 return true;
2129 * Checks if current town layout allows building here
2130 * @param t town
2131 * @param tile tile to check
2132 * @return true iff town layout allows building here
2133 * @note see layouts
2135 static inline bool TownLayoutAllowsHouseHere(Town *t, TileIndex tile)
2137 /* Allow towns everywhere when we don't build roads */
2138 if (!_settings_game.economy.allow_town_roads && !_generating_world) return true;
2140 CoordDiff grid_pos = TileCoordDiff(t->xy, tile);
2142 switch (t->layout) {
2143 case TL_2X2_GRID:
2144 if ((grid_pos.x % 3) == 0 || (grid_pos.y % 3) == 0) return false;
2145 break;
2147 case TL_3X3_GRID:
2148 if ((grid_pos.x % 4) == 0 || (grid_pos.y % 4) == 0) return false;
2149 break;
2151 default:
2152 break;
2155 return true;
2160 * Checks if current town layout allows 2x2 building here
2161 * @param t town
2162 * @param tile tile to check
2163 * @return true iff town layout allows 2x2 building here
2164 * @note see layouts
2166 static inline bool TownLayoutAllows2x2HouseHere(Town *t, TileIndex tile)
2168 /* Allow towns everywhere when we don't build roads */
2169 if (!_settings_game.economy.allow_town_roads && !_generating_world) return true;
2171 /* Compute relative position of tile. (Positive offsets are towards north) */
2172 CoordDiff grid_pos = TileCoordDiff(t->xy, tile);
2174 switch (t->layout) {
2175 case TL_2X2_GRID:
2176 grid_pos.x %= 3;
2177 grid_pos.y %= 3;
2178 if ((grid_pos.x != 2 && grid_pos.x != -1) ||
2179 (grid_pos.y != 2 && grid_pos.y != -1)) return false;
2180 break;
2182 case TL_3X3_GRID:
2183 if ((grid_pos.x & 3) < 2 || (grid_pos.y & 3) < 2) return false;
2184 break;
2186 default:
2187 break;
2190 return true;
2195 * Checks if 1x2 or 2x1 building is allowed here, also takes into account current town layout
2196 * Also, tests both building positions that occupy this tile
2197 * @param tile tile where the building should be built
2198 * @param t town
2199 * @param maxz all tiles should have the same height
2200 * @param noslope are slopes forbidden?
2201 * @param second diagdir from first tile to second tile
2203 static bool CheckTownBuild2House(TileIndex *tile, Town *t, int maxz, bool noslope, DiagDirection second)
2205 /* 'tile' is already checked in BuildTownHouse() - CanBuildHouseHere() and slope test */
2207 TileIndex tile2 = *tile + TileOffsByDiagDir(second);
2208 if (TownLayoutAllowsHouseHere(t, tile2) && CheckBuildHouseSameZ(tile2, maxz, noslope)) return true;
2210 tile2 = *tile + TileOffsByDiagDir(ReverseDiagDir(second));
2211 if (TownLayoutAllowsHouseHere(t, tile2) && CheckBuildHouseSameZ(tile2, maxz, noslope)) {
2212 *tile = tile2;
2213 return true;
2216 return false;
2221 * Checks if 2x2 building is allowed here, also takes into account current town layout
2222 * Also, tests all four building positions that occupy this tile
2223 * @param tile tile where the building should be built
2224 * @param t town
2225 * @param maxz all tiles should have the same height
2226 * @param noslope are slopes forbidden?
2228 static bool CheckTownBuild2x2House(TileIndex *tile, Town *t, int maxz, bool noslope)
2230 TileIndex tile2 = *tile;
2232 for (DiagDirection d = DIAGDIR_SE;; d++) { // 'd' goes through DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_END
2233 if (TownLayoutAllows2x2HouseHere(t, tile2) && CheckFree2x2Area(tile2, maxz, noslope)) {
2234 *tile = tile2;
2235 return true;
2237 if (d == DIAGDIR_END) break;
2238 tile2 += TileOffsByDiagDir(ReverseDiagDir(d)); // go clockwise
2241 return false;
2244 /** Get the flag to test/set for building uniqueness in a town. */
2245 static uint GetHouseUniqueFlags (const HouseSpec *hs)
2247 return (hs->building_flags & BUILDING_IS_CHURCH) ? (1 << TOWN_HAS_CHURCH) :
2248 (hs->building_flags & BUILDING_IS_STADIUM) ? (1 << TOWN_HAS_STADIUM) :
2253 * Check if a town can have a new house of a given type.
2254 * @param t The town to check.
2255 * @param house The house type that we want to add.
2256 * @param STR_NULL on success, else an error message.
2258 StringID IsNewTownHouseAllowed (const Town *t, HouseID house)
2260 const HouseSpec *hs = HouseSpec::Get(house);
2262 /* Don't let these counters overflow. Global counters are 32bit, there will never be that many houses. */
2263 if (hs->class_id != HOUSE_NO_CLASS) {
2264 /* id_count is always <= class_count, so it doesn't need to be checked. */
2265 if (t->cache.building_counts.class_count[hs->class_id] == UINT16_MAX) {
2266 return STR_ERROR_TOO_MANY_CLASS_HOUSES;
2268 } else {
2269 /* If the house has no class, check id_count instead. */
2270 if (t->cache.building_counts.id_count[house] == UINT16_MAX) {
2271 return STR_ERROR_TOO_MANY_HOUSES;
2275 /* Special houses that there can be only one of. */
2276 uint oneof = GetHouseUniqueFlags (hs);
2277 if (t->flags & oneof) return STR_ERROR_ONLY_ONE_BUILDING_PER_TOWN;
2279 return STR_NULL;
2283 * Really build a house.
2284 * @param t town to build house in
2285 * @param tile house location
2286 * @param house house type
2287 * @param random_bits random bits for the house
2289 void DoBuildHouse(Town *t, TileIndex tile, HouseID house, byte random_bits)
2291 t->cache.num_houses++;
2293 const HouseSpec *hs = HouseSpec::Get(house);
2295 /* Special houses that there can be only one of. */
2296 uint oneof = GetHouseUniqueFlags (hs);
2297 assert ((t->flags & oneof) == 0);
2298 t->flags |= oneof;
2300 byte construction_counter = 0;
2301 byte construction_stage = 0;
2303 if (_generating_world || _game_mode == GM_EDITOR) {
2304 uint32 r = Random();
2306 construction_stage = TOWN_HOUSE_COMPLETED;
2307 if (Chance16(1, 7)) construction_stage = GB(r, 0, 2);
2309 if (construction_stage == TOWN_HOUSE_COMPLETED) {
2310 ChangePopulation(t, hs->population);
2311 } else {
2312 construction_counter = GB(r, 2, 2);
2316 MakeTownHouse(tile, t, construction_counter, construction_stage, house, random_bits);
2317 UpdateTownRadius(t);
2318 UpdateTownCargoes(t, tile);
2322 * Tries to build a house at this tile
2323 * @param t town the house will belong to
2324 * @param tile where the house will be built
2325 * @return false iff no house can be built at this tile
2327 static bool BuildTownHouse(Town *t, TileIndex tile)
2329 /* forbidden building here by town layout */
2330 if (!TownLayoutAllowsHouseHere(t, tile)) return false;
2332 /* no house allowed at all, bail out */
2333 if (!CanBuildHouseHere(tile, false)) return false;
2335 Slope slope = GetTileSlope(tile);
2336 int maxz = GetTileMaxZ(tile);
2338 /* Get the town zone type of the current tile, as well as the climate.
2339 * This will allow to easily compare with the specs of the new house to build */
2340 HouseZonesBits rad = GetTownRadiusGroup(t, tile);
2342 /* Above snow? */
2343 int land = _settings_game.game_creation.landscape;
2344 if (land == LT_ARCTIC && maxz > HighestSnowLine()) land = -1;
2346 uint bitmask = (1 << rad) + (1 << (land + 12));
2348 /* bits 0-4 are used
2349 * bits 11-15 are used
2350 * bits 5-10 are not used. */
2351 HouseID houses[NUM_HOUSES];
2352 uint num = 0;
2353 uint probs[NUM_HOUSES];
2354 uint probability_max = 0;
2356 /* Generate a list of all possible houses that can be built. */
2357 for (uint i = 0; i < NUM_HOUSES; i++) {
2358 const HouseSpec *hs = HouseSpec::Get(i);
2360 /* Verify that the candidate house spec matches the current tile status */
2361 if ((~hs->building_availability & bitmask) != 0 || !hs->enabled || hs->grf_prop.override != INVALID_HOUSE_ID) continue;
2363 if (IsNewTownHouseAllowed (t, i) != STR_NULL) continue;
2365 /* Without NewHouses, all houses have probability '1' */
2366 uint cur_prob = (_loaded_newgrf_features.has_newhouses ? hs->probability : 1);
2367 probability_max += cur_prob;
2368 probs[num] = cur_prob;
2369 houses[num++] = (HouseID)i;
2372 TileIndex baseTile = tile;
2374 while (probability_max > 0) {
2375 /* Building a multitile building can change the location of tile.
2376 * The building would still be built partially on that tile, but
2377 * its northern tile would be elsewhere. However, if the callback
2378 * fails we would be basing further work from the changed tile.
2379 * So a next 1x1 tile building could be built on the wrong tile. */
2380 tile = baseTile;
2382 uint r = RandomRange(probability_max);
2383 uint i;
2384 for (i = 0; i < num; i++) {
2385 if (probs[i] > r) break;
2386 r -= probs[i];
2389 HouseID house = houses[i];
2390 probability_max -= probs[i];
2392 /* remove tested house from the set */
2393 num--;
2394 houses[i] = houses[num];
2395 probs[i] = probs[num];
2397 const HouseSpec *hs = HouseSpec::Get(house);
2399 if (_loaded_newgrf_features.has_newhouses && !_generating_world &&
2400 _game_mode != GM_EDITOR && (hs->extra_flags & BUILDING_IS_HISTORICAL) != 0) {
2401 continue;
2404 if (_cur_year < hs->min_year || _cur_year > hs->max_year) continue;
2406 /* Make sure there is no slope? */
2407 bool noslope = (hs->building_flags & TILE_NOT_SLOPED) != 0;
2408 if (noslope && slope != SLOPE_FLAT) continue;
2410 if (hs->building_flags & TILE_SIZE_2x2) {
2411 if (!CheckTownBuild2x2House(&tile, t, maxz, noslope)) continue;
2412 } else if (hs->building_flags & TILE_SIZE_2x1) {
2413 if (!CheckTownBuild2House(&tile, t, maxz, noslope, DIAGDIR_SW)) continue;
2414 } else if (hs->building_flags & TILE_SIZE_1x2) {
2415 if (!CheckTownBuild2House(&tile, t, maxz, noslope, DIAGDIR_SE)) continue;
2416 } else {
2417 /* 1x1 house checks are already done */
2420 byte random_bits = Random();
2422 if (HasBit(hs->callback_mask, CBM_HOUSE_ALLOW_CONSTRUCTION)) {
2423 uint16 callback_res = GetHouseCallback(CBID_HOUSE_ALLOW_CONSTRUCTION, 0, 0, house, t, tile, true, random_bits);
2424 if (callback_res != CALLBACK_FAILED && !Convert8bitBooleanCallback(hs->grf_prop.grffile, CBID_HOUSE_ALLOW_CONSTRUCTION, callback_res)) continue;
2427 DoBuildHouse(t, tile, house, random_bits);
2428 return true;
2431 return false;
2435 * Update data structures when a house is removed
2436 * @param tile Tile of the house
2437 * @param t Town owning the house
2438 * @param house House type
2440 static void DoClearTownHouseHelper(TileIndex tile, Town *t, HouseID house)
2442 assert(IsHouseTile(tile));
2443 DecreaseBuildingCount(t, house);
2444 DoClearSquare(tile);
2445 DeleteAnimatedTile(tile);
2447 DeleteNewGRFInspectWindow(GSF_HOUSES, tile);
2451 * Determines if a given HouseID is part of a multitile house.
2452 * The given ID is set to the ID of the north tile and the TileDiff to the north tile is returned.
2454 * @param house Is changed to the HouseID of the north tile of the same house
2455 * @return TileDiff from the tile of the given HouseID to the north tile
2457 TileIndexDiff GetHouseNorthPart(HouseID &house)
2459 if (house >= 3) { // house id 0,1,2 MUST be single tile houses, or this code breaks.
2460 if (HouseSpec::Get(house - 1)->building_flags & TILE_SIZE_2x1) {
2461 house--;
2462 return TileDiffXY(-1, 0);
2463 } else if (HouseSpec::Get(house - 1)->building_flags & BUILDING_2_TILES_Y) {
2464 house--;
2465 return TileDiffXY(0, -1);
2466 } else if (HouseSpec::Get(house - 2)->building_flags & BUILDING_HAS_4_TILES) {
2467 house -= 2;
2468 return TileDiffXY(-1, 0);
2469 } else if (HouseSpec::Get(house - 3)->building_flags & BUILDING_HAS_4_TILES) {
2470 house -= 3;
2471 return TileDiffXY(-1, -1);
2474 return 0;
2477 void ClearTownHouse(Town *t, TileIndex tile)
2479 assert(IsHouseTile(tile));
2481 HouseID house = GetHouseType(tile);
2483 /* need to align the tile to point to the upper left corner of the house */
2484 tile += GetHouseNorthPart(house); // modifies house to the ID of the north tile
2486 const HouseSpec *hs = HouseSpec::Get(house);
2488 /* Remove population from the town if the house is finished. */
2489 if (IsHouseCompleted(tile)) {
2490 ChangePopulation(t, -hs->population);
2493 t->cache.num_houses--;
2495 /* Clear flags for houses that only may exist once/town. */
2496 if (hs->building_flags & BUILDING_IS_CHURCH) {
2497 ClrBit(t->flags, TOWN_HAS_CHURCH);
2498 } else if (hs->building_flags & BUILDING_IS_STADIUM) {
2499 ClrBit(t->flags, TOWN_HAS_STADIUM);
2502 /* Do the actual clearing of tiles */
2503 uint eflags = hs->building_flags;
2504 DoClearTownHouseHelper(tile, t, house);
2505 if (eflags & BUILDING_2_TILES_Y) DoClearTownHouseHelper(tile + TileDiffXY(0, 1), t, ++house);
2506 if (eflags & BUILDING_2_TILES_X) DoClearTownHouseHelper(tile + TileDiffXY(1, 0), t, ++house);
2507 if (eflags & BUILDING_HAS_4_TILES) DoClearTownHouseHelper(tile + TileDiffXY(1, 1), t, ++house);
2509 UpdateTownRadius(t);
2511 /* Update cargo acceptance. */
2512 UpdateTownCargoes(t, tile);
2516 * Rename a town (server-only).
2517 * @param tile unused
2518 * @param flags type of operation
2519 * @param p1 town ID to rename
2520 * @param p2 unused
2521 * @param text the new name or an empty string when resetting to the default
2522 * @return the cost of this operation or an error
2524 CommandCost CmdRenameTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2526 Town *t = Town::GetIfValid(p1);
2527 if (t == NULL) return CMD_ERROR;
2529 bool reset = StrEmpty(text);
2531 if (!reset) {
2532 if (Utf8StringLength(text) >= MAX_LENGTH_TOWN_NAME_CHARS) return CMD_ERROR;
2533 if (!IsUniqueTownName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
2536 if (flags & DC_EXEC) {
2537 free(t->name);
2538 t->name = reset ? NULL : xstrdup(text);
2540 t->UpdateVirtCoord();
2541 InvalidateWindowData(WC_TOWN_DIRECTORY, 0, 1);
2542 SetWindowDirty(WC_SELECT_TOWN, 0);
2543 UpdateAllStationVirtCoords();
2545 return CommandCost();
2549 * Determines the first cargo with a certain town effect
2550 * @param effect Town effect of interest
2551 * @return first active cargo slot with that effect
2553 const CargoSpec *FindFirstCargoWithTownEffect(TownEffect effect)
2555 const CargoSpec *cs;
2556 FOR_ALL_CARGOSPECS(cs) {
2557 if (cs->town_effect == effect) return cs;
2559 return NULL;
2562 static void UpdateTownGrowRate(Town *t);
2565 * Change the cargo goal of a town.
2566 * @param tile Unused.
2567 * @param flags Type of operation.
2568 * @param p1 various bitstuffed elements
2569 * - p1 = (bit 0 - 15) - Town ID to cargo game of.
2570 * - p1 = (bit 16 - 23) - TownEffect to change the game of.
2571 * @param p2 The new goal value.
2572 * @param text Unused.
2573 * @return Empty cost or an error.
2575 CommandCost CmdTownCargoGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2577 if (_current_company != OWNER_DEITY) return CMD_ERROR;
2579 TownEffect te = (TownEffect)GB(p1, 16, 8);
2580 if (te < TE_BEGIN || te >= TE_END) return CMD_ERROR;
2582 uint16 index = GB(p1, 0, 16);
2583 Town *t = Town::GetIfValid(index);
2584 if (t == NULL) return CMD_ERROR;
2586 /* Validate if there is a cargo which is the requested TownEffect */
2587 const CargoSpec *cargo = FindFirstCargoWithTownEffect(te);
2588 if (cargo == NULL) return CMD_ERROR;
2590 if (flags & DC_EXEC) {
2591 t->goal[te] = p2;
2592 UpdateTownGrowRate(t);
2593 InvalidateWindowData(WC_TOWN_VIEW, index);
2596 return CommandCost();
2600 * Set a custom text in the Town window.
2601 * @param tile Unused.
2602 * @param flags Type of operation.
2603 * @param p1 Town ID to change the text of.
2604 * @param p2 Unused.
2605 * @param text The new text (empty to remove the text).
2606 * @return Empty cost or an error.
2608 CommandCost CmdTownSetText(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2610 if (_current_company != OWNER_DEITY) return CMD_ERROR;
2611 Town *t = Town::GetIfValid(p1);
2612 if (t == NULL) return CMD_ERROR;
2614 if (flags & DC_EXEC) {
2615 free(t->text);
2616 t->text = StrEmpty(text) ? NULL : xstrdup(text);
2617 InvalidateWindowData(WC_TOWN_VIEW, p1);
2620 return CommandCost();
2624 * Change the growth rate of the town.
2625 * @param tile Unused.
2626 * @param flags Type of operation.
2627 * @param p1 Town ID to cargo game of.
2628 * @param p2 Amount of days between growth, or TOWN_GROW_RATE_CUSTOM_NONE, or 0 to reset custom growth rate.
2629 * @param text Unused.
2630 * @return Empty cost or an error.
2632 CommandCost CmdTownGrowthRate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2634 if (_current_company != OWNER_DEITY) return CMD_ERROR;
2635 if ((p2 & TOWN_GROW_RATE_CUSTOM) != 0 && p2 != TOWN_GROW_RATE_CUSTOM_NONE) return CMD_ERROR;
2636 if (GB(p2, 16, 16) != 0) return CMD_ERROR;
2638 Town *t = Town::GetIfValid(p1);
2639 if (t == NULL) return CMD_ERROR;
2641 if (flags & DC_EXEC) {
2642 if (p2 == 0) {
2643 /* Clear TOWN_GROW_RATE_CUSTOM, UpdateTownGrowRate will determine a proper value */
2644 t->growth_rate = 0;
2645 } else {
2646 uint old_rate = t->growth_rate & ~TOWN_GROW_RATE_CUSTOM;
2647 if (t->grow_counter >= old_rate) {
2648 /* This also catches old_rate == 0 */
2649 t->grow_counter = p2;
2650 } else {
2651 /* Scale grow_counter, so half finished houses stay half finished */
2652 t->grow_counter = t->grow_counter * p2 / old_rate;
2654 t->growth_rate = p2 | TOWN_GROW_RATE_CUSTOM;
2656 UpdateTownGrowRate(t);
2657 InvalidateWindowData(WC_TOWN_VIEW, p1);
2660 return CommandCost();
2664 * Expand a town (scenario editor only).
2665 * @param tile Unused.
2666 * @param flags Type of operation.
2667 * @param p1 Town ID to expand.
2668 * @param p2 Amount to grow, or 0 to grow a random size up to the current amount of houses.
2669 * @param text Unused.
2670 * @return Empty cost or an error.
2672 CommandCost CmdExpandTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2674 if (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY) return CMD_ERROR;
2675 Town *t = Town::GetIfValid(p1);
2676 if (t == NULL) return CMD_ERROR;
2678 if (flags & DC_EXEC) {
2679 /* The more houses, the faster we grow */
2680 if (p2 == 0) {
2681 uint amount = RandomRange(ClampToU16(t->cache.num_houses / 10)) + 3;
2682 t->cache.num_houses += amount;
2683 UpdateTownRadius(t);
2685 uint n = amount * 10;
2686 do GrowTown(t); while (--n);
2688 t->cache.num_houses -= amount;
2689 } else {
2690 for (; p2 > 0; p2--) {
2691 /* Try several times to grow, as we are really suppose to grow */
2692 for (uint i = 0; i < 25; i++) if (GrowTown(t)) break;
2695 UpdateTownRadius(t);
2697 UpdateTownMaxPass(t);
2700 return CommandCost();
2704 * Delete a town (scenario editor or worldgen only).
2705 * @param tile Unused.
2706 * @param flags Type of operation.
2707 * @param p1 Town ID to delete.
2708 * @param p2 Unused.
2709 * @param text Unused.
2710 * @return Empty cost or an error.
2712 CommandCost CmdDeleteTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
2714 if (_game_mode != GM_EDITOR && !_generating_world) return CMD_ERROR;
2715 Town *t = Town::GetIfValid(p1);
2716 if (t == NULL) return CMD_ERROR;
2718 /* Stations refer to towns. */
2719 const Station *st;
2720 FOR_ALL_STATIONS(st) {
2721 if (st->town == t) {
2722 /* Non-oil rig stations are always a problem. */
2723 if (!(st->facilities & FACIL_AIRPORT) || st->airport.type != AT_OILRIG) return CMD_ERROR;
2724 /* We can only automatically delete oil rigs *if* there's no vehicle on them. */
2725 CommandCost ret = DoCommand(st->airport.tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2726 if (ret.Failed()) return ret;
2730 /* Depots refer to towns. */
2731 const Depot *d;
2732 FOR_ALL_DEPOTS(d) {
2733 if (d->town == t) return CMD_ERROR;
2736 /* Check all tiles for town ownership. */
2737 for (TileIndex tile = 0; tile < MapSize(); ++tile) {
2738 bool try_clear = false;
2739 if (IsHouseTile(tile)) {
2740 try_clear = GetTownIndex(tile) == t->index;
2741 } else if (IsIndustryTile(tile)) {
2742 try_clear = Industry::GetByTile(tile)->town == t;
2743 } else {
2744 switch (GetTileType(tile)) {
2745 case TT_MISC:
2746 if (IsTunnelTile(tile)) {
2747 try_clear = IsTileOwner(tile, OWNER_TOWN) && ClosestTownFromTile(tile) == t;
2748 break;
2750 if (!IsLevelCrossingTile(tile)) break;
2751 /* fall through */
2752 case TT_ROAD:
2753 try_clear = HasTownOwnedRoad(tile) && GetTownIndex(tile) == t->index;
2754 break;
2756 case TT_OBJECT:
2757 if (Town::GetNumItems() == 1) {
2758 /* No towns will be left, remove it! */
2759 try_clear = true;
2760 } else {
2761 Object *o = Object::GetByTile(tile);
2762 if (o->town == t) {
2763 if (o->type == OBJECT_STATUE) {
2764 /* Statue... always remove. */
2765 try_clear = true;
2766 } else {
2767 /* Tell to find a new town. */
2768 if (flags & DC_EXEC) o->town = NULL;
2772 break;
2774 default:
2775 break;
2778 if (try_clear) {
2779 CommandCost ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2780 if (ret.Failed()) return ret;
2784 /* The town destructor will delete the other things related to the town. */
2785 if (flags & DC_EXEC) delete t;
2787 return CommandCost();
2791 * Factor in the cost of each town action.
2792 * @see TownActions
2794 const byte _town_action_costs[TACT_COUNT] = {
2795 2, 4, 9, 35, 48, 53, 117, 175
2798 static CommandCost TownActionAdvertiseSmall(Town *t, DoCommandFlag flags)
2800 if (flags & DC_EXEC) {
2801 ModifyStationRatingAround(t->xy, _current_company, 0x40, 10);
2803 return CommandCost();
2806 static CommandCost TownActionAdvertiseMedium(Town *t, DoCommandFlag flags)
2808 if (flags & DC_EXEC) {
2809 ModifyStationRatingAround(t->xy, _current_company, 0x70, 15);
2811 return CommandCost();
2814 static CommandCost TownActionAdvertiseLarge(Town *t, DoCommandFlag flags)
2816 if (flags & DC_EXEC) {
2817 ModifyStationRatingAround(t->xy, _current_company, 0xA0, 20);
2819 return CommandCost();
2822 static CommandCost TownActionRoadRebuild(Town *t, DoCommandFlag flags)
2824 /* Check if the company is allowed to fund new roads. */
2825 if (!_settings_game.economy.fund_roads) return CMD_ERROR;
2827 if (flags & DC_EXEC) {
2828 t->road_build_months = 6;
2830 AddNewsItem<RoadRebuildNewsItem> (t->index, _current_company);
2831 AI::BroadcastNewEvent(new ScriptEventRoadReconstruction((ScriptCompany::CompanyID)(Owner)_current_company, t->index));
2832 Game::NewEvent(new ScriptEventRoadReconstruction((ScriptCompany::CompanyID)(Owner)_current_company, t->index));
2834 return CommandCost();
2838 * Check whether the land can be cleared.
2839 * @param tile Tile to check.
2840 * @return The tile can be cleared.
2842 static bool TryClearTile(TileIndex tile)
2844 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2845 CommandCost r = DoCommand(tile, 0, 0, DC_NONE, CMD_LANDSCAPE_CLEAR);
2846 cur_company.Restore();
2847 return r.Succeeded();
2851 * Perform a 9x9 tiles circular search from the center of the town
2852 * in order to find a free tile to place a statue
2853 * @param t town to search in
2854 * @param flags Used to check if the statue must be built or not.
2855 * @return Empty cost or an error.
2857 static CommandCost TownActionBuildStatue(Town *t, DoCommandFlag flags)
2859 static const uint STATUE_NUMBER_INNER_TILES = 25; // Number of tiles in the center of the city where we try to protect houses.
2861 if (!Object::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_OBJECTS);
2863 TileIndex statue_tile = INVALID_TILE;
2864 uint tile_count = 0;
2865 CircularTileIterator iter (t->xy, 9);
2866 for (TileIndex tile = iter; tile != INVALID_TILE; tile = ++iter) {
2867 tile_count++;
2869 /* Statues can be build on slopes, just like houses. Only the steep slopes is a no go. */
2870 if (IsSteepSlope(GetTileSlope(tile))) continue;
2871 /* Don't build statues under bridges. */
2872 if (HasBridgeAbove(tile)) continue;
2874 /* A clear-able open space is always preferred. */
2875 if (IsGroundTile(tile) && TryClearTile(tile)) {
2876 statue_tile = tile;
2877 break;
2880 bool house = IsHouseTile(tile);
2882 if (tile_count <= STATUE_NUMBER_INNER_TILES) {
2883 /* Searching inside the inner circle; store first house. */
2884 if (house && statue_tile == INVALID_TILE && TryClearTile(tile)) {
2885 statue_tile = tile;
2888 /* If we have reached the end of the inner circle, and have a saved house, terminate the search. */
2889 if (tile_count == STATUE_NUMBER_INNER_TILES && statue_tile != INVALID_TILE) break;
2890 } else {
2891 /* Searching outside the circle, just pick the first possible spot. */
2892 if (house && TryClearTile(tile)) {
2893 statue_tile = tile;
2894 break;
2898 if (statue_tile == INVALID_TILE) return_cmd_error(STR_ERROR_STATUE_NO_SUITABLE_PLACE);
2900 if (flags & DC_EXEC) {
2901 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2902 DoCommand(statue_tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
2903 cur_company.Restore();
2904 BuildObject(OBJECT_STATUE, statue_tile, _current_company, t);
2905 SetBit(t->statues, _current_company); // Once found and built, "inform" the Town.
2906 MarkTileDirtyByTile(statue_tile);
2908 return CommandCost();
2911 static CommandCost TownActionFundBuildings(Town *t, DoCommandFlag flags)
2913 /* Check if it's allowed to buy the rights */
2914 if (!_settings_game.economy.fund_buildings) return CMD_ERROR;
2916 if (flags & DC_EXEC) {
2917 /* Build next tick */
2918 t->grow_counter = 1;
2919 /* And grow for 3 months */
2920 t->fund_buildings_months = 3;
2922 /* Enable growth (also checking GameScript's opinion) */
2923 UpdateTownGrowRate(t);
2925 SetWindowDirty(WC_TOWN_VIEW, t->index);
2927 return CommandCost();
2930 static CommandCost TownActionBuyRights(Town *t, DoCommandFlag flags)
2932 /* Check if it's allowed to buy the rights */
2933 if (!_settings_game.economy.exclusive_rights) return CMD_ERROR;
2935 if (flags & DC_EXEC) {
2936 t->exclusive_counter = 12;
2937 t->exclusivity = _current_company;
2939 ModifyStationRatingAround(t->xy, _current_company, 130, 17);
2941 SetWindowClassesDirty(WC_STATION_VIEW);
2943 /* Spawn news message */
2944 AddNewsItem<ExclusiveRightsNewsItem> (t->index, Company::Get(_current_company));
2945 AI::BroadcastNewEvent(new ScriptEventExclusiveTransportRights((ScriptCompany::CompanyID)(Owner)_current_company, t->index));
2946 Game::NewEvent(new ScriptEventExclusiveTransportRights((ScriptCompany::CompanyID)(Owner)_current_company, t->index));
2948 return CommandCost();
2951 static CommandCost TownActionBribe(Town *t, DoCommandFlag flags)
2953 if (flags & DC_EXEC) {
2954 if (Chance16(1, 14)) {
2955 /* set as unwanted for 6 months */
2956 t->unwanted[_current_company] = 6;
2958 /* set all close by station ratings to 0 */
2959 Station *st;
2960 FOR_ALL_STATIONS(st) {
2961 if (st->town == t && st->owner == _current_company) {
2962 for (CargoID i = 0; i < NUM_CARGO; i++) st->goods[i].rating = 0;
2966 /* only show error message to the executing player. All errors are handled command.c
2967 * but this is special, because it can only 'fail' on a DC_EXEC */
2968 if (IsLocalCompany()) ShowErrorMessage(STR_ERROR_BRIBE_FAILED, INVALID_STRING_ID, WL_INFO);
2970 /* decrease by a lot!
2971 * ChangeTownRating is only for stuff in demolishing. Bribe failure should
2972 * be independent of any cheat settings
2974 if (t->ratings[_current_company] > RATING_BRIBE_DOWN_TO) {
2975 t->ratings[_current_company] = RATING_BRIBE_DOWN_TO;
2976 SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
2978 } else {
2979 ChangeTownRating(t, RATING_BRIBE_UP_STEP, RATING_BRIBE_MAXIMUM, DC_EXEC);
2982 return CommandCost();
2985 typedef CommandCost TownActionProc(Town *t, DoCommandFlag flags);
2986 static TownActionProc * const _town_action_proc[] = {
2987 TownActionAdvertiseSmall,
2988 TownActionAdvertiseMedium,
2989 TownActionAdvertiseLarge,
2990 TownActionRoadRebuild,
2991 TownActionBuildStatue,
2992 TownActionFundBuildings,
2993 TownActionBuyRights,
2994 TownActionBribe
2998 * Get a list of available actions to do at a town.
2999 * @param nump if not NULL add put the number of available actions in it
3000 * @param cid the company that is querying the town
3001 * @param t the town that is queried
3002 * @return bitmasked value of enabled actions
3004 uint GetMaskOfTownActions(int *nump, CompanyID cid, const Town *t)
3006 int num = 0;
3007 TownActions buttons = TACT_NONE;
3009 /* Spectators and unwanted have no options */
3010 if (cid != COMPANY_SPECTATOR && !(_settings_game.economy.bribe && t->unwanted[cid])) {
3012 /* Things worth more than this are not shown */
3013 Money avail = Company::Get(cid)->money + _price[PR_STATION_VALUE] * 200;
3015 /* Check the action bits for validity and
3016 * if they are valid add them */
3017 for (uint i = 0; i != lengthof(_town_action_costs); i++) {
3018 const TownActions cur = (TownActions)(1 << i);
3020 /* Is the company not able to bribe ? */
3021 if (cur == TACT_BRIBE && (!_settings_game.economy.bribe || t->ratings[cid] >= RATING_BRIBE_MAXIMUM)) continue;
3023 /* Is the company not able to buy exclusive rights ? */
3024 if (cur == TACT_BUY_RIGHTS && !_settings_game.economy.exclusive_rights) continue;
3026 /* Is the company not able to fund buildings ? */
3027 if (cur == TACT_FUND_BUILDINGS && !_settings_game.economy.fund_buildings) continue;
3029 /* Is the company not able to fund local road reconstruction? */
3030 if (cur == TACT_ROAD_REBUILD && !_settings_game.economy.fund_roads) continue;
3032 /* Is the company not able to build a statue ? */
3033 if (cur == TACT_BUILD_STATUE && HasBit(t->statues, cid)) continue;
3035 if (avail >= _town_action_costs[i] * _price[PR_TOWN_ACTION] >> 8) {
3036 buttons |= cur;
3037 num++;
3042 if (nump != NULL) *nump = num;
3043 return buttons;
3047 * Do a town action.
3048 * This performs an action such as advertising, building a statue, funding buildings,
3049 * but also bribing the town-council
3050 * @param tile unused
3051 * @param flags type of operation
3052 * @param p1 town to do the action at
3053 * @param p2 action to perform, @see _town_action_proc for the list of available actions
3054 * @param text unused
3055 * @return the cost of this operation or an error
3057 CommandCost CmdDoTownAction(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
3059 Town *t = Town::GetIfValid(p1);
3060 if (t == NULL || p2 >= lengthof(_town_action_proc)) return CMD_ERROR;
3062 if (!HasBit(GetMaskOfTownActions(NULL, _current_company, t), p2)) return CMD_ERROR;
3064 CommandCost cost(EXPENSES_OTHER, _price[PR_TOWN_ACTION] * _town_action_costs[p2] >> 8);
3066 CommandCost ret = _town_action_proc[p2](t, flags);
3067 if (ret.Failed()) return ret;
3069 if (flags & DC_EXEC) {
3070 SetWindowDirty(WC_TOWN_AUTHORITY, p1);
3073 return cost;
3076 static void UpdateTownRating(Town *t)
3078 /* Increase company ratings if they're low */
3079 const Company *c;
3080 FOR_ALL_COMPANIES(c) {
3081 if (t->ratings[c->index] < RATING_GROWTH_MAXIMUM) {
3082 t->ratings[c->index] = min((int)RATING_GROWTH_MAXIMUM, t->ratings[c->index] + RATING_GROWTH_UP_STEP);
3086 const Station *st;
3087 FOR_ALL_STATIONS(st) {
3088 if (DistanceSquare(st->xy, t->xy) <= t->cache.squared_town_zone_radius[0]) {
3089 if (st->time_since_load <= 20 || st->time_since_unload <= 20) {
3090 if (Company::IsValidID(st->owner)) {
3091 int new_rating = t->ratings[st->owner] + RATING_STATION_UP_STEP;
3092 t->ratings[st->owner] = min(new_rating, INT16_MAX); // do not let it overflow
3094 } else {
3095 if (Company::IsValidID(st->owner)) {
3096 int new_rating = t->ratings[st->owner] + RATING_STATION_DOWN_STEP;
3097 t->ratings[st->owner] = max(new_rating, INT16_MIN);
3103 /* clamp all ratings to valid values */
3104 for (uint i = 0; i < MAX_COMPANIES; i++) {
3105 t->ratings[i] = Clamp(t->ratings[i], RATING_MINIMUM, RATING_MAXIMUM);
3108 SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
3111 static void UpdateTownGrowRate(Town *t)
3113 ClrBit(t->flags, TOWN_IS_GROWING);
3114 SetWindowDirty(WC_TOWN_VIEW, t->index);
3116 if (_settings_game.economy.town_growth_rate == 0 && t->fund_buildings_months == 0) return;
3118 if (t->fund_buildings_months == 0) {
3119 /* Check if all goals are reached for this town to grow (given we are not funding it) */
3120 for (int i = TE_BEGIN; i < TE_END; i++) {
3121 switch (t->goal[i]) {
3122 case TOWN_GROWTH_WINTER:
3123 if (TileHeight(t->xy) >= GetSnowLine() && t->received[i].old_act == 0 && t->cache.population > 90) return;
3124 break;
3125 case TOWN_GROWTH_DESERT:
3126 if (GetTropicZone(t->xy) == TROPICZONE_DESERT && t->received[i].old_act == 0 && t->cache.population > 60) return;
3127 break;
3128 default:
3129 if (t->goal[i] > t->received[i].old_act) return;
3130 break;
3135 if ((t->growth_rate & TOWN_GROW_RATE_CUSTOM) != 0) {
3136 if (t->growth_rate != TOWN_GROW_RATE_CUSTOM_NONE) SetBit(t->flags, TOWN_IS_GROWING);
3137 SetWindowDirty(WC_TOWN_VIEW, t->index);
3138 return;
3142 * Towns are processed every TOWN_GROWTH_TICKS ticks, and this is the
3143 * number of times towns are processed before a new building is built.
3145 static const uint16 _grow_count_values[2][6] = {
3146 { 120, 120, 120, 100, 80, 60 }, // Fund new buildings has been activated
3147 { 320, 420, 300, 220, 160, 100 } // Normal values
3150 int n = 0;
3152 const Station *st;
3153 FOR_ALL_STATIONS(st) {
3154 if (DistanceSquare(st->xy, t->xy) <= t->cache.squared_town_zone_radius[0]) {
3155 if (st->time_since_load <= 20 || st->time_since_unload <= 20) {
3156 n++;
3161 uint16 m;
3163 if (t->fund_buildings_months != 0) {
3164 m = _grow_count_values[0][min(n, 5)];
3165 } else {
3166 m = _grow_count_values[1][min(n, 5)];
3167 if (n == 0 && !Chance16(1, 12)) return;
3170 /* Use the normal growth rate values if new buildings have been funded in
3171 * this town and the growth rate is set to none. */
3172 uint growth_multiplier = _settings_game.economy.town_growth_rate != 0 ? _settings_game.economy.town_growth_rate - 1 : 1;
3174 m >>= growth_multiplier;
3175 if (t->larger_town) m /= 2;
3177 t->growth_rate = m / (t->cache.num_houses / 50 + 1);
3178 t->grow_counter = min(t->growth_rate, t->grow_counter);
3180 SetBit(t->flags, TOWN_IS_GROWING);
3181 SetWindowDirty(WC_TOWN_VIEW, t->index);
3184 static void UpdateTownAmounts(Town *t)
3186 for (CargoID i = 0; i < NUM_CARGO; i++) t->supplied[i].NewMonth();
3187 for (int i = TE_BEGIN; i < TE_END; i++) t->received[i].NewMonth();
3188 if (t->fund_buildings_months != 0) t->fund_buildings_months--;
3190 SetWindowDirty(WC_TOWN_VIEW, t->index);
3193 static void UpdateTownUnwanted(Town *t)
3195 const Company *c;
3197 FOR_ALL_COMPANIES(c) {
3198 if (t->unwanted[c->index] > 0) t->unwanted[c->index]--;
3203 * Checks whether the local authority allows construction of a new station (rail, road, airport, dock) on the given tile
3204 * @param tile The tile where the station shall be constructed.
3205 * @param flags Command flags. DC_NO_TEST_TOWN_RATING is tested.
3206 * @return Succeeded or failed command.
3208 CommandCost CheckIfAuthorityAllowsNewStation(TileIndex tile, DoCommandFlag flags)
3210 if (!Company::IsValidID(_current_company) || (flags & DC_NO_TEST_TOWN_RATING)) return CommandCost();
3212 Town *t = LocalAuthorityTownFromTile(tile);
3213 if (t == NULL) return CommandCost();
3215 if (t->ratings[_current_company] > RATING_VERYPOOR) return CommandCost();
3217 SetDParam(0, t->index);
3218 return_cmd_error(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS);
3222 * Return the town closest to the given tile.
3223 * @param tile Starting point of the search.
3224 * @return Closest town to \a tile, or \c NULL if there are no towns.
3226 * @note This function only uses distance, the #ClosestTownFromTile function also takes town ownership into account.
3228 Town *CalcClosestTownFromTile(TileIndex tile)
3230 Town *t;
3231 uint best = UINT_MAX;
3232 Town *best_town = NULL;
3234 FOR_ALL_TOWNS(t) {
3235 uint dist = DistanceManhattan(tile, t->xy);
3236 if (dist < best) {
3237 best = dist;
3238 best_town = t;
3242 return best_town;
3246 * Return the town closest (in distance or ownership) to a given tile, within a given threshold.
3247 * @param tile Starting point of the search.
3248 * @param threshold Biggest allowed distance to the town.
3249 * @return Closest town to \a tile within \a threshold, or \c NULL if there is no such town.
3251 * @note If you only care about distance, you can use the #CalcClosestTownFromTile function.
3253 Town *ClosestTownFromTile(TileIndex tile, uint threshold)
3255 if (IsHouseTile(tile)) {
3256 return Town::GetByTile(tile);
3257 } else if (IsRoadTile(tile) || IsLevelCrossingTile(tile)) {
3258 if (HasTownOwnedRoad(tile)) return Town::GetByTile(tile);
3260 TownID tid = GetTownIndex(tile);
3262 if (tid == (TownID)INVALID_TOWN) {
3263 /* in the case we are generating "many random towns", this value may be INVALID_TOWN */
3264 if (_generating_world) return threshold == UINT_MAX ? CalcClosestTownFromTile(tile) : Town::find_closest<DistanceManhattan> (tile, threshold - 1);
3265 assert(Town::GetNumItems() == 0);
3266 return NULL;
3269 assert(Town::IsValidID(tid));
3270 Town *town = Town::Get(tid);
3272 if (DistanceManhattan(tile, town->xy) >= threshold) town = NULL;
3274 return town;
3277 return threshold == UINT_MAX ? CalcClosestTownFromTile(tile) : Town::find_closest<DistanceManhattan> (tile, threshold - 1);
3280 static bool _town_rating_test = false; ///< If \c true, town rating is in test-mode.
3281 static SmallMap<const Town *, int, 4> _town_test_ratings; ///< Map of towns to modified ratings, while in town rating test-mode.
3284 * Switch the town rating to test-mode, to allow commands to be tested without affecting current ratings.
3285 * The function is safe to use in nested calls.
3286 * @param mode Test mode switch (\c true means go to test-mode, \c false means leave test-mode).
3288 void SetTownRatingTestMode(bool mode)
3290 static int ref_count = 0; // Number of times test-mode is switched on.
3291 if (mode) {
3292 if (ref_count == 0) {
3293 _town_test_ratings.Clear();
3295 ref_count++;
3296 } else {
3297 assert(ref_count > 0);
3298 ref_count--;
3300 _town_rating_test = !(ref_count == 0);
3304 * Get the rating of a town for the #_current_company.
3305 * @param t Town to get the rating from.
3306 * @return Rating of the current company in the given town.
3308 static int GetRating(const Town *t)
3310 if (_town_rating_test) {
3311 SmallMap<const Town *, int>::iterator it = _town_test_ratings.Find(t);
3312 if (it != _town_test_ratings.End()) {
3313 return it->second;
3316 return t->ratings[_current_company];
3320 * Changes town rating of the current company
3321 * @param t Town to affect
3322 * @param add Value to add
3323 * @param max Minimum (add < 0) resp. maximum (add > 0) rating that should be achievable with this change.
3324 * @param flags Command flags, especially DC_NO_MODIFY_TOWN_RATING is tested
3326 void ChangeTownRating(Town *t, int add, int max, DoCommandFlag flags)
3328 /* if magic_bulldozer cheat is active, town doesn't penalize for removing stuff */
3329 if (t == NULL || (flags & DC_NO_MODIFY_TOWN_RATING) ||
3330 !Company::IsValidID(_current_company) ||
3331 (_cheats.magic_bulldozer.value && add < 0)) {
3332 return;
3335 int rating = GetRating(t);
3336 if (add < 0) {
3337 if (rating > max) {
3338 rating += add;
3339 if (rating < max) rating = max;
3341 } else {
3342 if (rating < max) {
3343 rating += add;
3344 if (rating > max) rating = max;
3347 if (_town_rating_test) {
3348 _town_test_ratings[t] = rating;
3349 } else {
3350 SetBit(t->have_ratings, _current_company);
3351 t->ratings[_current_company] = rating;
3352 SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
3357 * Does the town authority allow the (destructive) action of the current company?
3358 * @param flags Checking flags of the command.
3359 * @param t Town that must allow the company action.
3360 * @param type Type of action that is wanted.
3361 * @return A succeeded command if the action is allowed, a failed command if it is not allowed.
3363 CommandCost CheckforTownRating(DoCommandFlag flags, Town *t, TownRatingCheckType type)
3365 /* if magic_bulldozer cheat is active, town doesn't restrict your destructive actions */
3366 if (t == NULL || !Company::IsValidID(_current_company) ||
3367 _cheats.magic_bulldozer.value || (flags & DC_NO_TEST_TOWN_RATING)) {
3368 return CommandCost();
3371 /* minimum rating needed to be allowed to remove stuff */
3372 static const int needed_rating[][TOWN_RATING_CHECK_TYPE_COUNT] = {
3373 /* ROAD_REMOVE, TUNNELBRIDGE_REMOVE */
3374 { RATING_ROAD_NEEDED_PERMISSIVE, RATING_TUNNEL_BRIDGE_NEEDED_PERMISSIVE}, // Permissive
3375 { RATING_ROAD_NEEDED_NEUTRAL, RATING_TUNNEL_BRIDGE_NEEDED_NEUTRAL}, // Neutral
3376 { RATING_ROAD_NEEDED_HOSTILE, RATING_TUNNEL_BRIDGE_NEEDED_HOSTILE}, // Hostile
3379 /* check if you're allowed to remove the road/bridge/tunnel
3380 * owned by a town no removal if rating is lower than ... depends now on
3381 * difficulty setting. Minimum town rating selected by difficulty level
3383 int needed = needed_rating[_settings_game.difficulty.town_council_tolerance][type];
3385 if (GetRating(t) < needed) {
3386 SetDParam(0, t->index);
3387 return_cmd_error(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS);
3390 return CommandCost();
3393 void TownsMonthlyLoop()
3395 Town *t;
3397 FOR_ALL_TOWNS(t) {
3398 if (t->road_build_months != 0) t->road_build_months--;
3400 if (t->exclusive_counter != 0) {
3401 if (--t->exclusive_counter == 0) t->exclusivity = INVALID_COMPANY;
3404 UpdateTownAmounts(t);
3405 UpdateTownRating(t);
3406 UpdateTownGrowRate(t);
3407 UpdateTownUnwanted(t);
3408 UpdateTownCargoes(t);
3411 UpdateTownCargoBitmap();
3414 void TownsYearlyLoop()
3416 /* Increment house ages */
3417 for (TileIndex t = 0; t < MapSize(); t++) {
3418 if (!IsHouseTile(t)) continue;
3419 IncrementHouseAge(t);
3423 static CommandCost TerraformTile_Town(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
3425 if (AutoslopeEnabled()) {
3426 HouseID house = GetHouseType(tile);
3427 GetHouseNorthPart(house); // modifies house to the ID of the north tile
3428 const HouseSpec *hs = HouseSpec::Get(house);
3430 /* Here we differ from TTDP by checking TILE_NOT_SLOPED */
3431 if (((hs->building_flags & TILE_NOT_SLOPED) == 0) && !IsSteepSlope(tileh_new) &&
3432 (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
3433 bool allow_terraform = true;
3435 /* Call the autosloping callback per tile, not for the whole building at once. */
3436 house = GetHouseType(tile);
3437 hs = HouseSpec::Get(house);
3438 if (HasBit(hs->callback_mask, CBM_HOUSE_AUTOSLOPE)) {
3439 /* If the callback fails, allow autoslope. */
3440 uint16 res = GetHouseCallback(CBID_HOUSE_AUTOSLOPE, 0, 0, house, Town::GetByTile(tile), tile);
3441 if (res != CALLBACK_FAILED && ConvertBooleanCallback(hs->grf_prop.grffile, CBID_HOUSE_AUTOSLOPE, res)) allow_terraform = false;
3444 if (allow_terraform) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
3448 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
3451 /** Tile callback functions for a town */
3452 extern const TileTypeProcs _tile_type_town_procs = {
3453 DrawTile_Town, // draw_tile_proc
3454 GetSlopePixelZ_Town, // get_slope_z_proc
3455 ClearTile_Town, // clear_tile_proc
3456 AddAcceptedCargo_Town, // add_accepted_cargo_proc
3457 GetTileDesc_Town, // get_tile_desc_proc
3458 NULL, // get_tile_railway_status_proc
3459 NULL, // get_tile_road_status_proc
3460 NULL, // get_tile_waterway_status_proc
3461 NULL, // click_tile_proc
3462 AnimateTile_Town, // animate_tile_proc
3463 TileLoop_Town, // tile_loop_proc
3464 ChangeTileOwner_Town, // change_tile_owner_proc
3465 AddProducedCargo_Town, // add_produced_cargo_proc
3466 GetFoundation_Town, // get_foundation_proc
3467 TerraformTile_Town, // terraform_tile_proc
3471 HouseSpec _house_specs[NUM_HOUSES];
3473 void ResetHouses()
3475 memset(&_house_specs, 0, sizeof(_house_specs));
3476 memcpy(&_house_specs, &_original_house_specs, sizeof(_original_house_specs));
3478 /* Reset any overrides that have been set. */
3479 _house_mngr.ResetOverride();