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;
1339 return (target_rb & back_rb) != 0 && (target_rb & ~back_rb) != 0;
1386 return _grow_town_result == GROWTH_SUCCEED;
1401 }
while (!(cur_rb & target_bits));
1402 cur_rb &= ~target_bits;
1420 }
while (--_grow_town_result >= 0);
1422 return _grow_town_result == GROWTH_SUCCEED - 1;
1434 uint32 r = Random();
1435 uint a =
GB(r, 0, 2);
1436 uint b =
GB(r, 8, 2);
1471 for (ptr = _town_coord_mod; ptr !=
endof(_town_coord_mod); ++ptr) {
1484 for (ptr = _town_coord_mod; ptr !=
endof(_town_coord_mod); ++ptr) {
1501 void UpdateTownRadius(
Town *t)
1503 static const uint32 _town_squared_town_zone_radius_data[23][5] = {
1516 { 81, 36, 25, 0, 9},
1517 { 81, 36, 25, 16, 9},
1518 { 81, 49, 0, 25, 9},
1519 { 81, 64, 0, 25, 9},
1520 { 81, 64, 0, 36, 9},
1521 { 81, 64, 0, 36, 16},
1522 {100, 81, 0, 49, 16},
1523 {100, 81, 0, 49, 25},
1524 {121, 81, 0, 49, 25},
1525 {121, 81, 0, 49, 25},
1526 {121, 81, 0, 49, 36},
1544 void UpdateTownMaxPass(
Town *t)
1566 UpdateTownRadius(t);
1596 t->townnamegrfid = 0;
1603 t->townnameparts = townnameparts;
1612 int x = (int)size * 16 + 3;
1613 if (size ==
TSZ_RANDOM) x = (Random() & 0xF) + 8;
1618 UpdateTownRadius(t);
1626 UpdateTownRadius(t);
1627 UpdateTownMaxPass(t);
1666 if (t->
name != NULL && strcmp(t->
name, name) == 0)
return false;
1686 TownSize size = Extract<TownSize, 0, 2>(p1);
1687 bool city =
HasBit(p1, 2);
1688 TownLayout layout = Extract<TownLayout, 3, 3>(p1);
1690 bool random =
HasBit(p1, 6);
1691 uint32 townnameparts = p2;
1723 if (ret.
Failed())
return ret;
1726 static const byte price_mult[][
TSZ_RANDOM + 1] = {{ 15, 25, 40, 25 }, { 20, 35, 55, 35 }};
1728 assert_compile(
lengthof(price_mult[0]) == 4);
1731 byte mult = price_mult[city][size];
1738 _additional_cash_required = cost.
GetCost();
1746 t = CreateRandomTown(20, townnameparts, size, city, layout);
1750 _new_town_id = t->
index;
1754 DoCreateTown(t, tile, townnameparts, size, city, layout,
true);
1757 old_generating_world.
Restore();
1759 if (t != NULL && !
StrEmpty(text)) {
1764 if (_game_mode != GM_EDITOR) {
1769 GetString(company_name, STR_COMPANY_NAME,
lastof(company_name));
1771 char *cn =
stredup(company_name);
1797 default:
return tile;
1815 default:
return true;
1897 static Town *CreateRandomTown(uint attempts, uint32 townnameparts,
TownSize size,
bool city,
TownLayout layout)
1920 DoCreateTown(t, tile, townnameparts, size, city, layout,
false);
1928 cur_company.Restore();
1936 }
while (--attempts != 0);
1941 static const byte _num_initial_towns[4] = {5, 11, 23, 46};
1952 uint current_number = 0;
1956 uint32 townnameparts;
1957 TownNames town_names;
1970 if (CreateRandomTown(20, townnameparts,
TSZ_RANDOM, city, layout) != NULL) current_number++;
1975 if (current_number != 0)
return true;
2005 HouseZonesBits smallest = HZB_TOWN_EDGE;
2006 for (HouseZonesBits i = HZB_BEGIN; i < HZB_END; i++) {
2007 if (dist < t->cache.squared_town_zone_radius[i]) smallest = i;
2031 if (HouseSpec::Get(type)->building_flags & BUILDING_IS_ANIMATED)
AddAnimatedTile(tile);
2142 if ((grid_pos.
x % 3) == 0 || (grid_pos.
y % 3) == 0)
return false;
2146 if ((grid_pos.
x % 4) == 0 || (grid_pos.
y % 4) == 0)
return false;
2176 if ((grid_pos.
x != 2 && grid_pos.
x != -1) ||
2177 (grid_pos.
y != 2 && grid_pos.
y != -1))
return false;
2181 if ((grid_pos.
x & 3) < 2 || (grid_pos.
y & 3) < 2)
return false;
2268 uint bitmask = (1 << rad) + (1 << (land + 12));
2276 uint probability_max = 0;
2280 const HouseSpec *hs = HouseSpec::Get(i);
2286 if (hs->
class_id != HOUSE_NO_CLASS) {
2296 probability_max += cur_prob;
2297 probs[num] = cur_prob;
2303 while (probability_max > 0) {
2313 for (i = 0; i < num; i++) {
2314 if (probs[i] > r)
break;
2319 probability_max -= probs[i];
2323 houses[i] = houses[num];
2324 probs[i] = probs[num];
2326 const HouseSpec *hs = HouseSpec::Get(house);
2344 if (t->
flags & oneof)
continue;
2348 if (noslope && slope !=
SLOPE_FLAT)
continue;
2360 byte random_bits = Random();
2373 byte construction_counter = 0;
2374 byte construction_stage = 0;
2377 uint32 r = Random();
2380 if (
Chance16(1, 7)) construction_stage =
GB(r, 0, 2);
2385 construction_counter =
GB(r, 2, 2);
2389 MakeTownHouse(tile, t, construction_counter, construction_stage, house, random_bits);
2390 UpdateTownRadius(t);
2409 DoClearSquare(tile);
2425 if (HouseSpec::Get(house - 1)->building_flags & TILE_SIZE_2x1) {
2428 }
else if (HouseSpec::Get(house - 1)->building_flags & BUILDING_2_TILES_Y) {
2431 }
else if (HouseSpec::Get(house - 2)->building_flags & BUILDING_HAS_4_TILES) {
2434 }
else if (HouseSpec::Get(house - 3)->building_flags & BUILDING_HAS_4_TILES) {
2451 const HouseSpec *hs = HouseSpec::Get(house);
2474 UpdateTownRadius(t);
2520 FOR_ALL_CARGOSPECS(cs) {
2546 uint16 index =
GB(p1, 0, 16);
2610 uint old_rate = t->
growth_rate & ~TOWN_GROW_RATE_CUSTOM;
2647 UpdateTownRadius(t);
2649 uint n = amount * 10;
2654 for (; p2 > 0; p2--) {
2656 for (uint i = 0; i < 25; i++)
if (
GrowTown(t))
break;
2659 UpdateTownRadius(t);
2661 UpdateTownMaxPass(t);
2684 FOR_ALL_STATIONS(st) {
2685 if (st->
town == t) {
2690 if (ret.
Failed())
return ret;
2702 bool try_clear =
false;
2743 if (ret.
Failed())
return ret;
2748 if (flags &
DC_EXEC)
delete t;
2758 2, 4, 9, 35, 48, 53, 117, 175
2795 GetString(company_name, STR_COMPANY_NAME,
lastof(company_name));
2797 char *cn =
stredup(company_name);
2837 static const int STATUE_NUMBER_INNER_TILES = 25;
2856 if (statue_data->
tile_count <= STATUE_NUMBER_INNER_TILES) {
2886 if (flags & DC_EXEC) {
2902 if (flags & DC_EXEC) {
2921 if (flags & DC_EXEC) {
2932 SetDParam(0, STR_NEWS_EXCLUSIVE_RIGHTS_TITLE);
2933 SetDParam(1, STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION);
2945 if (flags & DC_EXEC) {
2952 FOR_ALL_STATIONS(st) {
2978 static TownActionProc *
const _town_action_proc[] = {
2979 TownActionAdvertiseSmall,
2980 TownActionAdvertiseMedium,
2981 TownActionAdvertiseLarge,
2982 TownActionRoadRebuild,
2984 TownActionFundBuildings,
2985 TownActionBuyRights,
3009 for (uint i = 0; i !=
lengthof(_town_action_costs); i++) {
3027 if (avail >= _town_action_costs[i] * _price[PR_TOWN_ACTION] >> 8) {
3034 if (nump != NULL) *nump = num;
3058 CommandCost ret = _town_action_proc[p2](t, flags);
3059 if (ret.
Failed())
return ret;
3061 if (flags & DC_EXEC) {
3068 static void UpdateTownRating(
Town *t)
3072 FOR_ALL_COMPANIES(c) {
3079 FOR_ALL_STATIONS(st) {
3081 if (st->time_since_load <= 20 || st->time_since_unload <= 20) {
3112 for (
int i = TE_BEGIN; i <
TE_END; i++) {
3113 switch (t->
goal[i]) {
3137 static const uint16 _grow_count_values[2][6] = {
3138 { 120, 120, 120, 100, 80, 60 },
3139 { 320, 420, 300, 220, 160, 100 }
3145 FOR_ALL_STATIONS(st) {
3147 if (st->time_since_load <= 20 || st->time_since_unload <= 20) {
3156 m = _grow_count_values[0][
min(n, 5)];
3158 m = _grow_count_values[1][
min(n, 5)];
3159 if (n == 0 && !
Chance16(1, 12))
return;
3166 m >>= growth_multiplier;
3176 static void UpdateTownAmounts(
Town *t)
3185 static void UpdateTownUnwanted(
Town *t)
3189 FOR_ALL_COMPANIES(c) {
3224 uint best = threshold;
3225 Town *best_town = NULL;
3255 if (tid == (TownID)INVALID_TOWN) {
3272 return Town::GetByTile(tile);
3289 static int ref_count = 0;
3291 if (ref_count == 0) {
3292 _town_test_ratings.
Clear();
3296 assert(ref_count > 0);
3299 _town_rating_test = !(ref_count == 0);
3309 if (_town_rating_test) {
3311 if (it != _town_test_ratings.
End()) {
3338 if (rating < max) rating =
max;
3343 if (rating > max) rating =
max;
3346 if (_town_rating_test) {
3347 _town_test_ratings[t] = rating;
3392 void TownsMonthlyLoop()
3403 UpdateTownAmounts(t);
3404 UpdateTownRating(t);
3406 UpdateTownUnwanted(t);
3413 void TownsYearlyLoop()
3427 const HouseSpec *hs = HouseSpec::Get(house);
3432 bool allow_terraform =
true;
3436 hs = HouseSpec::Get(house);
3453 GetSlopePixelZ_Town,
3455 AddAcceptedCargo_Town,
3457 GetTileTrackStatus_Town,
3461 ChangeTileOwner_Town,
3462 AddProducedCargo_Town,
3473 memset(&_house_specs, 0,
sizeof(_house_specs));