tron@2186: /* $Id$ */ tron@2186: truelight@0: #include "stdafx.h" Darkvater@1891: #include "openttd.h" tron@1299: #include "debug.h" tron@679: #include "map.h" truelight@0: #include "airport.h" tron@2159: #include "macros.h" tron@2159: #include "variables.h" truelight@0: truelight@0: AirportFTAClass *CountryAirport; truelight@0: AirportFTAClass *CityAirport; truelight@0: AirportFTAClass *Heliport, *Oilrig; truelight@0: AirportFTAClass *MetropolitanAirport; truelight@0: AirportFTAClass *InternationalAirport; truelight@0: truelight@0: static void AirportFTAClass_Constructor(AirportFTAClass *Airport, celestar@950: const byte *terminals, const byte *helipads, truelight@0: const byte entry_point, const byte acc_planes, truelight@0: const AirportFTAbuildup *FA, tron@909: const TileIndexDiffC *depots, const byte nof_depots); truelight@0: static void AirportFTAClass_Destructor(AirportFTAClass *Airport); truelight@0: truelight@0: static uint16 AirportGetNofElements(const AirportFTAbuildup *FA); truelight@0: static void AirportBuildAutomata(AirportFTAClass *Airport, const AirportFTAbuildup *FA); truelight@0: static byte AirportTestFTA(const AirportFTAClass *Airport); truelight@0: /*static void AirportPrintOut(const AirportFTAClass *Airport, const bool full_report); truelight@0: static byte AirportBlockToString(uint32 block);*/ truelight@0: tron@1093: void InitializeAirports(void) truelight@0: { truelight@0: // country airport celestar@950: CountryAirport = malloc(sizeof(AirportFTAClass)); tron@1019: celestar@950: AirportFTAClass_Constructor( tron@1019: CountryAirport, tron@1019: _airport_terminal_country, tron@1019: NULL, tron@1019: 16, tron@1019: ALL, tron@1019: _airport_fta_country, tron@1019: _airport_depots_country, celestar@950: lengthof(_airport_depots_country) celestar@950: ); truelight@0: truelight@0: // city airport celestar@950: CityAirport = malloc(sizeof(AirportFTAClass)); tron@1019: celestar@950: AirportFTAClass_Constructor( tron@1019: CityAirport, tron@1019: _airport_terminal_city, tron@1019: NULL, tron@1019: 19, tron@1019: ALL, tron@1019: _airport_fta_city, tron@1019: _airport_depots_city, celestar@950: lengthof(_airport_depots_city) celestar@950: ); truelight@0: truelight@0: // metropolitan airport celestar@950: MetropolitanAirport = malloc(sizeof(AirportFTAClass)); tron@1019: celestar@950: AirportFTAClass_Constructor( tron@1019: MetropolitanAirport, tron@1019: _airport_terminal_metropolitan, tron@1019: NULL, tron@1019: 20, tron@1019: ALL, tron@1019: _airport_fta_metropolitan, tron@1019: _airport_depots_metropolitan, celestar@950: lengthof(_airport_depots_metropolitan) celestar@950: ); truelight@0: truelight@0: // international airport truelight@0: InternationalAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass)); tron@1019: celestar@950: AirportFTAClass_Constructor( tron@1019: InternationalAirport, tron@1019: _airport_terminal_international, tron@1019: _airport_helipad_international, tron@1019: 37, tron@1019: ALL, tron@1019: _airport_fta_international, tron@1019: _airport_depots_international, celestar@950: lengthof(_airport_depots_international) celestar@950: ); truelight@0: truelight@0: // heliport, oilrig truelight@0: Heliport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass)); tron@1019: celestar@950: AirportFTAClass_Constructor( tron@1019: Heliport, tron@1019: NULL, tron@1019: _airport_helipad_heliport_oilrig, tron@1019: 7, tron@1019: HELICOPTERS_ONLY, tron@1019: _airport_fta_heliport_oilrig, tron@1019: NULL, celestar@950: 0 celestar@950: ); tron@1019: truelight@0: Oilrig = Heliport; // exactly the same structure for heliport/oilrig, so share state machine truelight@0: } truelight@0: tron@1093: void UnInitializeAirports(void) truelight@0: { truelight@0: AirportFTAClass_Destructor(CountryAirport); truelight@0: AirportFTAClass_Destructor(CityAirport); truelight@0: AirportFTAClass_Destructor(Heliport); truelight@0: AirportFTAClass_Destructor(MetropolitanAirport); truelight@0: AirportFTAClass_Destructor(InternationalAirport); truelight@0: } truelight@0: truelight@0: static void AirportFTAClass_Constructor(AirportFTAClass *Airport, celestar@950: const byte *terminals, const byte *helipads, truelight@0: const byte entry_point, const byte acc_planes, truelight@0: const AirportFTAbuildup *FA, tron@909: const TileIndexDiffC *depots, const byte nof_depots) truelight@0: { celestar@950: byte nofterminals, nofhelipads; celestar@950: byte nofterminalgroups = 0; celestar@950: byte nofhelipadgroups = 0; celestar@950: const byte * curr; celestar@950: int i; celestar@950: nofterminals = nofhelipads = 0; tron@1019: celestar@950: //now we read the number of terminals we have celestar@950: if (terminals != NULL) { celestar@950: i = terminals[0]; celestar@950: nofterminalgroups = i; celestar@950: curr = terminals; celestar@950: while (i-- > 0) { celestar@950: curr++; celestar@950: assert(*curr != 0); //we don't want to have an empty group celestar@950: nofterminals += *curr; celestar@950: } tron@1019: celestar@950: } celestar@950: Airport->terminals = terminals; celestar@950: tron@1019: //read helipads celestar@950: if (helipads != NULL) { celestar@950: i = helipads[0]; celestar@950: nofhelipadgroups = i; celestar@950: curr = helipads; celestar@950: while (i-- > 0) { celestar@950: curr++; celestar@950: assert(*curr != 0); //no empty groups please celestar@950: nofhelipads += *curr; celestar@950: } tron@1019: celestar@950: } celestar@950: Airport->helipads = helipads; celestar@950: truelight@0: // if there are more terminals than 6, internal variables have to be changed, so don't allow that truelight@0: // same goes for helipads truelight@0: if (nofterminals > MAX_TERMINALS) { printf("Currently only maximum of %2d terminals are supported (you wanted %2d)\n", MAX_TERMINALS, nofterminals);} truelight@0: if (nofhelipads > MAX_HELIPADS) { printf("Currently only maximum of %2d helipads are supported (you wanted %2d)\n", MAX_HELIPADS, nofhelipads);} truelight@0: // terminals/helipads are divided into groups. Groups are computed by dividing the number truelight@0: // of terminals by the number of groups. Half in half. If #terminals is uneven, first group truelight@0: // will get the less # of terminals truelight@0: truelight@0: assert(nofterminals <= MAX_TERMINALS); truelight@0: assert(nofhelipads <= MAX_HELIPADS); truelight@0: truelight@0: Airport->nofelements = AirportGetNofElements(FA); truelight@0: // check truelight@0: if (entry_point >= Airport->nofelements) {printf("Entry point (%2d) must be within the airport positions (which is max %2d)\n", entry_point, Airport->nofelements);} truelight@0: assert(entry_point < Airport->nofelements); truelight@0: truelight@0: Airport->acc_planes = acc_planes; truelight@0: Airport->entry_point = entry_point; tron@699: Airport->airport_depots = depots; tron@699: Airport->nof_depots = nof_depots; truelight@0: truelight@0: truelight@0: // build the state machine truelight@0: AirportBuildAutomata(Airport, FA); tron@2549: DEBUG(misc, 1) ("#Elements %2d; #Terminals %2d in %d group(s); #Helipads %2d in %d group(s); Entry Point %d", tron@2549: Airport->nofelements, nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups, Airport->entry_point tron@2549: ); truelight@0: truelight@0: truelight@0: { tron@2549: byte ret = AirportTestFTA(Airport); tron@2549: if (ret != MAX_ELEMENTS) printf("ERROR with element: %d\n", ret - 1); tron@2549: assert(ret == MAX_ELEMENTS); truelight@0: } truelight@0: // print out full information truelight@0: // true -- full info including heading, block, etc truelight@0: // false -- short info, only position and next position truelight@0: //AirportPrintOut(Airport, false); truelight@0: } truelight@0: truelight@0: static void AirportFTAClass_Destructor(AirportFTAClass *Airport) truelight@0: { truelight@0: int i; truelight@0: AirportFTA *current, *next; truelight@0: truelight@0: for (i = 0; i < Airport->nofelements; i++) { truelight@0: current = Airport->layout[i].next_in_chain; truelight@0: while (current != NULL) { truelight@0: next = current->next_in_chain; truelight@0: free(current); truelight@0: current = next; truelight@0: }; truelight@0: } truelight@0: free(Airport->layout); truelight@0: free(Airport); truelight@0: } truelight@0: truelight@0: static uint16 AirportGetNofElements(const AirportFTAbuildup *FA) truelight@0: { truelight@0: int i; truelight@0: uint16 nofelements = 0; truelight@0: int temp = FA[0].position; tron@2549: truelight@0: for (i = 0; i < MAX_ELEMENTS; i++) { truelight@0: if (temp != FA[i].position) { truelight@0: nofelements++; truelight@0: temp = FA[i].position; truelight@0: } tron@2549: if (FA[i].position == MAX_ELEMENTS) break; truelight@0: } truelight@0: return nofelements; truelight@0: } truelight@0: truelight@0: static void AirportBuildAutomata(AirportFTAClass *Airport, const AirportFTAbuildup *FA) truelight@0: { truelight@0: AirportFTA *FAutomata; truelight@0: AirportFTA *current; truelight@0: uint16 internalcounter, i; tron@2549: FAutomata = malloc(sizeof(AirportFTA) * Airport->nofelements); truelight@0: Airport->layout = FAutomata; truelight@0: internalcounter = 0; truelight@0: truelight@0: for (i = 0; i < Airport->nofelements; i++) { truelight@0: current = &Airport->layout[i]; truelight@0: current->position = FA[internalcounter].position; truelight@0: current->heading = FA[internalcounter].heading; truelight@0: current->block = FA[internalcounter].block; truelight@0: current->next_position = FA[internalcounter].next_in_chain; truelight@0: truelight@0: // outgoing nodes from the same position, create linked list tron@2549: while (current->position == FA[internalcounter + 1].position) { tron@2549: AirportFTA* newNode = malloc(sizeof(AirportFTA)); tron@2549: tron@2549: newNode->position = FA[internalcounter + 1].position; tron@2549: newNode->heading = FA[internalcounter + 1].heading; tron@2549: newNode->block = FA[internalcounter + 1].block; tron@2549: newNode->next_position = FA[internalcounter + 1].next_in_chain; truelight@0: // create link truelight@0: current->next_in_chain = newNode; truelight@0: current = current->next_in_chain; truelight@0: internalcounter++; truelight@0: } // while truelight@0: current->next_in_chain = NULL; truelight@0: internalcounter++; truelight@0: } truelight@0: } truelight@0: truelight@0: static byte AirportTestFTA(const AirportFTAClass *Airport) truelight@0: { truelight@0: byte position, i, next_element; truelight@0: AirportFTA *temp; truelight@0: next_element = 0; truelight@0: truelight@0: for (i = 0; i < Airport->nofelements; i++) { truelight@0: position = Airport->layout[i].position; tron@2549: if (position != next_element) return i; truelight@0: temp = &Airport->layout[i]; truelight@0: truelight@0: do { tron@2549: if (temp->heading > MAX_HEADINGS && temp->heading != 255) return i; tron@2549: if (temp->heading == 0 && temp->next_in_chain != 0) return i; tron@2549: if (position != temp->position) return i; tron@2549: if (temp->next_position >= Airport->nofelements) return i; truelight@0: temp = temp->next_in_chain; truelight@0: } while (temp != NULL); truelight@0: next_element++; truelight@0: } truelight@0: return MAX_ELEMENTS; truelight@0: } truelight@0: tron@2549: #if 0 tron@2549: static const char* const _airport_heading_strings[] = { truelight@0: "TO_ALL", truelight@0: "HANGAR", truelight@0: "TERM1", truelight@0: "TERM2", truelight@0: "TERM3", truelight@0: "TERM4", truelight@0: "TERM5", truelight@0: "TERM6", truelight@0: "HELIPAD1", truelight@0: "HELIPAD2", truelight@0: "TAKEOFF", truelight@0: "STARTTAKEOFF", truelight@0: "ENDTAKEOFF", truelight@0: "HELITAKEOFF", truelight@0: "FLYING", truelight@0: "LANDING", truelight@0: "ENDLANDING", truelight@0: "HELILANDING", truelight@0: "HELIENDLANDING", truelight@0: "DUMMY" // extra heading for 255 truelight@0: }; truelight@0: truelight@0: static void AirportPrintOut(const AirportFTAClass *Airport, const bool full_report) truelight@0: { truelight@0: AirportFTA *temp; truelight@0: uint16 i; truelight@0: byte heading; truelight@0: truelight@0: printf("(P = Current Position; NP = Next Position)\n"); truelight@0: for (i = 0; i < Airport->nofelements; i++) { truelight@0: temp = &Airport->layout[i]; truelight@0: if (full_report) { truelight@0: heading = (temp->heading == 255) ? MAX_HEADINGS+1 : temp->heading; truelight@0: printf("Pos:%2d NPos:%2d Heading:%15s Block:%2d\n", temp->position, temp->next_position, truelight@0: _airport_heading_strings[heading], AirportBlockToString(temp->block)); tron@2549: } else { tron@2549: printf("P:%2d NP:%2d", temp->position, temp->next_position); truelight@0: } truelight@0: while (temp->next_in_chain != NULL) { truelight@0: temp = temp->next_in_chain; truelight@0: if (full_report) { truelight@0: heading = (temp->heading == 255) ? MAX_HEADINGS+1 : temp->heading; truelight@0: printf("Pos:%2d NPos:%2d Heading:%15s Block:%2d\n", temp->position, temp->next_position, truelight@0: _airport_heading_strings[heading], AirportBlockToString(temp->block)); tron@2549: } else { tron@2549: printf("P:%2d NP:%2d", temp->position, temp->next_position); truelight@0: } truelight@0: } truelight@0: printf("\n"); truelight@0: } truelight@0: } truelight@0: truelight@0: truelight@0: static byte AirportBlockToString(uint32 block) truelight@0: { truelight@0: byte i = 0; truelight@0: if (block & 0xffff0000) { block >>= 16; i += 16; } truelight@0: if (block & 0x0000ff00) { block >>= 8; i += 8; } truelight@0: if (block & 0x000000f0) { block >>= 4; i += 4; } truelight@0: if (block & 0x0000000c) { block >>= 2; i += 2; } truelight@0: if (block & 0x00000002) { i += 1; } truelight@0: return i; tron@2549: } tron@2549: #endif truelight@0: truelight@0: const AirportFTAClass* GetAirport(const byte airport_type) truelight@0: { truelight@0: AirportFTAClass *Airport = NULL; truelight@0: //FIXME -- AircraftNextAirportPos_and_Order -> Needs something nicer, don't like this code truelight@0: // needs constant change if more airports are added truelight@0: switch (airport_type) { truelight@0: case AT_SMALL: Airport = CountryAirport; break; truelight@0: case AT_LARGE: Airport = CityAirport; break; truelight@0: case AT_METROPOLITAN: Airport = MetropolitanAirport; break; truelight@0: case AT_HELIPORT: Airport = Heliport; break; truelight@0: case AT_OILRIG: Airport = Oilrig; break; truelight@0: case AT_INTERNATIONAL: Airport = InternationalAirport; break; truelight@0: default: truelight@0: #ifdef DEBUG__ truelight@0: printf("Airport AircraftNextAirportPos_and_Order not yet implemented\n"); truelight@0: #endif truelight@0: assert(airport_type <= AT_INTERNATIONAL); truelight@0: } truelight@0: return Airport; truelight@0: } tron@2159: tron@2159: uint32 GetValidAirports(void) tron@2159: { tron@2159: uint32 bytemask = _avail_aircraft; /// sets the first 3 bytes, 0 - 2, @see AdjustAvailAircraft() tron@2159: tron@2159: // 1980-1-1 is --> 21915 tron@2159: // 1990-1-1 is --> 25568 tron@2159: if (_date >= 21915) {SETBIT(bytemask, 3);} // metropilitan airport 1980 tron@2159: if (_date >= 25568) {SETBIT(bytemask, 4);} // international airport 1990 tron@2159: return bytemask; tron@2159: }