Day twelve of Titancraft. The game got a next-era gun: a 120 mm smoothbore firing an armour-piercing fin-stabilized discarding-sabot round (APFSDS). The brief was “full simulation”: sabot separation, rod spin, penetration of a homogeneous armour plate, not a ready-made hit table. This entry is about the formulas behind a single shot, and why the penetration step is 50 nanoseconds.
The gunner and the ballistic computer
The player steps up to the gun and moves the reticle. A laser rangefinder measures the range along the reticle ray, to the plate, the ground or water, up to 5 km. The ballistic computer (Apfsds.solve_elevation) raises the barrel so the rod passes through the reticle point at that range. It flies a point mass with the same air drag and corrects the angle until the miss is under 2 mm.

Neither the trajectory nor the barrel angle goes over the network. The server sends three things: where the gun is, where the plate is, and the shot's seed. Every machine computes the shot itself, and randomness comes only from a hash of the seed, never from the engine's random generator. So for every player the rod takes the same path and punches the same hole.
One shot, four time steps
The whole shot is computed at once, the moment you fire: flight, sabot, penetration or ricochet. That takes about 0.1 s of CPU. The shot's history is recorded over time, and the replay only reads the record: live, with flight cameras, or slowed ×80 at the plate.
Inside one shot things happen at very different speeds, so each stage has its own step.
| Stage | Step | Steps | Why |
|---|---|---|---|
| Sabot separation | 2 µs | 6000 | first 12 msthe rod travels 3.3 mm per step |
| Flight | 50 µs | ~3600 | over 300 ma yaw wave is 70 m of travel |
| Penetration | 50 ns | 4962 | 200 mm plate~42 µm eroded per step |
| Ricochet | 200 ns | ~3350 | 0.67 ms of contactnose and tail in the gouge |
The replay is recorded less often than it is computed: the rod every 10 µs during sabot separation, every 200 µs in flight, penetration every 2 µs.
The sabot: three petals
The rod is thinner than the bore, so a sabot of three aluminium petals, 1.15 kg each, carries it. Each petal is a rigid body in its own plane. Each lets go of the rod at its own moment, 220 ± 60 µs. The oncoming flow pushes on the petal's front “scoop” with ½·ρ·v²·S and turns it outwards.

While a petal holds on, its force goes into the rod, sideways and as a turn about a 5 cm lever. Whichever petal lets go first pushes the rod its way. So sabot-induced yaw comes out on its own, with no dispersion table. Then the petals tumble, because pressure on the scoop ahead of the centre of mass makes them unstable, and fall to the ground.
Flight: drag, yaw, spin
The rod is a 17,600 kg/m³ tungsten alloy: 740 mm long, 22 mm across, 4.95 kg, leaving the muzzle at 1650 m/s. Drag grows with yaw ψ, the angle between the nose and the velocity:
F = ½·ρ·v²·S·Cd·(1 + 12·ψ²), Cd = 0.78Yaw is a damped oscillator in two transverse axes. Its frequency grows with speed, one wave per 70 m of travel, and the amplitude falls by e every 260 m:
ψ'' = −ω²·ψ − 2k·ψ' + sabot push, ω = 2π·v / 70 m, k = v / 260 mThe initial disturbance comes from muzzle gases: up to 0.15°. The fins are canted 0.5°, and the rod spins up towards the equilibrium ω = v·tan(0.5°) / R_fin, reaching 50 rev/s by 20 ms.

Tate–Alekseevskii penetration
The model is hydrodynamic: at these speeds both the rod and the armour at the bottom of the channel flow like fluids with strength. The bottom moves into the armour at a speed u found from the pressure balance:
½·ρr·(v − u)² + Yr = ½·ρt·u² + RtThe rod's strength is 1.8 GPa, the armour's penetration resistance 5.5 GPa, its density 7850 kg/m³. The equation is quadratic in u. Every 50 ns step the nose erodes, the tail decelerates and the channel grows:
tail -= (v - u) * STEP_PIERCE # the nose erodes
v -= ROD_STRENGTH / (ROD_DENSITY * tail) * STEP_PIERCE # the tail decelerates
hole += u * STEP_PIERCE # the channel grows
In this frame the rod moves at 1615 m/s and the channel bottom at 782 m/s. So each step erodes ~42 µm of rod, a five-hundredth of its diameter. 2 diameters before the rear face the armour starts to give way: its resistance falls smoothly to zero and the plug is punched out.
Why 50 ns exactly: we ran the same model with other steps, 200 mm plate, 1631 m/s at the plate:
| Step | Steps | Rod left, mm | Exit speed, m/s | Limit, mm |
|---|---|---|---|---|
| 5 ns | 49,613 | 540.1 | 1590.8 | 644.3 |
| 50 nsin game | 4962 | 540.1 | 1590.8 | 644.3 |
| 1 µs | 249 | 539.5 | 1590.6 | 644.4 |
| 5 µs | 50 | 538.2 | 1590.3 | 644.7 |
A 5 ns step gives the same numbers to a tenth of a millimetre, with 10 times as many steps. A 5 µs step is off by just 2 mm, but leaves 50 steps for the whole penetration, and the slow-motion replay has nothing to show. 50 ns is the coarsest step at which the replay (every 2 µs) runs smoothly and the numbers match the fine step.
If the armour is thicker than the rod can go, the channel ends where the rod has eroded away, and the rear face stays intact.

Fins wider than the hole
The fin span is 90 mm, the entry hole 37 mm. The fins do not fit into the channel: they hit the front face when the tail reaches it. At 300 m that happens 0.46 ms after the nose strikes. The fins are sheared off and melted, and six slots are left on the face, matching the rod's roll at that moment.

Ricochet: Tate's threshold
The critical impact angle comes from Tate's formula for a rod:
tan³β = ⅔ · (ρr·v² / Y) · (L² + D²) / (L·D)For the armour strength Y we take the same penetration resistance of 5.5 GPa: one armour constant for both effects. The threshold comes out at 80° at 1620 m/s, which is what modern rods show on firing ranges.
Above the threshold the rod does not enter, it slides. That is a planar rigid-body problem with a 200 ns step: the nose and the tail below the face push on the armour and plough a groove, the ridge of metal in front pushes them outwards at 40°, and a couple of forces turns the rod away from the plate. Once it leaves, we check bending against a 2.5 GPa strength and break it into pieces.
A 200 mm plate at 85° from 300 m: a gouge 1153 mm long and 13 mm deep, and the rod leaves at 1525 m/s in three pieces.


Ribs, like the Strv-103B
To “torture the physics”, we put ribs on the front face: 40 mm high every 180 mm. A rib is the same armour. Through a rib the nose erodes by Tate, and across the axis the rib pushes with a share of the armour's resistance over the rod's cross-section.
The rod is a free beam with a force at its end: the peak bending 4·F·L/27 is a third of the length from the nose. If it breaks, the nose fragment enters the plate first along the same channel but loses part of its penetration to tumbling.
A 120 mm plate at 78°: 568 mm of armour along the path. The rib pushes 2044 kN sideways and snaps the nose 246 mm from the tip. The rest still exits the back at 1398 m/s.

37 centimetres from 32 bits
On a range 3 km from the world centre, the gun started missing by 37 cm sideways. In Godot Vector3 is 32-bit: that far out a coordinate step is ~0.24 mm, and sabot separation takes 6000 steps of 3.3 mm. The rounding added up to a miss.
Now flight, petals and aiming are computed relative to the muzzle and converted to world coordinates only when recorded. The miss dropped to 5 mm.
The duel and the laser warning
For fun we added a duel with a bot: two guns 1500 m apart, 200 mm shields, 10 rounds each. The bot uses the same gun and the same shot computation: each machine works out the result itself. When the enemy lases us, the laser warning lights up the sector it shines from and beeps. After that the bot hurries.


While the gunner watches their shot through flight cameras, the duel does not pause: its clock runs with the replay. So “both knocked out” is possible: the enemy got its shot off while our rod was in flight.
What is left in the game
- The rod and the rangefinder will start hitting trees and buildings in their path.
- A second hit in an old hole will go through already weakened armour.
- Rib strikes and ricochet gouges will get a full impact calculation instead of the beam and groove-volume model.
- Sabot petals will fly apart as fast as in footage of real shots.
- New rounds, HEAT and HE-frag, and spaced armour.
