(svn r11950) [NewGRF_ports] -Sync with trunk r11566:11949.
/* $Id$ */
/** @file airport.cpp */
#include "stdafx.h"
#include "openttd.h"
#include "debug.h"
#include "airport.h"
#include "core/bitmath_func.hpp"
#include "core/alloc_func.hpp"
#include "date_func.h"
#include "settings_type.h"
#include "newgrf_fsmports.h"
/* static */ AirportFTAClass *AirportFTAClass::oil_rig; ///< "Special" holding pattern used for oil rigs.
/* static */ AirportFTAClass *AirportFTAClass::dummy; ///< A dummy holding pattern to be used when an airport has been removed, but the order to go to the airport has not been removed.
/* Uncomment this to print out a full report of the airport-structure
* You should either use
* - true: full-report, print out every state and choice with string-names
* OR
* - false: give a summarized report which only shows current and next position */
//#define DEBUG_AIRPORT false
static byte AirportTestFTA(uint num_positions, const AirportFTA *layout, const byte *terminals);
#ifdef DEBUG_AIRPORT
static void AirportPrintOut(uint nof_elements, const AirportFTA *layout, bool full_report);
#endif
AirportFTAClass::~AirportFTAClass()
{
for (uint i = 0; i < num_positions; i++) {
AirportFTA *current = layout[i].next;
while (current != NULL) {
AirportFTA *next = current->next;
free(current);
current = next;
};
}
free(layout);
}
static byte AirportTestFTA(uint num_positions, const AirportFTA *layout, const byte *terminals)
{
uint next_position = 0;
for (uint i = 0; i < num_positions; i++) {
uint position = layout[i].position;
if (position != next_position) return i;
const AirportFTA *first = &layout[i];
for (const AirportFTA *current = first; current != NULL; current = current->next) {
/* A heading must always be valid. The only exceptions are
* - multiple choices as start, identified by a special value of 255
* - terminal group which is identified by a special value of 255 */
if (current->heading > MAX_HEADINGS) {
if (current->heading != 255) return i;
if (current == first && current->next == NULL) return i;
if (current != first && current->next_position > terminals[0]) return i;
}
/* If there is only one choice, it must be at the end */
if (current->heading == 0 && current->next != NULL) return i;
/* Obviously the elements of the linked list must have the same identifier */
if (position != current->position) return i;
/* A next position must be within bounds */
if (current->next_position >= num_positions) return i;
}
next_position++;
}
return MAX_ELEMENTS;
}
#ifdef DEBUG_AIRPORT
static const char* const _airport_heading_strings[] = {
"TO_ALL",
"HANGAR",
"TERM1",
"TERM2",
"TERM3",
"TERM4",
"TERM5",
"TERM6",
"HELIPAD1",
"HELIPAD2",
"TAKEOFF",
"STARTTAKEOFF",
"ENDTAKEOFF",
"HELITAKEOFF",
"FLYING",
"LANDING",
"ENDLANDING",
"HELILANDING",
"HELIENDLANDING",
"TERM7",
"TERM8",
"HELIPAD3",
"HELIPAD4",
"DUMMY" // extra heading for 255
};
static void AirportPrintOut(uint nof_elements, const AirportFTA *layout, bool full_report)
{
if (!full_report) printf("(P = Current Position; NP = Next Position)\n");
for (uint i = 0; i < nof_elements; i++) {
for (const AirportFTA *current = &layout[i]; current != NULL; current = current->next) {
if (full_report) {
byte heading = (current->heading == 255) ? MAX_HEADINGS + 1 : current->heading;
printf("\tPos:%2d NPos:%2d Heading:%15s Block:%2d\n", current->position,
current->next_position, _airport_heading_strings[heading],
FindLastBit(current->block));
} else {
printf("P:%2d NP:%2d", current->position, current->next_position);
}
}
printf("\n");
}
}
#endif
std::list<uint16> GetAvailableAirports()
{
std::list<uint16> airports;
for (uint i = 0; i < GetNumFSMportsClasses(); i++) {
for (uint j = 0; j < GetNumCustomFSMports((FSMportsClassID)i); j++) {
const FSMportsSpec *spec = GetCustomFSMportsSpec((FSMportsClassID)i, j);
if (!HasBit(spec->callbackmask, CBM_STATION_AVAIL) ||
GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, spec, NULL, INVALID_TILE) != 0) {
airports.push_back(i << 8 | j);
}
}
}
return airports;
}