vehicle.c
changeset 2606 7ae924de184b
parent 2602 f0e2dcce3695
child 2611 65b5313bc525
equal deleted inserted replaced
2605:d9d7eecdd1f1 2606:7ae924de184b
   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