(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 ;))
--- 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);