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, 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, 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, 5,
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, 8,
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, 17,
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, 25,
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, 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, 0,
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, 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, 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, 3,
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 noise_level_,
00229 byte delta_z_,
00230 byte catchment_
00231 ) :
00232 moving_data(moving_data_),
00233 terminals(terminals_),
00234 helipads(helipads_),
00235 airport_depots(depots_),
00236 flags(flags_),
00237 nof_depots(nof_depots_),
00238 nofelements(AirportGetNofElements(apFA)),
00239 entry_points(entry_points_),
00240 size_x(size_x_),
00241 size_y(size_y_),
00242 noise_level(noise_level_),
00243 delta_z(delta_z_),
00244 catchment(catchment_)
00245 {
00246 byte nofterminalgroups, nofhelipadgroups;
00247
00248
00249
00250
00251 uint nofterminals = AirportGetTerminalCount(terminals, &nofterminalgroups);
00252 if (nofterminals > MAX_TERMINALS) {
00253 DEBUG(misc, 0, "[Ap] only a maximum of %d terminals are supported (requested %d)", MAX_TERMINALS, nofterminals);
00254 assert(nofterminals <= MAX_TERMINALS);
00255 }
00256
00257 uint nofhelipads = AirportGetTerminalCount(helipads, &nofhelipadgroups);
00258 if (nofhelipads > MAX_HELIPADS) {
00259 DEBUG(misc, 0, "[Ap] only a maximum of %d helipads are supported (requested %d)", MAX_HELIPADS, nofhelipads);
00260 assert(nofhelipads <= MAX_HELIPADS);
00261 }
00262
00263
00264
00265
00266 for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) {
00267 if (entry_points[i] >= nofelements) {
00268 DEBUG(misc, 0, "[Ap] entry (%d) must be within the airport (maximum %d)", entry_points[i], nofelements);
00269 assert(entry_points[i] < nofelements);
00270 }
00271 }
00272
00273
00274 layout = AirportBuildAutomata(nofelements, apFA);
00275 DEBUG(misc, 2, "[Ap] #count %3d; #term %2d (%dgrp); #helipad %2d (%dgrp); entries %3d, %3d, %3d, %3d",
00276 nofelements, nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups,
00277 entry_points[DIAGDIR_NE], entry_points[DIAGDIR_SE], entry_points[DIAGDIR_SW], entry_points[DIAGDIR_NW]);
00278
00279
00280
00281
00282 uint ret = AirportTestFTA(nofelements, layout, terminals);
00283 if (ret != MAX_ELEMENTS) DEBUG(misc, 0, "[Ap] problem with element: %d", ret - 1);
00284 assert(ret == MAX_ELEMENTS);
00285
00286 #ifdef DEBUG_AIRPORT
00287 AirportPrintOut(nofelements, layout, DEBUG_AIRPORT);
00288 #endif
00289 }
00290
00291
00292 AirportFTAClass::~AirportFTAClass()
00293 {
00294 for (uint i = 0; i < nofelements; i++) {
00295 AirportFTA *current = layout[i].next;
00296 while (current != NULL) {
00297 AirportFTA *next = current->next;
00298 free(current);
00299 current = next;
00300 };
00301 }
00302 free(layout);
00303 }
00304
00308 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
00309 {
00310 uint16 nofelements = 0;
00311 int temp = apFA[0].position;
00312
00313 for (uint i = 0; i < MAX_ELEMENTS; i++) {
00314 if (temp != apFA[i].position) {
00315 nofelements++;
00316 temp = apFA[i].position;
00317 }
00318 if (apFA[i].position == MAX_ELEMENTS) break;
00319 }
00320 return nofelements;
00321 }
00322
00323
00324
00325
00326 static byte AirportGetTerminalCount(const byte *terminals, byte *groups)
00327 {
00328 byte nof_terminals = 0;
00329 *groups = 0;
00330
00331 if (terminals != NULL) {
00332 uint i = terminals[0];
00333 *groups = i;
00334 while (i-- > 0) {
00335 terminals++;
00336 assert(*terminals != 0);
00337 nof_terminals += *terminals;
00338 }
00339 }
00340 return nof_terminals;
00341 }
00342
00343
00344 static AirportFTA* AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA)
00345 {
00346 AirportFTA *FAutomata = MallocT<AirportFTA>(nofelements);
00347 uint16 internalcounter = 0;
00348
00349 for (uint i = 0; i < nofelements; i++) {
00350 AirportFTA *current = &FAutomata[i];
00351 current->position = apFA[internalcounter].position;
00352 current->heading = apFA[internalcounter].heading;
00353 current->block = apFA[internalcounter].block;
00354 current->next_position = apFA[internalcounter].next;
00355
00356
00357 while (current->position == apFA[internalcounter + 1].position) {
00358 AirportFTA *newNode = MallocT<AirportFTA>(1);
00359
00360 newNode->position = apFA[internalcounter + 1].position;
00361 newNode->heading = apFA[internalcounter + 1].heading;
00362 newNode->block = apFA[internalcounter + 1].block;
00363 newNode->next_position = apFA[internalcounter + 1].next;
00364
00365 current->next = newNode;
00366 current = current->next;
00367 internalcounter++;
00368 }
00369 current->next = NULL;
00370 internalcounter++;
00371 }
00372 return FAutomata;
00373 }
00374
00375
00376 static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byte *terminals)
00377 {
00378 uint next_position = 0;
00379
00380 for (uint i = 0; i < nofelements; i++) {
00381 uint position = layout[i].position;
00382 if (position != next_position) return i;
00383 const AirportFTA *first = &layout[i];
00384
00385 for (const AirportFTA *current = first; current != NULL; current = current->next) {
00386
00387
00388
00389 if (current->heading > MAX_HEADINGS) {
00390 if (current->heading != 255) return i;
00391 if (current == first && current->next == NULL) return i;
00392 if (current != first && current->next_position > terminals[0]) return i;
00393 }
00394
00395
00396 if (current->heading == 0 && current->next != NULL) return i;
00397
00398 if (position != current->position) return i;
00399
00400 if (current->next_position >= nofelements) return i;
00401 }
00402 next_position++;
00403 }
00404 return MAX_ELEMENTS;
00405 }
00406
00407 #ifdef DEBUG_AIRPORT
00408 static const char* const _airport_heading_strings[] = {
00409 "TO_ALL",
00410 "HANGAR",
00411 "TERM1",
00412 "TERM2",
00413 "TERM3",
00414 "TERM4",
00415 "TERM5",
00416 "TERM6",
00417 "HELIPAD1",
00418 "HELIPAD2",
00419 "TAKEOFF",
00420 "STARTTAKEOFF",
00421 "ENDTAKEOFF",
00422 "HELITAKEOFF",
00423 "FLYING",
00424 "LANDING",
00425 "ENDLANDING",
00426 "HELILANDING",
00427 "HELIENDLANDING",
00428 "TERM7",
00429 "TERM8",
00430 "HELIPAD3",
00431 "HELIPAD4",
00432 "DUMMY"
00433 };
00434
00435 static void AirportPrintOut(uint nofelements, const AirportFTA *layout, bool full_report)
00436 {
00437 if (!full_report) printf("(P = Current Position; NP = Next Position)\n");
00438
00439 for (uint i = 0; i < nofelements; i++) {
00440 for (const AirportFTA *current = &layout[i]; current != NULL; current = current->next) {
00441 if (full_report) {
00442 byte heading = (current->heading == 255) ? MAX_HEADINGS + 1 : current->heading;
00443 printf("\tPos:%2d NPos:%2d Heading:%15s Block:%2d\n", current->position,
00444 current->next_position, _airport_heading_strings[heading],
00445 FindLastBit(current->block));
00446 } else {
00447 printf("P:%2d NP:%2d", current->position, current->next_position);
00448 }
00449 }
00450 printf("\n");
00451 }
00452 }
00453 #endif
00454
00455 const AirportFTAClass *GetAirport(const byte airport_type)
00456 {
00457
00458
00459 switch (airport_type) {
00460 default: NOT_REACHED();
00461 case AT_SMALL: return CountryAirport;
00462 case AT_LARGE: return CityAirport;
00463 case AT_METROPOLITAN: return MetropolitanAirport;
00464 case AT_HELIPORT: return Heliport;
00465 case AT_OILRIG: return Oilrig;
00466 case AT_INTERNATIONAL: return InternationalAirport;
00467 case AT_COMMUTER: return CommuterAirport;
00468 case AT_HELIDEPOT: return HeliDepot;
00469 case AT_INTERCON: return IntercontinentalAirport;
00470 case AT_HELISTATION: return HeliStation;
00471 case AT_DUMMY: return DummyAirport;
00472 }
00473 }
00474
00475
00476 uint32 GetValidAirports()
00477 {
00478 uint32 mask = 0;
00479
00480 if (_cur_year < 1960 || _settings_game.station.always_small_airport) SetBit(mask, 0);
00481 if (_cur_year >= 1955) SetBit(mask, 1);
00482 if (_cur_year >= 1963) SetBit(mask, 2);
00483 if (_cur_year >= 1980) SetBit(mask, 3);
00484 if (_cur_year >= 1990) SetBit(mask, 4);
00485 if (_cur_year >= 1983) SetBit(mask, 5);
00486 if (_cur_year >= 1976) SetBit(mask, 6);
00487 if (_cur_year >= 2002) SetBit(mask, 7);
00488 if (_cur_year >= 1980) SetBit(mask, 8);
00489 return mask;
00490 }