Skip to content

Releases: sha5b/Z-Steel-Soldiers

Z Remake 0.2.7 — production lines, and an AI that manoeuvres

Choose a tag to compare

@sha5b sha5b released this 24 Aug 06:44

The Bitmap Brothers' 1996 robot RTS, rebuilt in Godot 4. Twenty missions,
five planets, 49 headless test lanes — green in the editor and inside
the exported binary.

One file, no installer. The Mac build is unsigned, so the first launch
needs right-click → Open.


Production is a LINE, not a queue

Z has no build queue, and it never did. The five-slot FIFO in every
build up to now was invented. Select a factory, pick one unit type,
and it turns that out indefinitely until you pick something else.

  • Each unit is charged as it starts, so a stalled line costs nothing.
  • Switching keeps the build clock and refunds the abandoned unit.
  • Cancel stops the line and it stays stopped.
  • Every producer starts on the first entry of its own list, so a captured
    factory earns its keep immediately.
  • Three things pause a line without dropping it — no money, the
    population cap, and a fort with all four cannon mounts full — so it
    resumes by itself.

Nothing enters a building

The fort garrison is gone. A unit inside a building cannot be seen,
selected or counted. A fort now defends itself with its four tower
guns
: real cannons, on real cells, that fire, can be shot back off the
fort, and free their mount for a replacement when they die.

Tanks can finally attack an HQ

Two bugs, one symptom.

  • Every explosive weapon had no anti-structure damage at all. A heavy
    tank needed 341 seconds to raze a fort that a pyro robot razed in
    14. Now 18 seconds.
  • No crewed vehicle or cannon could fire on a fort, ever. Their range
    gate measured to the fort's middle — about 80 px inside its own wall,
    further than a medium tank's entire reach. It would drive up, track the
    fort with its turret, and never pull the trigger.

Cannons also take attack orders now, so the howitzer — the longest reach
on the map — is no longer the one unit whose fire you cannot direct.

A CPU opponent that manoeuvres

  • A strategic layer: a zone graph with adjacency, depth from its own
    fort, per-sector strength and value, and four stances (turtle,
    consolidate, expand, press).
  • Squads that muster behind the line, advance as a body with laggards
    closing up, and break off when beaten instead of feeding themselves in
    one at a time.
  • Turrets are no longer manoeuvre units. A cannon has speed 0, so
    drafting it into a squad dragged the squad's rally point onto an
    immobile gun and parked the whole army around it on one bridge.
  • Hardware needs a crew. Vehicles and cannons roll out unmanned, so
    the brain keeps infantry in reserve instead of building a car park.
  • Its cadences run on game time, so pausing no longer fires every
    timer at once on unpause.

Pathing, and the things you could see

  • Units path around buildings. Cells next to a wall now cost more, so
    a route prefers open ground instead of grinding along a factory wall —
    a vehicle's hull is exactly as wide as the gap a wall-hugging route
    leaves it.
  • A captured factory no longer inherits the previous owner's rally
    point
    (which, taken from the AI, marched everything you built at your
    own HQ).
  • Unit shadows are rasterised on the pixel grid instead of being
    smooth antialiased ellipses under 16 px sprites.
  • Fixed: the missile cannon and the fort battery were firing in complete
    silence, and medium/heavy tanks fired a missile sprite.

Verify your download

SHA256SUMS.txt is attached. Fedora users can install the RPM directly;
it carries a build stamp, so a rebuild always upgrades in place.

The binaries embed the original art and sound, so they are not MIT —
only the code is.
They are a convenience for people who already own the
game.

v0.2.0

Choose a tag to compare

@sha5b sha5b released this 21 Aug 06:03

sha5b.github.io/Z-Steel-Soldiers — screenshots and the write-up.

The code is now MIT. This project exists for the sport of it, and to see what it takes to translate a 1996 game's logic into Godot, so the reading matters more than the binary. Take the code, port it, reuse it.

Downloads

File Platform
z-remake-0.2.0-1.202608210751.fc44.x86_64.rpm Fedora — installs /usr/bin/z-remake, a desktop entry and the icon tree
z-remake-0.2.0-linux-x86_64 any Linux, one self-contained binary (chmod +x it)
z-remake-0.2.0-windows-x86_64.exe Windows, self-contained
z-remake-0.2.0-macos-universal.zip macOS, universal (x86_64 + arm64), unsigned

SHA256SUMS.txt covers all four.

The macOS app is not signed or notarized, because that needs a Mac and these are cross-built from Linux. First launch needs right-click → Open, or:

xattr -dr com.apple.quarantine "Z Remake (1996).app"

These binaries embed the original game's graphics and sound, which are © The Bitmap Brothers and are not covered by the MIT license. They are here for people who already own the game. The assets are not in the repository — the converters read from your own copy of the retail release.

Fixed in 0.2.0

An exported build loaded none of its content. The worst bug of the cycle, and it was invisible: all 47 test lanes were green in the editor while a packaged game came up with no building defs, no unit folders, no effect art and no map scenes. Godot packs an imported file as a .import sidecar and renames the real texture under .godot/imported/, and it converts text resources to binary. Every directory scan in the project filtered on the source extension (.tres, .png), so in a build they matched nothing. PackFiles folds the packed names back to the project names.

An exported build could not be tested at all. A release binary refuses a scene override on the command line, and main_scene is the title screen, so every test flag was unreachable once packaged — the suite only ever ran the editor's copy. The title screen now hands over to the match scene when it sees a test flag. That is what found the bug above. An editor-only green run proves nothing about a build.

Order paths drew only their last few pixels. Path smoothing collapses an open-ground route to its corners, so a move order comes back as two points, and the walker then drops the first one because it is the cell it already stands on. The path indicator was left with a single point, built no segments, and drew nothing but the destination marker. It now builds its first segment from the unit itself, which is what the original does. --orders-test asserts the path exists, starts at the unit, and spans the move.

Buildings never showed damage. A fort one shot from collapse looked untouched, and the ruin it left sat clean for the rest of the match.

A rebuilt RPM would not replace an installed one. Same name-version-release, different contents, so dnf had no reason to act and you could not tell two builds apart. Release now carries a build stamp.

Ported from the Zod Engine source, not guessed

The 1996 Bitmap Brothers code was never released. The Zod Engine is the open reimplementation this project's asset pack comes from, so it is the reference of record, and each behaviour cites its function in docs/RESEARCH.md.

  • Buildings burn (ZBuilding::ProcessBuildingsEffects). A damaged structure holds a population of effects — max_effects * (1 - hp/max_hp), topped up when short, each placed inside a per-type effects_box — mixed on one rand()%100 roll: 10% big smoke, 10% small fire smoke, 30% fire, 50% little fire. The loop has no destroyed check in the original either, which is exactly why a Z ruin keeps burning. Boxes and caps are verbatim from bfort / brobot / bvehicle / brepair / bradar.
  • Every explosive radius verified against zsettings.cpp SetDefaults: tough 40, light 40, medium 45, heavy 50, missile launcher 80, gun 40, howitzer 40, missile cannon 50, grenade 30, and all the zeros. The splash model matches ZServer::ProcessMissileDamage too — one roll per object, linear falloff, friendly fire off, a circle and not a box.
  • The CPU commits adaptively (ZBot::GoAllOut_3). It compares its share of the map's zones against a fair share and reads two numbers off it: what fraction of the idle army to re-task, and how long until the next cycle. Holding a fair share means a small slice on a slow cadence with a wider target list. Falling behind means a third of the army every few seconds. Targets are collected in the original's priority order and matched by mutual nearest (MatchTargets_3 / GiveOutOrders_3), so the army spreads over objectives instead of swarming one point.

Two items in docs/BUGS.md said "cannot be derived from the art alone". Both only needed somebody to open the file.

Tests

47 headless lanes, green in the editor and green inside the exported binary.

build/linux/z-remake.x86_64 --headless --art-test --quit-after 6000

A lane passes with zero SCRIPT ERROR lines and zero CHECK FAILED lines.