OpenTTD
airport.cpp
Go to the documentation of this file.
1 /* $Id: airport.cpp 26482 2014-04-23 20:13:33Z rubidium $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #include "stdafx.h"
13 #include "station_base.h"
14 #include "table/strings.h"
15 #include "table/airport_movement.h"
16 #include "table/airporttile_ids.h"
17 
18 #include "safeguards.h"
19 
20 
29 #define AIRPORT_GENERIC(name, terminals, num_helipads, flags, delta_z) \
30  static AirportFTAClass _airportfta_ ## name(_airport_moving_data_ ## name, terminals, \
31  num_helipads, _airport_entries_ ## name, flags, _airport_fta_ ## name, delta_z);
32 
39 #define AIRPORT(name, num_helipads, short_strip) \
40  AIRPORT_GENERIC(name, _airport_terminal_ ## name, num_helipads, AirportFTAClass::ALL | (short_strip ? AirportFTAClass::SHORT_STRIP : (AirportFTAClass::Flags)0), 0)
41 
48 #define HELIPORT(name, num_helipads, delta_z) \
49  AIRPORT_GENERIC(name, NULL, num_helipads, AirportFTAClass::HELICOPTERS, delta_z)
50 
51 AIRPORT(country, 0, true)
52 AIRPORT(city, 0, false)
53 HELIPORT(heliport, 1, 60)
54 AIRPORT(metropolitan, 0, false)
55 AIRPORT(international, 2, false)
56 AIRPORT(commuter, 2, true)
57 HELIPORT(helidepot, 1, 0)
58 AIRPORT(intercontinental, 2, false)
59 HELIPORT(helistation, 3, 0)
60 HELIPORT(oilrig, 1, 54)
61 AIRPORT_GENERIC(dummy, NULL, 0, AirportFTAClass::ALL, 0)
62 
63 #undef HELIPORT
64 #undef AIRPORT
65 #undef AIRPORT_GENERIC
66 
67 #include "table/airport_defaults.h"
68 
69 
70 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA);
71 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA);
72 
73 
82 AirportMovingData RotateAirportMovingData(const AirportMovingData *orig, Direction rotation, uint num_tiles_x, uint num_tiles_y)
83 {
85  amd.flag = orig->flag;
86  amd.direction = ChangeDir(orig->direction, (DirDiff)rotation);
87  switch (rotation) {
88  case DIR_N:
89  amd.x = orig->x;
90  amd.y = orig->y;
91  break;
92 
93  case DIR_E:
94  amd.x = orig->y;
95  amd.y = num_tiles_y * TILE_SIZE - orig->x - 1;
96  break;
97 
98  case DIR_S:
99  amd.x = num_tiles_x * TILE_SIZE - orig->x - 1;
100  amd.y = num_tiles_y * TILE_SIZE - orig->y - 1;
101  break;
102 
103  case DIR_W:
104  amd.x = num_tiles_x * TILE_SIZE - orig->y - 1;
105  amd.y = orig->x;
106  break;
107 
108  default: NOT_REACHED();
109  }
110  return amd;
111 }
112 
113 AirportFTAClass::AirportFTAClass(
114  const AirportMovingData *moving_data_,
115  const byte *terminals_,
116  const byte num_helipads_,
117  const byte *entry_points_,
118  Flags flags_,
119  const AirportFTAbuildup *apFA,
120  byte delta_z_
121 ) :
122  moving_data(moving_data_),
123  terminals(terminals_),
124  num_helipads(num_helipads_),
125  flags(flags_),
126  nofelements(AirportGetNofElements(apFA)),
127  entry_points(entry_points_),
128  delta_z(delta_z_)
129 {
130  /* Build the state machine itself */
131  this->layout = AirportBuildAutomata(this->nofelements, apFA);
132 }
133 
134 AirportFTAClass::~AirportFTAClass()
135 {
136  for (uint i = 0; i < nofelements; i++) {
137  AirportFTA *current = layout[i].next;
138  while (current != NULL) {
139  AirportFTA *next = current->next;
140  free(current);
141  current = next;
142  }
143  }
144  free(layout);
145 }
146 
152 static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
153 {
154  uint16 nofelements = 0;
155  int temp = apFA[0].position;
156 
157  for (uint i = 0; i < MAX_ELEMENTS; i++) {
158  if (temp != apFA[i].position) {
159  nofelements++;
160  temp = apFA[i].position;
161  }
162  if (apFA[i].position == MAX_ELEMENTS) break;
163  }
164  return nofelements;
165 }
166 
173 static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildup *apFA)
174 {
175  AirportFTA *FAutomata = MallocT<AirportFTA>(nofelements);
176  uint16 internalcounter = 0;
177 
178  for (uint i = 0; i < nofelements; i++) {
179  AirportFTA *current = &FAutomata[i];
180  current->position = apFA[internalcounter].position;
181  current->heading = apFA[internalcounter].heading;
182  current->block = apFA[internalcounter].block;
183  current->next_position = apFA[internalcounter].next;
184 
185  /* outgoing nodes from the same position, create linked list */
186  while (current->position == apFA[internalcounter + 1].position) {
187  AirportFTA *newNode = MallocT<AirportFTA>(1);
188 
189  newNode->position = apFA[internalcounter + 1].position;
190  newNode->heading = apFA[internalcounter + 1].heading;
191  newNode->block = apFA[internalcounter + 1].block;
192  newNode->next_position = apFA[internalcounter + 1].next;
193  /* create link */
194  current->next = newNode;
195  current = current->next;
196  internalcounter++;
197  }
198  current->next = NULL;
199  internalcounter++;
200  }
201  return FAutomata;
202 }
203 
209 const AirportFTAClass *GetAirport(const byte airport_type)
210 {
211  if (airport_type == AT_DUMMY) return &_airportfta_dummy;
212  return AirportSpec::Get(airport_type)->fsm;
213 }
214 
221 {
222  const Station *st = Station::GetByTile(hangar_tile);
223  const AirportFTAClass *apc = st->airport.GetFTA();
224  /* When we click on hangar we know the tile it is on. By that we know
225  * its position in the array of depots the airport has.....we can search
226  * layout for #th position of depot. Since layout must start with a listing
227  * of all depots, it is simple */
228  for (uint i = 0;; i++) {
229  if (st->airport.GetHangarTile(i) == hangar_tile) {
230  assert(apc->layout[i].heading == HANGAR);
231  return apc->layout[i].position;
232  }
233  }
234  NOT_REACHED();
235 }