(svn r1764) -Add: dynamic towns, you can now have up to 64k towns (let me know when
authortruelight
Tue, 01 Feb 2005 18:32:01 +0000
changeset 1260 c60e76928e5c
parent 1259 6dc9a1521c00
child 1261 d7c7447dd22d
(svn r1764) -Add: dynamic towns, you can now have up to 64k towns (let me know when
you have that amount of towns in a map ;))
ai_new.c
oldloader.c
saveload.c
town.h
town_cmd.c
town_gui.c
ttd.c
--- a/ai_new.c	Tue Feb 01 18:30:11 2005 +0000
+++ b/ai_new.c	Tue Feb 01 18:32:01 2005 +0000
@@ -366,11 +366,11 @@
     		//  increase the temp with one, and return. We will come back later here
     		//  to try again
     		p->ainew.temp++;
-        	if (p->ainew.from_type == AI_CITY) {
-        		if (p->ainew.temp >= _total_towns) p->ainew.temp = 0;
-        	} else {
-        		if (p->ainew.temp >= _total_industries) p->ainew.temp = 0;
-        	}
+				if (p->ainew.from_type == AI_CITY) {
+					if (p->ainew.temp >= (int)_total_towns) p->ainew.temp = 0;
+				} else {
+					if (p->ainew.temp >= _total_industries) p->ainew.temp = 0;
+				}
 
         	// Don't do an attempt if we are trying the same id as the last time...
         	if (p->ainew.last_id == p->ainew.temp) return;
@@ -489,15 +489,15 @@
    		}
    	}
 
-    // It was not a valid city
-   	//  increase the temp with one, and return. We will come back later here
-   	//  to try again
-   	p->ainew.temp++;
-    if (p->ainew.to_type == AI_CITY) {
-    	if (p->ainew.temp >= _total_towns) p->ainew.temp = 0;
-    } else {
-    	if (p->ainew.temp >= _total_industries) p->ainew.temp = 0;
-    }
+	// It was not a valid city
+	//  increase the temp with one, and return. We will come back later here
+	//  to try again
+	p->ainew.temp++;
+	if (p->ainew.to_type == AI_CITY) {
+		if (p->ainew.temp >= (int)_total_towns) p->ainew.temp = 0;
+	} else {
+		if (p->ainew.temp >= _total_industries) p->ainew.temp = 0;
+	}
 
    	// Don't do an attempt if we are trying the same id as the last time...
    	if (p->ainew.last_id == p->ainew.temp) return;
--- a/oldloader.c	Tue Feb 01 18:30:11 2005 +0000
+++ b/oldloader.c	Tue Feb 01 18:32:01 2005 +0000
@@ -595,6 +595,9 @@
 		if (o->xy == 0)
 			continue;
 
+		if (!AddBlockIfNeeded(&_town_pool, i))
+			error("Towns: failed loading savegame: too many towns");
+
 		t = GetTown(i);
 
 		t->xy = o->xy;
--- a/saveload.c	Tue Feb 01 18:30:11 2005 +0000
+++ b/saveload.c	Tue Feb 01 18:32:01 2005 +0000
@@ -944,7 +944,11 @@
 		case REF_ORDER:   return GetOrder(r - 1);
 		case REF_VEHICLE: return GetVehicle(r - 1);
 		case REF_STATION: return GetStation(r - 1);
-		case REF_TOWN:    return GetTown(r - 1);
+		case REF_TOWN: {
+			if (!AddBlockIfNeeded(&_town_pool, r - 1))
+				error("Towns: failed loading savegame: too many towns");
+			return GetTown(r - 1);
+		}
 
 		case REF_ROADSTOPS:
 			//return (byte*)_roadstops    + (r - 1) * sizeof(_roadstops[0]);
--- a/town.h	Tue Feb 01 18:30:11 2005 +0000
+++ b/town.h	Tue Feb 01 18:32:01 2005 +0000
@@ -1,6 +1,7 @@
 #ifndef TOWN_H
 #define TOWN_H
 
+#include "pool.h"
 #include "player.h"
 
 struct Town {
@@ -128,20 +129,30 @@
 
 bool CheckforTownRating(uint tile, uint32 flags, Town *t, byte type);
 
-VARDEF Town _towns[250];
-VARDEF uint _towns_size;
-
 VARDEF uint16 *_town_sort;
 
+extern MemoryPool _town_pool;
+
+/**
+ * Get the pointer to the town with index 'index'
+ */
 static inline Town *GetTown(uint index)
 {
-	assert(index < _towns_size);
-	return &_towns[index];
+	return (Town*)GetItemFromPool(&_town_pool, index);
 }
 
-#define FOR_ALL_TOWNS(t) for(t = _towns; t != &_towns[_towns_size]; t++)
+/**
+ * Get the current size of the TownPool
+ */
+static inline uint16 GetTownPoolSize(void)
+{
+	return _town_pool.total_items;
+}
 
-VARDEF int _total_towns; // For the AI: the amount of towns active
+#define FOR_ALL_TOWNS_FROM(t, start) for (t = GetTown(start); t != NULL; t = (t->index + 1 < GetTownPoolSize()) ? GetTown(t->index + 1) : NULL)
+#define FOR_ALL_TOWNS(t) FOR_ALL_TOWNS_FROM(t, 0)
+
+VARDEF uint _total_towns; // For the AI: the amount of towns active
 
 VARDEF bool _town_sort_dirty;
 VARDEF byte _town_sort_order;
--- a/town_cmd.c	Tue Feb 01 18:30:11 2005 +0000
+++ b/town_cmd.c	Tue Feb 01 18:32:01 2005 +0000
@@ -18,6 +18,27 @@
 #include "network.h"
 
 enum {
+	/* Max towns: 64000 (8 * 8000) */
+	TOWN_POOL_BLOCK_SIZE_BITS = 3,       /* In bits, so (1 << 3) == 8 */
+	TOWN_POOL_MAX_BLOCKS      = 8000,
+};
+
+/**
+ * Called if a new block is added to the town-pool
+ */
+static void TownPoolNewBlock(uint start_item)
+{
+	Town *t;
+
+	FOR_ALL_TOWNS_FROM(t, start_item)
+			t->index = start_item++;
+}
+
+/* Initialize the town-pool */
+MemoryPool _town_pool = { "Towns", TOWN_POOL_MAX_BLOCKS, TOWN_POOL_BLOCK_SIZE_BITS, sizeof(Town), &TownPoolNewBlock, 0, 0, NULL };
+
+
+enum {
 	TOWN_HAS_CHURCH     = 0x02,
 	TOWN_HAS_STADIUM    = 0x04
 };
@@ -413,13 +434,13 @@
 		return;
 
 	i = _cur_town_ctr;
+	if (++_cur_town_ctr >= GetTownPoolSize())
+		_cur_town_ctr = 0;
+
 	t = GetTown(i);
-	if (++i == _towns_size) i = 0;
-	_cur_town_ctr = i;
 
 	if (t->xy != 0)
 		TownTickHandler(t);
-
 }
 
 static byte GetTownRoadMask(TileIndex tile)
@@ -954,10 +975,22 @@
 	Town *t;
 	FOR_ALL_TOWNS(t) {
 		if (t->xy == 0) {
-			if (t->index > _total_towns) _total_towns = t->index;
+			uint index = t->index;
+
+			if (t->index > _total_towns)
+				_total_towns = t->index;
+
+			memset(t, 0, sizeof(Town));
+			t->index = index;
+
 			return t;
 		}
 	}
+
+	/* Check if we can add a block to the pool */
+	if (AddBlockToPool(&_town_pool))
+		return AllocateTown();
+
 	return NULL;
 }
 
@@ -1835,22 +1868,18 @@
 void InitializeTowns(void)
 {
 	Subsidy *s;
-	Town *t;
-	int i;
 
-	memset(_towns, 0, sizeof(_towns[0]) * _towns_size);
-
-	i = 0;
-	FOR_ALL_TOWNS(t)
-		t->index = i++;
+	/* Clean the town pool and create 1 block in it */
+	CleanPool(&_town_pool);
+	AddBlockToPool(&_town_pool);
 
 	memset(_subsidies, 0, sizeof(_subsidies));
 	for (s=_subsidies; s != endof(_subsidies); s++)
 		s->cargo_type = 0xFF;
 
 	_cur_town_ctr = 0;
+	_total_towns = 0;
 	_town_sort_dirty = true;
-	_total_towns = 0;
 }
 
 const TileTypeProcs _tile_type_town_procs = {
@@ -1941,12 +1970,24 @@
 static void Load_TOWN(void)
 {
 	int index;
-	while ((index = SlIterateArray()) != -1) {
-		Town *t = GetTown(index);
 
+	while ((index = SlIterateArray()) != -1) {
+		Town *t;
+
+		if (!AddBlockIfNeeded(&_town_pool, index))
+			error("Towns: failed loading savegame: too many towns");
+
+		t = GetTown(index);
 		SlObject(t, _town_desc);
-		if (index > _total_towns) _total_towns = index;
+
+		if ((uint)index > _total_towns)
+			_total_towns = index;
 	}
+
+	/* This is to ensure all pointers are within the limits of
+	 *  the size of the TownPool */
+	if (_cur_town_ctr >= GetTownPoolSize())
+		_cur_town_ctr = 0;
 }
 
 void AfterLoadTown(void)
--- a/town_gui.c	Tue Feb 01 18:30:11 2005 +0000
+++ b/town_gui.c	Tue Feb 01 18:32:01 2005 +0000
@@ -367,14 +367,18 @@
 {
 	char buf1[64];
 	const Town *t;
-	byte val;
+	uint16 val;
 	int r;
 
 	t = GetTown(*(const uint16*)a);
 	SetDParam(0, t->townnameparts);
 	GetString(buf1, t->townnametype);
 
-	if ( (val=*(const uint16*)b) != _last_town_idx) {
+	/* If 'b' is the same town as in the last round, use the cached value
+	 *  We do this to speed stuff up ('b' is called with the same value a lot of
+	*  times after eachother) */
+	val = *(const uint16*)b;
+	if (val != _last_town_idx) {
 		_last_town_idx = val;
 		t = GetTown(val);
 		SetDParam(0, t->townnameparts);
@@ -401,12 +405,12 @@
 	int n = 0;
 
 	/* Create array for sorting */
-	_town_sort = realloc(_town_sort, _towns_size * sizeof(_town_sort[0]));
+	_town_sort = realloc(_town_sort, GetTownPoolSize() * sizeof(_town_sort[0]));
 	if (_town_sort == NULL)
 		error("Could not allocate memory for the town-sorting-list");
 
 	FOR_ALL_TOWNS(t)
-		if(t->xy)
+		if (t->xy)
 			_town_sort[n++] = t->index;
 
 	_num_town_sort = n;
--- a/ttd.c	Tue Feb 01 18:30:11 2005 +0000
+++ b/ttd.c	Tue Feb 01 18:32:01 2005 +0000
@@ -503,7 +503,6 @@
 	_vehicles_size = lengthof(_vehicles);
 	_vehicle_sort = NULL;
 
-	_towns_size = lengthof(_towns);
 	_town_sort = NULL;
 
 	_industries_size = lengthof(_industries);
@@ -516,6 +515,8 @@
 static void UnInitializeDynamicVariables(void)
 {
 	/* Dynamic stuff needs to be free'd somewhere... */
+	CleanPool(&_town_pool);
+
 	free(_station_sort);
 
 	free(_vehicle_sort);