summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortruelight <truelight@openttd.org>2005-02-04 13:23:29 +0000
committertruelight <truelight@openttd.org>2005-02-04 13:23:29 +0000
commit42f98c7eec8cd46ea8452911fb4381f209de342f (patch)
tree512961ac36580ababc52512c67235f48f4bef8c8
parent88ebe22d8b6e844b501688673f71db3505ea2b57 (diff)
downloadopenttd-42f98c7eec8cd46ea8452911fb4381f209de342f.tar.xz
(svn r1783) -Add: Dynamic vehicles (now up to 64k of vehicles)
-rw-r--r--misc.c2
-rw-r--r--oldloader.c3
-rw-r--r--saveload.c9
-rw-r--r--ttd.c2
-rw-r--r--vehicle.c89
-rw-r--r--vehicle.h43
-rw-r--r--vehicle_gui.c2
7 files changed, 93 insertions, 57 deletions
diff --git a/misc.c b/misc.c
index bb7eb4f0e..9eaa4ab20 100644
--- a/misc.c
+++ b/misc.c
@@ -604,7 +604,7 @@ void IncreaseDate(void)
*/
ctr = _vehicle_id_ctr_day;
- for (i = 0; i != (_vehicles_size / vehicles_per_day) + 1 && ctr != _vehicles_size; i++) {
+ for (i = 0; i != ((uint)GetVehiclePoolSize() / vehicles_per_day) + 1 && ctr != GetVehiclePoolSize(); i++) {
Vehicle *v = GetVehicle(ctr++);
if ((t = v->type) != 0)
_on_new_vehicle_day_proc[t - 0x10](v);
diff --git a/oldloader.c b/oldloader.c
index 4ad72a72f..ad7455c4e 100644
--- a/oldloader.c
+++ b/oldloader.c
@@ -797,6 +797,9 @@ static void FixVehicle(OldVehicle *o, int num)
if (o->type == 0)
continue;
+ if (!AddBlockIfNeeded(&_vehicle_pool, i))
+ error("Vehicles: failed loading savegame: too many vehicles");
+
n = GetVehicle(i);
n->type = o->type;
diff --git a/saveload.c b/saveload.c
index 174d65703..66ac65af7 100644
--- a/saveload.c
+++ b/saveload.c
@@ -942,7 +942,11 @@ static void *IntToReference(uint r, uint t)
switch (t) {
case REF_ORDER: return GetOrder(r - 1);
- case REF_VEHICLE: return GetVehicle(r - 1);
+ case REF_VEHICLE: {
+ if (!AddBlockIfNeeded(&_vehicle_pool, r - 1))
+ error("Vehicles: failed loading savegame: too many vehicles");
+ return GetVehicle(r - 1);
+ }
case REF_STATION: {
if (!AddBlockIfNeeded(&_station_pool, r - 1))
error("Stations: failed loading savegame: too many stations");
@@ -962,6 +966,9 @@ static void *IntToReference(uint r, uint t)
and the index was not - 1.. correct for this */
if (r == INVALID_VEHICLE)
return NULL;
+
+ if (!AddBlockIfNeeded(&_vehicle_pool, r))
+ error("Vehicles: failed loading savegame: too many vehicles");
return GetVehicle(r);
}
default:
diff --git a/ttd.c b/ttd.c
index 342b84d5c..1f951b19d 100644
--- a/ttd.c
+++ b/ttd.c
@@ -496,7 +496,6 @@ static void InitializeDynamicVariables(void)
{
/* Dynamic stuff needs to be initialized somewhere... */
_roadstops_size = lengthof(_roadstops);
- _vehicles_size = lengthof(_vehicles);
_sign_size = lengthof(_sign_list);
_orders_size = lengthof(_orders);
@@ -512,6 +511,7 @@ static void UnInitializeDynamicVariables(void)
CleanPool(&_town_pool);
CleanPool(&_industry_pool);
CleanPool(&_station_pool);
+ CleanPool(&_vehicle_pool);
free(_station_sort);
free(_vehicle_sort);
diff --git a/vehicle.c b/vehicle.c
index 01cffe049..4a0048267 100644
--- a/vehicle.c
+++ b/vehicle.c
@@ -17,9 +17,27 @@
#define GEN_HASH(x,y) (((x & 0x1F80)>>7) + ((y & 0xFC0)))
enum {
- VEHICLES_MIN_FREE_FOR_AI = 90
+ /* Max vehicles: 64000 (512 * 125) */
+ VEHICLES_POOL_BLOCK_SIZE_BITS = 9, /* In bits, so (1 << 9) == 512 */
+ VEHICLES_POOL_MAX_BLOCKS = 125,
+
+ BLOCKS_FOR_SPECIAL_VEHICLES = 2, //! Blocks needed for special vehicles
};
+/**
+ * Called if a new block is added to the vehicle-pool
+ */
+static void VehiclePoolNewBlock(uint start_item)
+{
+ Vehicle *v;
+
+ FOR_ALL_VEHICLES_FROM(v, start_item)
+ v->index = start_item++;
+}
+
+/* Initialize the vehicle-pool */
+MemoryPool _vehicle_pool = { "Vehicle", VEHICLES_POOL_MAX_BLOCKS, VEHICLES_POOL_BLOCK_SIZE_BITS, sizeof(Vehicle), &VehiclePoolNewBlock, 0, 0, NULL };
+
void VehicleServiceInDepot(Vehicle *v)
{
v->date_of_last_service = _date;
@@ -205,49 +223,42 @@ static Vehicle *InitializeVehicle(Vehicle *v)
Vehicle *ForceAllocateSpecialVehicle(void)
{
- Vehicle *v;
- FOR_ALL_VEHICLES_FROM(v, NUM_NORMAL_VEHICLES) {
- if (v->type == 0)
- return InitializeVehicle(v);
- }
- return NULL;
-
-}
+ /* This stays a strange story.. there should always be room for special
+ * vehicles (special effects all over the map), but with 65k of vehicles
+ * is this realistic to double-check for that? For now we just reserve
+ * BLOCKS_FOR_SPECIAL_VEHICLES times block_size vehicles that may only
+ * be used for special vehicles.. should work nicely :) */
-Vehicle *ForceAllocateVehicle(void)
-{
Vehicle *v;
+
FOR_ALL_VEHICLES(v) {
- if (v->index >= NUM_NORMAL_VEHICLES)
+ /* No more room for the special vehicles, return NULL */
+ if (v->index >= (1 << _vehicle_pool.block_size_bits) * BLOCKS_FOR_SPECIAL_VEHICLES)
return NULL;
if (v->type == 0)
return InitializeVehicle(v);
}
+
return NULL;
}
Vehicle *AllocateVehicle(void)
{
+ /* See note by ForceAllocateSpecialVehicle() why we skip the
+ * first blocks */
Vehicle *v;
- int num;
- if (IS_HUMAN_PLAYER(_current_player)) {
- num = 0;
-
- FOR_ALL_VEHICLES(v) {
- if (v->index >= NUM_NORMAL_VEHICLES)
- break;
-
- if (v->type == 0)
- num++;
- }
-
- if (num <= VEHICLES_MIN_FREE_FOR_AI)
- return NULL;
+ FOR_ALL_VEHICLES_FROM(v, (1 << _vehicle_pool.block_size_bits) * BLOCKS_FOR_SPECIAL_VEHICLES) {
+ if (v->type == 0)
+ return InitializeVehicle(v);
}
- return ForceAllocateVehicle();
+ /* Check if we can add a block to the pool */
+ if (AddBlockToPool(&_vehicle_pool))
+ return AllocateVehicle();
+
+ return NULL;
}
void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
@@ -330,19 +341,20 @@ void UpdateVehiclePosHash(Vehicle *v, int x, int y)
void InitializeVehicles(void)
{
- Vehicle *v;
int i;
+ /* Clean the vehicle pool, and reserve enough blocks
+ * for the special vehicles, plus one for all the other
+ * vehicles (which is increased on-the-fly) */
+ CleanPool(&_vehicle_pool);
+ AddBlockToPool(&_vehicle_pool);
+ for (i = 0; i < BLOCKS_FOR_SPECIAL_VEHICLES; i++)
+ AddBlockToPool(&_vehicle_pool);
+
// clear it...
- memset(&_vehicles, 0, sizeof(_vehicles[0]) * _vehicles_size);
memset(&_waypoints, 0, sizeof(_waypoints));
memset(&_depots, 0, sizeof(_depots));
- // setup indexes..
- i = 0;
- FOR_ALL_VEHICLES(v)
- v->index = i++;
-
memset(_vehicle_position_hash, -1, sizeof(_vehicle_position_hash));
}
@@ -2034,9 +2046,14 @@ static void Load_VEHS(void)
Vehicle *v;
while ((index = SlIterateArray()) != -1) {
- Vehicle *v = GetVehicle(index);
+ Vehicle *v;
+ if (!AddBlockIfNeeded(&_vehicle_pool, index))
+ error("Vehicles: failed loading savegame: too many vehicles");
+
+ v = GetVehicle(index);
SlObject(v, _veh_descs[SlReadByte()]);
+
if (v->type == VEH_Train)
v->u.rail.first_engine = 0xffff;
@@ -2088,7 +2105,7 @@ static void Load_VEHS(void)
/* This is to ensure all pointers are within the limits of
_vehicles_size */
- if (_vehicle_id_ctr_day >= _vehicles_size)
+ if (_vehicle_id_ctr_day >= GetVehiclePoolSize())
_vehicle_id_ctr_day = 0;
}
diff --git a/vehicle.h b/vehicle.h
index a180036d9..716aad77d 100644
--- a/vehicle.h
+++ b/vehicle.h
@@ -1,6 +1,7 @@
#ifndef VEHICLE_H
#define VEHICLE_H
+#include "pool.h"
#include "vehicle_gui.h"
#include "order.h"
@@ -359,33 +360,41 @@ byte GetDirectionTowards(Vehicle *v, int x, int y);
#define END_ENUM_WAGONS(v) } while ( (v=v->next) != NULL);
/* vehicle.c */
-enum {
- NUM_NORMAL_VEHICLES = 2048,
- NUM_SPECIAL_VEHICLES = 512,
- NUM_VEHICLES = NUM_NORMAL_VEHICLES + NUM_SPECIAL_VEHICLES
-};
+VARDEF SortStruct *_vehicle_sort;
-VARDEF Vehicle _vehicles[NUM_VEHICLES];
-VARDEF uint _vehicles_size;
+extern MemoryPool _vehicle_pool;
-VARDEF SortStruct *_vehicle_sort;
+/**
+ * Get the pointer to the vehicle with index 'index'
+ */
+static inline Vehicle *GetVehicle(VehicleID index)
+{
+ return (Vehicle*)GetItemFromPool(&_vehicle_pool, index);
+}
-static inline Vehicle *GetVehicle(uint index)
+/**
+ * Get the current size of the VehiclePool
+ */
+static inline uint16 GetVehiclePoolSize(void)
{
- assert(index < _vehicles_size);
- return &_vehicles[index];
+ return _vehicle_pool.total_items;
}
+#define FOR_ALL_VEHICLES_FROM(v, start) for (v = GetVehicle(start); v != NULL; v = (v->index + 1 < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL)
+#define FOR_ALL_VEHICLES(v) FOR_ALL_VEHICLES_FROM(v, 0)
+
+/**
+ * Check if an index is a vehicle-index (so between 0 and max-vehicles)
+ *
+ * @return Returns true if the vehicle-id is in range
+ */
static inline bool IsVehicleIndex(uint index)
{
- if (index < _vehicles_size)
+ if (index < GetVehiclePoolSize())
return true;
- else
- return false;
-}
-#define FOR_ALL_VEHICLES(v) for(v = _vehicles; v != &_vehicles[_vehicles_size]; v++)
-#define FOR_ALL_VEHICLES_FROM(v, from) for(v = GetVehicle(from); v != &_vehicles[_vehicles_size]; v++)
+ return false;
+}
/* Returns order 'index' of a vehicle or NULL when it doesn't exists */
static inline Order *GetVehicleOrder(const Vehicle *v, int index)
diff --git a/vehicle_gui.c b/vehicle_gui.c
index 830a6bb46..62d720061 100644
--- a/vehicle_gui.c
+++ b/vehicle_gui.c
@@ -79,7 +79,7 @@ void BuildVehicleList(vehiclelist_d *vl, int type, int owner, int station)
if (!(vl->flags & VL_REBUILD)) return;
/* Create array for sorting */
- _vehicle_sort = realloc(_vehicle_sort, _vehicles_size * sizeof(_vehicle_sort[0]));
+ _vehicle_sort = realloc(_vehicle_sort, GetVehiclePoolSize() * sizeof(_vehicle_sort[0]));
if (_vehicle_sort == NULL)
error("Could not allocate memory for the vehicle-sorting-list");