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