# airport.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "debug.h"
    00014 #include "airport.h"
    00015 #include "airport_movement.h"
    00016 #include "core/alloc_func.hpp"
    00017 #include "date_func.h"
    00018 #include "settings_type.h"
    00019
    00020
    00021 /* 8-66 are mapped to 0-58, 83+ are mapped to 59+ */
    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   /* 32-42 are for turning the radar */
    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   /* 51-53 are for flag animation */
    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, // unused (copy of APT_SMALL_DEPOT_SE)
    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   /* 67-77 are for turning the radar */
    00079   APT_RADAR_FENCE_NE         = 78,
    00080   /* 79-89 are for turning the radar */
    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, // unused
    00093   APT_ROT_RUNWAY_END_FENCE_NE= 102, // unused
    00094   APT_ROT_RUNWAY_FENCE_SW    = 103, // unused
    00095   APT_ROT_RUNWAY_END_FENCE_SW= 104, // unused
    00096   APT_DEPOT_SW               = 105, // unused
    00097   APT_DEPOT_NW               = 106, // unused
    00098   APT_DEPOT_NE               = 107, // unused
    00099   APT_HELIPAD_2_FENCE_SE_SW  = 108, // unused
    00100   APT_HELIPAD_2_FENCE_SE     = 109, // unused
    00101   APT_LOW_BUILDING_FENCE_NW  = 110,
    00102   APT_LOW_BUILDING_FENCE_NE  = 111, // unused
    00103   APT_LOW_BUILDING_FENCE_SW  = 112, // unused
    00104   APT_LOW_BUILDING_FENCE_SE  = 113, // unused
    00105   APT_STAND_FENCE_NE         = 114, // unused
    00106   APT_STAND_FENCE_SE         = 115, // unused
    00107   APT_STAND_FENCE_SW         = 116, // unused
    00108   APT_APRON_FENCE_NE_2       = 117, // unused (copy of APT_APRON_FENCE_NE)
    00109   APT_APRON_FENCE_SE         = 118,
    00110   APT_HELIPAD_2_FENCE_NW_SW  = 119, // unused
    00111   APT_HELIPAD_2_FENCE_SW     = 120, // unused
    00112   APT_RADAR_FENCE_SE         = 121, // unused
    00113   /* 122-132 used for radar rotation */
    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   /* 141-143 used for flag animation */
    00123 };
    00124
    00126 static const byte _airport_sections_country[] = {
    00127   APT_SMALL_BUILDING_1,     APT_SMALL_BUILDING_2,    APT_SMALL_BUILDING_3,    APT_SMALL_DEPOT_SE,
    00128   APT_GRASS_FENCE_NE_FLAG,  APT_GRASS_1,             APT_GRASS_2,             APT_GRASS_FENCE_SW,
    00129   APT_RUNWAY_SMALL_FAR_END, APT_RUNWAY_SMALL_MIDDLE, APT_RUNWAY_SMALL_MIDDLE, APT_RUNWAY_SMALL_NEAR_END
    00130 };
    00131
    00133 static const byte _airport_sections_town[] = {
    00134   APT_BUILDING_1,           APT_APRON_FENCE_NW, APT_STAND_1,              APT_APRON_FENCE_NW,       APT_APRON_FENCE_NW, APT_DEPOT_SE,
    00135   APT_BUILDING_2,           APT_PIER,           APT_ROUND_TERMINAL,       APT_STAND_PIER_NE,        APT_APRON,          APT_APRON_FENCE_SW,
    00136   APT_BUILDING_3,           APT_STAND,          APT_PIER_NW_NE,           APT_APRON_S,              APT_APRON_HOR,      APT_APRON_N_FENCE_SW,
    00137   APT_RADIO_TOWER_FENCE_NE, APT_APRON_W,        APT_APRON_VER_CROSSING_S, APT_APRON_HOR_CROSSING_E, APT_ARPON_N,        APT_TOWER_FENCE_SW,
    00138   APT_EMPTY_FENCE_NE,       APT_APRON_S,        APT_APRON_HOR_CROSSING_W, APT_APRON_VER_CROSSING_N, APT_APRON_E,        APT_RADAR_GRASS_FENCE_SW,
    00139   APT_RUNWAY_END_FENCE_SE,  APT_RUNWAY_1,       APT_RUNWAY_2,             APT_RUNWAY_3,             APT_RUNWAY_4,       APT_RUNWAY_END_FENCE_SE
    00140 };
    00141
    00143 static const byte _airport_sections_metropolitan[] = {
    00144   APT_BUILDING_1,           APT_APRON_FENCE_NW, APT_STAND_1,        APT_APRON_FENCE_NW, APT_APRON_FENCE_NW, APT_DEPOT_SE,
    00145   APT_BUILDING_2,           APT_PIER,           APT_ROUND_TERMINAL, APT_STAND_PIER_NE,  APT_APRON,          APT_APRON_FENCE_SW,
    00146   APT_BUILDING_3,           APT_STAND,          APT_PIER_NW_NE,     APT_APRON_S,        APT_APRON_HOR,      APT_APRON_N_FENCE_SW,
    00147   APT_RADAR_FENCE_NE,       APT_APRON,          APT_APRON,          APT_APRON,          APT_APRON,          APT_TOWER_FENCE_SW,
    00148   APT_RUNWAY_END,           APT_RUNWAY_5,       APT_RUNWAY_5,       APT_RUNWAY_5,       APT_RUNWAY_5,       APT_RUNWAY_END,
    00149   APT_RUNWAY_END_FENCE_SE,  APT_RUNWAY_2,       APT_RUNWAY_2,       APT_RUNWAY_2,       APT_RUNWAY_2,       APT_RUNWAY_END_FENCE_SE
    00150 };
    00151
    00153 static const byte _airport_sections_international[] = {
    00154   APT_RUNWAY_END_FENCE_NW,  APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_END_FENCE_NW,
    00155   APT_RADIO_TOWER_FENCE_NE, APT_APRON,           APT_APRON,           APT_APRON,           APT_APRON,           APT_APRON,           APT_DEPOT_SE,
    00156   APT_BUILDING_3,           APT_APRON,           APT_STAND,           APT_BUILDING_2,      APT_STAND,           APT_APRON,           APT_APRON_FENCE_SW,
    00157   APT_DEPOT_SE,             APT_APRON,           APT_STAND,           APT_BUILDING_2,      APT_STAND,           APT_APRON,           APT_HELIPAD_1,
    00158   APT_APRON_FENCE_NE,       APT_APRON,           APT_STAND,           APT_TOWER,           APT_STAND,           APT_APRON,           APT_HELIPAD_1,
    00159   APT_APRON_FENCE_NE,       APT_APRON,           APT_APRON,           APT_APRON,           APT_APRON,           APT_APRON,           APT_RADAR_FENCE_SW,
    00160   APT_RUNWAY_END_FENCE_SE,  APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_END_FENCE_SE
    00161 };
    00162
    00164 static const byte _airport_sections_intercontinental[] = {
    00165   APT_RADAR_FENCE_NE,         APT_RUNWAY_END_FENCE_NE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW,        APT_RUNWAY_END_FENCE_NW_SW,
    00166   APT_RUNWAY_END_FENCE_NE_NW, APT_RUNWAY_2,               APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_END_FENCE_SE_SW, APT_APRON_FENCE_NE_SW,
    00167   APT_APRON_FENCE_NE,         APT_SMALL_BUILDING_1,       APT_APRON_FENCE_NE,  APT_APRON,           APT_APRON,           APT_APRON,           APT_APRON,           APT_RADIO_TOWER_FENCE_NE,   APT_APRON_FENCE_NE_SW,
    00168   APT_APRON_FENCE_NE,         APT_APRON_HALF_EAST,        APT_APRON_FENCE_NE,  APT_TOWER,           APT_HELIPAD_2,       APT_HELIPAD_2,       APT_APRON,           APT_APRON_FENCE_NW,         APT_APRON_FENCE_SW,
    00169   APT_APRON_FENCE_NE,         APT_APRON,                  APT_APRON,           APT_STAND,           APT_BUILDING_1,      APT_STAND,           APT_APRON,           APT_LOW_BUILDING,           APT_DEPOT_SE,
    00170   APT_DEPOT_SE,               APT_LOW_BUILDING,           APT_APRON,           APT_STAND,           APT_BUILDING_2,      APT_STAND,           APT_APRON,           APT_APRON,                  APT_APRON_FENCE_SW,
    00171   APT_APRON_FENCE_NE,         APT_APRON,                  APT_APRON,           APT_STAND,           APT_BUILDING_3,      APT_STAND,           APT_APRON,           APT_APRON,                  APT_APRON_FENCE_SW,
    00172   APT_APRON_FENCE_NE,         APT_APRON_FENCE_SE,         APT_APRON,           APT_STAND,           APT_ROUND_TERMINAL,  APT_STAND,           APT_APRON_FENCE_SW,  APT_APRON_HALF_WEST,        APT_APRON_FENCE_SW,
    00173   APT_APRON_FENCE_NE,         APT_GRASS_FENCE_NE_FLAG_2,  APT_APRON_FENCE_NE,  APT_APRON,           APT_APRON,           APT_APRON,           APT_APRON_FENCE_SW,  APT_EMPTY,                  APT_APRON_FENCE_NE_SW,
    00174   APT_APRON_FENCE_NE,         APT_RUNWAY_END_FENCE_NE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW, APT_RUNWAY_FENCE_NW,        APT_RUNWAY_END_FENCE_SE_SW,
    00175   APT_RUNWAY_END_FENCE_NE_SE, APT_RUNWAY_2,               APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_2,        APT_RUNWAY_END_FENCE_SE_SW, APT_EMPTY
    00176 };
    00177
    00178
    00180 static const byte _airport_sections_commuter[] = {
    00181   APT_TOWER,               APT_BUILDING_3, APT_HELIPAD_2_FENCE_NW, APT_HELIPAD_2_FENCE_NW, APT_DEPOT_SE,
    00182   APT_APRON_FENCE_NE,      APT_APRON,      APT_APRON,              APT_APRON,              APT_APRON_FENCE_SW,
    00183   APT_APRON_FENCE_NE,      APT_STAND,      APT_STAND,              APT_STAND,              APT_APRON_FENCE_SW,
    00184   APT_RUNWAY_END_FENCE_SE, APT_RUNWAY_2,   APT_RUNWAY_2,           APT_RUNWAY_2,           APT_RUNWAY_END_FENCE_SE
    00185 };
    00186
    00188 static const byte _airport_sections_heliport[] = {
    00189   APT_HELIPORT,
    00190 };
    00191
    00193 static const byte _airport_sections_helidepot[] = {
    00194   APT_LOW_BUILDING_FENCE_N,  APT_DEPOT_SE,
    00195   APT_HELIPAD_2_FENCE_NE_SE, APT_APRON_FENCE_SE_SW
    00196 };
    00197
    00199 static const byte _airport_sections_helistation[] = {
    00200   APT_DEPOT_SE,          APT_LOW_BUILDING_FENCE_NW, APT_HELIPAD_3_FENCE_NW, APT_HELIPAD_3_FENCE_NW_SW,
    00201   APT_APRON_FENCE_NE_SE, APT_APRON_FENCE_SE,        APT_APRON_FENCE_SE,     APT_HELIPAD_3_FENCE_SE_SW
    00202 };
    00203
    00204 const byte * const _airport_sections[] = {
    00205   _airport_sections_country,           // Country Airfield (small)
    00206   _airport_sections_town,              // City Airport (large)
    00207   _airport_sections_heliport,          // Heliport
    00208   _airport_sections_metropolitan,      // Metropolitain Airport (large)
    00209   _airport_sections_international,     // International Airport (xlarge)
    00210   _airport_sections_commuter,          // Commuter Airport (small)
    00211   _airport_sections_helidepot,         // Helidepot
    00212   _airport_sections_intercontinental,  // Intercontinental Airport (xxlarge)
    00213   _airport_sections_helistation,       // Helistation
    00214 };
    00215
    00216 assert_compile(NUM_AIRPORTS == lengthof(_airport_sections));
    00217
    00218 /* Uncomment this to print out a full report of the airport-structure
    00219  * You should either use
    00220  * - true: full-report, print out every state and choice with string-names
    00221  * OR
    00222  * - false: give a summarized report which only shows current and next position */
    00223 //#define DEBUG_AIRPORT false
    00224
    00225 static AirportFTAClass *_dummy_airport;
    00226 static AirportFTAClass *_country_airport;
    00227 static AirportFTAClass *_city_airport;
    00228 static AirportFTAClass *_oilrig;
    00229 static AirportFTAClass *_heliport;
    00230 static AirportFTAClass *_metropolitan_airport;
    00231 static AirportFTAClass *_international_airport;
    00232 static AirportFTAClass *_commuter_airport;
    00233 static AirportFTAClass *_heli_depot;
    00234 static AirportFTAClass *_intercontinental_airport;
    00235 static AirportFTAClass *_heli_station;
    00236
    00237
    00238 void InitializeAirports()
    00239 {
    00240   _dummy_airport = new AirportFTAClass(
    00241     _airport_moving_data_dummy,
    00242     NULL,
    00243     NULL,
    00244     _airport_entries_dummy,
    00245     AirportFTAClass::ALL,
    00246     _airport_fta_dummy,
    00247     NULL,
    00248     0,
    00249     0, 0, 0,
    00250     0,
    00251     0,
    00252     MAX_YEAR + 1, MAX_YEAR + 1
    00253   );
    00254
    00255   _country_airport = new AirportFTAClass(
    00256     _airport_moving_data_country,
    00257     _airport_terminal_country,
    00258     NULL,
    00259     _airport_entries_country,
    00260     AirportFTAClass::ALL | AirportFTAClass::SHORT_STRIP,
    00261     _airport_fta_country,
    00262     _airport_depots_country,
    00263     lengthof(_airport_depots_country),
    00264     4, 3, 3,
    00265     0,
    00266     4,
    00267     0, 1959
    00268   );
    00269
    00270   _city_airport = new AirportFTAClass(
    00271     _airport_moving_data_town,
    00272     _airport_terminal_city,
    00273     NULL,
    00274     _airport_entries_city,
    00275     AirportFTAClass::ALL,
    00276     _airport_fta_city,
    00277     _airport_depots_city,
    00278     lengthof(_airport_depots_city),
    00279     6, 6, 5,
    00280     0,
    00281     5,
    00282     1955, MAX_YEAR
    00283   );
    00284
    00285   _metropolitan_airport = new AirportFTAClass(
    00286     _airport_moving_data_metropolitan,
    00287     _airport_terminal_metropolitan,
    00288     NULL,
    00289     _airport_entries_metropolitan,
    00290     AirportFTAClass::ALL,
    00291     _airport_fta_metropolitan,
    00292     _airport_depots_metropolitan,
    00293     lengthof(_airport_depots_metropolitan),
    00294     6, 6, 8,
    00295     0,
    00296     6,
    00297     1980, MAX_YEAR
    00298   );
    00299
    00300   _international_airport = new AirportFTAClass(
    00301     _airport_moving_data_international,
    00302     _airport_terminal_international,
    00303     _airport_helipad_international,
    00304     _airport_entries_international,
    00305     AirportFTAClass::ALL,
    00306     _airport_fta_international,
    00307     _airport_depots_international,
    00308     lengthof(_airport_depots_international),
    00309     7, 7, 17,
    00310     0,
    00311     8,
    00312     1990, MAX_YEAR
    00313   );
    00314
    00315   _intercontinental_airport = new AirportFTAClass(
    00316     _airport_moving_data_intercontinental,
    00317     _airport_terminal_intercontinental,
    00318     _airport_helipad_intercontinental,
    00319     _airport_entries_intercontinental,
    00320     AirportFTAClass::ALL,
    00321     _airport_fta_intercontinental,
    00322     _airport_depots_intercontinental,
    00323     lengthof(_airport_depots_intercontinental),
    00324     9, 11, 25,
    00325     0,
    00326     10,
    00327     2002, MAX_YEAR
    00328   );
    00329
    00330   _heliport = new AirportFTAClass(
    00331     _airport_moving_data_heliport,
    00332     NULL,
    00333     _airport_helipad_heliport_oilrig,
    00334     _airport_entries_heliport_oilrig,
    00335     AirportFTAClass::HELICOPTERS,
    00336     _airport_fta_heliport_oilrig,
    00337     NULL,
    00338     0,
    00339     1, 1, 1,
    00340     60,
    00341     4,
    00342     1963, MAX_YEAR
    00343   );
    00344
    00345   _oilrig = new AirportFTAClass(
    00346     _airport_moving_data_oilrig,
    00347     NULL,
    00348     _airport_helipad_heliport_oilrig,
    00349     _airport_entries_heliport_oilrig,
    00350     AirportFTAClass::HELICOPTERS,
    00351     _airport_fta_heliport_oilrig,
    00352     NULL,
    00353     0,
    00354     1, 1, 0,
    00355     54,
    00356     3,
    00357     MAX_YEAR + 1, MAX_YEAR + 1
    00358   );
    00359
    00360   _commuter_airport = new AirportFTAClass(
    00361     _airport_moving_data_commuter,
    00362     _airport_terminal_commuter,
    00363     _airport_helipad_commuter,
    00364     _airport_entries_commuter,
    00365     AirportFTAClass::ALL | AirportFTAClass::SHORT_STRIP,
    00366     _airport_fta_commuter,
    00367     _airport_depots_commuter,
    00368     lengthof(_airport_depots_commuter),
    00369     5, 4, 4,
    00370     0,
    00371     4,
    00372     1983, MAX_YEAR
    00373   );
    00374
    00375   _heli_depot = new AirportFTAClass(
    00376     _airport_moving_data_helidepot,
    00377     NULL,
    00378     _airport_helipad_helidepot,
    00379     _airport_entries_helidepot,
    00380     AirportFTAClass::HELICOPTERS,
    00381     _airport_fta_helidepot,
    00382     _airport_depots_helidepot,
    00383     lengthof(_airport_depots_helidepot),
    00384     2, 2, 2,
    00385     0,
    00386     4,
    00387     1976, MAX_YEAR
    00388   );
    00389
    00390   _heli_station = new AirportFTAClass(
    00391     _airport_moving_data_helistation,
    00392     NULL,
    00393     _airport_helipad_helistation,
    00394     _airport_entries_helistation,
    00395     AirportFTAClass::HELICOPTERS,
    00396     _airport_fta_helistation,
    00397     _airport_depots_helistation,
    00398     lengthof(_airport_depots_helistation),
    00399     4, 2, 3,
    00400     0,
    00401     4,
    00402     1980, MAX_YEAR
    00403   );
    00404 }
    00405
    00406 void UnInitializeAirports()
    00407 {
    00408   delete _dummy_airport;
    00409   delete _country_airport;
    00410   delete _city_airport;
    00411   delete _heliport;
    00412   delete _metropolitan_airport;
    00413   delete _international_airport;
    00414   delete _commuter_airport;
    00415   delete _heli_depot;
    00416   delete _intercontinental_airport;
    00417   delete _heli_station;
    00418 }
    00419
    00420
    00421 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA);
    00422 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA);
    00423 static byte AirportGetTerminalCount(const byte *terminals, byte *groups);
    00424 static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byte *terminals);
    00425
    00426 #ifdef DEBUG_AIRPORT
    00427 static void AirportPrintOut(uint nofelements, const AirportFTA *layout, bool full_report);
    00428 #endif
    00429
    00430
    00431 AirportFTAClass::AirportFTAClass(
    00432   const AirportMovingData *moving_data_,
    00433   const byte *terminals_,
    00434   const byte *helipads_,
    00435   const byte *entry_points_,
    00436   Flags flags_,
    00437   const AirportFTAbuildup *apFA,
    00438   const TileIndexDiffC *depots_,
    00439   const byte nof_depots_,
    00440   uint size_x_,
    00441   uint size_y_,
    00442   byte noise_level_,
    00443   byte delta_z_,
    00444   byte catchment_,
    00445   Year first_available_,
    00446   Year last_available_
    00447 ) :
    00448   moving_data(moving_data_),
    00449   terminals(terminals_),
    00450   helipads(helipads_),
    00451   airport_depots(depots_),
    00452   flags(flags_),
    00453   nof_depots(nof_depots_),
    00454   nofelements(AirportGetNofElements(apFA)),
    00455   entry_points(entry_points_),
    00456   size_x(size_x_),
    00457   size_y(size_y_),
    00458   noise_level(noise_level_),
    00459   delta_z(delta_z_),
    00460   catchment(catchment_),
    00461   first_available(first_available_),
    00462   last_available(last_available_)
    00463 {
    00464   byte nofterminalgroups, nofhelipadgroups;
    00465
    00466   /* Set up the terminal and helipad count for an airport.
    00467    * TODO: If there are more than 10 terminals or 4 helipads, internal variables
    00468    * need to be changed, so don't allow that for now */
    00469   uint nofterminals = AirportGetTerminalCount(terminals, &nofterminalgroups);
    00470   if (nofterminals > MAX_TERMINALS) {
    00471     DEBUG(misc, 0, "[Ap] only a maximum of %d terminals are supported (requested %d)", MAX_TERMINALS, nofterminals);
    00472     assert(nofterminals <= MAX_TERMINALS);
    00473   }
    00474
    00475   uint nofhelipads = AirportGetTerminalCount(helipads, &nofhelipadgroups);
    00476   if (nofhelipads > MAX_HELIPADS) {
    00477     DEBUG(misc, 0, "[Ap] only a maximum of %d helipads are supported (requested %d)", MAX_HELIPADS, nofhelipads);
    00478     assert(nofhelipads <= MAX_HELIPADS);
    00479   }
    00480
    00481   /* Get the number of elements from the source table. We also double check this
    00482    * with the entry point which must be within bounds and use this information
    00483    * later on to build and validate the state machine */
    00484   for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) {
    00485     if (entry_points[i] >= nofelements) {
    00486       DEBUG(misc, 0, "[Ap] entry (%d) must be within the airport (maximum %d)", entry_points[i], nofelements);
    00487       assert(entry_points[i] < nofelements);
    00488     }
    00489   }
    00490
    00491   /* Build the state machine itself */
    00492   layout = AirportBuildAutomata(nofelements, apFA);
    00493   DEBUG(misc, 6, "[Ap] #count %3d; #term %2d (%dgrp); #helipad %2d (%dgrp); entries %3d, %3d, %3d, %3d",
    00494     nofelements, nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups,
    00495     entry_points[DIAGDIR_NE], entry_points[DIAGDIR_SE], entry_points[DIAGDIR_SW], entry_points[DIAGDIR_NW]);
    00496
    00497   /* Test if everything went allright. This is only a rude static test checking
    00498    * the symantic correctness. By no means does passing the test mean that the
    00499    * airport is working correctly or will not deadlock for example */
    00500   uint ret = AirportTestFTA(nofelements, layout, terminals);
    00501   if (ret != MAX_ELEMENTS) DEBUG(misc, 0, "[Ap] problem with element: %d", ret - 1);
    00502   assert(ret == MAX_ELEMENTS);
    00503
    00504 #ifdef DEBUG_AIRPORT
    00505   AirportPrintOut(nofelements, layout, DEBUG_AIRPORT);
    00506 #endif
    00507 }
    00508
    00509 AirportFTAClass::~AirportFTAClass()
    00510 {
    00511   for (uint i = 0; i < nofelements; i++) {
    00512     AirportFTA *current = layout[i].next;
    00513     while (current != NULL) {
    00514       AirportFTA *next = current->next;
    00515       free(current);
    00516       current = next;
    00517     };
    00518   }
    00519   free(layout);
    00520 }
    00521
    00522 bool AirportFTAClass::IsAvailable() const
    00523 {
    00524   if (_cur_year < this->first_available) return false;
    00525   if (_settings_game.station.never_expire_airports) return true;
    00526   return _cur_year <= this->last_available;
    00527 }
    00528
    00532 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
    00533 {
    00534   uint16 nofelements = 0;
    00535   int temp = apFA[0].position;
    00536
    00537   for (uint i = 0; i < MAX_ELEMENTS; i++) {
    00538     if (temp != apFA[i].position) {
    00539       nofelements++;
    00540       temp = apFA[i].position;
    00541     }
    00542     if (apFA[i].position == MAX_ELEMENTS) break;
    00543   }
    00544   return nofelements;
    00545 }
    00546
    00550 static byte AirportGetTerminalCount(const byte *terminals, byte *groups)
    00551 {
    00552   byte nof_terminals = 0;
    00553   *groups = 0;
    00554
    00555   if (terminals != NULL) {
    00556     uint i = terminals[0];
    00557     *groups = i;
    00558     while (i-- > 0) {
    00559       terminals++;
    00560       assert(*terminals != 0); // no empty groups please
    00561       nof_terminals += *terminals;
    00562     }
    00563   }
    00564   return nof_terminals;
    00565 }
    00566
    00567
    00568 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA)
    00569 {
    00570   AirportFTA *FAutomata = MallocT<AirportFTA>(nofelements);
    00571   uint16 internalcounter = 0;
    00572
    00573   for (uint i = 0; i < nofelements; i++) {
    00574     AirportFTA *current = &FAutomata[i];
    00575     current->position      = apFA[internalcounter].position;
    00576     current->heading       = apFA[internalcounter].heading;
    00577     current->block         = apFA[internalcounter].block;
    00578     current->next_position = apFA[internalcounter].next;
    00579
    00580     /* outgoing nodes from the same position, create linked list */
    00581     while (current->position == apFA[internalcounter + 1].position) {
    00582       AirportFTA *newNode = MallocT<AirportFTA>(1);
    00583
    00584       newNode->position      = apFA[internalcounter + 1].position;
    00585       newNode->heading       = apFA[internalcounter + 1].heading;
    00586       newNode->block         = apFA[internalcounter + 1].block;
    00587       newNode->next_position = apFA[internalcounter + 1].next;
    00588       /* create link */
    00589       current->next = newNode;
    00590       current = current->next;
    00591       internalcounter++;
    00592     }
    00593     current->next = NULL;
    00594     internalcounter++;
    00595   }
    00596   return FAutomata;
    00597 }
    00598
    00599
    00600 static byte AirportTestFTA(uint nofelements, const AirportFTA *layout, const byte *terminals)
    00601 {
    00602   uint next_position = 0;
    00603
    00604   for (uint i = 0; i < nofelements; i++) {
    00605     uint position = layout[i].position;
    00606     if (position != next_position) return i;
    00607     const AirportFTA *first = &layout[i];
    00608
    00609     for (const AirportFTA *current = first; current != NULL; current = current->next) {
    00610       /* A heading must always be valid. The only exceptions are
    00611        * - multiple choices as start, identified by a special value of 255
    00612        * - terminal group which is identified by a special value of 255 */
    00613       if (current->heading > MAX_HEADINGS) {
    00614         if (current->heading != 255) return i;
    00615         if (current == first && current->next == NULL) return i;
    00616         if (current != first && current->next_position > terminals[0]) return i;
    00617       }
    00618
    00619       /* If there is only one choice, it must be at the end */
    00620       if (current->heading == 0 && current->next != NULL) return i;
    00621       /* Obviously the elements of the linked list must have the same identifier */
    00622       if (position != current->position) return i;
    00623       /* A next position must be within bounds */
    00624       if (current->next_position >= nofelements) return i;
    00625     }
    00626     next_position++;
    00627   }
    00628   return MAX_ELEMENTS;
    00629 }
    00630
    00631 #ifdef DEBUG_AIRPORT
    00632 static const char * const _airport_heading_strings[] = {
    00633   "TO_ALL",
    00634   "HANGAR",
    00635   "TERM1",
    00636   "TERM2",
    00637   "TERM3",
    00638   "TERM4",
    00639   "TERM5",
    00640   "TERM6",
    00641   "HELIPAD1",
    00642   "HELIPAD2",
    00643   "TAKEOFF",
    00644   "STARTTAKEOFF",
    00645   "ENDTAKEOFF",
    00646   "HELITAKEOFF",
    00647   "FLYING",
    00648   "LANDING",
    00649   "ENDLANDING",
    00650   "HELILANDING",
    00651   "HELIENDLANDING",
    00652   "TERM7",
    00653   "TERM8",
    00654   "HELIPAD3",
    00655   "HELIPAD4",
    00656   "DUMMY" // extra heading for 255
    00657 };
    00658
    00659 static void AirportPrintOut(uint nofelements, const AirportFTA *layout, bool full_report)
    00660 {
    00661   if (!full_report) printf("(P = Current Position; NP = Next Position)\n");
    00662
    00663   for (uint i = 0; i < nofelements; i++) {
    00664     for (const AirportFTA *current = &layout[i]; current != NULL; current = current->next) {
    00665       if (full_report) {
    00666         byte heading = (current->heading == 255) ? MAX_HEADINGS + 1 : current->heading;
    00667         printf("\tPos:%2d NPos:%2d Heading:%15s Block:%2d\n", current->position,
    00668               current->next_position, _airport_heading_strings[heading],
    00669               FindLastBit(current->block));
    00670       } else {
    00671         printf("P:%2d NP:%2d", current->position, current->next_position);
    00672       }
    00673     }
    00674     printf("\n");
    00675   }
    00676 }
    00677 #endif
    00678
    00679 const AirportFTAClass *GetAirport(const byte airport_type)
    00680 {
    00681   /* FIXME -- AircraftNextAirportPos_and_Order -> Needs something nicer, don't like this code
    00682    * needs constant change if more airports are added */
    00683   switch (airport_type) {
    00684     default:               NOT_REACHED();
    00685     case AT_SMALL:         return _country_airport;
    00686     case AT_LARGE:         return _city_airport;
    00687     case AT_METROPOLITAN:  return _metropolitan_airport;
    00688     case AT_HELIPORT:      return _heliport;
    00689     case AT_OILRIG:        return _oilrig;
    00690     case AT_INTERNATIONAL: return _international_airport;
    00691     case AT_COMMUTER:      return _commuter_airport;
    00692     case AT_HELIDEPOT:     return _heli_depot;
    00693     case AT_INTERCON:      return _intercontinental_airport;
    00694     case AT_HELISTATION:   return _heli_station;
    00695     case AT_DUMMY:         return _dummy_airport;
    00696   }
    00697 }