[NewGRF] New Airports

Forum for technical discussions regarding development. If you have a general suggestion, problem or comment, please use one of the other forums.

Moderator: OpenTTD Developers

DaleStan
TTDPatch Developer
TTDPatch Developer
Posts: 10285
Joined: 18 Feb 2004 03:06
Contact:

Post by DaleStan »

richk67 wrote:
DaleStan wrote:Terminal selection is currently utterly insane, and I don't want to post a new format until get it figured it out.
Err... does that mean you dont want to discuss it before... (bit exclusive that!)
Explanations and ideas are both quite welcome; but the current system seems attach terminal selection to both vehicle state and position in the FTA, and then fall back to the default system if no selection instructions appear wherever the plane happens to be when it wants a terminal.
The way I see it, either (1) the fallback needs to be removed and an explicit "FIND_TERMINAL" state needs to be added, or (2) a substantially more through description of states, possible next-states for each, and when, exactly, an airplane selects its terminal, is required.

FIND_TERMINAL, although simple in theory, requires more thought in implementation, since it will break the FTA whenever an aircraft path does not cross a terminal selection instruction.

The state machine, as I understand it, is redundant, but still manages to be fragile and inconsistent:
  1. If there is only one entry for a position, the state machine follows that entry, always (Ignoring heading, even if it has some apparently meaningful value.)
  2. If the first entry for a position has a heading of 255, that just means that multiple options follow, and next is meaningless, even if it has some apparently meaningful value. (But it is not required that such an entry appear for the following entries to be used as options.)
  3. If the first entry of a multiple-entry position has a non-255 heading, it is obeyed as normal. (I think.)
  4. If the second entry has a heading of 255, it is used for terminal selection, as are all immediately following entries with headings of 255, and next instead means "check terminal group", but only if the airplane is in an appropriate state for selecting a terminal.
  5. If an entry (except the second) with a heading of 255 follows an entry with a non-255 heading, it is meaningless.
This must be fixed. To that end:
  1. Entry lists are terminated with a TO_ALL heading; no other device is available for ending a list of entries.
  2. Useful if all options require block-check overrides, so current-block has be moved out of the FTA section and into the MovementData section, and then the position-has-multiple-entries flag was removed.
  3. Defined to be true.
  4. Needs to be fixed, but I have not figured out how. It obviously cannot be detached from the position information (compare airport_movement.h:374 and airport_movement.h:375), but it is absurd to specify terminal selection instructions for every single position, and equally absurd to just guess and check until you figure out where selection instructions are required.
  5. The terminal selection system will be defined to include all terminal-selection directives, even if they are non-adjacent.
richk67 wrote:I dont think Im confused on the OTTD blocks and headings/states.
Well, then, you're confusing me. First you say "I would suggest reserve 00-3F for standard movements, terms at 40-7F, helipads 80-BF, and C0-FF for expansion custom movements." This sounds like the aircraft state, and as such, makes sense, but then you say that this would permit us to store it cleanly in four int64s, which would make sense if you were discussing blocks, but does not make sense when discussing states.
richk67 wrote:I do get a grey mist fogging over when you get into Prop this, and Action that. High level description was invented for a purpose ;)
I feel I'm describing things appropriately (if I didn't, I'd be describing them differently), but it does assume knowledge of how newgrf works.

An action is basically a string (counted, not terminated, FWIW) of bytes. The first byte defines the action: if it's an 00, this is an action 0; an 01, an action 1; an 0F, an action F; a 12, an action 12; &c.
By convention, the leading 0 is stripped when discussing actions (It's "action 3", not "action 03"), but almost nowhere else.

A property is a piece of static data, set in an action 0. eg, an introduction date, a purchase price, a vehicle's default cargo, a set of sprite layouts, an industry layout, a state machine, &c.

A callback works something like a property that can be changed dynamically by the GRF, depending on a large number of variables, but is also a way for a GRF to report whether a player is allowed to do $FOO, or which, if any, of $BAR, $BAZ, and $QUUX automatically happen whenever the player does $FOO.
To get a good answer, ask a Smart Question. Similarly, if you want a bug fixed, write a Useful Bug Report. No TTDPatch crashlog? Then follow directions.
Projects: NFORenum (download) | PlaneSet (Website) | grfcodec (download) | grfdebug.log parser
richk67
Tycoon
Tycoon
Posts: 2363
Joined: 05 Jun 2003 16:21
Location: Up North
Contact:

Post by richk67 »

DaleStan wrote:
richk67 wrote:I dont think Im confused on the OTTD blocks and headings/states.
Well, then, you're confusing me. First you say "I would suggest reserve 00-3F for standard movements, terms at 40-7F, helipads 80-BF, and C0-FF for expansion custom movements." This sounds like the aircraft state, and as such, makes sense, but then you say that this would permit us to store it cleanly in four int64s, which would make sense if you were discussing blocks, but does not make sense when discussing states.
OK I see the confusion now. Currently there is a 1:1 relationship between the TERM state and the TERMn_block flag. I expect that will have to continue in the new schema. So yes, I was discussing states, but since there is (currently) a direct linkage between the state and the block for terminals, I was sort of discussing both. (And several other states/headings have direct correlations in the block map.) If the linkage is going to be broken in the new method, then I can see why you thought I was confused/confusing them.

Even so, my assertion stands. If you have 256 blocks available, then you also require 256 bits to represent them; = 4 x int64. And there should still be a 1:1 relationship of TERM states to term_blocks. (ie. a successfully accepted TERM state/command/heading should reserve the respective term_block to prevent other aircraft from going there.)
DaleStan wrote:
richk67 wrote:I do get a grey mist fogging over when you get into Prop this, and Action that. High level description was invented for a purpose ;)
I feel I'm describing things appropriately (if I didn't, I'd be describing them differently), but it does assume knowledge of how newgrf works.
And therein lies the difficulty. Not having any background in TTDP or newgrf, its a bit of a mystery - one I am not keen to learn (if I want something to learn more about, its how OTTD C code does things). NFO and its input/output formats I will leave to you.

Once you have a defined schema, I will write a windows program (in Visual Basic 6, since its the only windows language I have) to code up the airport without graphics, and then output the file for your end, with spaces in the right places for the graphics. Provides a human-readable airport definition.

If that is not what you had in mind at all, or if there is already a translation tool, then please specify the format you want. (eg. produce a text file formatted in NFO Renum style, with gaps left on bytes 3-6 for the graphics info.)
OTTD NewGRF_ports. Add an airport design via newgrf.Superceded by Yexo's NewGrf Airports 2
Want to organise your trains? Try Routemarkers.
--- ==== --- === --- === ---
Firework Photography
DaleStan
TTDPatch Developer
TTDPatch Developer
Posts: 10285
Joined: 18 Feb 2004 03:06
Contact:

Post by DaleStan »

richk67 wrote:I would suggest reserve 00-3F for standard movements, terms at 40-7F, helipads 80-BF, and C0-FF for expansion custom movements.
OK, I think I understand.
You want the states HANGAR, TAKEOFF, STARTTAKEOFF, ENDTAKEOFF, HELITAKEOFF, FLYING, LANDING, ENDLANDING, HELILANDING, and HELIENDLANDING to retain their current 1, 10d..18d values, the TERMn states to be moved up to 40h..7Fh, the HELIPADn states moved up to 80h..BFh, and C0h..FFh to be reserved for various special values (what types of headings might appear here?), right?

The only issue I see with this is that each state must have a callback function, and the function pointers are stored in _aircraft_state_handlers[] (aircraft_cmd.c:1567..1585)
It should not be hard to just use the same callback[0] for all the 40..BF states, but it seems like a better choice would be to move them to either 00..7F or 80..FF, to reduce the number of checks. In any case, what you currently have as the 00..3F entries will still require a callback table, and keeping one with that many empty slots seems undesirable. But I'm not coding the improved new airport engine, so that's not my business.

If you think that having the TERMn and HELIPADn entries in separate spaces would make things easier, things can be defined to work that way.
However, for reasons of NFO style[1], the in-NFO headings will stay at 00..7F for terminals and helipads, and 80..FF for other headings and special values.

Note that the internal format does not have to exactly match the NFO format. If the internals map one set of numbers to the named constants, and NFO maps a different set to those named constants, the NFO values just have to be run through a 256-entry translation table before being used in Open. This procedure is relatively fast in the first place, and need only be performed upon GRF load, so it will not affect game speed at all.

[0] This is another good way of thinking of NFO callbacks. They're functions that are called whenever the host program (Patch or Open) needs more information, and they return a number in 0..7EFFh (No, that 'E' is not a typo; the range really is 0 to 32511d. Yes, that's a strange range; it's a strange calling convention.) The meaning of the various return values depends on which callback was called.
[1] NFO does, believe it or not, have a style.
richk67 wrote:One feature I really want to see (and is obviously easy with this bitmapped method) is to check and reserve several blocks (can you say "PBS for airports"). I tried to see if I could do it with the current OTTD blocks, but it looks like no.
I did a bit of grepping, but found no place where any two blocks were ORed together, so I assumed that such a feature was not useful, and did not try to implement it. Widening the <check-block> to a 256-bit field is not in the NFO nature; if you need this much power, I think it's time to add a special <next> meaning "call the path-selection callback". I see no reason to widen <block>; each position is in at most one block, (right?) and I don't see any major issue with reserving one value for indicating NOTHING_block. Yes, that does mean that one bit per airport will be wasted. So?
richk67 wrote:Currently there is a 1:1 relationship between the TERM state and the TERMn_block flag. (And several other states/headings have direct correlations in the block map.)
There are others too? Which ones? I didn't spot any, and I may decide to leave the link broken, but mindlessly breaking links is a bad thing.
richk67 wrote:If you have 256 blocks available, then you also require 256 bits to represent them; = 4 x int64. And there should still be a 1:1 relationship of TERM states to term_blocks. (ie. a successfully accepted TERM state/command/heading should reserve the respective term_block to prevent other aircraft from going there.)
Yes and Yes.
This is probably a non-issue, but it may be faster on 32-bit platforms to do use an int32[8] instead of an int64[4]. If/when Open's code switches to C++, this should change to a bitset<255>,[2] since that passes the best way to store, access, set, &c. decisions off to the library writers, who usually manage both better and more robust implementations than us mere application programmers.

[2] 255 since only blocks 00..FE can be reserved. However, AIUI, sizeof(bitset<255>)==sizeof(bitset<256>), except possibly on extraordinarily unusual hardware.
[4] Not A Footnote
[8] Not A Footnote
richk67 wrote:(in Visual Basic 6, since its the only windows language I have)
/me points at http://www.bloodshed.net.
richk67 wrote:with gaps left on bytes 3-6 for the graphics info.
May I ask where you got that idea? The graphics info in the spec is entirely contained in statement "Action 1..3 and property 09 function as for rail stations."
- Action 1 defines one or more sets, each containing one or more real sprites.
- Actions 2 and 3 control which set(s) of sprites is/are used. Action 2 is also used for coding the callback "functions".
- Property 09 encodes all the sprite metadata: which members of the selected sprite set are used, where they are drawn, how they are drawn, &c.

Hm... Minor problem:

Code: Select all

//callback for the TO_ALL pseudo-heading
static void AircraftEventHandler_General(Vehicle *v, const AirportFTAClass *Airport) {
	DEBUG(misc, 0) ("OK, you shouldn't be here, check your Airport Scheme!");
	assert(0);
}
How difficult would it be to fix that by defining that the callbacks are called according to the aircraft state, not according to the <heading> in the FTA info? (NFO style requires a default in all switches and an else in all if cascades, and frowns heavily upon the if(true){...}else{...} construct and all its relatives.)

I'll get the current spec up in a bit, once I clean it up, but I am aware of the following three "issues":
1) It still doesn't define terminal-group selection, but I've asked Darkvater about how that works. Now I need to either (a) wait for an answer, (b) dig around in the source and try to figure it out for myself, or (c) add a callback, and basically ignore the system that Open currently uses.
2) It breaks if an airport larger than 16x16 is defined. This can be extended to 256x256 very simply, but won't unless this is a problem.
3) Setting/checking the reservation for multiple blocks (PBS for airports) is not implemented. If it is necessary, it will be done in a callback.
To get a good answer, ask a Smart Question. Similarly, if you want a bug fixed, write a Useful Bug Report. No TTDPatch crashlog? Then follow directions.
Projects: NFORenum (download) | PlaneSet (Website) | grfcodec (download) | grfdebug.log parser
DaleStan
TTDPatch Developer
TTDPatch Developer
Posts: 10285
Joined: 18 Feb 2004 03:06
Contact:

Post by DaleStan »

DaleStan wrote:How difficult would it be to fix that by defining that the callbacks are called according to the aircraft state, not according to the <heading> in the FTA info?
It turns out that I didn't look closely enough. The state callbacks *are* called based on aircraft state, not FTA heading. Never mind.
DaleStan wrote:1) It still doesn't define terminal-group selection, but I've asked Darkvater about how that works. Now I need to either (a) wait for an answer, (b) dig around in the source and try to figure it out for myself, or (c) add a callback, and basically ignore the system that Open currently uses.
/me went with b.

Bad Idea. Really Bad Idea.
When I start studying source, I'm not often happy until I understand it.
Occasionally I discover that I was happier not understanding it.
This is one of those cases.
I'm not sure whether I should be scared that I understand it, scared that it works, or scared that someone else can produce code as convoluted as mine. (That's a compliment, Darkvater, in case it wasn't clear.)


Format version 2: Additions and changes are marked in bold, removals are marked in red


Prop 16 contains the feature of the vehicles that will use this station, default is 00. (Currently only 00 and 03 are supported)


Prop 17 defines airport movement data and the state machine. It is variable-lengthed and formatted as follows:
<num-pos> <pos-data>...

<num-pos> is a byte.

<pos-data> is variable-length and repeated <num-data> times.
The <pos-data> corresponding to the hangar(s), if any, must be the first entries in the <pos-data> array, and must correspond to the hangar locations given in prop 19.

It consists of:
<X> <Y> <Z> <flags> <direction> <block> (<next-info>)* [FF]

<X> and <Y> are words, interpreted as signed integers. They are the X and Y locations of this postion relative to the north corner of the airport. (A tile is 16 (10h) units in each direction.)

<Z> is a byte, as an unsigned integer, giving the height above the ground for this position. One landscaping level is eight units. Aircraft in flight ignore this setting. The default for heliports is 3C and for oil rigs is 36. This is intended to allow placing a helipad on top of a building while still allowing other things at ground level in the same airport.

<flags> is a word, formatted as follows:
The high nine bits are flags:
07 : Movement for current state (possibly) completed; process and update state.
08
: Do not clamp speed to taxiing limit.
09 : This is an airplane take-off location.
10 : Aircraft must wait several ticks prior to turning in this position.
11 : This is an airplane landing location.
12 : Force aircraft facing.
13 : Play the airplane brake noise when switching to this position.
14 : This is a helicopter take-off location.
15 : This is a helicopter landing location.

(bits 9..15 map to the AMED_* constants.)

If bit 12 is set, the low three bits specify the direction that the aircraft is turned to face upon reaching this position.

If both bits 1 and 3 are set, this is the point where airplanes enter this state machine.
If both bits 6 and 7 are set, this is the point where choppers enter this state machine.

<direction> is a byte, and ignored unless bit 4 of <flags> is set. If that bit is set, the aircraft is turned to face the specified direction.


<block> is a byte, indicating which block this position is a part of. Block FF may have any number of aircraft in it at any one time; all others may have at most one at a time. If <block> is the controlling block for a single terminal or helipad, it must have the same value as the <heading> for going to that terminal/helipad. All other block values may be used in any way you desire.

<next-info> is three bytes, in one of the two following formats:
1)
<heading> <check-block> <next>

<heading> is a byte.
If heading is in 00..3F, it specifies the number of the terminal this aircraft is going to.
If heading is in 40..7F, the low 6 bits specify the number of the helipad this chopper is going to.
(Yes, airports can have up to 64 each terminals and helicopter pads. This should be sufficient for most purposes.)

The following special values are also available:
80: HANGAR -- Aircraft is going to a hangar, or if at a hangar, enters it for servicing. (Next: TAKEOFF, HELITAKEOFF, TERMn, HELIPADn) [0][1]
81: TAKEOFF -- Airplane is headed for the runway for takeoff. (Next: STARTTAKEOFF)
82: STARTTAKEOFF -- Airplane is accellerating down the runway; (Next: ENDTAKEOFF)
83: ENDTAKEOFF -- The airplane is rising into the air. (Next: none; enters state machine of next airport, with state FLYING)[2]
84: HELITAKEOFF -- Like TAKEOFF, but for choppers. (Next: HELIENDTAKEOFF)
N/A: FLYING -- The aircraft is in the air, headed for its next order. (Next: LANDING, HELILANDING) [3]
85: LANDING -- The airplane wants to land. (Next: ENDLANDING)
86: ENDLANDING -- The airplane is rolling down the runway, and will come to a stop at the end. (Next: HANGAR, TERMn) [0]
87: HELILANDING -- Like LANDING, but for choppers. (Next: HELIENDLANDING)
88: HELIENDLANDING -- Like ENDLANDING, but for choppers. (Next: HANGAR, HELIPADn, TERMn if no helipads) [0][1]
89: HELIENDTAKEOFF -- Like ENDTAKEOFF, but for choppers. (Merge with ENDTAKEOFF?)
FF: ELSE -- All headings not previously mentioned (also used to mark the last <next-info> entry)

[0] These states have TERMn nexts, and should have terminal selection instructions if necessary.
[1] These states have HELIPADn nexts, and should have helipad selection instructions if necessary.
[2] These are currently machine exit states. To guard against additional states being added, <next-info> should be be FF FF <cur-pos>, that is "Always return here."
[3] No plane will ever query the state machine in the FLYING state; it will update to LANDING or HELILANDING first, and return to FLYING if it did not find an acceptable landing location.


2) <type> <check-block> <group> (Select terminal/helipad from group)
<type> is a byte, either FE (terminal selection) or FD (helipad selection)

The aircraft needs to know what terminal to go to. If <check-block> is clear, select the first free terminal from <group> (terminals are assigned to groups by prop 1A), and then return to this position with the selected heading. If <check-block> is occupied, or no free terminals exist in <group>, continue to the next terminal selection, or wait in this position if no more selections exist.
These may be specified anywhere in the <next-info> list.


These entries are required for terminal selection on HANGAR and *ENDLANDING positions if this airport has multiple groups, and are ignored otherwise. The *ENDLANDINGs should contain <*ENDLANDING> FF <self-pos> entries to keep the state machine here until it wakes up to the fact that it needs to select a terminal.


Prop 18 functions as prop 0A and 0F, but copies prop 17 instead.


Prop 19 sets the hangar postion(s). It consists of a byte counting the number of hangars, and then that many <X> <Y> pairs (both bytes, as unsigned integers) giving the (X,Y) offset of each hangar from the north corner of the airport.


Props 1A and 1B set the number of terminals and helipads in each terminal/helipad group, respectively:
<num-in-group>* 00
<num-in-group> is a byte, and is repeated until a 00 is encountered.
The sum of all <num-in-group> for each property must not exceed 64.


The <heading>s 00..7F (in prop 17) are assigned by these properties; 00/40 to the first item in the first group, 01/41 to the next item in the first group or the first item in the next group, &c.


Prop 1C is a byte which sets the airport type (small/large/heliport) for the purposes of LA build permissions, crash probablilty, and vehicle variable 44. Oil rig (03) exists internally, but may not be set by .grf files.


Prop 1D sets the types of aircraft that can land here:
00 : airplanes only
01 : all (default)
02 : choppers only


Prop 1E is two bytes; the first being the entry position for airplanes, and the second being the entry position for choppers. Must be set properly for both types, even if one type cannot land here. (This airport could be a replacement for an airport where that type could land.)


Prop 1F sets which tiles are animated:
<num-animated-tiles> (<X> <Y>)...
The tile at each (<X>,<Y>) is redrawn every tick. Callback 14 is also called to determine which sprite arrangement to use for this tile.


Properties 08, 09, 0A, 0B, 10, 12, and 13 function as for rail stations, except that bit 1 of prop 0B must be set.
Properties 0C, 0D 0E, 0F, 11, and 14 are meaningless (and ignored) in the context of airports.

Callback 13 works as for rail stations.
Callback 14 works as for rail stations, but may also return 100h to indicate "Build no tile here."
Callback 3C (no action 0 bit) is called whenever a plane with a set minimum-runway-length wants to switch to a STARTLANDING or TAKEOFF position, and whenever a plane is given orders to this airport (assuming it passes prop 1C).
Variable 10 contains the position that the plane wishes to enter, or FFFFFFFF if an order was added.
The low byte of the return contains the length of this runway (ignored if var 10 is FFFFFFFF), and the high byte contains the length of the longest runway at this airport.
If the plane is in the air and it cannot land, it circles. If the plane is on the ground and it cannot take off, it stops.

Actions 1..3 work as for rail stations.
Action 4 works as for rail stations for C5xx IDs, and possibly for the C4xx IDs.

The third byte of vehicle variable 44 will have at least the following distinct (and airport-independent) values:
- In hangar
- On a pad
- Taxiing
- Taking off
- Landing
- In flight

The high byte of vehicle variable 44 will contain the <Z> value for the current position.


Example: the Country Airport's prop 17 could read as follows:

Code: Select all

17 17 //Prop 17, 17h locations
35 00 03 00 00 83 10 FF // 00 In hangar
   // Terminal and pad selection instructions would appear here, if necessary.
   FF FF 01 // Always go to 01
35 00 1B 00 00 00 00 09 // 01 Taxi to right outside depot
   80 FF 00 // hangar; go to 00
   00 00 02 // Terminal 0; supress check of block 00 and go to 02
   01 FF 04 // Terminal 1; go to 04
   84 FF 13 // HELITAKEOFF; go to 13
   FF FF 06 // ELSE; go to 06
20 00 17 00 00 87 10 00 // 02 Terminal 0
   FF FF 01 // Always go to 01
0A 00 17 00 00 87 10 01 // 03 Terminal 1
   FF FF 05 // Always go to 05
2B 00 25 00 00 00 00 09 // 04 Going towards terminal 2
   01 FF 05 // Terminal 1; go to 05
   80 FF 01 // Hangar; go to 01
   81 FF 06 // Takeoff; go to 06
   FF FF 01 // ELSE (Heli takeoff) go to 01
18 00 25 00 00 00 00 09 // 05 Going towards terminal 2
   01 01 03 // Terminal 1; supress check of block 01 and go to 03
   FF FF 04 // ELSE go to 04
35 00 25 00 00 00 00 09 // 06 Going for takeoff
   FF FF 07
3D 00 28 00 00 81 10 09 // 07 Taxi to start of runway (takeoff)
   FF FF 08
03 00 28 00 00 80 01 FF // 08 Accelerate to end of runway
   FF FF 09
B1 FE 28 00 00 80 03 FF // 09 Take off
   FF FF 09 // ignored; the aircraft has left this state machine
B1 00 28 00 00 80 05 FF // 0A Fly to landing position in air
   85 FF 0B // Landing; go to 0B
   87 FF 14 // heli-landing; go to 14
   FF FF 0F // Else; go to 0F
38 00 28 00 00 80 09 09 // 0B Going down for land
   FF FF 0C
03 00 28 00 00 00 21 09 // 0C Just landed, brake until end of runway
   FF FF 0D
07 00 28 00 00 80 00 09 // 0D Just landed, turn around and taxi 1 square
   // Terminal selection instructions would appear here, if necessary.
   01 FF 05 // Terminal 1
   FF FF 0E
35 00 28 00 00 00 00 09 // 0E Taxi from runway to crossing
   FF FF 01
E1 FE C1 00 00 00 05 FF // 0F Fly around waiting for a landing spot (north-east)
   FF FF 10
01 00 01 00 00 00 05 FF // 10 Fly around waiting for a landing spot (north-west)
   FF FF 11
01 01 01 00 00 00 05 FF // 11 Fly around waiting for a landing spot (south-west)
   FF FF 12
11 01 31 00 00 00 05 FF // 12 Fly around waiting for a landing spot (south)
   FF FF 0A
2C 00 25 00 00 80 40 FF // 13 Helicopter takeoff
   FF FF 16 // This is changed, due to the new HELIENDTAKEOFF state
2C 00 28 00 00 80 05 09 // 14 In position above landing spot helicopter
   FF FF 15
2C 00 28 00 00 80 00 09 // 15 Helicopter landing
   // Terminal or pad selection instructions would appear here, if necessary.
   // Terminal selection instructions would be ignored here if any helipads exist.
   FF FF 01
2C 00 25 00 00 80 05 FF // 16 Heli end takeoff
   FF FF 16 //Ignored; the heli has left the state machine.
To get a good answer, ask a Smart Question. Similarly, if you want a bug fixed, write a Useful Bug Report. No TTDPatch crashlog? Then follow directions.
Projects: NFORenum (download) | PlaneSet (Website) | grfcodec (download) | grfdebug.log parser
richk67
Tycoon
Tycoon
Posts: 2363
Joined: 05 Jun 2003 16:21
Location: Up North
Contact:

Post by richk67 »

Looks good Dalestan, Ive a few comments below. Please seriously consider the benefits of the <block> / <check_block> structure I outline below. I think it would a) make life easier, b) be simple but powerful.
DaleStan wrote: <block> is a byte, indicating which block this position is a part of. Block FF may have any number of aircraft in it at any one time; all others may have at most one at a time. If <block> is the controlling block for a single terminal or helipad, it must have the same value as the <heading> for going to that terminal/helipad. All other block values may be used in any way you desire.
I dont understand why you have moved away from a bit-mapped block structure (as is current). I also cant see how you actually store the reserved block marker for the airport.

This <block> byte would need interpretation to check against the airport's reserved blocks.

I think this is much better - I'll show it as just 4 bits of a larger bitmapping.

Aircraft has block 0100 in its check_block.
Airport_block_status is currently 0011.

To check if aircraft can reserve block: Airport_block_status AND check_block. If answer is 0, can reserve block.

To reserve block: Airport_block_status = Airport_block_status OR check_block.

To release block (if we know it is set): Airport_block_status = Airport_block_status XOR check_block.

My comment about PBS on airports works instantly with this bitmapping method. All the aircraft needs is *more than one block* listed in its check_block. eg. 0101 in the above example. (which of course is blocked because bit 0 is already set in the airport_block_status.)

So you can easily encode "check that this ROUTE is available", and if so, reserve it.

Your current idea seems to make checking against the Airport_block_status considerably less simple. So much so, I cant actually see how this would be achieved. (Unless there is some assumed block_byte to airport_block_status conversion going on.) I cant see how an aircraft can reserve more than one block in your design. (And that ability is really necessary - and is currently used.)

My structure does require a large block bitmap to be stored (most of which will be zeros). It may be better to reduce the maximum number of allowable blocks to say 128, (even then its 16 bytes each time we use it). This would reduce the number of terminals & helipads to release enough space. We *really* dont need 128 terms + helis!

If we wanted to head down to 64 bits, then that will limit the number of terminals and helipads too much. On the other hand, I cant see anyone wanting to create an airport with more than say, 16 helipads - however I can envisage 20 terms fairly easily.

How about 96 bits for blocks: 32 for terminals, 32 for helipads, 32 for "other" blocks. This reduces the block bitmap down to 12 bytes, which is much more manageable.
[0] These states have TERMn nexts, and should have terminal selection instructions if necessary.
[1] These states have HELIPADn nexts, and should have helipad selection instructions if necessary.
This implies that terminal & helipad checking only occurs when the aircraft is in the ENDLANDING state. This is very limiting, and prohibits use of buffer-queues; ie. an aircraft lands, taxis off the runway to a holding area where it waits until its turn to check for a terminal. In several of the current airport designs, this is the action associated with the AIRPORT_ENTRANCE block.
Prop 1C is a byte which sets the airport type (small/large/heliport) for the purposes of LA build permissions, crash probablilty, and vehicle variable 44. Oil rig (03) exists internally, but may not be set by .grf files.
I would definitely add a "medium" size in there as well.
Prop 1D sets the types of aircraft that can land here:
00 : airplanes only
01 : all (default)
02 : choppers only
I think a better structure for this is to just have a set of bits:
Bit 1: large airplanes
Bit 2: small airplanes
Bit 3: helicopters
Bit 4: airships (so we can make special airports for them)
If the plane is in the air and it cannot land, it circles. If the plane is on the ground and it cannot take off, it stops.
This will cause deadlocks if it stops. Always better to default back to the hangar instead.
OTTD NewGRF_ports. Add an airport design via newgrf.Superceded by Yexo's NewGrf Airports 2
Want to organise your trains? Try Routemarkers.
--- ==== --- === --- === ---
Firework Photography
richk67
Tycoon
Tycoon
Posts: 2363
Joined: 05 Jun 2003 16:21
Location: Up North
Contact:

Post by richk67 »

Is there any way to move this thread to the Development forum... it really doesnt fit in Graphics any more!
OTTD NewGRF_ports. Add an airport design via newgrf.Superceded by Yexo's NewGrf Airports 2
Want to organise your trains? Try Routemarkers.
--- ==== --- === --- === ---
Firework Photography
User avatar
prissi
Chief Executive
Chief Executive
Posts: 647
Joined: 15 Nov 2004 19:46
Location: Berlin, Germany
Contact:

Post by prissi »

Just a curious question from somebody completely ignorant: Seeing this hell of coding, I keep asking myself, if it would not easier to devote this effort to allow players to built their own airport. (Like in the SimuTTD-version.)

Then players are offered runways, taxiways, terminal stops, depots, towers and what no else. A lot of existing code could be reused (the one for roads, rails, stations, maybe even heliports). It would allow to design airports of your choice and size freely. This would circumvent also lots of problems with wrong terrain or with the city administration. Just make you airports long and small, and it will fit into a valley. Giving players something to choose usually enhances gameplay a lot.
richk67
Tycoon
Tycoon
Posts: 2363
Joined: 05 Jun 2003 16:21
Location: Up North
Contact:

Post by richk67 »

prissi wrote:Just a curious question from somebody completely ignorant: Seeing this hell of coding, I keep asking myself, if it would not easier to devote this effort to allow players to built their own airport. (Like in the SimuTTD-version.)
Except the nightmare "hell of coding" for custom airports would be infinitely worse than coding for the finite state machine. The biggest two problems on airports are avoiding deadlock situations, and routing aircraft around the airport to an available terminal. Custom airports have no solution for this - and will just generate a million bug reports on the lines of "I built this custom airport, and my aircraft are stuck."
It would allow to design airports of your choice and size freely. This would circumvent also lots of problems with wrong terrain or with the city administration. Just make you airports long and small, and it will fit into a valley. Giving players something to choose usually enhances gameplay a lot.
However, our system will allow players to create properly debugged airports, including ones that are long and thin. (One of my future projects is a long/thin - probably 4x9.)
OTTD NewGRF_ports. Add an airport design via newgrf.Superceded by Yexo's NewGrf Airports 2
Want to organise your trains? Try Routemarkers.
--- ==== --- === --- === ---
Firework Photography
Jango
Traffic Manager
Traffic Manager
Posts: 189
Joined: 28 Aug 2004 12:13

Post by Jango »

Just to join the debate :)

I remember a little while back when I mocked up a "custom" airport in Java just to see whether it would be possible. I had a thread per airplane, no animation, and no graphics apart from a unfancy grid with coloured blocks.

Well, it worked.

In terms of preventing deadlocks: yes, this is difficult and takes a little bit of algorithmical fun to do.

1) Firstly, you need to define what your actual paths are. This should be fairly straightforward. You'd need taxiways to airports and hangers, and tarmac presumably around the terminals.
2) You need to then work out which paths are one-way only. This is relatively easy, just assign taxiways from incoming runways (or the incoming end of a dual purpose runway) as leading into the airport, and taxiways to outgoing runways lead out of the airport.
3) Now for the tricky bit. The way I solved loops in paths was to use path-based routing, where I made planes decide on the optimal path to their next destination (a free terminal, runway or hanger) before moving. The planes would only be assigned paths one at a time, and would require a complete path before moving. Any blocks that are designated as one-way can be travelled in without prior booking, but dual-direction blocks must be "pre-booked" before the plane enters the critical section.

Anyone who's got any experience in concurrent programming will know that the most reliable way of programming this kind of problem is to model first. You use semaphors and monitors to avoid deadlocks in critical sections of code, and the same process can be followed here.

The key thing is not to allow multiple planes heading in different directions into the same critical section. A critical section is defined as any path that can be travelled in any direction.

So, the long and short of it: :)
1) I'm positive it can be done. I tried it with big airports with hundreds of "planes" with dual-purpose and single-purpose runways, with 50 landing terminals.
2) It uses a ton of CPU
3) You need some prior concurrent programming knowledge
4) You need to know OpenTTD like the back of your hand.
5) I don't have time to do it, and I don't know OpenTTD much anyway

Hope that inspires someone :)
User avatar
Korenn
Tycoon
Tycoon
Posts: 1735
Joined: 26 Mar 2004 01:27
Location: Netherlands
Contact:

Post by Korenn »

if you have a model like that you can use simple validation techniques to find deadlock situations... has potential.
User avatar
prissi
Chief Executive
Chief Executive
Posts: 647
Joined: 15 Nov 2004 19:46
Location: Berlin, Germany
Contact:

Post by prissi »

One could leave it to the player as a challenge to make it deadlock free. TGis is the same challenge as for building networks. There players are allowed to make changes. And using one way exits/entries for runways, I think it would not be too hard to make most simple to medium designes deadlock free. I am still not sure if ensuring a deadlock free state machine is much easier than just building and altering designs to make everything deadlock free.

But of course, deadlocks are really a nightmare ...
DaleStan
TTDPatch Developer
TTDPatch Developer
Posts: 10285
Joined: 18 Feb 2004 03:06
Contact:

Post by DaleStan »

richk67 wrote:
DaleStan wrote:<block> is a byte, indicating which block this position is a part of. Block FF may have any number of aircraft in it at any one time; all others may have at most one at a time. If <block> is the controlling block for a single terminal or helipad, it must have the same value as the <heading> for going to that terminal/helipad. All other block values may be used in any way you desire.
I dont understand why you have moved away from a bit-mapped block structure (as is current).
Because, in 95% of cases, you only need to indicate at most one block, and using 32 bytes (or even 12) to encode that which can usually be represented in one byte does not seem appropriate.

Idea: Change <check-block> to a single byte (check that block, or no block if it is FF), except that if the byte is FE, read the check instructions from the following bit-field (width to be determined sometime) instead?

The other option is to have a <check-block> of FE mean "call the block-checking callback", which would could be coded as anything from
(global: bool block[MAX_BLOCKS];// If block[n] == true, that block is reserved.)
return !(block[0]||block[5]||block[2]); //return true (proceed) if blocks 0, 5, and 2 are clear
to
return !((block[0]&&block[1])||(block[2]&&block[3])||block[10]); //return true (proceed) if block 10 is clear, at least one of blocks 0,1 are clear, and at least one of blocks 2,3 are clear.
to far more complex constructs involving un-heated taxiways that cannot be used during the winter months because they iced over, or airports that start small and grow more terminals, (and hence larger state machines) as they age, or ... <insert idea here>

(If FE appeared at multiple positions, a position check would be also be required. A method to report which blocks should be reserved would also be present.)
richk67 wrote:I also cant see how you actually store the reserved block marker for the airport.
int64 block_reservations[4];
byte block;
To reserve block: block_reservations[block/64] |= int64(1) << (block%64);
To check block: if (block_reservations[block/64] | int64(1) << (block%64)) ...
To to unreserve block: block_reservations[block/64] &= ~((int64(1) << (block%64));

Except that creation of the two fields ((int64(1) << (block%64) and ~((int64(1) << (block%64))) and possibly the calculation of block/64 would be done on GRF-load, not in-game, so it would really read:
To reserve a block: block_reservations[block_group] |= setmask;
To check a block: if (block_reservations[block_group] | setmask) ...
To to unreserve a block: block_reservations[block_group] &= clearmask;
richk67 wrote:This <block> byte would need interpretation to check against the airport's reserved blocks.
A *LOT* of NFO needs interpretation before being used by the internals. But it's all one-shot processing done on GRF load.

And I haven't yet seen an airport layout that requires airport-PBS. No point in designing support until it is needed.
richk67 wrote:I cant see how an aircraft can reserve more than one block in your design. (And that ability is really necessary - and is currently used.)
Currently used? ... Oh, right. I wasn't properly clear on this, but there is an implicit "check and, if free, reserve block belonging to next position, unless it the same as the block belonging to the current position" in all FTA instructions (<next-info>). This is the behaviour if <check-block> is NOTHING_block (FF). If <check-block> is the block belonging to the <next>, the behaviour is "check no block". If <check-block> is FOO_block, then both <next> -> <block> and FOO_block are checked and if both are free, both are reserved. This is the way the current machine works, and it seems reasonable enough.
richk67 wrote:I cant see anyone wanting to create an airport with more than say, 16 helipads - however I can envisage 20 terms fairly easily.

How about 96 bits for blocks: 32 for terminals, 32 for helipads, 32 for "other" blocks. This reduces the block bitmap down to 12 bytes, which is much more manageable.
All blocks not assigned to a terminal/helipad are generic blocks. The current international airport uses what? 22 blocks for 8 total pads? If the relationship is linear, then 32 pads (22 terminals and 10 helipads, maybe?) would require a total of 88 blocks, which is painfully close to that rather arbitrary 96 block limit.
richk67 wrote:
[0] These states have TERMn nexts, and should have terminal selection instructions if necessary.
[1] These states have HELIPADn nexts, and should have helipad selection instructions if necessary.
This implies that terminal & helipad checking only occurs when the aircraft is in the ENDLANDING state. This is very limiting, and prohibits use of buffer-queues; ie. an aircraft lands, taxis off the runway to a holding area where it waits until its turn to check for a terminal. In several of the current airport designs, this is the action associated with the AIRPORT_ENTRANCE block.
Yes, pad selection only occurs from the END[HELI]LANDING state, but it does not prohibit buffer queues, and, unless I'm missing something, it's not associated with AIRPORT_ENTRANCE_block, or any other block, for that matter.
I read through the state machine, and I'm pretty sure that the callback for FOO_STATE is only called if the first entry for the current position is {<pos>, FOO_STATE, <block>, <next>}. See the aircraft_cmd.c:1626..1629. The callbacks, which are responsible for such things as calling AirportFindFreeTerminal/AirportFindFreeHelipad, and updating the state, are now called only if bit 7 of <flags> is set. So, you can hold an aircraft in the ENDLANDING state as long as you want, simply by not setting bit 7 in <flags> until you're ready for it to select a pad.

The only potential issue here is if an airplane with eg a TERM1 heading gets misdirected to, eg a hangar, but I don't see how that could happen in a valid state machine.
richk67 wrote:
Prop 1C is a byte which sets the airport type (small/large/heliport) for the purposes of LA build permissions, crash probability, and vehicle variable 44. Oil rig (03) exists internally, but may not be set by .grf files.
I would definitely add a "medium" size in there as well.
What meaning would "medium" have? Aircraft come in three types. Large, which require large airports for safe landings, small, which can safely land on any runway, and choppers, which are ... choppers and entirely ignore the runway setting. Further restrictions should be done with the minimum-runway-length callback, not by adding a whole bunch airport sizes.

Whether failing the minimum-runway length callback should (1) cause the plane to not land or (2) increase the crash chance is open for discussion.
richk67 wrote:
Prop 1D sets the types of aircraft that can land here:
00 : airplanes only
01 : all (default)
02 : choppers only
I think a better structure for this is to just have a set of bits:
Bit 1: large airplanes
Bit 2: small airplanes
Bit 3: helicopters
Bit 4: airships (so we can make special airports for them)
Airships are choppers in every way that matters. Including the fact that they have rotors.
And this would allow the rather illogical arrangement of an airport that permits large airplanes to land, but not small ones. Personally, I don't even like the the concept of an airport where choppers are not allowed to land.
Now that I think about it some more, I am considering just stripping this property entirely, and saying "The user is responsible for not sending airplanes to heliports." The main purpose of this property is for preventing the user from sending an airplane to a heilport. However, you can't prevent the user from building an airport, issuing orders, and then replacing the airport with a heliport, and since that defeats what is basically this property's only function, I guess I don't much see the point in having it.
I put it in because it existed elsewhere, but that's not always a very good reason.

richk67 wrote:
If the plane is in the air and it cannot land, it circles. If the plane is on the ground and it cannot take off, it stops.
This will cause deadlocks if it stops. Always better to default back to the hangar instead.
No, "stop" as in "when a plane wants to leave a terminal it checks for a sufficiently long runway. If no such runway exists, it behaves as if the the start-stop button was pushed." But "stop in hangar" is indeed a better solution.
Jango wrote:I remember a little while back when I mocked up a "custom" airport in Java just to see whether it would be possible. I had a thread per airplane
For reasons I will not go into, planes are processed sequentially, all in a single thread.
Can you recode single-threaded? If so, can you then translate it into C?

If so, I expect that someone here will be probably able to shoehorn it into Open, and I'll put this NFO design away as an interesting exercise that turned out to be unnecessary.
Jango wrote:2) It uses a ton of CPU
That will also have to be fixed. Single threading may actually improve things by removing the mutex overhead.

The current FTA is quite quick, because almost all decisions are made with equality and inequality comparisons; the binary and, or, and xor; and table lookups.
prissi wrote:One could leave it to the player as a challenge to make it deadlock free. TGis is the same challenge as for building networks. There players are allowed to make changes. And using one way exits/entries for runways, I think it would not be too hard to make most simple to medium designes deadlock free.

But of course, deadlocks are really a nightmare ...
With rail systems, deadlocks can be rectified, by
1) reversing a few trains (and possibly reversing/removing some signals too)
2) removing some track and replacing it with one or more depots, or
3) in the absolute worst case, crashing the train(s).

1 and 3 cannot be done with aircraft, and I'm not convinced that 2 is guaranteed to work for airplanes. I'm not even convinced that it's guaranteed to work for trains.
To get a good answer, ask a Smart Question. Similarly, if you want a bug fixed, write a Useful Bug Report. No TTDPatch crashlog? Then follow directions.
Projects: NFORenum (download) | PlaneSet (Website) | grfcodec (download) | grfdebug.log parser
MeusH
Tycoon
Tycoon
Posts: 4349
Joined: 25 Oct 2004 15:39
Location: Mississauga

Post by MeusH »

Let me suggest the airport building style. The whole aircraft behaviour needs to be changed, anyway, so airports can be changed, too.

Airports can be done similiar way to train junctions. Plane just should know where is the landing point, takeoff point, and what to do if all terminals are busy.
Also, the patchfinder should take under account reversing (notice the reversed signal at the end of "runway"?
Attachments
suggestion_of_building_airports_similiar_to_rail_junctions.png
suggestion_of_building_airports_similiar_to_rail_junctions.png (76.43 KiB) Viewed 4967 times
User avatar
Darkvater
Tycoon
Tycoon
Posts: 3053
Joined: 24 Feb 2003 18:45
Location: Hong Kong

Post by Darkvater »

DaleStan wrote:07 : Movement for current state (possibly) completed; process and update state.
I don't get this flag? What does it have to do with the newgrf? What does it even want to do? Currently the aircraft_cmd code decides when the current state is completed and should update.
DaleStan wrote:If <block> is the controlling block for a single terminal or helipad, it must have the same value as the <heading> for going to that terminal/helipad. All other block values may be used in any way you desire.
This means in the case of 128+128 that you can have a maximum of only 128 blocks because the first 128 are used by terminals and helipads. That's why I was thinking that this splitup was not the best. 64+196 would be a better choice imho. Or even (32 + 228).

I could think of 2 (+2) more states form a request by Born_Acorn. TAKEOFF_SMALL, TAKEOFF_LARGE (+ LANDING_SMALL, LANDING_LARGE). Probably not the best names, but this could control takeoff/landing positions of different-sized airplanes. Small airplanes take off sooner and land later for example. In code I can see this somewhat the following: all planes go to STARTTAKEOFF, when there it decides which one to take next (TAKEOFF, TAKEOFF_SMALL, TAKEOFF_LARGE) based on the airplane size (some flag). This way the internal routing is kept the same for all aircraft and not cluttered. Of course probably someone would want dedicated airstrips for small-planes...but that would overly complicate writing an FTA I think. :roll:
DaleStan wrote:86: ENDLANDING -- The airplane is rolling down the runway, and will come to a stop at the end. (Next: HANGAR, TERMn) [0]
Or TAKEOFF if the order has been changed while the plane was landing.

I had some thought about PBS at school today and it is not that easy as I think you (richk67) think. First of all the airport needs to know it has reserved which blocks (ok, easy part). Then you NOT only need a check_block(s) info, but also a reserve_block(s) info that would perhaps in addition to reserving the next_position will also reserve the reserve_block(s). You probably don't want to always reserve the check_block(s) for your airport but perhaps less?

richk67: currently only one block ever is reserved by any airplane to the contrary to what you are saying. The only 'double' reservations are done for terminals, but that is actually a trick. The airplane comes up to the terminal and sees that it is occupied. But because its state (TERM1) is the same as its heading and next position (TERM1_block) the plane knows that it was in fact him that reserved the terminal and ignores the set-block check.

MeusH: that is exactly how airports work now, just with pre-built junctions instead of building it piece by piece. Just as a side-note: your 'junction' does not take into account that your airplane coming from the hangar for a takeoff must check both the diagonal and the small vertical section to the 'runway' to avoid a deadlock.

If anyone has questions for me about something airport-related:
please either post it here, or PM me as I will be gone skiing for the next week :)
TrueLight: "Did you bother to read any of the replies, or you just pressed 'Reply' and started typing?"
<@[R-Dk]FoRbiDDeN> "HELP, this litte arrow thing keeps following my mouse, and I can't make it go away."
User avatar
shampie
Engineer
Engineer
Posts: 120
Joined: 13 Feb 2005 01:13
Location: Eindhoven - Netherlands Ottawa - Canada

Post by shampie »

Suggestion towards building airports outside of town/cities and still get from center of town:
(see image below) The bus station and airport are one station.
P.S this can be done currently but limited, trying to put the airport further away will give you the message that the station is to spread out.

*If you are wondering how to make a station like this try this:
-Place a bus station in the middle of town;
-remove some roads (and if needed some buildings) to make a straight line towards outside of the city;
-Build a trainstation that is long enough to cover the tiles;
-Build an airport on the other side of the trainstation (all stations against echother)
-Destroy the trainstation (the Bus station and Airport should not be deleted)
-build whatever you want on the spot the trainstation used to be.
Voila!

If it would be allowed to build stations futher appart (spread out) a bigger airport would be VERY interesting!

Shampz
Attachments
example.JPG
example.JPG (180.78 KiB) Viewed 4942 times
richk67
Tycoon
Tycoon
Posts: 2363
Joined: 05 Jun 2003 16:21
Location: Up North
Contact:

Post by richk67 »

Darkvater wrote:I had some thought about PBS at school today and it is not that easy as I think you (richk67) think. First of all the airport needs to know it has reserved which blocks (ok, easy part). Then you NOT only need a check_block(s) info, but also a reserve_block(s) info that would perhaps in addition to reserving the next_position will also reserve the reserve_block(s). You probably don't want to always reserve the check_block(s) for your airport but perhaps less?
OK. Consider your picture of the city airport:
Image
(OK its not the block diagram, but I will use it to illustrate how the block reserving can work like PBS).

Aircraft 1 has landed, and Aircraft 2 is on position 3. Aircraft 1 wants a terminal, and selects the route via blocks 15,16,17,7,2. Aircraft 2 wants the hangar, and checks "blocks" 3,6,1,0. As none of these block bits overlap, each aircraft reserves its "path", and can set off in safety around the airport.

To me, this is PBS. Two vehicles entering the signalling block, as long as their paths do not overlap. And very simply done with a bitmapping.
richk67: currently only one block ever is reserved by any airplane to the contrary to what you are saying. The only 'double' reservations are done for terminals, but that is actually a trick. The airplane comes up to the terminal and sees that it is occupied. But because its state (TERM1) is the same as its heading and next position (TERM1_block) the plane knows that it was in fact him that reserved the terminal and ignores the set-block check.
Hmm. I was confused then by your description on the webpage:
"Make sure that when an airplane occupies 2 or more blocks (to avoid any deadlocks), to add that extra block too just before it would enter the state in that block. As noted above, the airplane else would see the block only occupied and not know that it was set by hime some time ago."
To me, that sort of stated that an airplane can occupy 2 or more blocks.

Well, Ive clearly got some brain-ache on this. I will create my intercontinental airport and then have a pause from this. (BTW I have created my terminal-to-state&flag mapping, and it works flawlessly. I was able to add another 4 terminals, and 2 helipads to the state machine table, without breaking existing save games. So my intercontinental is buildable within existing OTTD code. :) )[/img]
OTTD NewGRF_ports. Add an airport design via newgrf.Superceded by Yexo's NewGrf Airports 2
Want to organise your trains? Try Routemarkers.
--- ==== --- === --- === ---
Firework Photography
DaleStan
TTDPatch Developer
TTDPatch Developer
Posts: 10285
Joined: 18 Feb 2004 03:06
Contact:

Post by DaleStan »

Definitions:
The word "callback" shall refer to the numbered NFO callbacks.
The word "handler" shall refer to the AircraftEventHandler_* functions in aircraft_cmd.c.
The word "helipad" shall refer to parts of an airport where only helicopters load and unload.
The word "terminal" shall refer to parts of an airport where airplanes load and unload, and where choppers load and unload in the absence of any helipads.
The word "pad" shall refer to anything that is either a helipad or a terminal.

These definitions apply equally to all related constructs, such as plural forms or all-caps in named constants.
Darkvater wrote:
DaleStan wrote:07 : Movement for current state (possibly) completed; process and update state.
I don't get this flag? What does it have to do with the newgrf? What does it even want to do? Currently the aircraft_cmd code decides when the current state is completed and should update.
My current understanding is that the MoveAirplane knows to decides to call the FOO_STATE handler at pos because the entry {pos, FOO_STATE, block, next} is the first entry for pos. The first entry, however, has been ripped into little tiny bits and shoved all sorts of other places by in the NFO format, and its heading entry no longer exists. However, there still needs to be a way to signal that the test in airport_cmd.c:1627 ("if (current->heading == v->u.air.state)") should succeed, and the state handler should be called.
We can't have AircraftEventHandler_AtTerminal get called while the airplane is on TERM_GROUP_2_ENTER1_block; but that's what's all too likely to happen if there's no way to indicate when the handler should be called.

Maybe that bit was poorly described. Internally, its meaning is "call the state handler for this aircraft's current state."
Darkvater wrote:
DaleStan wrote:If <block> is the controlling block for a single terminal or helipad, it must have the same value as the <heading> for going to that terminal/helipad. All other block values may be used in any way you desire.
This means in the case of 128+128 that you can have a maximum of only 128 blocks because the first 128 are used by terminals and helipads.
No.
The state split is 64 terminal states, 64 helipad states, and 128 special states.
The block split is NUM_TERMINALS terminal blocks, NUM_HELIPADS helipad blocks, and (256 - NUM_PADS) generic blocks. If there are 26 pads then there'll be 230 generic blocks. If there are 56 pads, 200 generic blocks.
If someone actually defines an airport with 64 terminals and 64 helipads, then yes, there will only be 128 generic blocks, but I have to agree with richk67 on this one. I do not see that happening.
Darkvater wrote:I could think of 2 (+2) more states form a request by Born_Acorn. TAKEOFF_SMALL, TAKEOFF_LARGE (+ LANDING_SMALL, LANDING_LARGE). This could control takeoff/landing positions of different-sized airplanes. Small airplanes take off sooner and land later for example. In code I can see this somewhat the following: all planes go to STARTTAKEOFF, when there it decides which one to take next (TAKEOFF, TAKEOFF_SMALL, TAKEOFF_LARGE) based on the airplane size (some flag).
Don't planes go from TAKEOFF to STARTTAKEOFF, not the other way around?
There are only two plane sizes; small and large. I'd still like to have all three states, though, with FOO being a pseudo-state that catches both of FOO_SMALL and FOO_LARGE. Would that be horribly difficult to code?
IMO, _SMALL and _LARGE should be attached to ENDLANDING and STARTTAKEOFF only. In all other cases, either the runway length callback (TAKEOFF/LANDING) or the fact that it was already split (ENDTAKEOFF) should be used to control the where the plane goes instead.

Similarly, I'm not convinced that HELIENDTAKEOFF needs to be distinct from ENDTAKEOFF. Any objections to merging the two?
Darkvater wrote:Of course probably someone would want dedicated airstrips for small-planes...but that would overly complicate writing an FTA I think.
No, not really. Just use the entries ... {pos, TAKEOFF, 0, SHORT_RUNWAY_pos), {pos, TAKEOFF, 0, LONG_RUNWAY_pos}, ... Then a plane attempting to take off will first check SHORT_RUNWAY_pos's block. If that block is clear, callback 3C is called to determine the length of the short runway. If the short runway is long enough, the plane will take that branch. Otherwise, the plane will check to see if LONG_RUNWAY_pos's block is clear and then if the long runway is long enough. If both runways fail, for whatever reason, the plane will simply go on to the next entry.
The same applies to the [HELI]LANDING states.
Not quite dedicated, but close enough, IMO.

I will have to adjust callback 3C slightly for this, though, but that's a relatively simple procedure.
Darkvater wrote:
DaleStan wrote:86: ENDLANDING -- The airplane is rolling down the runway, and will come to a stop at the end. (Next: HANGAR, TERMn)
Or TAKEOFF if the order has been changed while the plane was landing.
Thanks. Noted and updated. I assume the same applies for HELIENDLANDING?
Darkvater wrote:First of all the airport needs to know it has reserved which blocks (ok, easy part). Then you NOT only need a check_block(s) info, but also a reserve_block(s) info that would perhaps in addition to reserving the next_position will also reserve the reserve_block(s). You probably don't want to always reserve the check_block(s) for your airport but perhaps less?
A callback could do this with minimal difficulty, assuming it is spec'ed correctly.

Darkvater:
I asked a question about the current state machine, but either my question or your answer got lost somewhere, probably in one of my plethora of disconnects, crashes, reboots, &c. (Yesterday was NOT a good day for my computer.) I'll try to reproduce it, and add more supporting/clarifying information. (Forums are so much more suited to these long involved questions than IRC.)

Assuming the named constants work as their names imply, and given this adjusted FTA information:

Code: Select all

static const byte _airport_terminal_international[] = {3, 2, 2, 2};
static const byte _airport_helipad_international[] = {2, 1, 1};
static const AirportFTAbuildup _airport_fta_international[] = {
{0, HANGAR, NOTHING_block}/*Entry 0*/, {0, 255, TERM_GROUP_1_block, 0}/*Entry 1*/, {0, 255, TERM_GROUP_2_block, 1}/*Entry 2*/, {0, 255, TERM_GROUP_3_block, 2}/*Entry 3*/, {0, 255, HELIPAD_GROUP_1_block, 0}/*Entry 4*/, {0, 255, HELIPAD_GROUP_2_block, 1}/*Entry 5*/, // Actual motion instructions appear here, but are not relevant to this discussion
// information for additional positions appear here, but are not relevant to this discussion
};
First, is that code correct, to the extent that it is provided? If not, please correct it; I believe the intended behaviour should be readily apparent.
Assuming that code is correct, when an aircraft leaves the hangar, one of AirportFindFreeTerminal or AirportFindFreeHelipad is called, according to the aircraft's type.
First let us consider airplanes. Assuming all three of TERM_GROUP_n_block are reserved, what happens? Does AirportFindFreeTerminal fail (and if so, please enlighten me as to which code controls that; I could not find it), or does AirportFindFreeTerminal go on to entry 4?
Repeating this procedure for AirportFindFreeHelipad: Does it skip entries 1..3, as it should, and begin with entry 4 (same "which code" question), or does it start with entry 1?
To get a good answer, ask a Smart Question. Similarly, if you want a bug fixed, write a Useful Bug Report. No TTDPatch crashlog? Then follow directions.
Projects: NFORenum (download) | PlaneSet (Website) | grfcodec (download) | grfdebug.log parser
MeusH
Tycoon
Tycoon
Posts: 4349
Joined: 25 Oct 2004 15:39
Location: Mississauga

Post by MeusH »

Darkvater wrote:MeusH: that is exactly how airports work now, just with pre-built junctions instead of building it piece by piece. Just as a side-note: your 'junction' does not take into account that your airplane coming from the hangar for a takeoff must check both the diagonal and the small vertical section to the 'runway' to avoid a deadlock.
Yes! Just let players construct airports similiar way they build the junctions. However, as you have noticed, more advanced "signalling" should be included, or even some kind of script (Colobot features scripting game objectes).
Darkvater wrote:I will be gone skiing for the next week :)
Have fun!
DaleStan
TTDPatch Developer
TTDPatch Developer
Posts: 10285
Joined: 18 Feb 2004 03:06
Contact:

Post by DaleStan »

MeusH wrote:However, as you have noticed, more advanced "signalling" should be included, or even some kind of script (Colobot features scripting game objectes).
The same to you as I said to Jango. Design, and preferably, code, a functional building and signalling/scripting system, and I'll be willing to write this whole NFO business off, on the grounds that a better solution exists.
To get a good answer, ask a Smart Question. Similarly, if you want a bug fixed, write a Useful Bug Report. No TTDPatch crashlog? Then follow directions.
Projects: NFORenum (download) | PlaneSet (Website) | grfcodec (download) | grfdebug.log parser
Jango
Traffic Manager
Traffic Manager
Posts: 189
Joined: 28 Aug 2004 12:13

Post by Jango »

I haven't got any time to be modifying any code, and besides going on holiday tonight for a week.

However, I enclose the AirportSimulation for those who might wish to see how the multi-threaded version works. It shouldn't be too much effort to make it single-threaded.

You want to be running the Model/TestAirport class.
Attachments
src.zip
(16.9 KiB) Downloaded 189 times
Post Reply

Return to “OpenTTD Development”

Who is online

Users browsing this forum: No registered users and 32 guests