Solution for the daylength-patch town shrinking syndrome

Forum for technical discussions regarding development. If you have a general suggestion, problem or comment, please use one of the other forums.

Moderator: OpenTTD Developers

Post Reply
KeldorKatarn
Transport Coordinator
Transport Coordinator
Posts: 274
Joined: 13 Apr 2010 21:31

Solution for the daylength-patch town shrinking syndrome

Post by KeldorKatarn »

Recently I noticed, as many before, that with a daylength factor, towns start to shrink like crazy.

The issue is, as was already guessed in a few threads, that the loop that destroys and rebuilds buildings works with ticks, not days (btw, the entire concept of ticks is so stone age that it is really horrifying that this game still uses that as a concept of time at all. That's causing all kinds of bugs and problems and limitations for extensibility. You guys should really re-design that at some point)

Anyway, the fix is to change the tile variable time_until_rebuild from uint16 in the strange unit "number of tile loop updates" to int32 and store a date instead.

Since the value was decremented before only when evaluated (if my C++ is still right, god who writes such unreadable code), that SHOULD mean that this counter only started decreasing AFTER the minimum lifetime of the house in question was reached. Strangely enough that minimum seems to be mostly 0... is that value unused?

The code is like this: (the appropriate changes to the savegame loading etc have to be done also of course). I can't specify that code since I'm using all kinds of patches and I have my own savegame versioning for that. But anyone knowing how to handle patches will know how to adjust this to a trunk patch:

Code: Select all

--- src/town.h	(revision 26273)
+++ src/town.h	(working copy)
@@ -89,7 +89,7 @@
 	AcceptanceMatrix cargo_accepted; ///< Bitmap of cargoes accepted by houses for each 4*4 map square of the town.
 	uint32 cargo_accepted_total;     ///< NOSAVE: Bitmap of all cargoes accepted by houses in this town.
 
-	uint16 time_until_rebuild;     ///< time until we rebuild a house
+	int32 time_until_rebuild;      ///< date at which we we rebuild a house
 
 	uint16 grow_counter;           ///< counter to count when to grow
 	uint16 growth_rate;            ///< town growth rate

Code: Select all

Index: src/town_cmd.cpp
===================================================================
--- src/town_cmd.cpp	(revision 26273)
+++ src/town_cmd.cpp	(working copy)
 
 	Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
 
+	const int32 ticks_per_tile_loop = 256;
+
 	if ((hs->building_flags & BUILDING_HAS_1_TILE) &&
 			HasBit(t->flags, TOWN_IS_GROWING) &&
 			CanDeleteHouse(tile) &&
 			GetHouseAge(tile) >= hs->minimum_life &&
-			--t->time_until_rebuild == 0) {
-		t->time_until_rebuild = GB(r, 16, 8) + 192;
+			t->time_until_rebuild <= (_date - (hs->minimum_life * DAYS_IN_YEAR))) {
+		
+		int32 tile_loops_until_rebuild = GB(r, 16, 8) + 192;
+		t->time_until_rebuild = _date + ((tile_loops_until_rebuild * ticks_per_tile_loop) / DEFAULT_DAY_TICKS);
 
 		ClearTownHouse(t, tile);

Code: Select all

 static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSize size, bool city, TownLayout layout, bool manual)
 {
+	const int32 tile_loops_until_rebuild = 10;
+	const int32 ticks_per_tile_loop = 256;
+
 	t->xy = tile;
 	t->cache.num_houses = 0;
-	t->time_until_rebuild = 10;
+	t->time_until_rebuild = _date + ((tile_loops_until_rebuild * ticks_per_tile_loop) / DEFAULT_DAY_TICKS);
 	UpdateTownRadius(t);
 	t->flags = 0;
 	t->cache.population = 0;
At least that's one version to fix it. It shows that this is the issue. other solutions are of course possible, but the adjusting to using the actual date is probably needed to make it independent of any change of DAY_TICKS.

DEFAULT_DAY_TICKS here is btw the old 74 ticks independent of any daylength factor.

Any authors of daylength patches should try to incorporate this fix in their patches as otherwise the shrinking of towns is really a major issue. I had towns halve their size in less than 10 years.
User avatar
Dudok22
Engineer
Engineer
Posts: 11
Joined: 13 Oct 2013 14:54
Location: Slovakia

Re: Solution for the daylength-patch town shrinking syndrome

Post by Dudok22 »

I hope YAPP author will fix this issue. On the day length factor >= 5 shrinking of towns makes game unplayable. At first I thought stations were poorly serviced and that it caused population to drop.
KeldorKatarn
Transport Coordinator
Transport Coordinator
Posts: 274
Joined: 13 Apr 2010 21:31

Re: Solution for the daylength-patch town shrinking syndrome

Post by KeldorKatarn »

No I tested it, I had the game running for 30 years with a factor of 8, the towns grew fine and at the same rate per year as they did with factor 1 (this last bit might depend on HOW the daylength is implemented however. In my version the town growth is linked to it as well)

One more issue btw is that running ticks of the vehicles must be promoted from uint8 to uint16 or they will overflow once the dayticks go beyond 256.

With those two fixes in place most of the issues are gone. There are some things left with newGRFs like for example in FIRS the number of supply crates to arrive in 3 months never change, so if the production rate is constant, as most of these patches do it, that requirement becomes easier to fulfill.

A nice effect of a daylength patch btw is that it immensely increases performance. A lot of computation is done with the vehicles per day. And those computations are evenly spead between the ticks of each day. More ticks per day = more space to spread that out, so the computations per tick become a lot less. With daylength factor 8 you can roughly handle 8 times as many vehicles on the map, easy.
Eddi
Tycoon
Tycoon
Posts: 8267
Joined: 17 Jan 2007 00:14

Re: Solution for the daylength-patch town shrinking syndrome

Post by Eddi »

KeldorKatarn wrote:There are some things left with newGRFs like for example in FIRS the number of supply crates to arrive in 3 months never change, so if the production rate is constant, as most of these patches do it, that requirement becomes easier to fulfill.
that can only meaningfully be solved in one of two ways:
  • stretch out the production so it is run only every daylength*256 ticks (some people do not want that, other people do)
  • expose the daylength factor (or number of production steps in this month) to NewGRFs (this won't magically fix existing sets, but might improve future ones)
Post Reply

Return to “OpenTTD Development”

Who is online

Users browsing this forum: No registered users and 38 guests