Awesome tutorial. Let me fill in a few pieces:
There are two kinds of tags (XML elements) in a system definition. There are "creation" tags and there are "location" tags. A creation tag is something that creates an object in the system. For example:
This creates a station of the given type. But where does it create it? It creates it wherever the parent "location" tag says. A location tag is an element that specifies a particular location in the system.
The outermost tag is a location tag:
In the code above, since the Station tag is inside the SystemGroup tag, the station gets created at the SystemGroup's location, which is 0,0.
In general, the purpose of a location tag is to offset from its parent's location to some new location.
The Orbitals tag is a location tag that offsets from some center to a point on an orbit:
The "distance" attribute is the radius of the orbit (unless otherwise specified, all distances are expressed in light-seconds). The "angle" is (no surprise) the angle around the orbit (as in standard trig, angle=0 is along the positive X axis). In this example, an angle of 90 is straight up.
Remember that the Orbitals tag is relative to its parent. It just so happens that its parent is the SystemGroup, so the parent location is 0,0. But if the Orbitals were inside a different location, it would be relative to that.
Notice that there are two orbital definitions. The outermost, offsets from its parent (0,0) to a point 10 light-seconds in the 90 degrees direction (straight up). Then the inner Orbitals offset from its parent 5 light-seconds in the 0 degrees direction (to the right). The station will therefore be placed 10 light-seconds up and 5 light-seconds to the right from 0,0.
Orbitals has many additional attributes to define its behavior, but in the end, it's all about positioning things on an orbit.
The "count" attribute creates multiple of whatever orbitals element contains. If you've specified an absolute location (as above) it will just create multiple stations in the same spot. But you can specify a random location. By adding the "random" keyword as an angle, you create a station at a random angle on the orbit. When multiple stations are created (with the count attribute) each station will be placed at a different (random) angle.
There are other kinds of tags that offset the location:
Siblings: This tag moves along the orbit of its parent. You can use the arcInc and radiusInc attributes to move along the orbit of the parent. Or you can pick a random angle on the parent's orbit.
Trojan and AntiTrojan and just special cases of the Siblings tag. They always move 60 degrees forward or 60 degrees back on their parent's orbit. In practice they are identical to Siblings with angleInc="60" and angleInc="-60" [BTW: arcInc moves along the orbit in light-seconds. angleInc moves in degrees.]
Offset: This tag offsets in cartessian (x,y) instead of orbital coordinates.
There are two other special tags that require explanation. First is Lookup.
The Lookup tag is just a way to share portions of the system definition. It is like a macro.
When the above is processed, the <Lookup...> element will be replaced with the contents defined in the SystemPartTable; the result is:
The other interesting tag is Label. A label is like a placeholder location that later gets filled in with something.
When the system places planets, it also positions labels around the planets. For example:
The above creates an ice planet with a label in orbit around it at 2d6+10 light-seconds. What's in the label? Nothing yet. Later, there are other tags that "fill" labels with stations:
The RandomLocation tag loops over all free labels and picks one randomly. The locationCriteria attribute is a way of preferring particular labels (+planet means prefer labels with the "planet" attribute).
Once we pick a label, we use that as the location for anything inside the RandomLocation tag. In this case, we create a station at that location.
But what if you want to create a random station? Then you can use:
The RandomStation tag chooses a random station that matches the stationCriteria and the attributes of the location.
The full picture looks like this:
1. When planets are generated a bunch of labels are created. Each label has a set of attributes describing something about the location of the label (e.g., a label will have the "planet" attribute if it is around a planet.)
2. The RandomLocation tag picks a random label. It uses the locationCriteria specified in the RandomLocation tag to pick a label. In the example above, we prefer labels that have the "planet" attribute.
3. Let's say that we pick a random label with the following attributes: "planet, planetary, frost". These attributes now get associated (temporarily) with the label's location.
4. Now that we've picked a label and location, we process the RandomStation tag. We loop over every single StationType and assign each station a probability of being at this location. We compute the probability as follows:
a. We compare the stationCriteria against the attributes of the station. If the station does not match, we exclude it. Otherwise, we adjust the probability accordingly. In the example above, we make sure that the station has the "friendly" attribute.
b. Next we check the levelFrequency attribute on the StationType and compare against the level of the system. (Any station that does not have a levelFrequency is considered not random and is excluded).
c. Finally we check the locationCriteria attribute on the StationType and compare it against the attributes at the label's location (most of the attributes come from the label itself, but we also take any attributes in the system into account).
5. Once we've computed the probability of all stations, we roll a random number and choose a station.
There are other tags that work on similar principles. The FillLocations tag is an iterated version of the above. It loops over all empty labels and proceeds to pick random stations to fill them.