50 #include "table/strings.h"
67 if (CleaningPool())
return;
75 FOR_ALL_INDUSTRIES(i) assert(i->
town !=
this);
79 FOR_ALL_OBJECTS(o) assert(o->
town !=
this);
102 this->psa_list.clear();
171 return (_price[PR_CLEAR_HOUSE] * this->
removal_cost) >> 8;
175 static int _grow_town_result;
178 enum TownGrowthResult {
180 GROWTH_SEARCH_STOPPED = 0
185 static Town *CreateRandomTown(uint attempts, uint32 townnameparts,
TownSize size,
bool city,
TownLayout layout);
187 static void TownDrawHouseLift(
const TileInfo *ti)
192 typedef void TownDrawTileProc(
const TileInfo *ti);
193 static TownDrawTileProc *
const _town_draw_tile_procs[1] = {
220 if (HouseSpec::Get(house_id)->grf_prop.spritegroup[0] != NULL) {
221 DrawNewHouseTile(ti, house_id);
224 house_id = HouseSpec::Get(house_id)->
grf_prop.subst_id;
242 ti->
x + dcts->subtile_x,
243 ti->
y + dcts->subtile_y,
255 int proc = dcts->draw_proc - 1;
257 if (proc >= 0) _town_draw_tile_procs[proc](ti);
261 static int GetSlopePixelZ_Town(
TileIndex tile, uint x, uint y)
276 const HouseSpec *hs = HouseSpec::Get(hid);
294 AnimateNewHouseTile(tile);
304 if (!(HouseSpec::Get(
GetHouseType(tile))->building_flags & BUILDING_IS_ANIMATED)) {
325 pos += (pos < dest) ? 1 : -1;
347 const int tx =
TileX(tile);
348 const int ty =
TileY(tile);
350 TileXY(
max(0, tx - (
int) dist),
max(0, ty - (
int) dist)),
355 Town *t = Town::GetByTile(atile);
436 AnimateNewHouseConstruction(tile);
480 const HouseSpec *hs = HouseSpec::Get(house_id);
490 Town *t = Town::GetByTile(tile);
496 for (uint i = 0; i < 256; i++) {
504 uint amt =
GB(callback, 0, 8);
505 if (amt == 0)
continue;
515 uint amt =
GB(r, 0, 8) / 8 + 1;
523 uint amt =
GB(r, 8, 8) / 8 + 1;
535 CanDeleteHouse(tile) &&
540 ClearTownHouse(t, tile);
552 if (!CanDeleteHouse(tile))
return CMD_ERROR;
560 Town *t = Town::GetByTile(tile);
571 ClearTownHouse(t, tile);
580 const HouseSpec *hs = HouseSpec::Get(house_id);
581 Town *t = Town::GetByTile(tile);
584 for (uint i = 0; i < 256; i++) {
596 produced[CT_PASSENGERS]++;
604 static inline void AddAcceptedCargoSetMask(
CargoID cargo, uint amount,
CargoArray &acceptance, uint32 *always_accepted)
606 if (cargo ==
CT_INVALID || amount == 0)
return;
607 acceptance[cargo] += amount;
608 SetBit(*always_accepted, cargo);
611 static void AddAcceptedCargo_Town(
TileIndex tile,
CargoArray &acceptance, uint32 *always_accepted)
617 for (uint8 i = 0; i <
lengthof(accepts); i++) {
636 AddAcceptedCargoSetMask(accepts[0],
GB(callback, 0, 4), acceptance, always_accepted);
637 AddAcceptedCargoSetMask(accepts[1],
GB(callback, 4, 4), acceptance, always_accepted);
640 AddAcceptedCargoSetMask(CT_FOOD,
GB(callback, 8, 4), acceptance, always_accepted);
642 AddAcceptedCargoSetMask(accepts[2],
GB(callback, 8, 4), acceptance, always_accepted);
649 for (uint8 i = 0; i <
lengthof(accepts); i++) {
650 AddAcceptedCargoSetMask(accepts[i], hs->
cargo_acceptance[i], acceptance, always_accepted);
657 const HouseSpec *hs = HouseSpec::Get(house);
662 uint16 callback_res = GetHouseCallback(
CBID_HOUSE_CUSTOM_NAME, house_completed ? 1 : 0, 0, house, Town::GetByTile(tile), tile);
664 if (callback_res > 0x400) {
668 if (new_name != STR_NULL && new_name != STR_UNDEFINED) {
674 if (!house_completed) {
676 td->
str = STR_LAI_TOWN_INDUSTRY_DESCRIPTION_UNDER_CONSTRUCTION;
707 if (
TileX(tile) % AcceptanceMatrix::GRID == 0 &&
TileY(tile) % AcceptanceMatrix::GRID == 0) {
731 AddAcceptedCargo_Town(tile, accepted, &dummy);
732 AddProducedCargo_Town(tile, produced);
737 for (uint cid = 0; cid <
NUM_CARGO; cid++) {
738 if (accepted[cid] >= 8)
SetBit(acc, cid);
758 if (
TileX(tile) % AcceptanceMatrix::GRID == 0 &&
TileY(tile) % AcceptanceMatrix::GRID == 0) {
773 FOR_ALL_TOWNS(town) {
780 static void TownTickHandler(
Town *t)
797 if (_game_mode == GM_EDITOR)
return;
844 dist_multi = (dist_multi + 1) * 4;
845 for (uint pos = 4; pos < dist_multi; pos++) {
850 if (pos & 2) cur += tid_lt[2];
892 if (desired_slope != cur_slope &&
ComplementSlope(desired_slope) != cur_slope) {
910 static bool TerraformTownTile(
TileIndex tile,
int edges,
int dir)
915 if (r.
Failed() || r.
GetCost() >= (_price[PR_TERRAFORM] + 2) * 8)
return false;
920 static void LevelTownLand(
TileIndex tile)
931 TerraformTownTile(tile, tileh & SLOPE_ELEVATED, 0);
951 default: NOT_REACHED();
954 if ((grid_pos.
x % 3) == 0) rcmd |=
ROAD_Y;
955 if ((grid_pos.
y % 3) == 0) rcmd |=
ROAD_X;
959 if ((grid_pos.
x % 4) == 0) rcmd |=
ROAD_Y;
960 if ((grid_pos.
y % 4) == 0) rcmd |=
ROAD_X;
970 default: rb_template =
ROAD_ALL;
break;
1028 _grow_town_result = GROWTH_SUCCEED;
1048 _grow_town_result = GROWTH_SUCCEED;
1079 uint8 bridge_length = 0;
1087 if (bridge_length++ >= 4) {
1091 bridge_tile += delta;
1095 if (bridge_length++ >= 11) {
1099 bridge_tile += delta;
1104 if (bridge_length == 1)
return false;
1106 for (uint8 times = 0; times <= 22; times++) {
1112 _grow_town_result = GROWTH_SUCCEED;
1147 _grow_town_result = GROWTH_SEARCH_STOPPED;
1157 default: NOT_REACHED();
1173 do target_dir =
RandomDiagDir();
while (target_dir == source_dir);
1199 _grow_town_result = GROWTH_SEARCH_STOPPED;
1204 default: NOT_REACHED();
1217 bool allow_house =
true;
1243 default: NOT_REACHED();
1271 if (
Chance16(1, 6)) LevelTownLand(house_tile);
1276 _grow_town_result = GROWTH_SUCCEED;
1282 _grow_town_result = GROWTH_SEARCH_STOPPED;
1334 return (target_rb & back_rb) != 0 && (target_rb & ~back_rb) != 0;
1381 return _grow_town_result == GROWTH_SUCCEED;
1396 }
while (!(cur_rb & target_bits));
1397 cur_rb &= ~target_bits;
1415 }
while (--_grow_town_result >= 0);
1417 return _grow_town_result == GROWTH_SUCCEED - 1;
1429 uint32 r = Random();
1430 uint a =
GB(r, 0, 2);
1431 uint b =
GB(r, 8, 2);
1466 for (ptr = _town_coord_mod; ptr !=
endof(_town_coord_mod); ++ptr) {
1479 for (ptr = _town_coord_mod; ptr !=
endof(_town_coord_mod); ++ptr) {
1496 void UpdateTownRadius(
Town *t)
1498 static const uint32 _town_squared_town_zone_radius_data[23][5] = {
1511 { 81, 36, 25, 0, 9},
1512 { 81, 36, 25, 16, 9},
1513 { 81, 49, 0, 25, 9},
1514 { 81, 64, 0, 25, 9},
1515 { 81, 64, 0, 36, 9},
1516 { 81, 64, 0, 36, 16},
1517 {100, 81, 0, 49, 16},
1518 {100, 81, 0, 49, 25},
1519 {121, 81, 0, 49, 25},
1520 {121, 81, 0, 49, 25},
1521 {121, 81, 0, 49, 36},
1539 void UpdateTownMaxPass(
Town *t)
1561 UpdateTownRadius(t);
1591 t->townnamegrfid = 0;
1598 t->townnameparts = townnameparts;
1607 int x = (int)size * 16 + 3;
1608 if (size ==
TSZ_RANDOM) x = (Random() & 0xF) + 8;
1613 UpdateTownRadius(t);
1621 UpdateTownRadius(t);
1622 UpdateTownMaxPass(t);
1661 if (t->
name != NULL && strcmp(t->
name, name) == 0)
return false;
1681 TownSize size = Extract<TownSize, 0, 2>(p1);
1682 bool city =
HasBit(p1, 2);
1683 TownLayout layout = Extract<TownLayout, 3, 3>(p1);
1685 bool random =
HasBit(p1, 6);
1686 uint32 townnameparts = p2;
1718 if (ret.
Failed())
return ret;
1721 static const byte price_mult[][
TSZ_RANDOM + 1] = {{ 15, 25, 40, 25 }, { 20, 35, 55, 35 }};
1723 assert_compile(
lengthof(price_mult[0]) == 4);
1726 byte mult = price_mult[city][size];
1733 _additional_cash_required = cost.
GetCost();
1741 t = CreateRandomTown(20, townnameparts, size, city, layout);
1745 _new_town_id = t->
index;
1749 DoCreateTown(t, tile, townnameparts, size, city, layout,
true);
1752 old_generating_world.
Restore();
1754 if (t != NULL && !
StrEmpty(text)) {
1759 if (_game_mode != GM_EDITOR) {
1764 GetString(company_name, STR_COMPANY_NAME,
lastof(company_name));
1766 char *cn =
stredup(company_name);
1792 default:
return tile;
1810 default:
return true;
1892 static Town *CreateRandomTown(uint attempts, uint32 townnameparts,
TownSize size,
bool city,
TownLayout layout)
1915 DoCreateTown(t, tile, townnameparts, size, city, layout,
false);
1923 cur_company.Restore();
1931 }
while (--attempts != 0);
1936 static const byte _num_initial_towns[4] = {5, 11, 23, 46};
1947 uint current_number = 0;
1951 uint32 townnameparts;
1952 TownNames town_names;
1965 if (CreateRandomTown(20, townnameparts,
TSZ_RANDOM, city, layout) != NULL) current_number++;
1970 if (current_number != 0)
return true;
2000 HouseZonesBits smallest = HZB_TOWN_EDGE;
2001 for (HouseZonesBits i = HZB_BEGIN; i < HZB_END; i++) {
2002 if (dist < t->cache.squared_town_zone_radius[i]) smallest = i;
2026 if (HouseSpec::Get(type)->building_flags & BUILDING_IS_ANIMATED)
AddAnimatedTile(tile);
2137 if ((grid_pos.
x % 3) == 0 || (grid_pos.
y % 3) == 0)
return false;
2141 if ((grid_pos.
x % 4) == 0 || (grid_pos.
y % 4) == 0)
return false;
2171 if ((grid_pos.
x != 2 && grid_pos.
x != -1) ||
2172 (grid_pos.
y != 2 && grid_pos.
y != -1))
return false;
2176 if ((grid_pos.
x & 3) < 2 || (grid_pos.
y & 3) < 2)
return false;
2263 uint bitmask = (1 << rad) + (1 << (land + 12));
2271 uint probability_max = 0;
2275 const HouseSpec *hs = HouseSpec::Get(i);
2281 if (hs->
class_id != HOUSE_NO_CLASS) {
2291 probability_max += cur_prob;
2292 probs[num] = cur_prob;
2298 while (probability_max > 0) {
2308 for (i = 0; i < num; i++) {
2309 if (probs[i] > r)
break;
2314 probability_max -= probs[i];
2318 houses[i] = houses[num];
2319 probs[i] = probs[num];
2321 const HouseSpec *hs = HouseSpec::Get(house);
2339 if (t->
flags & oneof)
continue;
2343 if (noslope && slope !=
SLOPE_FLAT)
continue;
2355 byte random_bits = Random();
2368 byte construction_counter = 0;
2369 byte construction_stage = 0;
2372 uint32 r = Random();
2375 if (
Chance16(1, 7)) construction_stage =
GB(r, 0, 2);
2380 construction_counter =
GB(r, 2, 2);
2384 MakeTownHouse(tile, t, construction_counter, construction_stage, house, random_bits);
2385 UpdateTownRadius(t);
2404 DoClearSquare(tile);
2420 if (HouseSpec::Get(house - 1)->building_flags & TILE_SIZE_2x1) {
2423 }
else if (HouseSpec::Get(house - 1)->building_flags & BUILDING_2_TILES_Y) {
2426 }
else if (HouseSpec::Get(house - 2)->building_flags & BUILDING_HAS_4_TILES) {
2429 }
else if (HouseSpec::Get(house - 3)->building_flags & BUILDING_HAS_4_TILES) {
2446 const HouseSpec *hs = HouseSpec::Get(house);
2469 UpdateTownRadius(t);
2515 FOR_ALL_CARGOSPECS(cs) {
2541 uint16 index =
GB(p1, 0, 16);
2605 uint old_rate = t->
growth_rate & ~TOWN_GROW_RATE_CUSTOM;
2642 UpdateTownRadius(t);
2644 uint n = amount * 10;
2649 for (; p2 > 0; p2--) {
2651 for (uint i = 0; i < 25; i++)
if (
GrowTown(t))
break;
2654 UpdateTownRadius(t);
2656 UpdateTownMaxPass(t);
2679 FOR_ALL_STATIONS(st) {
2680 if (st->
town == t) {
2685 if (ret.
Failed())
return ret;
2697 bool try_clear =
false;
2738 if (ret.
Failed())
return ret;
2743 if (flags &
DC_EXEC)
delete t;
2753 2, 4, 9, 35, 48, 53, 117, 175
2790 GetString(company_name, STR_COMPANY_NAME,
lastof(company_name));
2792 char *cn =
stredup(company_name);
2832 static const int STATUE_NUMBER_INNER_TILES = 25;
2851 if (statue_data->
tile_count <= STATUE_NUMBER_INNER_TILES) {
2881 if (flags & DC_EXEC) {
2897 if (flags & DC_EXEC) {
2916 if (flags & DC_EXEC) {
2927 SetDParam(0, STR_NEWS_EXCLUSIVE_RIGHTS_TITLE);
2928 SetDParam(1, STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION);
2940 if (flags & DC_EXEC) {
2947 FOR_ALL_STATIONS(st) {
2973 static TownActionProc *
const _town_action_proc[] = {
2974 TownActionAdvertiseSmall,
2975 TownActionAdvertiseMedium,
2976 TownActionAdvertiseLarge,
2977 TownActionRoadRebuild,
2979 TownActionFundBuildings,
2980 TownActionBuyRights,
3004 for (uint i = 0; i !=
lengthof(_town_action_costs); i++) {
3022 if (avail >= _town_action_costs[i] * _price[PR_TOWN_ACTION] >> 8) {
3029 if (nump != NULL) *nump = num;
3053 CommandCost ret = _town_action_proc[p2](t, flags);
3054 if (ret.
Failed())
return ret;
3056 if (flags & DC_EXEC) {
3063 static void UpdateTownRating(
Town *t)
3067 FOR_ALL_COMPANIES(c) {
3074 FOR_ALL_STATIONS(st) {
3076 if (st->time_since_load <= 20 || st->time_since_unload <= 20) {
3107 for (
int i = TE_BEGIN; i <
TE_END; i++) {
3108 switch (t->
goal[i]) {
3132 static const uint16 _grow_count_values[2][6] = {
3133 { 120, 120, 120, 100, 80, 60 },
3134 { 320, 420, 300, 220, 160, 100 }
3140 FOR_ALL_STATIONS(st) {
3142 if (st->time_since_load <= 20 || st->time_since_unload <= 20) {
3151 m = _grow_count_values[0][
min(n, 5)];
3153 m = _grow_count_values[1][
min(n, 5)];
3154 if (n == 0 && !
Chance16(1, 12))
return;
3161 m >>= growth_multiplier;
3171 static void UpdateTownAmounts(
Town *t)
3180 static void UpdateTownUnwanted(
Town *t)
3184 FOR_ALL_COMPANIES(c) {
3219 uint best = threshold;
3220 Town *best_town = NULL;
3250 if (tid == (TownID)INVALID_TOWN) {
3267 return Town::GetByTile(tile);
3284 static int ref_count = 0;
3286 if (ref_count == 0) {
3287 _town_test_ratings.
Clear();
3291 assert(ref_count > 0);
3294 _town_rating_test = !(ref_count == 0);
3304 if (_town_rating_test) {
3306 if (it != _town_test_ratings.
End()) {
3333 if (rating < max) rating =
max;
3338 if (rating > max) rating =
max;
3341 if (_town_rating_test) {
3342 _town_test_ratings[t] = rating;
3387 void TownsMonthlyLoop()
3398 UpdateTownAmounts(t);
3399 UpdateTownRating(t);
3401 UpdateTownUnwanted(t);
3408 void TownsYearlyLoop()
3422 const HouseSpec *hs = HouseSpec::Get(house);
3427 bool allow_terraform =
true;
3431 hs = HouseSpec::Get(house);
3448 GetSlopePixelZ_Town,
3450 AddAcceptedCargo_Town,
3452 GetTileTrackStatus_Town,
3456 ChangeTileOwner_Town,
3457 AddProducedCargo_Town,
3468 memset(&_house_specs, 0,
sizeof(_house_specs));