A deeper dive into entities and attributes

Published on
Last changed on

Hello! In this previous post, we went over an entities and attributes overview, which hopefully exposed, in a clear fashion, the basic building blocks of the upcoming Ad Lumens "game engine".

In this post I would like to dive a little deeper on exactly how entities are designed, manufactured and what their operational requirements are. Same overall goal:

Chronofagism

The first reality of it all is: this is time-consuming. Very time-consuming. Hopefully the dive we are about to get into will be able to explain/justify it, but several factors kick in:

  • "Two step forward, one step backward" very much summarises the qualitative phase I am currently in. That means experimenting, prototyping, trying to anticipate upcoming mechanics problems/incompatibilities between what is and what will problably be.
  • Quantitatively is less of a problem, although still a lot to do: this is more about populating content, finding nice, relevant, varied and (hopefully) original ideas
  • … while making it all fit inside a clear, solid and logical unified system.

The two entity types this post will talk about are two among around 220 that have been (and are being) designed. I think that illustrates why this (nice and interesting) endeavour is taking so long! Note: this is about 50% of the entity classes, so about as many more will be to work on.

Quick overview of our deep dive

  1. We will use two arbitrarily selected entity types, rather different in the role they play. Both belonging to the unit layer
  2. We will discover what their slots are
  3. We will pick a material used in the crafting of those units.
  4. We will discover how attribute emergence works, also using examples and explanations
  5. We will briefly touch on what manufacturing them means
  6. And finally we will discover how unit-layer entities can run and operate, usually within the context of a higher-order entity

Entity types

We will use two rather different entity types:

  • A specific energy generation unit: the Tokamak fusion reactor
  • And a specific ship frame unit: the Load-bearing Frame

They are humanly defined as follow:

Entity typeDescription
Tokamak fusion reactorTokamak fusion reactors confine and heat plasma using strong toroidal magnetic fields combined with a central current. They achieve stable, long-duration fusion reactions through well-established magnetic confinement techniques and remain the most mature approach for continuous power generation.
Load-bearing FrameA fixed-geometry structural frame that never changes shape during operation. All forces from thrust, rotation, impacts, and docking are resolved locally through rigid members, making behaviour highly predictable and easy to model. Performance is tightly constrained by material limits and joint strength, and failure tends to be abrupt rather than graceful. While inefficient under extreme acceleration or asymmetric loads, this frame excels in reliability, simplicity, and low control overhead, forming the baseline architecture for early spacecraft, stations, and orbital infrastructure.

Their availability is gated behind the following sciences:

Entity typeTierScience
Tokamak fusion reactor1Fusion physics
Load-bearing frame1Metallurgical chemistry

Which makes them both entry-level entity types, i.e., ones available at the very beginning of the game.

Their slot definitions is as follows:

Tokamak fusion reactor slots
SlotMass fractionTag
VACUUM_VESSEL0.35/0.31/0.39STRUCTURE_CONTAINMENT
SUPPORT_FRAME0.15/0.13/0.17STRUCTURE_SUPPORT
TOROIDAL_MAGNET_COILS0.20/0.18/0.22MAGNETIC_CONTAINMENT
PLASMA_HEATING_SYSTEM0.15/0.13/0.17ENERGY_GENERATION
CENTRAL_SOLENOID0.10/0.09/0.11ELECTROMAGNETIC_CONTROL
DIVERTOR_PLATES0.08/0.07/0.09PARTICLE_ABSORPTION
FEEDBACK_SENSORS0.05/0.04/0.06PLASMA_DETECTION
CRYOGENIC_COOLING0.02/0.01/0.03TEMPERATURE_REGULATION
Load-bearing frame slots
SlotMass fractionTag
RIGID_MEMBERS0.40/0.35/0.45STRUCTURE_SUPPORT
JOINTS0.20/0.18/0.22INTERFACE_SUPPORT
LOAD_BEARING_LATTICE0.15/0.13/0.17STRUCTURE_DISTRIBUTION
FORCE_RESOLVER0.10/0.09/0.11FORCE_DISTRIBUTION
STRESS_CONCENTRATOR0.08/0.07/0.09FORCE_CONTROL
PREDICTABILITY_OPTIMIZER0.07/0.06/0.08STRUCTURE_STABILISATION

Where all masses are expressed in fractions (base/minimum/maximum), and end up being normalised so that their sum == 1.0. As you will see below, mass fraction do have an impact in terms of game mechanics; they are not here only for fluff!

Materials and tags

In order to manufacture/build/craft instances of the two entity types above, a faction needs to use materials. The fact that material themselves need to be crafted is interesting, but irrelevant to this post.

As the previous post briefly explained, materials can be only used to manufacture a unit slot if they have the tag that matches the one assigned to that slot.
Conveniently, the tag STRUCTURE_SUPPORT is used in both entity types (for the slots SUPPORT_FRAME and RIGID_MEMBERS), which is why we will use it for our deep dive.

Our picked material for structure: Titanium-reinforced structural alloy

This alloy, belonging to the entity class MATERIAL_METAL, has the tag STRUCTURE_SUPPORT, so is the one we will use for this example.

This section will be an opportunity to show how materials are generally defined; so even though all the details therein will not be immediately relevant to our dive exercice, it's always nice to get those extra bits, isn't it?

Titanium-reinforced structural alloy
"Field"Content
DescriptionAlloys primarily composed of titanium, exhibiting high strength-to-weight ratio, corrosion resistance, and uniform microstructure. The lattice maintains dimensional stability under repeated thermal cycling and mechanical load, balancing toughness, ductility, and fatigue endurance.
Science / tiermetallurgical chemistry / 1
Crafting ingredientsTi (0.88), Al (0.05), V (0.05), Fe (0.02)
AttributesSee below!
TagsSTRUCTURE_SUPPORT, STRUCTURE_STABILISATION, FORCE_DISTRIBUTION, ELASTICITY_ADAPTATION, ENTROPY_REGULATION, MASS_REGULATION, PRESSURE_STABILISATION, ENERGY_ABSORPTION, PHASE_STABILISATION, FORCE_CONTROL, THERMAL_CONTROL, ELASTICITY_CONTROL, VIBRATION_DAMPING, ENERGY_CONVERSION, FORCE_AMPLIFICATION, PARTICLE_STABILISATION, DEFECT_SELF-REPAIR, THERMAL_STABILISATION, INTERFACE_STABILISATION, FORCE_ADAPTATION

Attributes deserve their own table, as they are common to all materials. In other words: all materials, whether metals, polymers, time crystals or biomaterials, share these attributes.

Important: all material attribute values are expressed as a multiplier of Iron (Fe). This choice was made because Iron is a univeral point of convergence whether energy is added or removed; in many ways, it is also the most stable element in the universe.

  • The Secret of Steel, not Iron!
Titanium-reinforced structural alloy attributes
Attribute symbolAttribute nameAttribute descriptionUnitValue
STRIStructural IntegrityCapacity to resist fracture, deformation, and fatigue under sustained or sudden load, reflecting bond strength, defect tolerance, and mechanical reliability across scales.Pa2.8
COHSCohesion StabilityStrength and persistence of internal bonding across molecular or lattice structures, determining resistance to separation, delamination, and structural disorder over time.J/m21.5
DEFTDefect ToleranceCapacity to maintain functional performance despite structural imperfections, impurities, or microfractures, supporting reliability under imperfect fabrication conditions.normalised1.2
THSRThermal Stability RangeTemperature interval across which the material maintains structure and function without phase change, breakdown, or loss of mechanical, electrical, or chemical integrity.K1.1
RADTRadiation ToleranceCapacity to endure ionising or high-energy radiation exposure without structural damage, property drift, or functional loss across prolonged or intense energetic bombardment.Gy1.2

This is only 5 attributes out of 44 possessed by all materials; but only those 5 are going to be used in our example.

Player factions will of course be able to manufacture slightly better (or worse!) versions of such materials!

Attribute emergence expressions

Now each of our two example units (the reactor and the frame) also have attributes; these make far more sense in functional/performance terms and are more "macro" in the characteristics they describe.

One universal unit-level attribute is Integrity (ING). By universal is meant that all units have the ING attribute.

This attribute is defined as follows:

ING attribute details
Attribute symbolAttribute nameAttribute descriptionUnit
INGIntegrityThe amount of damage energy the unit can absorb per unit mass before becoming non-viable. It tracks the presence of physical degradation, fractures, or circuit damage that threatens the entity's existence.J/kg

One extremely important point: ING, like many other unit attributes, is expressed per unit of mass. Which means it is an intensive attribute. Very logically, to obtain the actual total integrity of a unit, one must simply multiply its ING attribute value by its mass. This then results in an extensive (or quantitative) attribute value!

The ING expression for the reactor

Is defined as:

(2.8e5 
+ 3.6e5 * norm(
    sawhm('STRI', ['PRESSURE_VESSEL','SUPPORT_FRAME']) 
    * math.sqrt(sawhm('COHS', ['PRESSURE_VESSEL','MODERATOR_WATER'])) 
    * math.sqrt(sawhm('DEFT', ['CONTROL_RODS','HEAT_EXCHANGER'])) 
    * (0.7 + 0.3 * sawhm('RADT', ['SAFETY_SHIELDING','PRESSURE_VESSEL'])), 
    0.16, 
    0.40
)) * rho_mod

The ING expression for the frame

Is defined as:

(3.0e4 
+ 3.0e4 
    * norm(sawhm('STRI', ['RIGID_MEMBERS', 'JOINTS', 'LOAD_BEARING_LATTICE']) 
    * math.sqrt(sawhm('COHS', ['RIGID_MEMBERS', 'JOINTS'])) 
    * math.sqrt(sawhm('DEFT', ['FORCE_RESOLVER', 'PREDICTABILITY_OPTIMIZER'])) 
    * (0.7 + 0.3 * sawhm('THSR', ['RIGID_MEMBERS', 'JOINTS'])), 
    0.16, 
    0.30
)) * rho_mod

Emergence explanation

The expressions above of course deserve a little bit of explanation!

First, the values are temporary so can be more or less ignored. What is important is the form of each expression, which I will try and detail here.

The basic anatomy of an expression is as follows:

(BASE + SPAN * normalise(
  DRIVER
  * math.sqrt(SHAPER_1)
  * math.sqrt(SHAPER_2)
  * (0.7 + 0.3 * LIMITER),
  M,
  K
)) * density_multiplier

More details:

ParameterExplanation
BASEThe minimum achievable value of the attribute. Represents worst-case performance (poor materials, bad combinations).
SPANThe maximum improvement above BASE. Defines the range of variation the system can express.
normNormalisation layer; implemeted as y = M + (1 - M) * (1 - exp(-K * x))
MThe baseline output of the normalisation, prevents the result from ever reaching 0.
KSteepness; controls how quickly the normalisation function saturates.
DRIVERThe primary controlling factor of the attribute. It very often aggregates material attribute values across several slots.
SHAPERSSecondary attributes that influence how effective the driver is. Applied as square roots to reduce dominance, smooth the scaling and avoid multiplicative explosion/collapse.
LIMITERA soft cap / gating factor.
density_multiplierAKA rho_mod, an overall density multiplier that potentially penalises designs outside an accepted density window (min/max expressed in kg/m3).
sawhmIs a helper function among several. This one in particular is slot_attribute_weighted_harmonic_mean and produces an effective value dominated by the weakest contributors, while still respecting mass distribution.

Emergence breakdown

First, let's examine a typical driver/shaper/limiter:

norm(sawhm('STRI', ['RIGID_MEMBERS', 'JOINTS', 'LOAD_BEARING_LATTICE'])

This does the following:

  1. It picks the slots whose names/symbols are ['RIGID_MEMBERS', 'JOINTS', 'LOAD_BEARING_LATTICE']
  2. It takes the materials that were slotted into them
  3. For each material (they do not have to be all the same), it picks the STRI attribute as a multiple of Iron
  4. It then performs a weighted hamornic mean on each slot on the list of STRI attribute values, thus taking into account mass fractions of the picked slots
  5. Then returns the value

Next, let's imagine a crafting design results in the normalise output being 0.5 and the final computed unit densities being within the allowed ranges. We will then end up with the following intensive intensive values

  • For the reactor: 2.8e5 + 3.6e5 * 0.5 = 4.6e5 J/kg
  • For the frame: 3.0e4 + 3.0e4 * 0.5 = 4.5e4 J/kg

Which, when multiplied by the total desired mass, will result in final ING values for both units.

Why is this time-consuming?

Well, first of all each entity class has to be assigned unit-level attributes (note: I have not really started working on entity-level attributes yet, although those should be quicker/easier as they will emerge from far less moving parts).

Then several things have to be done for each entity type (as children of their respective entity classes):

  1. Define the slots
  2. Each attribute has to be mapped to an expression (dynamic since each entity type has a unique slot layout)
  3. Given ~200 entity types and around 15 attributes per entity class so far (including universal ones)… well yeah… it does take time

But this is all making good progress! I estimate being about halfway through this process; knowing a lot of time has been spent on going backwards and forwards after discovering "problems". Standard stuff :-)

Another complexity layer: crafting time and difficulties

The above various steps illustrate the kind of logic that will be run when designing an entity based on an entity type. In memory data will hopefully make this reasonably quick.

But that is just the design; once that design is saved in the database, etc. a player faction still has to manufacture the unit using its specifications: mass fractions, materials used, etc. Here two main attributes are taken into account:

  • MTIM or manufacturing time, expressed in s/kg
  • MDIF or manufaturing difficulty, expressed in the engine's internal difficulty class (more on this in an upcoming post)

Both attributes are intensive: they represent the inherent and qualitative difficulty and time to manufacture/craft the unit; to compute the final time and difficulty the engine takes them both and modifies them using the unit's desired mass (obvious) but also the faction's expertise in the manufacturing of such an entity type.

It is still a bit early to talk about faction skills, but too late: in a nutshell, some faction-wide skills (as opposed to crew member skills) will be applied to the manufacturing process, and will allow factions to (non-exhaustive list):

  • Manufacture more quickly
  • Manufacture more easily
  • Manufacture with a higher chance of high quality output

Neat, heh? :-)

Yet another complexity layer: entity metabolism

Now we are happy: we have designed our unit-layer entity and we have manufactured it. So it sits there or what? No of course not, its exists to be slotted into a higher-order entity - for example: a ship!

It's kind of screamingly obvious but it bears repeating: a ship runs on power. Sometimes a lot of power.

  • Unlimited power!

But that's okay… this is sci-fi!

But that's not okay as Ad Lumens tries to be almost realistic. :-)

Enter what is perhaps a solution (it certainly looks like it at the moment!): Entity Metabolism.
First of all, even equipment, units, ships, etc. all have metabolisms - the principle is not limited to organic/living units, but is applied to everything that:

  • Consumes
  • Produces
  • … and generates waste

So a human crew member will consume food, atmosphere, entertainment, etc. It will produce work, morale, social cohesion (or lack thereof!), and generate waste (heat, organic, atmospheric, perhaps others). A cyborg will consume mostly energy and perhaps parts? Will produce pretty much what a human does and probably generate only waste heat. All this, for crew members and "smaller entities" is to be determined still.

What is however well under way is the mechanics for larger stuff, namely: units. Now units can be split into broad families when it comes to metabolism:

  • Units that generate power by burning fuel
  • Units that generate power by harvesting it passively from the environment (no, there are no wind turbines in space, although it is probably a good idea to think about them in atmospheres!)
  • Units that store energy and can release it in a system when needed
  • Units that consume energy

… all of which will generate waste: heat, radiation, etc. Said waste must be managed lest you turn a ship into radioactive slag. Not good, very not good.

Metabolisms are thus being put in place, slowly… and via unit-layer attributes such as:

Attribute symbolAttribute nameAttribute descriptionUnit
ENEFEnergy efficiencyFraction of input or output energy successfully converted into intended input/output, capturing losses due to heat, resistance, or inefficiencies across operational processes.normalised
PWDSPower densityRate of energy generation or consumption per unit mass, defining how intensively a system produces or draws power relative to its size and structural capacity.W/kg
ENDSEnergy densityAmount of energy stored per unit mass, defining how much usable energy a system can carry intrinsically, shaping endurance, autonomy, and storage efficiency.J/kg
DISRDischarge rateMaximum rate at which stored energy can be released per unit mass, governing burst output capability, responsiveness, and peak power delivery under load.W/kg
RECRRecharge rateMaximum rate at which energy can be absorbed and stored per unit mass, defining recovery speed, cycling efficiency, and resistance to thermal or structural charging limits.W/kg

All the above are intensive; again, this means that a final unit corresponding attribute will have to be multiplied by its mass, to get, for example, total energy density (for a battery).

Another important detail of metabolism is the route via which resources can be transported. Why? Well to cover cases similar to the following:

  • A propulsion engine being fed its fuel via more than one storage unit
  • Some units being assigned dedicated power sources; for various reasons: critical support, or to avoid unwanted strain of other systems.
  • When a ship or station has several heat dissipation units/heat buffers. In which case the route determines the destination of waste heat.

… and so on. :-)

In conclusion

This was reasonably long and dense so thank you for reading what I hope can start to clarify some mechanics around entity design and manufacturing! As always, please feel free to comment, or drop a constructive feedback message here or directly on Discord.

Sounds complex? Sure it kind of is. But again, my goal is to put in place a complex system that does not feel complicated to use. So anyone would be able to chuck in default values and launch a manufaturing process, without the least care in the world about optimising a unit!

Please signin to add your comment.