Combat skill: attacks, raids, defense

Combat exists to move ore. Raiding is how you take another player’s mined ore; attacks soften defenses and kill structs; defense keeps your own ore and infrastructure alive. Raids steal ore. That’s it. Your account is never at risk from raids. The single most important fact: raidability is a live state predicate about the defender’s fleet and Command Ship — not the shield level number. The displayed shield value (e.g. 25–125) only sets raid PoW difficulty (a timer). “Shields are up” does not mean “cannot be raided.” Gate = IsDefenderCommandStructVulnerable() (no owner / no fleet / fleet off-station / no CMD ship / CMD destroyed / CMD offline). Keep your fleet on station with the Command Ship online and you are effectively unraidable; to raid someone, you must catch them with the gate open — or open it by destroying (or power-starving) their Command Ship. Vulnerability is a state you can force, not just one to wait for. (The Command Ship only defends home while the fleet is on station, so sending your fleet away to raid opens your gate until it returns.)

Conventions (TX_FLAGS, -- rule, -D 3 PoW, the per-player charge bar, one-tx-at-a-time) come from conventions.md. Interface: if Structs Desktop MCP is connected, prefer structs_intel (scout, valid_targets, raid_readiness, battle_log) and structs_action/structs_strike for engagements — simulate and strike_options are struct-scoped (there is no planet-raid preflight simulator). Use raid_readiness {only_gaps:true} before combat to find READY/PARTIAL/BLIND ambit coverage, and battle_log {category:"all"} when you need all planet activity rather than only struct_attack. The structsd commands below are the complete fallback.

When to use it

Decisions

Two ways to raid: opportunistic vs siege

Shield-vulnerability is a state you can create, not just one you wait for. This is the most-missed idea in raiding. There are two modes:

An online Command Ship should trigger the question “can I destroy it?”, not “next target.” See the siege procedure below.

Idle is not vulnerable (and the fleet-move trap)

A dormant owner (idle for days) is not a vulnerable one. Powered structs stay online with no player action, so an idle owner’s Command Ship keeps defending indefinitely — the opportunistic gate stays shut. Never infer raidability from an inactivity signal or a UI “vulnerable”/”inactive” badge (those are derived from activity, not the live shield predicate). Confirm the live state: Command Ship online + fleet on station.

The trap this avoids is real and strictly-negative: moving your fleet to a not-yet-vulnerable target drops your own shields (fleet off-station) and exposes your stored ore, for a raid that can never complete. If you move your fleet, commit to the siege, not just the move. (The upside: a dormant owner who holds ore and won’t rebuild is the best siege target — the window you force open stays open.)

Raid go/no-go (the most important decision)

Use scripts/scout.sh [planet-id] for a structured read, then decide by mode:

  1. Is there ore to take? — defender player storedOre > 0 (StoredOreAttributeId on the player object; do not read the planet’s buriedOre). A successful raid seizes all of it at MsgPlanetRaidComplete (atomic; no partial loot). No ore → no raid, in either mode.
  2. Is the raidability gate open right now? — fleet off-station, or Command Ship offline/destroyed/absent. This is not the displayed shield number.
  3. Will you survive the resolution and the window? — your fleet must out-damage the defense, and (for a siege) kill the Command Ship before an active defender rebuilds it.

There is no planet-raid simulator (simulate/strike_options are struct-scoped). Run the three reads — player storedOre, the gate, blockStartRaid — per candidate. Do not declare the network empty from a partial sample.

When NOT to raid: no/low stored ore; a shield so high the PoW outlasts your window; a well-defended Command Ship guarded by a bloc that will retaliate for less ore than you’d lose; or you cannot reach the Command Ship’s ambit. Raiding is an expedition — it costs you a fleet locked away and your home undefended by fleet. Expected ore must beat that cost. An honest no-go (or “watch and wait”) is a win, not a failure.

Defense doctrine

Desktop autonomous-combat controls

Current Desktop schemas are intentionally small:

Legacy response modes/per-incident caps, time windows, mid-raid refining, and separate vulnerability/siege gates are not current controls. Evaluate loops with autonomy:"advise"; preview-only strike planning is separate. Mid-raid refine is paused by chain v0.21.0, so response hardening recalls/restores the fleet instead.

Decisions live in playbooks/situations/under-attack, guild-war, and playbooks/meta/counter-strategies.

How a raid resolves

blockStartRaid is the defender’s vulnerability clock, and raid PoW age is measured from it:

The clock only runs while your raider is present at the target — it is set at arrival if the defender is already vulnerable (opportunistic), or the moment their Command Ship drops while you’re there (siege). So a raid is a race against the defender noticing and restoring the gate. Scout the CMD ship and fleet position first. For an opportunistic raid, don’t move your fleet until the gate is already open; for a siege, moving in is step one and you open it yourself.

A raid steals ore. A successful raid seizes all of the defender’s storedOre (StoredOreAttributeId on the player) and nothing more — it does not destroy the player or their structs. Settlement is atomic at MsgPlanetRaidComplete; there is no partial loot and no refund. Killing the defender’s Command Ship opens the shieldsVulnerable window so the raid can complete; if the defender restores or rebuilds it before you finish, completion is rejected (shields_active) and you get nothing. Beware the reverse: trigger_raid_defeat_by_destruction is on the Command Ship, so if your raiding CMD ship is destroyed while away, your fleet is defeated (attackerDefeated) and sent home. Win path for ore: strip same-ambit blockers → destroy the defender’s CMD ship → complete the raid before they rebuild it (most reliable vs an offline defender).

Procedure — opportunistic raid (defender already vulnerable)

  1. Scout — scripts/scout.sh [planet-id] (or structsd query structs planet [id] + player + struct queries). Confirm the go conditions above: player storedOre, Command Ship status (offline/destroyed/absent or fleet off-station), and blockStartRaid. Do not treat the planet’s buried ore or the shield number as the loot or the gate.
  2. Optional stealth — stealth a unit before approach (struct-stealth-activate, 2 charge); attacking later auto-drops it.
  3. Move fleet to the target (instant). Your fleet (and your Command Ship) is now away; you can’t build/mine at home while away, and your own planet’s shields are now vulnerable until the fleet returns — refine your home ore before you leave.
    structsd tx structs fleet-move TX_FLAGS -- [fleet-id] [destination-location-id]
    
  4. Approval Block — fleet is your raider and now at the target; defender’s CMD ship is down (verified); your home ore is refined or below your theft tolerance; you accept an auto-submitted completion landing minutes-to-hours out.
  5. Raid compute (expedition, auto-submits completion — the documented -y exception):
    nohup structsd tx structs planet-raid-compute -D 3 --from [key] --gas auto --gas-adjustment 1.5 -y -- [fleet-id] \
      > memory/jobs/raid-[fleet-id].log 2>&1 & echo $! > memory/jobs/raid-[fleet-id].pid
    
  6. Move fleet home and refine the stolen ore immediately — it’s stealable in your hands now too.

If the defender restores their Command Ship mid-raid, the clock resets — withdraw or wait for it to drop again.

Procedure — siege raid (force the window open)

Use this when the target holds ore but is shielded (Command Ship online, fleet on station) — the case an opportunistic raid can’t touch. It costs a fleet engagement and leaves your home exposed, so run the go/no-go above first. Best against a dormant defender who won’t rebuild.

  1. Scout the Command Ship’s ambit and defenders — scripts/scout.sh [planet-id] surfaces the defender’s Command Ship id and status; query it directly with structsd query structs struct [commandStruct-id] for its operatingAmbit. To enumerate the same-ambit structs that can block for it, use the Guild Stack (“defenders by planet” — there is no structsd CLI command that lists a planet’s structs). Confirm you have weapons that reach the Command Ship’s ambit.
  2. Refine your own ore and move your fleet to the target. Your home shields drop while away — accept that exposure as the cost of the siege. A planet holds one visiting fleet by default; if the slot is taken, fleet-move is queue_full.
    structsd tx structs fleet-move TX_FLAGS -- [fleet-id] [destination-location-id]
    

    At this point planet-raid-compute will still reject (no active raid window) — that is expected; the window isn’t open yet.

  3. Strip same-ambit blockers, then destroy the Command Ship with struct-attack (space repeated attacks; the charge bar is per-player and doesn’t bank — coordinate multiple accounts to focus-fire if you have them). Destroying it fires the chain’s vulnerability hook and opens shieldsVulnerable with your raider present.
    structsd tx structs struct-attack TX_FLAGS -- [operating-struct-id] [target-id] [weapon-system]
    
  4. Verify the window is open — structsd query structs planet [planet-id] shows blockStartRaid != 0 (raid status shieldsVulnerable). Only now is compute worthwhile.
  5. Raid compute (same command as opportunistic step 5), then move home and refine the seized ore immediately.

Watch for the defender rebuilding the Command Ship (an active defender will) — if it comes back online with the fleet on station before your proof lands, the clock resets and completion fails. Never let your raiding Command Ship die while away (attackerDefeated).

For Desktop structs_hash start, RAID and BUILD require the real block_start; the hasher refuses to guess because a current-block anchor always produces a chain-rejected proof. MINE/REFINE may omit it: Desktop resolves the struct’s planet and reads the shared planet ore clock.

Procedure — direct attack

Scout the target’s ambit and defense type, position (Command Ship only) into range, then fire. The attack needs only the attacking struct and its owner online — your Command Ship does not need to be online to attack, change defenders, or change stealth. The target must be a built struct: a struct that is still building cannot be attacked (unbuilt), and a destroyed one is rejected (destroyed); the target’s online status is irrelevant. The CLI prompts; verify target IDs and that you aren’t crossing guild lines you didn’t intend to (attacking another guild’s structs is a Tier 2 act of war). Note most weapons are single-target (primaryWeaponTargets = 1) — the comma list only spreads damage for weapons whose target count is > 1.

Planner false-negative fallback. structs_strike and structs_intel {query:"strike_options"} are advisers, not chain authority. A 2026-09-24 playtest saw both report “no reach” while an online, land-operating Mobile Artillery was co-located with a land Command Ship; the direct attack succeeded. Before accepting an “unreachable” verdict, refresh the raw attacker, target, and fleet records and independently confirm:

  1. attacker is built, online, not destroyed, and its owner is online;
  2. attacker and target resolve to the same planet (a fleet struct’s locationId is a fleet id, so follow that fleet’s locationId to the planet);
  3. the selected weapon’s reach bitmask includes the target’s current operatingAmbit;
  4. target is built, not destroyed, and not hidden from that attacker.

If all four hold, the planner refusal is a Desktop bug or stale-cache result, not proof that the chain will reject. Use the ordinary struct-attack action/preflight and let the chain arbitrate; record the planner output plus the fresh raw reads for a bug report. This fallback does not waive normal approval or rules of engagement.

structsd tx structs struct-attack TX_FLAGS -- [operating-struct-id] [target-id,target-id2,...] [weapon-system]

Attacks cost 3-5 charge from your per-player bar; space repeated attacks accordingly.

Procedure — defense setup

structsd tx structs struct-defense-set TX_FLAGS -- [defender-struct-id] [protected-struct-id]
structsd tx structs struct-defense-clear TX_FLAGS -- [defender-struct-id]

Only fleet structs can be assigned as a defender (canDefend: true; 1 charge each; stagger ~6 s on one key) as long as the defender is built, online, and co-located with the protected struct — ambit is not required to assign. Planetary types (Ore Extractor, Refinery, Ore Bunker, PDC, generators, …) are rejected. Ambit decides what the defender can do: same-ambit is required only to block (intercept a hit), while a cross-ambit defender still counters whenever its weapon can reach the attacker. Spread fleet defenders across ambits for counter coverage; keep same-ambit defenders where you need real interception. Minimum viable defense: at least one combat struct per ambit guarding the Command Ship (6 HP; most fleet structs are 3 HP).

Tactical reference

Targeting (which struct hits which ambit)

Struct Lives In Primary Secondary
Command Ship Any (movable) current ambit only —
Battleship Space Land, Water (armour-piercing) Space
Starfighter Space Space Space (Attack Run, ≥1 hit)
Frigate Space Space, Air —
Pursuit Fighter Air Air —
Stealth Bomber Air Land, Water —
High Alt Interceptor Air Space, Air —
Mobile Artillery Land Land, Water —
Tank Land Land —
SAM Launcher Land Space, Air —
Cruiser Water Land, Water Air
Destroyer Water Air, Water —
Submersible Water Space, Water —

The Command Ship is the only struct that can change ambits (struct-move); it attacks only its current ambit. Reposition it into range to attack, or out of range to hide.

Weapon control vs defense (evasion + armour-piercing)

Target Defense vs Guided vs Unguided
Signal Jamming (Battleship, Pursuit Fighter, Cruiser) 66% miss full hit
Defensive Maneuver (High Alt Interceptor) full hit 66% miss
Armour (Tank, Field Generator, Continental Power Plant, World Engine) full hit, −1 dmg full hit, −1 dmg
Stealth Mode (Stealth Bomber, Submersible) same-ambit only same-ambit only
Indirect Combat (Mobile Artillery) full hit full hit
None full hit full hit

Use unguided vs Signal Jamming, guided vs Defensive Maneuver. Armour reduces damage by 1 — except against armour-piercing weapons (the Battleship primary), which ignore it. The Battleship is the dedicated answer to Tanks and to the (now armoured) power generators. Minimum damage after reduction is always 1.

Combat resolution notes

Commands reference

Action CLI Command
Attack structsd tx structs struct-attack TX_FLAGS -- [struct-id] [target-ids] [weapon-system]
Raid compute (PoW + auto-complete) structsd tx structs planet-raid-compute -D 3 TX_FLAGS_APPROVED -- [fleet-id]
Raid complete (manual, rare) structsd tx structs planet-raid-complete TX_FLAGS -- [fleet-id] [proof] [nonce]
Fleet move structsd tx structs fleet-move TX_FLAGS -- [fleet-id] [destination-location-id]
Defense set / clear structsd tx structs struct-defense-set \| struct-defense-clear TX_FLAGS -- [defender-id] [protected-id]
Stealth on / off structsd tx structs struct-stealth-activate \| struct-stealth-deactivate TX_FLAGS -- [struct-id]
Move Command Ship (ambit) structsd tx structs struct-move TX_FLAGS -- [cmd-ship-id] [ambit] [slot] [location]

Raid flow: scout → (CMD ship down?) → fleet-move → raid-compute → fleet-move home → refine. planet-raid-compute is the documented -y exception; your Approval Block is the gate. planet-raid-complete does not consume charge.

Requires: structsd on PATH and a signing key.

Verification

Errors

See also