295 } |
295 } |
296 |
296 |
297 return NULL; |
297 return NULL; |
298 } |
298 } |
299 |
299 |
300 Vehicle *AllocateVehicle(void) |
300 /* |
|
301 * finds a free vehicle in the memory or allocates a new one |
|
302 * returns a pointer to the first free vehicle or NULL if all vehicles are in use |
|
303 * *skip_vehicles is an offset to where in the array we should begin looking |
|
304 * this is to avoid looping though the same vehicles more than once after we learned that they are not free |
|
305 * this feature is used by AllocateVehicles() since it need to allocate more than one and when |
|
306 * another block is added to _vehicle_pool, since we only do that when we know it's already full |
|
307 */ |
|
308 static Vehicle *AllocateSingleVehicle(VehicleID *skip_vehicles) |
301 { |
309 { |
302 /* See note by ForceAllocateSpecialVehicle() why we skip the |
310 /* See note by ForceAllocateSpecialVehicle() why we skip the |
303 * first blocks */ |
311 * first blocks */ |
304 Vehicle *v; |
312 Vehicle *v; |
305 |
313 const int offset = (1 << VEHICLES_POOL_BLOCK_SIZE_BITS) * BLOCKS_FOR_SPECIAL_VEHICLES; |
306 FOR_ALL_VEHICLES_FROM(v, (1 << _vehicle_pool.block_size_bits) * BLOCKS_FOR_SPECIAL_VEHICLES) { |
314 |
307 if (v->type == 0) |
315 if (*skip_vehicles < (_vehicle_pool.total_items - offset)) { // make sure the offset in the array is not larger than the array itself |
308 return InitializeVehicle(v); |
316 FOR_ALL_VEHICLES_FROM(v, offset + *skip_vehicles) { |
|
317 (*skip_vehicles)++; |
|
318 if (v->type == 0) |
|
319 return InitializeVehicle(v); |
|
320 } |
309 } |
321 } |
310 |
322 |
311 /* Check if we can add a block to the pool */ |
323 /* Check if we can add a block to the pool */ |
312 if (AddBlockToPool(&_vehicle_pool)) |
324 if (AddBlockToPool(&_vehicle_pool)) |
313 return AllocateVehicle(); |
325 return AllocateSingleVehicle(skip_vehicles); |
314 |
326 |
315 return NULL; |
327 return NULL; |
316 } |
328 } |
317 |
329 |
|
330 Vehicle *AllocateVehicle(void) |
|
331 { |
|
332 VehicleID counter = 0; |
|
333 return AllocateSingleVehicle(&counter); |
|
334 } |
|
335 |
318 /** Allocates a lot of vehicles and frees them again |
336 /** Allocates a lot of vehicles and frees them again |
319 * @param vl pointer to an array of vehicles that can store all the vehicles in the test |
337 * @param vl pointer to an array of vehicles to get allocated. Can be NULL if the vehicles aren't needed (makes it test only) |
320 * @param num number of vehicles to test for |
338 * @param num number of vehicles to allocate room for |
321 * returns true if there is room to allocate all the vehicles |
339 * returns true if there is room to allocate all the vehicles |
322 */ |
340 */ |
323 bool AllocateVehicles(Vehicle **vl, int num) |
341 bool AllocateVehicles(Vehicle **vl, int num) |
324 { |
342 { |
325 int i; |
343 int i; |
326 Vehicle *v; |
344 Vehicle *v; |
327 bool success = true; |
345 VehicleID counter = 0; |
328 |
346 |
329 for(i = 0; i != num; i++) { |
347 for(i = 0; i != num; i++) { |
330 vl[i] = v = AllocateVehicle(); |
348 v = AllocateSingleVehicle(&counter); |
331 if (v == NULL) { |
349 if (v == NULL) { |
332 success = false; |
350 return false; |
333 break; |
351 } |
334 } |
352 if (vl != NULL) { |
335 v->type = 1; |
353 vl[i] = v; |
336 } |
354 } |
337 |
355 } |
338 while (--i >= 0) { |
356 |
339 vl[i]->type = 0; |
357 return true; |
340 } |
|
341 |
|
342 return success; |
|
343 } |
358 } |
344 |
359 |
345 |
360 |
346 void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc) |
361 void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc) |
347 { |
362 { |
1548 int veh_counter = 0; |
1563 int veh_counter = 0; |
1549 do { |
1564 do { |
1550 veh_counter++; |
1565 veh_counter++; |
1551 } while ((v = v->next) != NULL); |
1566 } while ((v = v->next) != NULL); |
1552 |
1567 |
1553 { |
1568 if (!AllocateVehicles(NULL, veh_counter)) { |
1554 Vehicle **vl = malloc(sizeof(Vehicle*) * veh_counter); // some platforms do not support Vehicle *vl[veh_counter] |
1569 return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
1555 bool can_allocate_vehicles = AllocateVehicles(vl, veh_counter); |
|
1556 free(vl); |
|
1557 if (!can_allocate_vehicles) { |
|
1558 return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
|
1559 } |
|
1560 } |
1570 } |
1561 } |
1571 } |
1562 |
1572 |
1563 v = v_front; |
1573 v = v_front; |
1564 |
1574 |