Some thoughts and some design

When I wrote this about a month ago (august 2004) I expected Vurlix to be done with his new map array. After that a multilevel addition could be made to the map array. Since then, nothing has changed to the map array and we will probably do both changes at the same time, along with some more redesigning. I originally wrote this on paper and I haven't come to putting it online until now. Some of the stuff here is probably deprecated already and this text would probably need some adaptation. It also does not explicitely consider underground building, signals on bridges etc. I have thought of these when writing this, just didn't write that down :-) Still, I will put it here unchanged and will edit it later.

If you have any comments about this text, please tell me. You'll always find me on #openttd, so just drop by. You can also just put your comments at the bottom of this page.

Matthijs (blathijs)


Before really thinking about how to implement new stuff, I will just list a few things that should be supported.



For lack of a better name, I will call these supports. A supports is basically a highway style elevation on which tracks can be built. It is supported on pillars, the type and/or position of every pillar might be different for different tiles. There are multiple types of supports, similar to multiple types of bridges.


Thinking some more about supports, I concluded that there would be quite some rules about what combinations of tracks on top, underneath and pillars are permittable. It would probably be quite complicated (also for the UI) to allow the user to control every aspect of this. The solution I have in mind, is "morphing", which means that the user just builds tracks. The game will have a list of permittable combinations, which it uses to change the tile and tiles around to get an acceptable situation. This requires very well defined rules about combinations. Most of these rules should be specified explicetely in some format for every different type, or at least be heavily parameterized.



Signals and switches

The data structure should support building every track combination and every signal combination everywhere where building tracks is supported. Some combinations might be forbidden in some places, but should never be unsupported.


Building on slopes should be supported as it is currently. (ie, when building on a slope, it is automatically flattened). It should be supported in a cleaner way, for I think right now the map array doesn't record the slope building, but only the renderer determines that it is used...

Solution, first part -- Using multilayer

(Note: I will here use the word tile to describe both an (x,y) combination and a (x,y,z) combination depending on context... Sorry about that) This first part just describes the things necessary to use a multilayer map, given that it is already build somehow. Using here means not building anything, just letting the simulation roll along.

We surely need more information for each tile.

A naive solution would be to just add a z component to our map array, meaning that we store stuff for every (x,y,z) tile, instead of for every (x,y) tile. This is the easiest and fastest solution. It will require a lot of extra storage, since we allocate memory for every layer on every tile, even while most (95% ?) of the tiles will only be single layered.

A better solution would be to just allocate memory for the ground tile, since every tile on the map will have at least one ground tile. The ground tile will then have two pointers, to the tiles above and below (or possibly just one pointer for above or below). For tiles that are single-layered, these pointers are just NULL, otherwise they will store a pointer to the tile above or below. Each tile will also store its Z-coordinate. Currently this is stored as the z coordinate of the northern corner, but I have a gut feeling that it would make sense to store the z coordinate of the lowest corner, and then store the offsets of every corner to this value. The offsets could just be coded as a 4 bit value, one bit for every corner: raised or not raised. There would be complications with tiles with tileh >= 15 though, these are tiles whose highest and lowest corner are 2 apart. Maybe these things could be stored on two different levels, ie they would be treated as two different tiles. Problem with that is that we should have some way of storing that a corner is _not_ present in a given tile. The plus side of this solution is that we could have diagonal cliffs...

Every tile would also need extra info about the pillars below and suspensions above for bridges and supports, etc. This info would be needed to render and later to determine what can be built around it.

Solution, second part - Building around multilayer

This part describes building normal tracks and stations around bridges and supports and so.

For each tile, we need to store what can be built on top of it. We also need to store what tracks/construction it blocks below and how far down (pillars will block all the way down, but for some bridges, they will only block the tile directly below for example. For this we would need to choose number of blocking points, for example, the center of a tile, the for corners, the centers of the sides are the 9 points that would make the most sense to me. Here can be noted that the corner blocking points block only tile filling constructions such as stations and town buildings, but the center blocking point will also block straight tracks, etc.

With this information we can quickly determine whether something can be built or not. When it can't be built directly morphing should/could be applied, but that's for the next part.

Solution, third part - Building multilayer

The central part of this third part would be morphing and determining how to store information so that it can be used to morph tiles. Unfortuanetely I have not yet written this part (though I have given extensive thought to it).

The ramp problem

Thinking about this, there was one problem that kept bugging me. I named it "The ramp problem". A ramp in this case is a track that is not horizontal, but has on end of the track lifted. You will see natural ramps, where the ground is just slanted upwards. These are no problem, we will just record the slope of the tile and record that a track was built on top. Another type is a semi-natural ramp, where the ground is sloped, but not really fitting. In this case, just putting a handfull of bricks will make the ramp fit and the track can be built. Currently this is all handled in the graphics renderer and the getSlope (or something like that) functions, which is kinda ugly. There is no explicit way of building these slopes in the map array. We should store this explicitely in the new map array. For most brick slopes this is easy, they just fill up the ground until it is flat. For this we just add another tile above the ground on which we will build the tracks. Ramps, on the other hand are tricky because the ramp and the ground underneath are on the same Z coordinate. We can't just modify the tileh (or new map array equivalent) of the tile, because then we won't be able to remove the slope (or even distinguish between a natural slope and a brick-enhanced one). All this also applies to non-natural ramps, like the ones at the end of bridges.

Solutions to the ramp problem

I think we can conclude that there is not really a perfect solution for this problem, so I am open to suggestions.


Put your comments here, if you have them. I will do so soon.