(svn r1783) -Add: Dynamic vehicles (now up to 64k of vehicles)
authortruelight
Fri, 04 Feb 2005 13:23:29 +0000
changeset 1279 4f83fbde72de
parent 1278 1fbb6cf8d3f1
child 1280 b6925875de49
(svn r1783) -Add: Dynamic vehicles (now up to 64k of vehicles)
misc.c
oldloader.c
saveload.c
ttd.c
vehicle.c
vehicle.h
vehicle_gui.c
--- a/misc.c	Fri Feb 04 07:52:12 2005 +0000
+++ b/misc.c	Fri Feb 04 13:23:29 2005 +0000
@@ -604,7 +604,7 @@
 	*/
 
 	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);
--- a/oldloader.c	Fri Feb 04 07:52:12 2005 +0000
+++ b/oldloader.c	Fri Feb 04 13:23:29 2005 +0000
@@ -797,6 +797,9 @@
 		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;
--- a/saveload.c	Fri Feb 04 07:52:12 2005 +0000
+++ b/saveload.c	Fri Feb 04 13:23:29 2005 +0000
@@ -942,7 +942,11 @@
 
 	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 @@
 			    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:
--- a/ttd.c	Fri Feb 04 07:52:12 2005 +0000
+++ b/ttd.c	Fri Feb 04 13:23:29 2005 +0000
@@ -496,7 +496,6 @@
 {
 	/* 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 @@
 	CleanPool(&_town_pool);
 	CleanPool(&_industry_pool);
 	CleanPool(&_station_pool);
+	CleanPool(&_vehicle_pool);
 
 	free(_station_sort);
 	free(_vehicle_sort);
--- a/vehicle.c	Fri Feb 04 07:52:12 2005 +0000
+++ b/vehicle.c	Fri Feb 04 13:23:29 2005 +0000
@@ -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 @@
 
 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 *v;
 
-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 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 @@
 	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 @@
 
 	/* 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;
 }
 
--- a/vehicle.h	Fri Feb 04 07:52:12 2005 +0000
+++ b/vehicle.h	Fri Feb 04 13:23:29 2005 +0000
@@ -1,6 +1,7 @@
 #ifndef VEHICLE_H
 #define VEHICLE_H
 
+#include "pool.h"
 #include "vehicle_gui.h"
 #include "order.h"
 
@@ -359,34 +360,42 @@
 #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 Vehicle _vehicles[NUM_VEHICLES];
-VARDEF uint _vehicles_size;
-
 VARDEF SortStruct *_vehicle_sort;
 
-static inline Vehicle *GetVehicle(uint index)
+extern MemoryPool _vehicle_pool;
+
+/**
+ * Get the pointer to the vehicle with index 'index'
+ */
+static inline Vehicle *GetVehicle(VehicleID index)
 {
-	assert(index < _vehicles_size);
-	return &_vehicles[index];
+	return (Vehicle*)GetItemFromPool(&_vehicle_pool, index);
 }
 
+/**
+ * Get the current size of the VehiclePool
+ */
+static inline uint16 GetVehiclePoolSize(void)
+{
+	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;
+
+	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++)
-
 /* Returns order 'index' of a vehicle or NULL when it doesn't exists */
 static inline Order *GetVehicleOrder(const Vehicle *v, int index)
 {
--- a/vehicle_gui.c	Fri Feb 04 07:52:12 2005 +0000
+++ b/vehicle_gui.c	Fri Feb 04 13:23:29 2005 +0000
@@ -79,7 +79,7 @@
 	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");