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"
2004-08-09 17:04:08 +00:00
2005-12-14 06:20:23 +00:00
static AirportFTAClass * CountryAirport ;
static AirportFTAClass * CityAirport ;
static AirportFTAClass * Oilrig ;
static AirportFTAClass * Heliport ;
static AirportFTAClass * MetropolitanAirport ;
static AirportFTAClass * InternationalAirport ;
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 ,
2005-01-06 11:39:00 +00:00
const TileIndexDiffC * depots , const byte nof_depots ) ;
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 ) ;
/*static void AirportPrintOut(const AirportFTAClass *Airport, const bool full_report);
static byte AirportBlockToString ( uint32 block ) ; */
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 ,
2005-01-09 08:49:40 +00:00
lengthof ( _airport_depots_country )
) ;
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 ,
2005-01-09 08:49:40 +00:00
lengthof ( _airport_depots_city )
) ;
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 ,
2005-01-09 08:49:40 +00:00
lengthof ( _airport_depots_metropolitan )
) ;
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 ,
2005-01-09 08:49:40 +00:00
lengthof ( _airport_depots_international )
) ;
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 ,
2005-01-09 08:49:40 +00:00
0
) ;
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
}
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 ) ;
}
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 ,
2005-01-06 11:39:00 +00:00
const TileIndexDiffC * depots , const byte nof_depots )
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 ;
const byte * curr ;
int i ;
nofterminals = nofhelipads = 0 ;
2005-01-15 08:58:31 +00:00
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 + + ;
assert ( * curr ! = 0 ) ; //we don't want to have an empty group
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
//AirportPrintOut(Airport, false);
}
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 ) {
AirportFTA * newNode = malloc ( sizeof ( AirportFTA ) ) ;
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 " ,
" DUMMY " // extra heading for 255
} ;
static void AirportPrintOut ( const AirportFTAClass * Airport , const bool full_report )
{
AirportFTA * temp ;
uint16 i ;
byte heading ;
printf ( " (P = Current Position; NP = Next Position) \n " ) ;
for ( i = 0 ; i < Airport - > nofelements ; i + + ) {
temp = & Airport - > layout [ i ] ;
if ( full_report ) {
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 ) {
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 " ) ;
}
}
static byte AirportBlockToString ( uint32 block )
{
byte 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 ;
2005-10-23 13:04:44 +00:00
}
# endif
2004-08-09 17:04:08 +00:00
const AirportFTAClass * GetAirport ( const byte airport_type )
{
AirportFTAClass * Airport = NULL ;
//FIXME -- AircraftNextAirportPos_and_Order -> Needs something nicer, don't like this code
// needs constant change if more airports are added
switch ( airport_type ) {
case AT_SMALL : Airport = CountryAirport ; break ;
case AT_LARGE : Airport = CityAirport ; break ;
case AT_METROPOLITAN : Airport = MetropolitanAirport ; break ;
case AT_HELIPORT : Airport = Heliport ; break ;
case AT_OILRIG : Airport = Oilrig ; break ;
case AT_INTERNATIONAL : Airport = InternationalAirport ; break ;
default :
# ifdef DEBUG__
printf ( " Airport AircraftNextAirportPos_and_Order not yet implemented \n " ) ;
# endif
assert ( airport_type < = AT_INTERNATIONAL ) ;
}
return Airport ;
}
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()
// 1980-1-1 is --> 21915
// 1990-1-1 is --> 25568
2005-11-14 19:48:04 +00:00
if ( _date > = 21915 ) SETBIT ( bytemask , 3 ) ; // metropilitan airport 1980
if ( _date > = 25568 ) SETBIT ( bytemask , 4 ) ; // international airport 1990
2005-07-21 22:15:02 +00:00
return bytemask ;
}