00001
00002
00005 #include "stdafx.h"
00006 #include "debug.h"
00007 #include "airport.h"
00008 #include "airport_movement.h"
00009 #include "core/bitmath_func.hpp"
00010 #include "core/alloc_func.hpp"
00011 #include "date_func.h"
00012 #include "settings_type.h"
00013
00014
00015
00016
00017
00018
00019
00020
00021 static AirportFTAClass *DummyAirport;
00022 static AirportFTAClass *CountryAirport;
00023 static AirportFTAClass *CityAirport;
00024 static AirportFTAClass *Oilrig;
00025 static AirportFTAClass *Heliport;
00026 static AirportFTAClass *MetropolitanAirport;
00027 static AirportFTAClass *InternationalAirport;
00028 static AirportFTAClass *CommuterAirport;
00029 static AirportFTAClass *HeliDepot;
00030 static AirportFTAClass *IntercontinentalAirport;
00031 static AirportFTAClass *HeliStation;
00032
00033
00034 void InitializeAirports()
00035 {
00036 DummyAirport = new AirportFTAClass(
00037 _airport_moving_data_dummy,
00038 NULL,
00039 NULL,
00040 _airport_entries_dummy,
00041 AirportFTAClass::ALL,
00042 _airport_fta_dummy,
00043 NULL,
00044 0,
00045 0, 0, 0,
00046 0,
00047 0
00048 );
00049
00050 CountryAirport = new AirportFTAClass(
00051 _airport_moving_data_country,
00052 _airport_terminal_country,
00053 NULL,
00054 _airport_entries_country,
00055 AirportFTAClass::ALL | AirportFTAClass::SHORT_STRIP,
00056 _airport_fta_country,
00057 _airport_depots_country,
00058 lengthof(_airport_depots_country),
00059 4, 3, 3,
00060 0,
00061 4
00062 );
00063
00064 CityAirport = new AirportFTAClass(
00065 _airport_moving_data_town,
00066 _airport_terminal_city,
00067 NULL,
00068 _airport_entries_city,
00069 AirportFTAClass::ALL,
00070 _airport_fta_city,
00071 _airport_depots_city,
00072 lengthof(_airport_depots_city),
00073 6, 6, 5,
00074 0,
00075 5
00076 );
00077
00078 MetropolitanAirport = new AirportFTAClass(
00079 _airport_moving_data_metropolitan,
00080 _airport_terminal_metropolitan,
00081 NULL,
00082 _airport_entries_metropolitan,
00083 AirportFTAClass::ALL,
00084 _airport_fta_metropolitan,
00085 _airport_depots_metropolitan,
00086 lengthof(_airport_depots_metropolitan),
00087 6, 6, 8,
00088 0,
00089 6
00090 );
00091
00092 InternationalAirport = new AirportFTAClass(
00093 _airport_moving_data_international,
00094 _airport_terminal_international,
00095 _airport_helipad_international,
00096 _airport_entries_international,
00097 AirportFTAClass::ALL,
00098 _airport_fta_international,
00099 _airport_depots_international,
00100 lengthof(_airport_depots_international),
00101 7, 7, 17,
00102 0,
00103 8
00104 );
00105
00106 IntercontinentalAirport = new AirportFTAClass(
00107 _airport_moving_data_intercontinental,
00108 _airport_terminal_intercontinental,
00109 _airport_helipad_intercontinental,
00110 _airport_entries_intercontinental,
00111 AirportFTAClass::ALL,
00112 _airport_fta_intercontinental,
00113 _airport_depots_intercontinental,
00114 lengthof(_airport_depots_intercontinental),
00115 9, 11, 25,
00116 0,
00117 10
00118 );
00119
00120 Heliport = new AirportFTAClass(
00121 _airport_moving_data_heliport,
00122 NULL,
00123 _airport_helipad_heliport_oilrig,
00124 _airport_entries_heliport_oilrig,
00125 AirportFTAClass::HELICOPTERS,
00126 _airport_fta_heliport_oilrig,
00127 NULL,
00128 0,
00129 1, 1, 1,
00130 60,
00131 4
00132 );
00133
00134 Oilrig = new AirportFTAClass(
00135 _airport_moving_data_oilrig,
00136 NULL,
00137 _airport_helipad_heliport_oilrig,
00138 _airport_entries_heliport_oilrig,
00139 AirportFTAClass::HELICOPTERS,
00140 _airport_fta_heliport_oilrig,
00141 NULL,
00142 0,
00143 1, 1, 0,
00144 54,
00145 3
00146 );
00147
00148 CommuterAirport = new AirportFTAClass(
00149 _airport_moving_data_commuter,
00150 _airport_terminal_commuter,
00151 _airport_helipad_commuter,
00152 _airport_entries_commuter,
00153 AirportFTAClass::ALL | AirportFTAClass::SHORT_STRIP,
00154 _airport_fta_commuter,
00155 _airport_depots_commuter,
00156 lengthof(_airport_depots_commuter),
00157 5, 4, 4,
00158 0,
00159 4
00160 );
00161
00162 HeliDepot = new AirportFTAClass(
00163 _airport_moving_data_helidepot,
00164 NULL,
00165 _airport_helipad_helidepot,
00166 _airport_entries_helidepot,
00167 AirportFTAClass::HELICOPTERS,
00168 _airport_fta_helidepot,
00169 _airport_depots_helidepot,
00170 lengthof(_airport_depots_helidepot),
00171 2, 2, 2,
00172 0,
00173 4
00174 );
00175
00176 HeliStation = new AirportFTAClass(
00177 _airport_moving_data_helistation,
00178 NULL,
00179 _airport_helipad_helistation,
00180 _airport_entries_helistation,
00181 AirportFTAClass::HELICOPTERS,
00182 _airport_fta_helistation,
00183 _airport_depots_helistation,
00184 lengthof(_airport_depots_helistation),
00185 4, 2, 3,
00186 0,
00187 4
00188 );
00189 }
00190
00191 void UnInitializeAirports()
00192 {
00193 delete DummyAirport;
00194 delete CountryAirport;
00195 delete CityAirport;
00196 delete Heliport;
00197 delete MetropolitanAirport;
00198 delete InternationalAirport;
00199 delete CommuterAirport;
00200 delete HeliDepot;
00201 delete IntercontinentalAirport;
00202 delete HeliStation;
00203 }
00204
00205
00206 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA);
00207 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA);
00208 static byte AirportGetTerminalCount(const byte *terminals, byte *groups);
00209 static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byte *terminals);
00210
00211 #ifdef DEBUG_AIRPORT
00212 static void AirportPrintOut(uint nofelements, const AirportFTA *layout, bool full_report);
00213 #endif
00214
00215
00216 AirportFTAClass::AirportFTAClass(
00217 const AirportMovingData *moving_data_,
00218 const byte *terminals_,
00219 const byte *helipads_,
00220 const byte *entry_points_,
00221 Flags flags_,
00222 const AirportFTAbuildup *apFA,
00223 const TileIndexDiffC *depots_,
00224 const byte nof_depots_,
00225 uint size_x_,
00226 uint size_y_,
00227 byte noise_level_,
00228 byte delta_z_,
00229 byte catchment_
00230 ) :
00231 moving_data(moving_data_),
00232 terminals(terminals_),
00233 helipads(helipads_),
00234 airport_depots(depots_),
00235 flags(flags_),
00236 nof_depots(nof_depots_),
00237 nofelements(AirportGetNofElements(apFA)),
00238 entry_points(entry_points_),
00239 size_x(size_x_),
00240 size_y(size_y_),
00241 noise_level(noise_level_),
00242 delta_z(delta_z_),
00243 catchment(catchment_)
00244 {
00245 byte nofterminalgroups, nofhelipadgroups;
00246
00247
00248
00249
00250 uint nofterminals = AirportGetTerminalCount(terminals, &nofterminalgroups);
00251 if (nofterminals > MAX_TERMINALS) {
00252 DEBUG(misc, 0, "[Ap] only a maximum of %d terminals are supported (requested %d)", MAX_TERMINALS, nofterminals);
00253 assert(nofterminals <= MAX_TERMINALS);
00254 }
00255
00256 uint nofhelipads = AirportGetTerminalCount(helipads, &nofhelipadgroups);
00257 if (nofhelipads > MAX_HELIPADS) {
00258 DEBUG(misc, 0, "[Ap] only a maximum of %d helipads are supported (requested %d)", MAX_HELIPADS, nofhelipads);
00259 assert(nofhelipads <= MAX_HELIPADS);
00260 }
00261
00262
00263
00264
00265 for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) {
00266 if (entry_points[i] >= nofelements) {
00267 DEBUG(misc, 0, "[Ap] entry (%d) must be within the airport (maximum %d)", entry_points[i], nofelements);
00268 assert(entry_points[i] < nofelements);
00269 }
00270 }
00271
00272
00273 layout = AirportBuildAutomata(nofelements, apFA);
00274 DEBUG(misc, 6, "[Ap] #count %3d; #term %2d (%dgrp); #helipad %2d (%dgrp); entries %3d, %3d, %3d, %3d",
00275 nofelements, nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups,
00276 entry_points[DIAGDIR_NE], entry_points[DIAGDIR_SE], entry_points[DIAGDIR_SW], entry_points[DIAGDIR_NW]);
00277
00278
00279
00280
00281 uint ret = AirportTestFTA(nofelements, layout, terminals);
00282 if (ret != MAX_ELEMENTS) DEBUG(misc, 0, "[Ap] problem with element: %d", ret - 1);
00283 assert(ret == MAX_ELEMENTS);
00284
00285 #ifdef DEBUG_AIRPORT
00286 AirportPrintOut(nofelements, layout, DEBUG_AIRPORT);
00287 #endif
00288 }
00289
00290
00291 AirportFTAClass::~AirportFTAClass()
00292 {
00293 for (uint i = 0; i < nofelements; i++) {
00294 AirportFTA *current = layout[i].next;
00295 while (current != NULL) {
00296 AirportFTA *next = current->next;
00297 free(current);
00298 current = next;
00299 };
00300 }
00301 free(layout);
00302 }
00303
00307 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
00308 {
00309 uint16 nofelements = 0;
00310 int temp = apFA[0].position;
00311
00312 for (uint i = 0; i < MAX_ELEMENTS; i++) {
00313 if (temp != apFA[i].position) {
00314 nofelements++;
00315 temp = apFA[i].position;
00316 }
00317 if (apFA[i].position == MAX_ELEMENTS) break;
00318 }
00319 return nofelements;
00320 }
00321
00325 static byte AirportGetTerminalCount(const byte *terminals, byte *groups)
00326 {
00327 byte nof_terminals = 0;
00328 *groups = 0;
00329
00330 if (terminals != NULL) {
00331 uint i = terminals[0];
00332 *groups = i;
00333 while (i-- > 0) {
00334 terminals++;
00335 assert(*terminals != 0);
00336 nof_terminals += *terminals;
00337 }
00338 }
00339 return nof_terminals;
00340 }
00341
00342
00343 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA)
00344 {
00345 AirportFTA *FAutomata = MallocT<AirportFTA>(nofelements);
00346 uint16 internalcounter = 0;
00347
00348 for (uint i = 0; i < nofelements; i++) {
00349 AirportFTA *current = &FAutomata[i];
00350 current->position = apFA[internalcounter].position;
00351 current->heading = apFA[internalcounter].heading;
00352 current->block = apFA[internalcounter].block;
00353 current->next_position = apFA[internalcounter].next;
00354
00355
00356 while (current->position == apFA[internalcounter + 1].position) {
00357 AirportFTA *newNode = MallocT<AirportFTA>(1);
00358
00359 newNode->position = apFA[internalcounter + 1].position;
00360 newNode->heading = apFA[internalcounter + 1].heading;
00361 newNode->block = apFA[internalcounter + 1].block;
00362 newNode->next_position = apFA[internalcounter + 1].next;
00363
00364 current->next = newNode;
00365 current = current->next;
00366 internalcounter++;
00367 }
00368 current->next = NULL;
00369 internalcounter++;
00370 }
00371 return FAutomata;
00372 }
00373
00374
00375 static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byte *terminals)
00376 {
00377 uint next_position = 0;
00378
00379 for (uint i = 0; i < nofelements; i++) {
00380 uint position = layout[i].position;
00381 if (position != next_position) return i;
00382 const AirportFTA *first = &layout[i];
00383
00384 for (const AirportFTA *current = first; current != NULL; current = current->next) {
00385
00386
00387
00388 if (current->heading > MAX_HEADINGS) {
00389 if (current->heading != 255) return i;
00390 if (current == first && current->next == NULL) return i;
00391 if (current != first && current->next_position > terminals[0]) return i;
00392 }
00393
00394
00395 if (current->heading == 0 && current->next != NULL) return i;
00396
00397 if (position != current->position) return i;
00398
00399 if (current->next_position >= nofelements) return i;
00400 }
00401 next_position++;
00402 }
00403 return MAX_ELEMENTS;
00404 }
00405
00406 #ifdef DEBUG_AIRPORT
00407 static const char * const _airport_heading_strings[] = {
00408 "TO_ALL",
00409 "HANGAR",
00410 "TERM1",
00411 "TERM2",
00412 "TERM3",
00413 "TERM4",
00414 "TERM5",
00415 "TERM6",
00416 "HELIPAD1",
00417 "HELIPAD2",
00418 "TAKEOFF",
00419 "STARTTAKEOFF",
00420 "ENDTAKEOFF",
00421 "HELITAKEOFF",
00422 "FLYING",
00423 "LANDING",
00424 "ENDLANDING",
00425 "HELILANDING",
00426 "HELIENDLANDING",
00427 "TERM7",
00428 "TERM8",
00429 "HELIPAD3",
00430 "HELIPAD4",
00431 "DUMMY"
00432 };
00433
00434 static void AirportPrintOut(uint nofelements, const AirportFTA *layout, bool full_report)
00435 {
00436 if (!full_report) printf("(P = Current Position; NP = Next Position)\n");
00437
00438 for (uint i = 0; i < nofelements; i++) {
00439 for (const AirportFTA *current = &layout[i]; current != NULL; current = current->next) {
00440 if (full_report) {
00441 byte heading = (current->heading == 255) ? MAX_HEADINGS + 1 : current->heading;
00442 printf("\tPos:%2d NPos:%2d Heading:%15s Block:%2d\n", current->position,
00443 current->next_position, _airport_heading_strings[heading],
00444 FindLastBit(current->block));
00445 } else {
00446 printf("P:%2d NP:%2d", current->position, current->next_position);
00447 }
00448 }
00449 printf("\n");
00450 }
00451 }
00452 #endif
00453
00454 const AirportFTAClass *GetAirport(const byte airport_type)
00455 {
00456
00457
00458 switch (airport_type) {
00459 default: NOT_REACHED();
00460 case AT_SMALL: return CountryAirport;
00461 case AT_LARGE: return CityAirport;
00462 case AT_METROPOLITAN: return MetropolitanAirport;
00463 case AT_HELIPORT: return Heliport;
00464 case AT_OILRIG: return Oilrig;
00465 case AT_INTERNATIONAL: return InternationalAirport;
00466 case AT_COMMUTER: return CommuterAirport;
00467 case AT_HELIDEPOT: return HeliDepot;
00468 case AT_INTERCON: return IntercontinentalAirport;
00469 case AT_HELISTATION: return HeliStation;
00470 case AT_DUMMY: return DummyAirport;
00471 }
00472 }
00473
00474
00475 uint32 GetValidAirports()
00476 {
00477 uint32 mask = 0;
00478
00479 if (_cur_year < 1960 || _settings_game.station.always_small_airport) SetBit(mask, 0);
00480 if (_cur_year >= 1955) SetBit(mask, 1);
00481 if (_cur_year >= 1963) SetBit(mask, 2);
00482 if (_cur_year >= 1980) SetBit(mask, 3);
00483 if (_cur_year >= 1990) SetBit(mask, 4);
00484 if (_cur_year >= 1983) SetBit(mask, 5);
00485 if (_cur_year >= 1976) SetBit(mask, 6);
00486 if (_cur_year >= 2002) SetBit(mask, 7);
00487 if (_cur_year >= 1980) SetBit(mask, 8);
00488 return mask;
00489 }