src/airport.cpp
author rubidium
Tue, 22 Jan 2008 21:00:30 +0000
branchNewGRF_ports
changeset 6872 1c4a4a609f85
parent 6871 5a9dc001e1ad
child 10724 68a692eacf22
permissions -rw-r--r--
(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;
}