00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "debug.h"
00014 #include "airport.h"
00015 #include "table/airport_movement.h"
00016 #include "core/alloc_func.hpp"
00017 #include "date_func.h"
00018 #include "settings_type.h"
00019
00020
00021
00022 enum AirportTiles {
00023 APT_APRON = 0,
00024 APT_APRON_FENCE_NW = 1,
00025 APT_APRON_FENCE_SW = 2,
00026 APT_STAND = 3,
00027 APT_APRON_W = 4,
00028 APT_APRON_S = 5,
00029 APT_APRON_VER_CROSSING_S = 6,
00030 APT_APRON_HOR_CROSSING_W = 7,
00031 APT_APRON_VER_CROSSING_N = 8,
00032 APT_APRON_HOR_CROSSING_E = 9,
00033 APT_APRON_E = 10,
00034 APT_ARPON_N = 11,
00035 APT_APRON_HOR = 12,
00036 APT_APRON_N_FENCE_SW = 13,
00037 APT_RUNWAY_1 = 14,
00038 APT_RUNWAY_2 = 15,
00039 APT_RUNWAY_3 = 16,
00040 APT_RUNWAY_4 = 17,
00041 APT_RUNWAY_END_FENCE_SE = 18,
00042 APT_BUILDING_2 = 19,
00043 APT_TOWER_FENCE_SW = 20,
00044 APT_ROUND_TERMINAL = 21,
00045 APT_BUILDING_3 = 22,
00046 APT_BUILDING_1 = 23,
00047 APT_DEPOT_SE = 24,
00048 APT_STAND_1 = 25,
00049 APT_STAND_PIER_NE = 26,
00050 APT_PIER_NW_NE = 27,
00051 APT_PIER = 28,
00052 APT_EMPTY = 29,
00053 APT_EMPTY_FENCE_NE = 30,
00054 APT_RADAR_GRASS_FENCE_SW = 31,
00055
00056 APT_RADIO_TOWER_FENCE_NE = 43,
00057 APT_SMALL_BUILDING_3 = 44,
00058 APT_SMALL_BUILDING_2 = 45,
00059 APT_SMALL_BUILDING_1 = 46,
00060 APT_GRASS_FENCE_SW = 47,
00061 APT_GRASS_2 = 48,
00062 APT_GRASS_1 = 49,
00063 APT_GRASS_FENCE_NE_FLAG = 50,
00064
00065 APT_RUNWAY_SMALL_NEAR_END = 54,
00066 APT_RUNWAY_SMALL_MIDDLE = 55,
00067 APT_RUNWAY_SMALL_FAR_END = 56,
00068 APT_SMALL_DEPOT_SE = 57,
00069 APT_HELIPORT = 58,
00070 APT_RUNWAY_END = 59,
00071 APT_RUNWAY_5 = 60,
00072 APT_TOWER = 61,
00073 APT_SMALL_DEPOT_SE_2 = 62,
00074 APT_APRON_FENCE_NE = 63,
00075 APT_RUNWAY_END_FENCE_NW = 64,
00076 APT_RUNWAY_FENCE_NW = 65,
00077 APT_RADAR_FENCE_SW = 66,
00078
00079 APT_RADAR_FENCE_NE = 78,
00080
00081 APT_HELIPAD_1 = 90,
00082 APT_HELIPAD_2_FENCE_NW = 91,
00083 APT_HELIPAD_2 = 92,
00084 APT_APRON_FENCE_NE_SW = 93,
00085 APT_RUNWAY_END_FENCE_NW_SW = 94,
00086 APT_RUNWAY_END_FENCE_SE_SW = 95,
00087 APT_RUNWAY_END_FENCE_NE_NW = 96,
00088 APT_RUNWAY_END_FENCE_NE_SE = 97,
00089 APT_HELIPAD_2_FENCE_NE_SE = 98,
00090 APT_APRON_FENCE_SE_SW = 99,
00091 APT_LOW_BUILDING_FENCE_N = 100,
00092 APT_ROT_RUNWAY_FENCE_NE = 101,
00093 APT_ROT_RUNWAY_END_FENCE_NE= 102,
00094 APT_ROT_RUNWAY_FENCE_SW = 103,
00095 APT_ROT_RUNWAY_END_FENCE_SW= 104,
00096 APT_DEPOT_SW = 105,
00097 APT_DEPOT_NW = 106,
00098 APT_DEPOT_NE = 107,
00099 APT_HELIPAD_2_FENCE_SE_SW = 108,
00100 APT_HELIPAD_2_FENCE_SE = 109,
00101 APT_LOW_BUILDING_FENCE_NW = 110,
00102 APT_LOW_BUILDING_FENCE_NE = 111,
00103 APT_LOW_BUILDING_FENCE_SW = 112,
00104 APT_LOW_BUILDING_FENCE_SE = 113,
00105 APT_STAND_FENCE_NE = 114,
00106 APT_STAND_FENCE_SE = 115,
00107 APT_STAND_FENCE_SW = 116,
00108 APT_APRON_FENCE_NE_2 = 117,
00109 APT_APRON_FENCE_SE = 118,
00110 APT_HELIPAD_2_FENCE_NW_SW = 119,
00111 APT_HELIPAD_2_FENCE_SW = 120,
00112 APT_RADAR_FENCE_SE = 121,
00113
00114 APT_HELIPAD_3_FENCE_SE_SW = 133,
00115 APT_HELIPAD_3_FENCE_NW_SW = 134,
00116 APT_HELIPAD_3_FENCE_NW = 135,
00117 APT_LOW_BUILDING = 136,
00118 APT_APRON_FENCE_NE_SE = 137,
00119 APT_APRON_HALF_EAST = 138,
00120 APT_APRON_HALF_WEST = 139,
00121 APT_GRASS_FENCE_NE_FLAG_2 = 140,
00122
00123 };
00124
00125 #include "table/airport_defaults.h"
00126 #include "table/airporttiles.h"
00127
00128 AirportSpec AirportSpec::dummy = {NULL, NULL, 0, 0, 0, 0, 0, MIN_YEAR, MIN_YEAR};
00129 AirportSpec AirportSpec::oilrig = {NULL, NULL, 0, 1, 1, 0, 4, MIN_YEAR, MIN_YEAR};
00130
00131
00137 const AirportSpec *AirportSpec::Get(byte type)
00138 {
00139 if (type == AT_OILRIG) return &oilrig;
00140 assert(type < NUM_AIRPORTS);
00141 extern const AirportSpec _origin_airport_specs[];
00142 return &_origin_airport_specs[type];
00143 }
00144
00150 const AirportTileSpec *AirportTileSpec::Get(StationGfx gfx)
00151 {
00152 assert(gfx < NUM_AIRPORTTILES);
00153 extern const AirportTileSpec _origin_airporttile_specs[];
00154 return &_origin_airporttile_specs[gfx];
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164 static AirportFTAClass *_dummy_airport;
00165 static AirportFTAClass *_country_airport;
00166 static AirportFTAClass *_city_airport;
00167 static AirportFTAClass *_oilrig;
00168 static AirportFTAClass *_heliport;
00169 static AirportFTAClass *_metropolitan_airport;
00170 static AirportFTAClass *_international_airport;
00171 static AirportFTAClass *_commuter_airport;
00172 static AirportFTAClass *_heli_depot;
00173 static AirportFTAClass *_intercontinental_airport;
00174 static AirportFTAClass *_heli_station;
00175
00176
00177 void InitializeAirports()
00178 {
00179 _dummy_airport = new AirportFTAClass(
00180 _airport_moving_data_dummy,
00181 NULL,
00182 NULL,
00183 _airport_entries_dummy,
00184 AirportFTAClass::ALL,
00185 _airport_fta_dummy,
00186 0
00187 );
00188
00189 _country_airport = new AirportFTAClass(
00190 _airport_moving_data_country,
00191 _airport_terminal_country,
00192 NULL,
00193 _airport_entries_country,
00194 AirportFTAClass::ALL | AirportFTAClass::SHORT_STRIP,
00195 _airport_fta_country,
00196 0
00197 );
00198
00199 _city_airport = new AirportFTAClass(
00200 _airport_moving_data_town,
00201 _airport_terminal_city,
00202 NULL,
00203 _airport_entries_city,
00204 AirportFTAClass::ALL,
00205 _airport_fta_city,
00206 0
00207 );
00208
00209 _metropolitan_airport = new AirportFTAClass(
00210 _airport_moving_data_metropolitan,
00211 _airport_terminal_metropolitan,
00212 NULL,
00213 _airport_entries_metropolitan,
00214 AirportFTAClass::ALL,
00215 _airport_fta_metropolitan,
00216 0
00217 );
00218
00219 _international_airport = new AirportFTAClass(
00220 _airport_moving_data_international,
00221 _airport_terminal_international,
00222 _airport_helipad_international,
00223 _airport_entries_international,
00224 AirportFTAClass::ALL,
00225 _airport_fta_international,
00226 0
00227 );
00228
00229 _intercontinental_airport = new AirportFTAClass(
00230 _airport_moving_data_intercontinental,
00231 _airport_terminal_intercontinental,
00232 _airport_helipad_intercontinental,
00233 _airport_entries_intercontinental,
00234 AirportFTAClass::ALL,
00235 _airport_fta_intercontinental,
00236 0
00237 );
00238
00239 _heliport = new AirportFTAClass(
00240 _airport_moving_data_heliport,
00241 NULL,
00242 _airport_helipad_heliport_oilrig,
00243 _airport_entries_heliport_oilrig,
00244 AirportFTAClass::HELICOPTERS,
00245 _airport_fta_heliport_oilrig,
00246 60
00247 );
00248
00249 _oilrig = new AirportFTAClass(
00250 _airport_moving_data_oilrig,
00251 NULL,
00252 _airport_helipad_heliport_oilrig,
00253 _airport_entries_heliport_oilrig,
00254 AirportFTAClass::HELICOPTERS,
00255 _airport_fta_heliport_oilrig,
00256 54
00257 );
00258
00259 _commuter_airport = new AirportFTAClass(
00260 _airport_moving_data_commuter,
00261 _airport_terminal_commuter,
00262 _airport_helipad_commuter,
00263 _airport_entries_commuter,
00264 AirportFTAClass::ALL | AirportFTAClass::SHORT_STRIP,
00265 _airport_fta_commuter,
00266 0
00267 );
00268
00269 _heli_depot = new AirportFTAClass(
00270 _airport_moving_data_helidepot,
00271 NULL,
00272 _airport_helipad_helidepot,
00273 _airport_entries_helidepot,
00274 AirportFTAClass::HELICOPTERS,
00275 _airport_fta_helidepot,
00276 0
00277 );
00278
00279 _heli_station = new AirportFTAClass(
00280 _airport_moving_data_helistation,
00281 NULL,
00282 _airport_helipad_helistation,
00283 _airport_entries_helistation,
00284 AirportFTAClass::HELICOPTERS,
00285 _airport_fta_helistation,
00286 0
00287 );
00288 }
00289
00290 void UnInitializeAirports()
00291 {
00292 delete _dummy_airport;
00293 delete _country_airport;
00294 delete _city_airport;
00295 delete _heliport;
00296 delete _metropolitan_airport;
00297 delete _international_airport;
00298 delete _commuter_airport;
00299 delete _heli_depot;
00300 delete _intercontinental_airport;
00301 delete _heli_station;
00302 }
00303
00304
00305 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA);
00306 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA);
00307 static byte AirportGetTerminalCount(const byte *terminals, byte *groups);
00308 static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byte *terminals);
00309
00310 #ifdef DEBUG_AIRPORT
00311 static void AirportPrintOut(uint nofelements, const AirportFTA *layout, bool full_report);
00312 #endif
00313
00314
00315 AirportFTAClass::AirportFTAClass(
00316 const AirportMovingData *moving_data_,
00317 const byte *terminals_,
00318 const byte *helipads_,
00319 const byte *entry_points_,
00320 Flags flags_,
00321 const AirportFTAbuildup *apFA,
00322 byte delta_z_
00323 ) :
00324 moving_data(moving_data_),
00325 terminals(terminals_),
00326 helipads(helipads_),
00327 flags(flags_),
00328 nofelements(AirportGetNofElements(apFA)),
00329 entry_points(entry_points_),
00330 delta_z(delta_z_)
00331 {
00332 byte nofterminalgroups, nofhelipadgroups;
00333
00334
00335
00336
00337 uint nofterminals = AirportGetTerminalCount(terminals, &nofterminalgroups);
00338 if (nofterminals > MAX_TERMINALS) {
00339 DEBUG(misc, 0, "[Ap] only a maximum of %d terminals are supported (requested %d)", MAX_TERMINALS, nofterminals);
00340 assert(nofterminals <= MAX_TERMINALS);
00341 }
00342
00343 uint nofhelipads = AirportGetTerminalCount(helipads, &nofhelipadgroups);
00344 if (nofhelipads > MAX_HELIPADS) {
00345 DEBUG(misc, 0, "[Ap] only a maximum of %d helipads are supported (requested %d)", MAX_HELIPADS, nofhelipads);
00346 assert(nofhelipads <= MAX_HELIPADS);
00347 }
00348
00349
00350
00351
00352 for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) {
00353 if (entry_points[i] >= nofelements) {
00354 DEBUG(misc, 0, "[Ap] entry (%d) must be within the airport (maximum %d)", entry_points[i], nofelements);
00355 assert(entry_points[i] < nofelements);
00356 }
00357 }
00358
00359
00360 layout = AirportBuildAutomata(nofelements, apFA);
00361 DEBUG(misc, 6, "[Ap] #count %3d; #term %2d (%dgrp); #helipad %2d (%dgrp); entries %3d, %3d, %3d, %3d",
00362 nofelements, nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups,
00363 entry_points[DIAGDIR_NE], entry_points[DIAGDIR_SE], entry_points[DIAGDIR_SW], entry_points[DIAGDIR_NW]);
00364
00365
00366
00367
00368 uint ret = AirportTestFTA(nofelements, layout, terminals);
00369 if (ret != MAX_ELEMENTS) DEBUG(misc, 0, "[Ap] problem with element: %d", ret - 1);
00370 assert(ret == MAX_ELEMENTS);
00371
00372 #ifdef DEBUG_AIRPORT
00373 AirportPrintOut(nofelements, layout, DEBUG_AIRPORT);
00374 #endif
00375 }
00376
00377 AirportFTAClass::~AirportFTAClass()
00378 {
00379 for (uint i = 0; i < nofelements; i++) {
00380 AirportFTA *current = layout[i].next;
00381 while (current != NULL) {
00382 AirportFTA *next = current->next;
00383 free(current);
00384 current = next;
00385 };
00386 }
00387 free(layout);
00388 }
00389
00390 bool AirportSpec::IsAvailable() const
00391 {
00392 if (_cur_year < this->min_year) return false;
00393 if (_settings_game.station.never_expire_airports) return true;
00394 return _cur_year <= this->max_year;
00395 }
00396
00400 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
00401 {
00402 uint16 nofelements = 0;
00403 int temp = apFA[0].position;
00404
00405 for (uint i = 0; i < MAX_ELEMENTS; i++) {
00406 if (temp != apFA[i].position) {
00407 nofelements++;
00408 temp = apFA[i].position;
00409 }
00410 if (apFA[i].position == MAX_ELEMENTS) break;
00411 }
00412 return nofelements;
00413 }
00414
00418 static byte AirportGetTerminalCount(const byte *terminals, byte *groups)
00419 {
00420 byte nof_terminals = 0;
00421 *groups = 0;
00422
00423 if (terminals != NULL) {
00424 uint i = terminals[0];
00425 *groups = i;
00426 while (i-- > 0) {
00427 terminals++;
00428 assert(*terminals != 0);
00429 nof_terminals += *terminals;
00430 }
00431 }
00432 return nof_terminals;
00433 }
00434
00435
00436 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA)
00437 {
00438 AirportFTA *FAutomata = MallocT<AirportFTA>(nofelements);
00439 uint16 internalcounter = 0;
00440
00441 for (uint i = 0; i < nofelements; i++) {
00442 AirportFTA *current = &FAutomata[i];
00443 current->position = apFA[internalcounter].position;
00444 current->heading = apFA[internalcounter].heading;
00445 current->block = apFA[internalcounter].block;
00446 current->next_position = apFA[internalcounter].next;
00447
00448
00449 while (current->position == apFA[internalcounter + 1].position) {
00450 AirportFTA *newNode = MallocT<AirportFTA>(1);
00451
00452 newNode->position = apFA[internalcounter + 1].position;
00453 newNode->heading = apFA[internalcounter + 1].heading;
00454 newNode->block = apFA[internalcounter + 1].block;
00455 newNode->next_position = apFA[internalcounter + 1].next;
00456
00457 current->next = newNode;
00458 current = current->next;
00459 internalcounter++;
00460 }
00461 current->next = NULL;
00462 internalcounter++;
00463 }
00464 return FAutomata;
00465 }
00466
00467
00468 static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byte *terminals)
00469 {
00470 uint next_position = 0;
00471
00472 for (uint i = 0; i < nofelements; i++) {
00473 uint position = layout[i].position;
00474 if (position != next_position) return i;
00475 const AirportFTA *first = &layout[i];
00476
00477 for (const AirportFTA *current = first; current != NULL; current = current->next) {
00478
00479
00480
00481 if (current->heading > MAX_HEADINGS) {
00482 if (current->heading != 255) return i;
00483 if (current == first && current->next == NULL) return i;
00484 if (current != first && current->next_position > terminals[0]) return i;
00485 }
00486
00487
00488 if (current->heading == 0 && current->next != NULL) return i;
00489
00490 if (position != current->position) return i;
00491
00492 if (current->next_position >= nofelements) return i;
00493 }
00494 next_position++;
00495 }
00496 return MAX_ELEMENTS;
00497 }
00498
00499 #ifdef DEBUG_AIRPORT
00500 static const char * const _airport_heading_strings[] = {
00501 "TO_ALL",
00502 "HANGAR",
00503 "TERM1",
00504 "TERM2",
00505 "TERM3",
00506 "TERM4",
00507 "TERM5",
00508 "TERM6",
00509 "HELIPAD1",
00510 "HELIPAD2",
00511 "TAKEOFF",
00512 "STARTTAKEOFF",
00513 "ENDTAKEOFF",
00514 "HELITAKEOFF",
00515 "FLYING",
00516 "LANDING",
00517 "ENDLANDING",
00518 "HELILANDING",
00519 "HELIENDLANDING",
00520 "TERM7",
00521 "TERM8",
00522 "HELIPAD3",
00523 "HELIPAD4",
00524 "DUMMY"
00525 };
00526
00527 static void AirportPrintOut(uint nofelements, const AirportFTA *layout, bool full_report)
00528 {
00529 if (!full_report) printf("(P = Current Position; NP = Next Position)\n");
00530
00531 for (uint i = 0; i < nofelements; i++) {
00532 for (const AirportFTA *current = &layout[i]; current != NULL; current = current->next) {
00533 if (full_report) {
00534 byte heading = (current->heading == 255) ? MAX_HEADINGS + 1 : current->heading;
00535 printf("\tPos:%2d NPos:%2d Heading:%15s Block:%2d\n", current->position,
00536 current->next_position, _airport_heading_strings[heading],
00537 FindLastBit(current->block));
00538 } else {
00539 printf("P:%2d NP:%2d", current->position, current->next_position);
00540 }
00541 }
00542 printf("\n");
00543 }
00544 }
00545 #endif
00546
00547 const AirportFTAClass *GetAirport(const byte airport_type)
00548 {
00549
00550
00551 switch (airport_type) {
00552 default: NOT_REACHED();
00553 case AT_SMALL: return _country_airport;
00554 case AT_LARGE: return _city_airport;
00555 case AT_METROPOLITAN: return _metropolitan_airport;
00556 case AT_HELIPORT: return _heliport;
00557 case AT_OILRIG: return _oilrig;
00558 case AT_INTERNATIONAL: return _international_airport;
00559 case AT_COMMUTER: return _commuter_airport;
00560 case AT_HELIDEPOT: return _heli_depot;
00561 case AT_INTERCON: return _intercontinental_airport;
00562 case AT_HELISTATION: return _heli_station;
00563 case AT_DUMMY: return _dummy_airport;
00564 }
00565 }