summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortruelight <truelight@openttd.org>2005-02-01 18:32:01 +0000
committertruelight <truelight@openttd.org>2005-02-01 18:32:01 +0000
commit59ac6e8c4b2e564a864260d6715d2128a291b1d0 (patch)
treeb7d40aab99c9bff1a5304e4659c8cc7748b8a881
parent567224e94089f26e0c64aa37c7c40937285fb8fa (diff)
downloadopenttd-59ac6e8c4b2e564a864260d6715d2128a291b1d0.tar.xz
(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 ;))
-rw-r--r--ai_new.c28
-rw-r--r--oldloader.c3
-rw-r--r--saveload.c6
-rw-r--r--town.h25
-rw-r--r--town_cmd.c69
-rw-r--r--town_gui.c12
-rw-r--r--ttd.c3
7 files changed, 105 insertions, 41 deletions
diff --git a/ai_new.c b/ai_new.c
index c6bcfae0e..885c04e85 100644
--- a/ai_new.c
+++ b/ai_new.c
@@ -366,11 +366,11 @@ static void AiNew_State_LocateRoute(Player *p) {
// 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 @@ static void AiNew_State_LocateRoute(Player *p) {
}
}
- // 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;
diff --git a/oldloader.c b/oldloader.c
index 4862c14a2..1b8bca9c2 100644
--- a/oldloader.c
+++ b/oldloader.c
@@ -595,6 +595,9 @@ static void FixTown(OldTown *o, int num, byte town_name_type)
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;
diff --git a/saveload.c b/saveload.c
index 54931a2bb..6378ea0ff 100644
--- a/saveload.c
+++ b/saveload.c
@@ -944,7 +944,11 @@ static void *IntToReference(uint r, uint t)
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]);
diff --git a/town.h b/town.h
index a8757d596..c5c3b574f 100644
--- a/town.h
+++ b/town.h
@@ -1,6 +1,7 @@
#ifndef TOWN_H
#define TOWN_H
+#include "pool.h"
#include "player.h"
struct Town {
@@ -128,20 +129,30 @@ enum {
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);
+}
+
+/**
+ * Get the current size of the TownPool
+ */
+static inline uint16 GetTownPoolSize(void)
+{
+ return _town_pool.total_items;
}
-#define FOR_ALL_TOWNS(t) for(t = _towns; t != &_towns[_towns_size]; t++)
+#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 int _total_towns; // For the AI: the amount of towns active
+VARDEF uint _total_towns; // For the AI: the amount of towns active
VARDEF bool _town_sort_dirty;
VARDEF byte _town_sort_order;
diff --git a/town_cmd.c b/town_cmd.c
index eb6f5eaa6..eeb1aff49 100644
--- a/town_cmd.c
+++ b/town_cmd.c
@@ -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 @@ void OnTick_Town(void)
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 @@ static Town *AllocateTown(void)
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 TownsMonthlyLoop(void)
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;
- _town_sort_dirty = true;
_total_towns = 0;
+ _town_sort_dirty = true;
}
const TileTypeProcs _tile_type_town_procs = {
@@ -1941,12 +1970,24 @@ static void Save_TOWN(void)
static void Load_TOWN(void)
{
int index;
+
while ((index = SlIterateArray()) != -1) {
- Town *t = GetTown(index);
+ 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)
diff --git a/town_gui.c b/town_gui.c
index 96922d357..cd08386b1 100644
--- a/town_gui.c
+++ b/town_gui.c
@@ -367,14 +367,18 @@ static int CDECL TownNameSorter(const void *a, const void *b)
{
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 @@ static void MakeSortedTownList(void)
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;
diff --git a/ttd.c b/ttd.c
index 0b15b06a3..d78164faa 100644
--- a/ttd.c
+++ b/ttd.c
@@ -503,7 +503,6 @@ static void InitializeDynamicVariables(void)
_vehicles_size = lengthof(_vehicles);
_vehicle_sort = NULL;
- _towns_size = lengthof(_towns);
_town_sort = NULL;
_industries_size = lengthof(_industries);
@@ -516,6 +515,8 @@ static void InitializeDynamicVariables(void)
static void UnInitializeDynamicVariables(void)
{
/* Dynamic stuff needs to be free'd somewhere... */
+ CleanPool(&_town_pool);
+
free(_station_sort);
free(_vehicle_sort);