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 #include "table/airporttile_ids.h"
00020 #include "table/airport_defaults.h"
00021 #include "table/airporttiles.h"
00022
00023 AirportSpec AirportSpec::dummy = {NULL, NULL, 0, 0, 0, 0, 0, MIN_YEAR, MIN_YEAR};
00024 AirportSpec AirportSpec::oilrig = {NULL, NULL, 0, 1, 1, 0, 4, MIN_YEAR, MIN_YEAR};
00025
00026
00032 const AirportSpec *AirportSpec::Get(byte type)
00033 {
00034 if (type == AT_OILRIG) return &oilrig;
00035 assert(type < NUM_AIRPORTS);
00036 extern const AirportSpec _origin_airport_specs[];
00037 return &_origin_airport_specs[type];
00038 }
00039
00045 const AirportTileSpec *AirportTileSpec::Get(StationGfx gfx)
00046 {
00047 assert(gfx < NUM_AIRPORTTILES);
00048 extern const AirportTileSpec _origin_airporttile_specs[];
00049 return &_origin_airporttile_specs[gfx];
00050 }
00051
00052
00053
00054
00055
00056
00057
00058
00059 static AirportFTAClass *_dummy_airport;
00060 static AirportFTAClass *_country_airport;
00061 static AirportFTAClass *_city_airport;
00062 static AirportFTAClass *_oilrig;
00063 static AirportFTAClass *_heliport;
00064 static AirportFTAClass *_metropolitan_airport;
00065 static AirportFTAClass *_international_airport;
00066 static AirportFTAClass *_commuter_airport;
00067 static AirportFTAClass *_heli_depot;
00068 static AirportFTAClass *_intercontinental_airport;
00069 static AirportFTAClass *_heli_station;
00070
00071
00072 void InitializeAirports()
00073 {
00074 _dummy_airport = new AirportFTAClass(
00075 _airport_moving_data_dummy,
00076 NULL,
00077 NULL,
00078 _airport_entries_dummy,
00079 AirportFTAClass::ALL,
00080 _airport_fta_dummy,
00081 0
00082 );
00083
00084 _country_airport = new AirportFTAClass(
00085 _airport_moving_data_country,
00086 _airport_terminal_country,
00087 NULL,
00088 _airport_entries_country,
00089 AirportFTAClass::ALL | AirportFTAClass::SHORT_STRIP,
00090 _airport_fta_country,
00091 0
00092 );
00093
00094 _city_airport = new AirportFTAClass(
00095 _airport_moving_data_town,
00096 _airport_terminal_city,
00097 NULL,
00098 _airport_entries_city,
00099 AirportFTAClass::ALL,
00100 _airport_fta_city,
00101 0
00102 );
00103
00104 _metropolitan_airport = new AirportFTAClass(
00105 _airport_moving_data_metropolitan,
00106 _airport_terminal_metropolitan,
00107 NULL,
00108 _airport_entries_metropolitan,
00109 AirportFTAClass::ALL,
00110 _airport_fta_metropolitan,
00111 0
00112 );
00113
00114 _international_airport = new AirportFTAClass(
00115 _airport_moving_data_international,
00116 _airport_terminal_international,
00117 _airport_helipad_international,
00118 _airport_entries_international,
00119 AirportFTAClass::ALL,
00120 _airport_fta_international,
00121 0
00122 );
00123
00124 _intercontinental_airport = new AirportFTAClass(
00125 _airport_moving_data_intercontinental,
00126 _airport_terminal_intercontinental,
00127 _airport_helipad_intercontinental,
00128 _airport_entries_intercontinental,
00129 AirportFTAClass::ALL,
00130 _airport_fta_intercontinental,
00131 0
00132 );
00133
00134 _heliport = new AirportFTAClass(
00135 _airport_moving_data_heliport,
00136 NULL,
00137 _airport_helipad_heliport_oilrig,
00138 _airport_entries_heliport_oilrig,
00139 AirportFTAClass::HELICOPTERS,
00140 _airport_fta_heliport_oilrig,
00141 60
00142 );
00143
00144 _oilrig = new AirportFTAClass(
00145 _airport_moving_data_oilrig,
00146 NULL,
00147 _airport_helipad_heliport_oilrig,
00148 _airport_entries_heliport_oilrig,
00149 AirportFTAClass::HELICOPTERS,
00150 _airport_fta_heliport_oilrig,
00151 54
00152 );
00153
00154 _commuter_airport = new AirportFTAClass(
00155 _airport_moving_data_commuter,
00156 _airport_terminal_commuter,
00157 _airport_helipad_commuter,
00158 _airport_entries_commuter,
00159 AirportFTAClass::ALL | AirportFTAClass::SHORT_STRIP,
00160 _airport_fta_commuter,
00161 0
00162 );
00163
00164 _heli_depot = new AirportFTAClass(
00165 _airport_moving_data_helidepot,
00166 NULL,
00167 _airport_helipad_helidepot,
00168 _airport_entries_helidepot,
00169 AirportFTAClass::HELICOPTERS,
00170 _airport_fta_helidepot,
00171 0
00172 );
00173
00174 _heli_station = new AirportFTAClass(
00175 _airport_moving_data_helistation,
00176 NULL,
00177 _airport_helipad_helistation,
00178 _airport_entries_helistation,
00179 AirportFTAClass::HELICOPTERS,
00180 _airport_fta_helistation,
00181 0
00182 );
00183 }
00184
00185 void UnInitializeAirports()
00186 {
00187 delete _dummy_airport;
00188 delete _country_airport;
00189 delete _city_airport;
00190 delete _heliport;
00191 delete _metropolitan_airport;
00192 delete _international_airport;
00193 delete _commuter_airport;
00194 delete _heli_depot;
00195 delete _intercontinental_airport;
00196 delete _heli_station;
00197 }
00198
00199
00200 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA);
00201 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA);
00202 static byte AirportGetTerminalCount(const byte *terminals, byte *groups);
00203 static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byte *terminals);
00204
00205 #ifdef DEBUG_AIRPORT
00206 static void AirportPrintOut(uint nofelements, const AirportFTA *layout, bool full_report);
00207 #endif
00208
00209
00210 AirportFTAClass::AirportFTAClass(
00211 const AirportMovingData *moving_data_,
00212 const byte *terminals_,
00213 const byte *helipads_,
00214 const byte *entry_points_,
00215 Flags flags_,
00216 const AirportFTAbuildup *apFA,
00217 byte delta_z_
00218 ) :
00219 moving_data(moving_data_),
00220 terminals(terminals_),
00221 helipads(helipads_),
00222 flags(flags_),
00223 nofelements(AirportGetNofElements(apFA)),
00224 entry_points(entry_points_),
00225 delta_z(delta_z_)
00226 {
00227 byte nofterminalgroups, nofhelipadgroups;
00228
00229
00230
00231
00232 uint nofterminals = AirportGetTerminalCount(terminals, &nofterminalgroups);
00233 if (nofterminals > MAX_TERMINALS) {
00234 DEBUG(misc, 0, "[Ap] only a maximum of %d terminals are supported (requested %d)", MAX_TERMINALS, nofterminals);
00235 assert(nofterminals <= MAX_TERMINALS);
00236 }
00237
00238 uint nofhelipads = AirportGetTerminalCount(helipads, &nofhelipadgroups);
00239 if (nofhelipads > MAX_HELIPADS) {
00240 DEBUG(misc, 0, "[Ap] only a maximum of %d helipads are supported (requested %d)", MAX_HELIPADS, nofhelipads);
00241 assert(nofhelipads <= MAX_HELIPADS);
00242 }
00243
00244
00245
00246
00247 for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) {
00248 if (entry_points[i] >= nofelements) {
00249 DEBUG(misc, 0, "[Ap] entry (%d) must be within the airport (maximum %d)", entry_points[i], nofelements);
00250 assert(entry_points[i] < nofelements);
00251 }
00252 }
00253
00254
00255 layout = AirportBuildAutomata(nofelements, apFA);
00256 DEBUG(misc, 6, "[Ap] #count %3d; #term %2d (%dgrp); #helipad %2d (%dgrp); entries %3d, %3d, %3d, %3d",
00257 nofelements, nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups,
00258 entry_points[DIAGDIR_NE], entry_points[DIAGDIR_SE], entry_points[DIAGDIR_SW], entry_points[DIAGDIR_NW]);
00259
00260
00261
00262
00263 uint ret = AirportTestFTA(nofelements, layout, terminals);
00264 if (ret != MAX_ELEMENTS) DEBUG(misc, 0, "[Ap] problem with element: %d", ret - 1);
00265 assert(ret == MAX_ELEMENTS);
00266
00267 #ifdef DEBUG_AIRPORT
00268 AirportPrintOut(nofelements, layout, DEBUG_AIRPORT);
00269 #endif
00270 }
00271
00272 AirportFTAClass::~AirportFTAClass()
00273 {
00274 for (uint i = 0; i < nofelements; i++) {
00275 AirportFTA *current = layout[i].next;
00276 while (current != NULL) {
00277 AirportFTA *next = current->next;
00278 free(current);
00279 current = next;
00280 };
00281 }
00282 free(layout);
00283 }
00284
00285 bool AirportSpec::IsAvailable() const
00286 {
00287 if (_cur_year < this->min_year) return false;
00288 if (_settings_game.station.never_expire_airports) return true;
00289 return _cur_year <= this->max_year;
00290 }
00291
00295 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
00296 {
00297 uint16 nofelements = 0;
00298 int temp = apFA[0].position;
00299
00300 for (uint i = 0; i < MAX_ELEMENTS; i++) {
00301 if (temp != apFA[i].position) {
00302 nofelements++;
00303 temp = apFA[i].position;
00304 }
00305 if (apFA[i].position == MAX_ELEMENTS) break;
00306 }
00307 return nofelements;
00308 }
00309
00313 static byte AirportGetTerminalCount(const byte *terminals, byte *groups)
00314 {
00315 byte nof_terminals = 0;
00316 *groups = 0;
00317
00318 if (terminals != NULL) {
00319 uint i = terminals[0];
00320 *groups = i;
00321 while (i-- > 0) {
00322 terminals++;
00323 assert(*terminals != 0);
00324 nof_terminals += *terminals;
00325 }
00326 }
00327 return nof_terminals;
00328 }
00329
00330
00331 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA)
00332 {
00333 AirportFTA *FAutomata = MallocT<AirportFTA>(nofelements);
00334 uint16 internalcounter = 0;
00335
00336 for (uint i = 0; i < nofelements; i++) {
00337 AirportFTA *current = &FAutomata[i];
00338 current->position = apFA[internalcounter].position;
00339 current->heading = apFA[internalcounter].heading;
00340 current->block = apFA[internalcounter].block;
00341 current->next_position = apFA[internalcounter].next;
00342
00343
00344 while (current->position == apFA[internalcounter + 1].position) {
00345 AirportFTA *newNode = MallocT<AirportFTA>(1);
00346
00347 newNode->position = apFA[internalcounter + 1].position;
00348 newNode->heading = apFA[internalcounter + 1].heading;
00349 newNode->block = apFA[internalcounter + 1].block;
00350 newNode->next_position = apFA[internalcounter + 1].next;
00351
00352 current->next = newNode;
00353 current = current->next;
00354 internalcounter++;
00355 }
00356 current->next = NULL;
00357 internalcounter++;
00358 }
00359 return FAutomata;
00360 }
00361
00362
00363 static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byte *terminals)
00364 {
00365 uint next_position = 0;
00366
00367 for (uint i = 0; i < nofelements; i++) {
00368 uint position = layout[i].position;
00369 if (position != next_position) return i;
00370 const AirportFTA *first = &layout[i];
00371
00372 for (const AirportFTA *current = first; current != NULL; current = current->next) {
00373
00374
00375
00376 if (current->heading > MAX_HEADINGS) {
00377 if (current->heading != 255) return i;
00378 if (current == first && current->next == NULL) return i;
00379 if (current != first && current->next_position > terminals[0]) return i;
00380 }
00381
00382
00383 if (current->heading == 0 && current->next != NULL) return i;
00384
00385 if (position != current->position) return i;
00386
00387 if (current->next_position >= nofelements) return i;
00388 }
00389 next_position++;
00390 }
00391 return MAX_ELEMENTS;
00392 }
00393
00394 #ifdef DEBUG_AIRPORT
00395 static const char * const _airport_heading_strings[] = {
00396 "TO_ALL",
00397 "HANGAR",
00398 "TERM1",
00399 "TERM2",
00400 "TERM3",
00401 "TERM4",
00402 "TERM5",
00403 "TERM6",
00404 "HELIPAD1",
00405 "HELIPAD2",
00406 "TAKEOFF",
00407 "STARTTAKEOFF",
00408 "ENDTAKEOFF",
00409 "HELITAKEOFF",
00410 "FLYING",
00411 "LANDING",
00412 "ENDLANDING",
00413 "HELILANDING",
00414 "HELIENDLANDING",
00415 "TERM7",
00416 "TERM8",
00417 "HELIPAD3",
00418 "HELIPAD4",
00419 "DUMMY"
00420 };
00421
00422 static void AirportPrintOut(uint nofelements, const AirportFTA *layout, bool full_report)
00423 {
00424 if (!full_report) printf("(P = Current Position; NP = Next Position)\n");
00425
00426 for (uint i = 0; i < nofelements; i++) {
00427 for (const AirportFTA *current = &layout[i]; current != NULL; current = current->next) {
00428 if (full_report) {
00429 byte heading = (current->heading == 255) ? MAX_HEADINGS + 1 : current->heading;
00430 printf("\tPos:%2d NPos:%2d Heading:%15s Block:%2d\n", current->position,
00431 current->next_position, _airport_heading_strings[heading],
00432 FindLastBit(current->block));
00433 } else {
00434 printf("P:%2d NP:%2d", current->position, current->next_position);
00435 }
00436 }
00437 printf("\n");
00438 }
00439 }
00440 #endif
00441
00442 const AirportFTAClass *GetAirport(const byte airport_type)
00443 {
00444
00445
00446 switch (airport_type) {
00447 default: NOT_REACHED();
00448 case AT_SMALL: return _country_airport;
00449 case AT_LARGE: return _city_airport;
00450 case AT_METROPOLITAN: return _metropolitan_airport;
00451 case AT_HELIPORT: return _heliport;
00452 case AT_OILRIG: return _oilrig;
00453 case AT_INTERNATIONAL: return _international_airport;
00454 case AT_COMMUTER: return _commuter_airport;
00455 case AT_HELIDEPOT: return _heli_depot;
00456 case AT_INTERCON: return _intercontinental_airport;
00457 case AT_HELISTATION: return _heli_station;
00458 case AT_DUMMY: return _dummy_airport;
00459 }
00460 }