This page is part of a series giving an Overview of Simutrans Code.
CHAPTER 1: THE WORLD
Welt and karte_t
welt ("world") is the most important object in Simutrans. It's of class karte_t ("map type", declared in simworld.h). It has a two-dimensional array of planquadrat_t ("plot square type") objects, named plan. For each two-dimensional(x,y) coordinate, koord ("co-ordinate"), there is a planquadrat_t object. You can retrieve it with the method planquadrat_t *lookup(koord).
welt
karte_t is a singleton (only one world per invocation), but Simutrans' founder, Hajo, was not sure about that decision, as we can see in /ground/grund.h:
/** * Pointer to the world of this ground. Static to conserve space. * Change to instance variable once more than one world is available. * @author Hj. Malthaner */ static karte_t *welt;
The planquadrat_t class
planquadrat_t ( simplan.h, "plot squares") objects are containers for ground elements ( grund_t ) that share the same position of the map, but have different heights. You can get the element at a certain height with the method grund_t *planquadrat_t:: get_boden_in_hoehe(sint16). You can directly get the ground object from the welt with grund_t *karte_t::lookup(koord3d).
The grund_t class
grund_t ( ground/grund.h ) objects contain a list, objlist (dingliste_t) of all objects (Dinge, "things") that belong to a certain 3D position on the map. grund_t objects may have ways (Weg, such as roads, railways/-+track+-, and others), numbered from integer 0 to integer 2. They are always at index 0 and 1 in the object list, objlist_t. (Other objects follow at higher indexes). grund_t objects also have an image ( bild ) that depends on the type of slope, climate, etc. All other objects belonging to that grund_t also store their images themselves. The methods in connection with the ways the object has are (other types used in them are explained below):
Grund_t methods
- Methods to know how many ways there are: +-bool hat_wege()+- ("has ways"),
uint8 has_two_ways() - Methods to get (or know if there is) one of the ways:
weg_t *get_weg_nr(int)("get way number"),-+ weg_t *get_weg(waytype_t)+-,bool hat_weg(waytype_t) - Methods to know the system type of way:
uint8 get_styp(waytype_t)(-+track+- ways can have one of several system types, i.e. elevated and tramways) - Methods to know the allowed directions for a certain way:
virtual ribi_t::ribi get_weg_ribi(waytype_t),virtual ribi_t::ribi get_weg_ribi_unmasked(waytype_t). (Ribi, short for Richtungsbits, "direction bits", because they are stored as a bitmask.) - Method to get a way object:
wayobj_t *get_wayobj( waytype_t) - Methods to build/destroy ways:
sint64 neuen_weg_bauen(weg_t *, ribi_t::ribi, player_t *)"build new way" (the last parameter was previously Spieler, "player"),bool weg_erweitern(waytype_t, ribi_t::ribi)"extend way",sint32 weg_entfernen(waytype_t, bool ribi_rem)"delete way" - Method to move along a way:
bool get_neighbour(grund_t *&to, waytype_t, ribi_t::~ribi ribi)Returns the grund_t we arrive to, if any, if we want to move (+-1,0) or (0,+-1) without leaving the way). If type isinvalid_wtthen only slopes are checked and no concrete way is followed. Earlier versions of this function may have used akoord dirfor the last parameter and the comments still mention this.
Ground types
grund_t objects may be of one of these types ( virtual typ get_typ() ):
1 grund_t::boden (normal ground)
2 grund_t::wasser (water)
3 grund_t::fundament (foundations for other objects: houses, etc.)
4 grund_t::tunnelboden
5 grund_t::brueckenboden (bridge ground)
6 grund_t::monorailboden
Note that the code uses two German terms that can both be translated to "ground" in English. Grund is used for a tile with certain XYZ co-ordinates. Boden is used to indicate the "floor" or "surface" of common subtypes of Grund; you can think of the most common tile as something like "ground tile" or "earthen floor".
Ground flags
grund_t objects may have none or several of these flags:
0 grund_t::keine_flags (no flags)
1 grund_t::dirty (needs to be redrawn)
2 grund_t::is_kartenboden (is the actual ground which grass/water/house/way on it)
4 grund_t::has_text
8 grund_t::marked (will have a frame (ditto))
16 grund_t::draw_as_ding (is a slope, etc.)
32 grund_t::is_halt_flag (is part of a halt=stop)
64 grund_t::has_way1 (has, at least one way)
128 grund_t::has_way2 (has two ways attached)
grund_t is an abstract class. Known subclasses are: boden_t ( boden/boden.h ), wasser_t ( boden/wasser.h ), fundament_h ( boden/fundament.h ), brueckenboden_t ( boden/brueckenboden.h ), monorailboden_t ( boden/monorailboden.h ). Tunnels ( tunnelboden_t ) are a subclass of boden_t.
Way types
Way types ( waytype_t ) are such fundamental data in Simutrans that they are defined in simtypes.h (together with integer sizes, for instance). They are:
-1 waytype_t::invalid_wt
0 waytype_t::ignore_wt
1 waytype_t::road_wt
2 waytype_t::track_wt
3 waytype_t::water_wt
4 waytype_t::overheadlines_wt
5 waytype_t::monorail_wt
6 waytype_t::maglev_wt
7 waytype_t::tram_wt
8 waytype_t::narrowgauge_wt
16 waytype_t::air_wt
128 waytype_t::powerline_wt
Object class
Objects are in the abstract class obj_t in obj/simobj.h. They were previously known as things, from the German Dinge. They have an owner (previously besitzer) and may or may not be physically located in a location in the welt. Vehicles and ways are objects, but not the only ones. There are many different types: smoke, buildings, tunnels, bridges, depots, roadsigns, ground objects, labels, and all kinds of vehicles... Interestingly enough, a thing may be a vehicle and a way at the same time, which opens a huge world of possibilities... They also have an associated image ( bild ). If we know the index of a certain object, we can retrieve it with obj_t *grund_t::obj_bei(uint8).
And what about time? Well, let's hear the wise words of Prissi, the project lead of Simutrans Standard (edited for this wiki):
obj_t object] can have three periodic calls: for very regular and fast actions which require exclusive access on the map (moving cars, collision avoidance) there is sync_step, called before every frame. Slower actions like route finding, way building etc. is done in step(), where the map can change in between slightly. Some objects (most notably trees) require seasonal changes, which are covered by the relatively new action method of check_season();
( sync_steppable.h was completely removed in 2023. I can't find any forum thread discussing this change, unless it was the eventual outcome of this proposal.)
All objects that must be advanced in synchrony must therefore implement the interface sync_steppable (in ifc/sync_steppable.h). welt keeps a list of sync_steppables (sync_list) and periodically calls the only method they have to implement to become a fully-fledged sync_steppable guy:
Delta_t
delta_t represents how many simulation ticks the object must advance.
It returns false when the thing wants to be removed from the sync_list and deleted.
Scheduled additions and deletions from the sync_list are done carefully through intermediate lists and also in sync.
And welt moves around in its sync_step method:
-
void karte_t::sync_step(long delta_t, bool sync, bool display) - with
delta_tthe simulation ticks to advance, -
syncimplies that things will be added/deleted to the sync_list and sync_step methods will be actually called, - and
displaymeans that some time consuming things like message displaying, follow convoy or water animation won't be done (like in some steps of fast forward mode).