vehicle.c
changeset 4972 c7f92c6b74e4
parent 4925 74022d4dfd85
child 5062 470335730a60
equal deleted inserted replaced
4971:2a9325fca331 4972:c7f92c6b74e4
    77 	CMD_SEND_AIRCRAFT_TO_HANGAR,
    77 	CMD_SEND_AIRCRAFT_TO_HANGAR,
    78 };
    78 };
    79 
    79 
    80 
    80 
    81 enum {
    81 enum {
    82 	/* Max vehicles: 64000 (512 * 125) */
       
    83 	VEHICLES_POOL_BLOCK_SIZE_BITS = 9,       /* In bits, so (1 << 9) == 512 */
       
    84 	VEHICLES_POOL_MAX_BLOCKS      = 125,
       
    85 
       
    86 	BLOCKS_FOR_SPECIAL_VEHICLES   = 2, ///< Blocks needed for special vehicles
    82 	BLOCKS_FOR_SPECIAL_VEHICLES   = 2, ///< Blocks needed for special vehicles
    87 };
    83 };
    88 
    84 
    89 /**
    85 /**
    90  * Called if a new block is added to the vehicle-pool
    86  * Called if a new block is added to the vehicle-pool
    93 {
    89 {
    94 	Vehicle *v;
    90 	Vehicle *v;
    95 
    91 
    96 	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
    92 	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
    97 	 * TODO - This is just a temporary stage, this will be removed. */
    93 	 * TODO - This is just a temporary stage, this will be removed. */
    98 	for (v = GetVehicle(start_item); v != NULL; v = (v->index + 1 < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) v->index = start_item++;
    94 	for (v = GetVehicle(start_item); v != NULL; v = (v->index + 1U < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) v->index = start_item++;
    99 }
    95 }
   100 
    96 
   101 /* Initialize the vehicle-pool */
    97 /* Initialize the vehicle-pool */
   102 MemoryPool _vehicle_pool = { "Vehicle", VEHICLES_POOL_MAX_BLOCKS, VEHICLES_POOL_BLOCK_SIZE_BITS, sizeof(Vehicle), &VehiclePoolNewBlock, NULL, 0, 0, NULL };
    98 DEFINE_POOL(Vehicle, Vehicle, VehiclePoolNewBlock, NULL)
   103 
    99 
   104 void VehicleServiceInDepot(Vehicle *v)
   100 void VehicleServiceInDepot(Vehicle *v)
   105 {
   101 {
   106 	v->date_of_last_service = _date;
   102 	v->date_of_last_service = _date;
   107 	v->breakdowns_since_last_service = 0;
   103 	v->breakdowns_since_last_service = 0;
   295 
   291 
   296 	Vehicle *v;
   292 	Vehicle *v;
   297 
   293 
   298 	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
   294 	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
   299 	 * TODO - This is just a temporary stage, this will be removed. */
   295 	 * TODO - This is just a temporary stage, this will be removed. */
   300 	for (v = GetVehicle(0); v != NULL; v = (v->index + 1 < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) {
   296 	for (v = GetVehicle(0); v != NULL; v = (v->index + 1U < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) {
   301 		/* No more room for the special vehicles, return NULL */
   297 		/* No more room for the special vehicles, return NULL */
   302 		if (v->index >= (1 << _vehicle_pool.block_size_bits) * BLOCKS_FOR_SPECIAL_VEHICLES)
   298 		if (v->index >= (1 << Vehicle_POOL_BLOCK_SIZE_BITS) * BLOCKS_FOR_SPECIAL_VEHICLES)
   303 			return NULL;
   299 			return NULL;
   304 
   300 
   305 		if (!IsValidVehicle(v)) return InitializeVehicle(v);
   301 		if (!IsValidVehicle(v)) return InitializeVehicle(v);
   306 	}
   302 	}
   307 
   303 
   312  * finds a free vehicle in the memory or allocates a new one
   308  * finds a free vehicle in the memory or allocates a new one
   313  * returns a pointer to the first free vehicle or NULL if all vehicles are in use
   309  * returns a pointer to the first free vehicle or NULL if all vehicles are in use
   314  * *skip_vehicles is an offset to where in the array we should begin looking
   310  * *skip_vehicles is an offset to where in the array we should begin looking
   315  * this is to avoid looping though the same vehicles more than once after we learned that they are not free
   311  * this is to avoid looping though the same vehicles more than once after we learned that they are not free
   316  * this feature is used by AllocateVehicles() since it need to allocate more than one and when
   312  * this feature is used by AllocateVehicles() since it need to allocate more than one and when
   317  * another block is added to _vehicle_pool, since we only do that when we know it's already full
   313  * another block is added to _Vehicle_pool, since we only do that when we know it's already full
   318  */
   314  */
   319 static Vehicle *AllocateSingleVehicle(VehicleID *skip_vehicles)
   315 static Vehicle *AllocateSingleVehicle(VehicleID *skip_vehicles)
   320 {
   316 {
   321 	/* See note by ForceAllocateSpecialVehicle() why we skip the
   317 	/* See note by ForceAllocateSpecialVehicle() why we skip the
   322 	 * first blocks */
   318 	 * first blocks */
   323 	Vehicle *v;
   319 	Vehicle *v;
   324 	const int offset = (1 << VEHICLES_POOL_BLOCK_SIZE_BITS) * BLOCKS_FOR_SPECIAL_VEHICLES;
   320 	const int offset = (1 << Vehicle_POOL_BLOCK_SIZE_BITS) * BLOCKS_FOR_SPECIAL_VEHICLES;
   325 
   321 
   326 	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
   322 	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
   327 	 * TODO - This is just a temporary stage, this will be removed. */
   323 	 * TODO - This is just a temporary stage, this will be removed. */
   328 	if (*skip_vehicles < (_vehicle_pool.total_items - offset)) { // make sure the offset in the array is not larger than the array itself
   324 	if (*skip_vehicles < (_Vehicle_pool.total_items - offset)) { // make sure the offset in the array is not larger than the array itself
   329 		for (v = GetVehicle(offset + *skip_vehicles); v != NULL; v = (v->index + 1 < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) {
   325 		for (v = GetVehicle(offset + *skip_vehicles); v != NULL; v = (v->index + 1U < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) {
   330 			(*skip_vehicles)++;
   326 			(*skip_vehicles)++;
   331 			if (!IsValidVehicle(v)) return InitializeVehicle(v);
   327 			if (!IsValidVehicle(v)) return InitializeVehicle(v);
   332 		}
   328 		}
   333 	}
   329 	}
   334 
   330 
   335 	/* Check if we can add a block to the pool */
   331 	/* Check if we can add a block to the pool */
   336 	if (AddBlockToPool(&_vehicle_pool))
   332 	if (AddBlockToPool(&_Vehicle_pool))
   337 		return AllocateSingleVehicle(skip_vehicles);
   333 		return AllocateSingleVehicle(skip_vehicles);
   338 
   334 
   339 	return NULL;
   335 	return NULL;
   340 }
   336 }
   341 
   337 
   449 	uint i;
   445 	uint i;
   450 
   446 
   451 	/* Clean the vehicle pool, and reserve enough blocks
   447 	/* Clean the vehicle pool, and reserve enough blocks
   452 	 *  for the special vehicles, plus one for all the other
   448 	 *  for the special vehicles, plus one for all the other
   453 	 *  vehicles (which is increased on-the-fly) */
   449 	 *  vehicles (which is increased on-the-fly) */
   454 	CleanPool(&_vehicle_pool);
   450 	CleanPool(&_Vehicle_pool);
   455 	AddBlockToPool(&_vehicle_pool);
   451 	AddBlockToPool(&_Vehicle_pool);
   456 	for (i = 0; i < BLOCKS_FOR_SPECIAL_VEHICLES; i++)
   452 	for (i = 0; i < BLOCKS_FOR_SPECIAL_VEHICLES; i++)
   457 		AddBlockToPool(&_vehicle_pool);
   453 		AddBlockToPool(&_Vehicle_pool);
   458 
   454 
   459 	for (i = 0; i < lengthof(_vehicle_position_hash); i++) {
   455 	for (i = 0; i < lengthof(_vehicle_position_hash); i++) {
   460 		_vehicle_position_hash[i] = INVALID_VEHICLE;
   456 		_vehicle_position_hash[i] = INVALID_VEHICLE;
   461 	}
   457 	}
   462 }
   458 }
  3175 	Vehicle *v;
  3171 	Vehicle *v;
  3176 
  3172 
  3177 	while ((index = SlIterateArray()) != -1) {
  3173 	while ((index = SlIterateArray()) != -1) {
  3178 		Vehicle *v;
  3174 		Vehicle *v;
  3179 
  3175 
  3180 		if (!AddBlockIfNeeded(&_vehicle_pool, index))
  3176 		if (!AddBlockIfNeeded(&_Vehicle_pool, index))
  3181 			error("Vehicles: failed loading savegame: too many vehicles");
  3177 			error("Vehicles: failed loading savegame: too many vehicles");
  3182 
  3178 
  3183 		v = GetVehicle(index);
  3179 		v = GetVehicle(index);
  3184 		SlObject(v, _veh_descs[SlReadByte()]);
  3180 		SlObject(v, _veh_descs[SlReadByte()]);
  3185 
  3181