2005-07-24 14:12:37 +00:00
/* $Id$ */
2004-08-09 17:04:08 +00:00
# include "stdafx.h"
2005-06-02 19:30:21 +00:00
# include "openttd.h"
2005-02-05 15:58:59 +00:00
# include "debug.h"
2004-12-15 22:18:54 +00:00
# include "map.h"
2004-08-09 17:04:08 +00:00
# include "airport.h"
2005-07-21 22:15:02 +00:00
# include "macros.h"
# include "variables.h"
2006-05-01 11:27:39 +00:00
# include "airport_movement.h"
2006-08-14 14:21:15 +00:00
# include "date.h"
2004-08-09 17:04:08 +00:00
2006-07-26 03:33:12 +00:00
static AirportFTAClass * CountryAirport ;
static AirportFTAClass * CityAirport ;
static AirportFTAClass * Oilrig ;
static AirportFTAClass * Heliport ;
static AirportFTAClass * MetropolitanAirport ;
static AirportFTAClass * InternationalAirport ;
static AirportFTAClass * CommuterAirport ;
static AirportFTAClass * HeliDepot ;
static AirportFTAClass * IntercontinentalAirport ;
static AirportFTAClass * HeliStation ;
2004-08-09 17:04:08 +00:00
static void AirportFTAClass_Constructor ( AirportFTAClass * Airport ,
2006-06-23 22:05:40 +00:00
const byte * terminals , const byte * helipads ,
const byte entry_point , const byte acc_planes ,
const AirportFTAbuildup * FA ,
const TileIndexDiffC * depots , const byte nof_depots ,
2006-05-20 15:13:27 +00:00
uint size_x , uint size_y
) ;
2004-08-09 17:04:08 +00:00
static void AirportFTAClass_Destructor ( AirportFTAClass * Airport ) ;
static uint16 AirportGetNofElements ( const AirportFTAbuildup * FA ) ;
static void AirportBuildAutomata ( AirportFTAClass * Airport , const AirportFTAbuildup * FA ) ;
static byte AirportTestFTA ( const AirportFTAClass * Airport ) ;
2006-06-27 21:25:53 +00:00
#if 0
static void AirportPrintOut ( const AirportFTAClass * Airport , const bool full_report ) ;
# endif
2004-08-09 17:04:08 +00:00
2005-01-22 20:23:18 +00:00
void InitializeAirports ( void )
2004-08-09 17:04:08 +00:00
{
// country airport
2005-01-09 08:49:40 +00:00
CountryAirport = malloc ( sizeof ( AirportFTAClass ) ) ;
2005-01-15 08:58:31 +00:00
2005-01-09 08:49:40 +00:00
AirportFTAClass_Constructor (
2005-01-15 08:58:31 +00:00
CountryAirport ,
_airport_terminal_country ,
NULL ,
16 ,
ALL ,
_airport_fta_country ,
_airport_depots_country ,
2006-05-20 15:13:27 +00:00
lengthof ( _airport_depots_country ) ,
4 , 3
2005-01-09 08:49:40 +00:00
) ;
2004-08-09 17:04:08 +00:00
// city airport
2005-01-09 08:49:40 +00:00
CityAirport = malloc ( sizeof ( AirportFTAClass ) ) ;
2005-01-15 08:58:31 +00:00
2005-01-09 08:49:40 +00:00
AirportFTAClass_Constructor (
2005-01-15 08:58:31 +00:00
CityAirport ,
_airport_terminal_city ,
NULL ,
19 ,
ALL ,
_airport_fta_city ,
_airport_depots_city ,
2006-05-20 15:13:27 +00:00
lengthof ( _airport_depots_city ) ,
6 , 6
2005-01-09 08:49:40 +00:00
) ;
2004-08-09 17:04:08 +00:00
// metropolitan airport
2005-01-09 08:49:40 +00:00
MetropolitanAirport = malloc ( sizeof ( AirportFTAClass ) ) ;
2005-01-15 08:58:31 +00:00
2005-01-09 08:49:40 +00:00
AirportFTAClass_Constructor (
2005-01-15 08:58:31 +00:00
MetropolitanAirport ,
_airport_terminal_metropolitan ,
NULL ,
20 ,
ALL ,
_airport_fta_metropolitan ,
_airport_depots_metropolitan ,
2006-05-20 15:13:27 +00:00
lengthof ( _airport_depots_metropolitan ) ,
6 , 6
2005-01-09 08:49:40 +00:00
) ;
2004-08-09 17:04:08 +00:00
// international airport
InternationalAirport = ( AirportFTAClass * ) malloc ( sizeof ( AirportFTAClass ) ) ;
2005-01-15 08:58:31 +00:00
2005-01-09 08:49:40 +00:00
AirportFTAClass_Constructor (
2005-01-15 08:58:31 +00:00
InternationalAirport ,
_airport_terminal_international ,
_airport_helipad_international ,
37 ,
ALL ,
_airport_fta_international ,
_airport_depots_international ,
2006-05-20 15:13:27 +00:00
lengthof ( _airport_depots_international ) ,
7 , 7
2005-01-09 08:49:40 +00:00
) ;
2004-08-09 17:04:08 +00:00
2006-06-23 22:05:40 +00:00
// intercontintental airport
IntercontinentalAirport = ( AirportFTAClass * ) malloc ( sizeof ( AirportFTAClass ) ) ;
AirportFTAClass_Constructor (
IntercontinentalAirport ,
_airport_terminal_intercontinental ,
_airport_helipad_intercontinental ,
43 ,
ALL ,
_airport_fta_intercontinental ,
_airport_depots_intercontinental ,
lengthof ( _airport_depots_intercontinental ) ,
9 , 11
) ;
2004-08-09 17:04:08 +00:00
// heliport, oilrig
Heliport = ( AirportFTAClass * ) malloc ( sizeof ( AirportFTAClass ) ) ;
2005-01-15 08:58:31 +00:00
2005-01-09 08:49:40 +00:00
AirportFTAClass_Constructor (
2005-01-15 08:58:31 +00:00
Heliport ,
NULL ,
_airport_helipad_heliport_oilrig ,
7 ,
HELICOPTERS_ONLY ,
_airport_fta_heliport_oilrig ,
NULL ,
2006-05-20 15:13:27 +00:00
0 ,
1 , 1
2005-01-09 08:49:40 +00:00
) ;
2005-01-15 08:58:31 +00:00
2004-08-09 17:04:08 +00:00
Oilrig = Heliport ; // exactly the same structure for heliport/oilrig, so share state machine
2006-06-23 22:05:40 +00:00
// commuter airport
CommuterAirport = malloc ( sizeof ( AirportFTAClass ) ) ;
AirportFTAClass_Constructor (
CommuterAirport ,
_airport_terminal_commuter ,
_airport_helipad_commuter ,
22 ,
ALL ,
_airport_fta_commuter ,
_airport_depots_commuter ,
lengthof ( _airport_depots_commuter ) ,
5 , 4
) ;
// helidepot airport
HeliDepot = malloc ( sizeof ( AirportFTAClass ) ) ;
AirportFTAClass_Constructor (
HeliDepot ,
NULL ,
_airport_helipad_helidepot ,
4 ,
HELICOPTERS_ONLY ,
_airport_fta_helidepot ,
_airport_depots_helidepot ,
lengthof ( _airport_depots_helidepot ) ,
2 , 2
) ;
// helistation airport
HeliStation = malloc ( sizeof ( AirportFTAClass ) ) ;
AirportFTAClass_Constructor (
HeliStation ,
NULL ,
_airport_helipad_helistation ,
25 ,
HELICOPTERS_ONLY ,
_airport_fta_helistation ,
_airport_depots_helistation ,
lengthof ( _airport_depots_helistation ) ,
4 , 2
) ;
2004-08-09 17:04:08 +00:00
}
2005-01-22 20:23:18 +00:00
void UnInitializeAirports ( void )
2004-08-09 17:04:08 +00:00
{
AirportFTAClass_Destructor ( CountryAirport ) ;
AirportFTAClass_Destructor ( CityAirport ) ;
AirportFTAClass_Destructor ( Heliport ) ;
AirportFTAClass_Destructor ( MetropolitanAirport ) ;
AirportFTAClass_Destructor ( InternationalAirport ) ;
2006-06-23 22:05:40 +00:00
AirportFTAClass_Destructor ( CommuterAirport ) ;
AirportFTAClass_Destructor ( HeliDepot ) ;
AirportFTAClass_Destructor ( IntercontinentalAirport ) ;
AirportFTAClass_Destructor ( HeliStation ) ;
2004-08-09 17:04:08 +00:00
}
static void AirportFTAClass_Constructor ( AirportFTAClass * Airport ,
2005-01-09 08:49:40 +00:00
const byte * terminals , const byte * helipads ,
2004-08-09 17:04:08 +00:00
const byte entry_point , const byte acc_planes ,
const AirportFTAbuildup * FA ,
2006-05-20 15:13:27 +00:00
const TileIndexDiffC * depots , const byte nof_depots ,
uint size_x , uint size_y
)
2004-08-09 17:04:08 +00:00
{
2005-01-09 08:49:40 +00:00
byte nofterminals , nofhelipads ;
byte nofterminalgroups = 0 ;
byte nofhelipadgroups = 0 ;
2006-07-26 03:33:12 +00:00
const byte * curr ;
2005-01-09 08:49:40 +00:00
int i ;
nofterminals = nofhelipads = 0 ;
2005-01-15 08:58:31 +00:00
2006-05-20 15:13:27 +00:00
Airport - > size_x = size_x ;
Airport - > size_y = size_y ;
2005-01-09 08:49:40 +00:00
//now we read the number of terminals we have
if ( terminals ! = NULL ) {
i = terminals [ 0 ] ;
nofterminalgroups = i ;
curr = terminals ;
while ( i - - > 0 ) {
curr + + ;
2006-08-28 18:53:03 +00:00
assert ( * curr ! = 0 ) ; //we don't want to have an empty group
2005-01-09 08:49:40 +00:00
nofterminals + = * curr ;
}
2005-01-15 08:58:31 +00:00
2005-01-09 08:49:40 +00:00
}
Airport - > terminals = terminals ;
2005-01-15 08:58:31 +00:00
//read helipads
2005-01-09 08:49:40 +00:00
if ( helipads ! = NULL ) {
i = helipads [ 0 ] ;
nofhelipadgroups = i ;
curr = helipads ;
while ( i - - > 0 ) {
curr + + ;
assert ( * curr ! = 0 ) ; //no empty groups please
nofhelipads + = * curr ;
}
2005-01-15 08:58:31 +00:00
2005-01-09 08:49:40 +00:00
}
Airport - > helipads = helipads ;
2004-08-09 17:04:08 +00:00
// if there are more terminals than 6, internal variables have to be changed, so don't allow that
// same goes for helipads
if ( nofterminals > MAX_TERMINALS ) { printf ( " Currently only maximum of %2d terminals are supported (you wanted %2d) \n " , MAX_TERMINALS , nofterminals ) ; }
if ( nofhelipads > MAX_HELIPADS ) { printf ( " Currently only maximum of %2d helipads are supported (you wanted %2d) \n " , MAX_HELIPADS , nofhelipads ) ; }
// terminals/helipads are divided into groups. Groups are computed by dividing the number
// of terminals by the number of groups. Half in half. If #terminals is uneven, first group
// will get the less # of terminals
assert ( nofterminals < = MAX_TERMINALS ) ;
assert ( nofhelipads < = MAX_HELIPADS ) ;
Airport - > nofelements = AirportGetNofElements ( FA ) ;
// check
if ( entry_point > = Airport - > nofelements ) { printf ( " Entry point (%2d) must be within the airport positions (which is max %2d) \n " , entry_point , Airport - > nofelements ) ; }
assert ( entry_point < Airport - > nofelements ) ;
Airport - > acc_planes = acc_planes ;
Airport - > entry_point = entry_point ;
2004-12-18 12:19:04 +00:00
Airport - > airport_depots = depots ;
Airport - > nof_depots = nof_depots ;
2004-08-09 17:04:08 +00:00
// build the state machine
AirportBuildAutomata ( Airport , FA ) ;
2005-10-23 13:04:44 +00:00
DEBUG ( misc , 1 ) ( " #Elements %2d; #Terminals %2d in %d group(s); #Helipads %2d in %d group(s); Entry Point %d " ,
Airport - > nofelements , nofterminals , nofterminalgroups , nofhelipads , nofhelipadgroups , Airport - > entry_point
) ;
2004-08-09 17:04:08 +00:00
{
2005-10-23 13:04:44 +00:00
byte ret = AirportTestFTA ( Airport ) ;
if ( ret ! = MAX_ELEMENTS ) printf ( " ERROR with element: %d \n " , ret - 1 ) ;
assert ( ret = = MAX_ELEMENTS ) ;
2004-08-09 17:04:08 +00:00
}
// print out full information
// true -- full info including heading, block, etc
// false -- short info, only position and next position
2006-06-27 21:25:53 +00:00
#if 0
AirportPrintOut ( Airport , false ) ;
# endif
2004-08-09 17:04:08 +00:00
}
static void AirportFTAClass_Destructor ( AirportFTAClass * Airport )
{
int i ;
AirportFTA * current , * next ;
for ( i = 0 ; i < Airport - > nofelements ; i + + ) {
current = Airport - > layout [ i ] . next_in_chain ;
while ( current ! = NULL ) {
next = current - > next_in_chain ;
free ( current ) ;
current = next ;
} ;
}
free ( Airport - > layout ) ;
free ( Airport ) ;
}
static uint16 AirportGetNofElements ( const AirportFTAbuildup * FA )
{
int i ;
uint16 nofelements = 0 ;
int temp = FA [ 0 ] . position ;
2005-10-23 13:04:44 +00:00
2004-08-09 17:04:08 +00:00
for ( i = 0 ; i < MAX_ELEMENTS ; i + + ) {
if ( temp ! = FA [ i ] . position ) {
nofelements + + ;
temp = FA [ i ] . position ;
}
2005-10-23 13:04:44 +00:00
if ( FA [ i ] . position = = MAX_ELEMENTS ) break ;
2004-08-09 17:04:08 +00:00
}
return nofelements ;
}
static void AirportBuildAutomata ( AirportFTAClass * Airport , const AirportFTAbuildup * FA )
{
AirportFTA * FAutomata ;
AirportFTA * current ;
uint16 internalcounter , i ;
2005-10-23 13:04:44 +00:00
FAutomata = malloc ( sizeof ( AirportFTA ) * Airport - > nofelements ) ;
2004-08-09 17:04:08 +00:00
Airport - > layout = FAutomata ;
internalcounter = 0 ;
for ( i = 0 ; i < Airport - > nofelements ; i + + ) {
current = & Airport - > layout [ i ] ;
current - > position = FA [ internalcounter ] . position ;
current - > heading = FA [ internalcounter ] . heading ;
current - > block = FA [ internalcounter ] . block ;
current - > next_position = FA [ internalcounter ] . next_in_chain ;
// outgoing nodes from the same position, create linked list
2005-10-23 13:04:44 +00:00
while ( current - > position = = FA [ internalcounter + 1 ] . position ) {
2006-07-26 03:33:12 +00:00
AirportFTA * newNode = malloc ( sizeof ( AirportFTA ) ) ;
2005-10-23 13:04:44 +00:00
newNode - > position = FA [ internalcounter + 1 ] . position ;
newNode - > heading = FA [ internalcounter + 1 ] . heading ;
newNode - > block = FA [ internalcounter + 1 ] . block ;
newNode - > next_position = FA [ internalcounter + 1 ] . next_in_chain ;
2004-08-09 17:04:08 +00:00
// create link
current - > next_in_chain = newNode ;
current = current - > next_in_chain ;
internalcounter + + ;
} // while
current - > next_in_chain = NULL ;
internalcounter + + ;
}
}
static byte AirportTestFTA ( const AirportFTAClass * Airport )
{
byte position , i , next_element ;
AirportFTA * temp ;
next_element = 0 ;
for ( i = 0 ; i < Airport - > nofelements ; i + + ) {
position = Airport - > layout [ i ] . position ;
2005-10-23 13:04:44 +00:00
if ( position ! = next_element ) return i ;
2004-08-09 17:04:08 +00:00
temp = & Airport - > layout [ i ] ;
do {
2005-10-23 13:04:44 +00:00
if ( temp - > heading > MAX_HEADINGS & & temp - > heading ! = 255 ) return i ;
if ( temp - > heading = = 0 & & temp - > next_in_chain ! = 0 ) return i ;
if ( position ! = temp - > position ) return i ;
if ( temp - > next_position > = Airport - > nofelements ) return i ;
2004-08-09 17:04:08 +00:00
temp = temp - > next_in_chain ;
} while ( temp ! = NULL ) ;
next_element + + ;
}
return MAX_ELEMENTS ;
}
2005-10-23 13:04:44 +00:00
#if 0
static const char * const _airport_heading_strings [ ] = {
2004-08-09 17:04:08 +00:00
" TO_ALL " ,
" HANGAR " ,
" TERM1 " ,
" TERM2 " ,
" TERM3 " ,
" TERM4 " ,
" TERM5 " ,
" TERM6 " ,
" HELIPAD1 " ,
" HELIPAD2 " ,
" TAKEOFF " ,
" STARTTAKEOFF " ,
" ENDTAKEOFF " ,
" HELITAKEOFF " ,
" FLYING " ,
" LANDING " ,
" ENDLANDING " ,
" HELILANDING " ,
" HELIENDLANDING " ,
2006-06-23 22:05:40 +00:00
" TERM7 " ,
" TERM8 " ,
" HELIPAD3 " ,
" HELIPAD4 " ,
2006-08-28 18:53:03 +00:00
" DUMMY " // extra heading for 255
2004-08-09 17:04:08 +00:00
} ;
2006-06-27 21:25:53 +00:00
static uint AirportBlockToString ( uint32 block )
{
uint i = 0 ;
if ( block & 0xffff0000 ) { block > > = 16 ; i + = 16 ; }
if ( block & 0x0000ff00 ) { block > > = 8 ; i + = 8 ; }
if ( block & 0x000000f0 ) { block > > = 4 ; i + = 4 ; }
if ( block & 0x0000000c ) { block > > = 2 ; i + = 2 ; }
if ( block & 0x00000002 ) { i + = 1 ; }
return i ;
}
2004-08-09 17:04:08 +00:00
static void AirportPrintOut ( const AirportFTAClass * Airport , const bool full_report )
{
byte heading ;
2006-06-27 21:25:53 +00:00
uint i ;
2004-08-09 17:04:08 +00:00
printf ( " (P = Current Position; NP = Next Position) \n " ) ;
for ( i = 0 ; i < Airport - > nofelements ; i + + ) {
2006-06-27 21:25:53 +00:00
const AirportFTA * temp = & Airport - > layout [ i ] ;
2004-08-09 17:04:08 +00:00
if ( full_report ) {
2006-06-27 21:25:53 +00:00
heading = ( temp - > heading = = 255 ) ? MAX_HEADINGS + 1 : temp - > heading ;
printf ( " Pos:%2d NPos:%2d Heading:%15s Block:%2d \n " ,
temp - > position , temp - > next_position ,
_airport_heading_strings [ heading ] , AirportBlockToString ( temp - > block )
) ;
2005-10-23 13:04:44 +00:00
} else {
printf ( " P:%2d NP:%2d " , temp - > position , temp - > next_position ) ;
2004-08-09 17:04:08 +00:00
}
while ( temp - > next_in_chain ! = NULL ) {
temp = temp - > next_in_chain ;
if ( full_report ) {
2006-06-27 21:25:53 +00:00
heading = ( temp - > heading = = 255 ) ? MAX_HEADINGS + 1 : temp - > heading ;
printf ( " Pos:%2d NPos:%2d Heading:%15s Block:%2d \n " ,
temp - > position , temp - > next_position ,
_airport_heading_strings [ heading ] , AirportBlockToString ( temp - > block )
) ;
2005-10-23 13:04:44 +00:00
} else {
printf ( " P:%2d NP:%2d " , temp - > position , temp - > next_position ) ;
2004-08-09 17:04:08 +00:00
}
}
printf ( " \n " ) ;
}
}
2005-10-23 13:04:44 +00:00
# endif
2004-08-09 17:04:08 +00:00
2006-07-26 03:33:12 +00:00
const AirportFTAClass * GetAirport ( const byte airport_type )
2004-08-09 17:04:08 +00:00
{
//FIXME -- AircraftNextAirportPos_and_Order -> Needs something nicer, don't like this code
// needs constant change if more airports are added
switch ( airport_type ) {
2006-06-27 21:25:53 +00:00
default : NOT_REACHED ( ) ;
case AT_SMALL : return CountryAirport ;
case AT_LARGE : return CityAirport ;
case AT_METROPOLITAN : return MetropolitanAirport ;
case AT_HELIPORT : return Heliport ;
case AT_OILRIG : return Oilrig ;
case AT_INTERNATIONAL : return InternationalAirport ;
case AT_COMMUTER : return CommuterAirport ;
case AT_HELIDEPOT : return HeliDepot ;
case AT_INTERCON : return IntercontinentalAirport ;
case AT_HELISTATION : return HeliStation ;
2004-08-09 17:04:08 +00:00
}
}
2005-07-21 22:15:02 +00:00
2006-05-01 11:27:39 +00:00
const AirportMovingData * GetAirportMovingData ( byte airport_type , byte position )
{
assert ( airport_type < lengthof ( _airport_moving_datas ) ) ;
assert ( position < GetAirport ( airport_type ) - > nofelements ) ;
return & _airport_moving_datas [ airport_type ] [ position ] ;
}
2005-07-21 22:15:02 +00:00
uint32 GetValidAirports ( void )
{
uint32 bytemask = _avail_aircraft ; /// sets the first 3 bytes, 0 - 2, @see AdjustAvailAircraft()
2006-08-16 11:49:52 +00:00
if ( _cur_year > = 1980 ) SETBIT ( bytemask , 3 ) ; // metropilitan airport
if ( _cur_year > = 1990 ) SETBIT ( bytemask , 4 ) ; // international airport
if ( _cur_year > = 1983 ) SETBIT ( bytemask , 5 ) ; // commuter airport
if ( _cur_year > = 1976 ) SETBIT ( bytemask , 6 ) ; // helidepot
if ( _cur_year > = 2002 ) SETBIT ( bytemask , 7 ) ; // intercontinental airport
if ( _cur_year > = 1980 ) SETBIT ( bytemask , 8 ) ; // helistation
2005-07-21 22:15:02 +00:00
return bytemask ;
}