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 |