DEFENSE · NUKER OPERATION IDENTITY

Launch a Nuke Once and Preserve the Exact Operation Record

CURATED PATH

These links are maintained for a concrete prerequisite, failure mode, debugging step, or next lesson instead of generic topic similarity.

Defense / Combat

Recommended next steps

Separate offensive launch operations from local Safe ModeDefense boundaryConnect nuclear threats to fortification planningDefense preparationCheck the visibility boundary for the target RoomTarget verification
Verification statusChinese source article: Reviewed in full · Official engine: Checked — launchNuke zeroes the exact Nuker's Energy and Ghodium, sets cooldown, creates a target Nuke object and emits no Room event · Target boundary: The article does not select a player, target room, coordinates, timing or strategic outcome

VERIFICATION

Evidence and test status

Chinese source article
Reviewed in full
Official engine
Checked — launchNuke zeroes the exact Nuker's Energy and Ghodium, sets cooldown, creates a target Nuke object and emits no Room event
Target boundary
The article does not select a player, target room, coordinates, timing or strategic outcome
Static code review
Passed — target-bound confirmation, exact Nuker identity, accepted-call pending record, local signature and optional target-object verification
JavaScript syntax
Passed
Screeps Console test
Pending
Live protected-area rejection, launch, cooldown, resource consumption and target Nuke observation
Pending
Genuine room or Console screenshots
Pending
Last verified
August 3, 2026

Use two evidence layers

launchNuke() is irreversible and does not emit a Room event in the official engine. Preserve two evidence layers:

  • local launcher evidence from the exact Nuker ID, its post-launch cooldown, and its Energy and Ghodium Stores;
  • target evidence from an exact Nuke object at the reviewed room and coordinates when that room is visible.

Target vision is not required to submit the API call. It is required only for direct observation of the created Nuke object.

Bind approval to Nuker and target

function buildNukeConfirmation(request) {
  return [
    'LAUNCH_NUKE',
    request.nukerId,
    request.targetRoomName,
    request.x,
    request.y
  ].join('_');
}

function isValidTarget(request) {
  return (
    typeof request.targetRoomName === 'string'
    && /^[WE]\d+[NS]\d+$/.test(
      request.targetRoomName
    )
    && Number.isInteger(request.x)
    && request.x >= 0
    && request.x <= 49
    && Number.isInteger(request.y)
    && request.y >= 0
    && request.y <= 49
  );
}

Including the Nuker ID prevents approval for one launcher from being reused by another structure. Any change to room name or coordinates invalidates the old confirmation.

Validate the exact launch request

function evaluateNukeLaunch(request) {
  if (!request || request.enabled !== true) {
    return { ready: false, status: 'request-disabled' };
  }
  if (!isValidTarget(request)) {
    return { ready: false, status: 'invalid-target' };
  }
  if (
    request.confirmation
    !== buildNukeConfirmation(request)
  ) {
    return {
      ready: false,
      status: 'confirmation-mismatch'
    };
  }

  const nuker = Game.getObjectById(request.nukerId);
  if (
    !nuker
    || nuker.my !== true
    || nuker.structureType !== STRUCTURE_NUKER
  ) {
    return { ready: false, status: 'nuker-invalid' };
  }
  if (nuker.isActive() !== true) {
    return { ready: false, status: 'nuker-inactive' };
  }
  if (nuker.cooldown > 0) {
    return { ready: false, status: 'nuker-cooldown' };
  }

  const distance = Game.map.getRoomLinearDistance(
    nuker.room.name,
    request.targetRoomName,
    false
  );
  if (distance > NUKE_RANGE) {
    return { ready: false, status: 'target-out-of-range' };
  }

  if (
    nuker.store.getUsedCapacity(RESOURCE_ENERGY)
    < NUKER_ENERGY_CAPACITY
  ) {
    return { ready: false, status: 'energy-shortage' };
  }
  if (
    nuker.store.getUsedCapacity(RESOURCE_GHODIUM)
    < NUKER_GHODIUM_CAPACITY
  ) {
    return { ready: false, status: 'ghodium-shortage' };
  }

  return { ready: true, status: 'launch-ready', nuker };
}

Current state can still change before intent processing. The method return code is the submission boundary. Protected or unavailable target-room rules must be handled through the documented return code rather than guessed from stale Memory.

Record only an accepted launch

function submitNukeLaunch(request) {
  const decision = evaluateNukeLaunch(request);
  if (!decision.ready) {
    if (request) request.enabled = false;
    return decision;
  }

  const nuker = decision.nuker;
  const target = new RoomPosition(
    request.x,
    request.y,
    request.targetRoomName
  );

  request.enabled = false;
  request.lastAttemptAt = Game.time;

  const result = nuker.launchNuke(target);
  request.lastResult = result;

  if (result !== OK) {
    request.status = 'launch-rejected';
    return {
      status: request.status,
      result
    };
  }

  Memory.pendingNukeLaunches ??= {};
  Memory.pendingNukeLaunches[nuker.id] = {
    submittedAt: Game.time,
    nukerId: nuker.id,
    launchRoomName: nuker.room.name,
    targetRoomName: request.targetRoomName,
    x: request.x,
    y: request.y,
    expectedCooldown: NUKER_COOLDOWN,
    expectedLandTime:
      Game.time + NUKE_LAND_TIME,
    before: {
      energy: nuker.store.getUsedCapacity(
        RESOURCE_ENERGY
      ),
      ghodium: nuker.store.getUsedCapacity(
        RESOURCE_GHODIUM
      ),
      cooldown: nuker.cooldown
    }
  };

  request.status = 'accepted-awaiting-verification';

  return {
    status: request.status,
    result,
    nukerId: nuker.id,
    targetRoomName: request.targetRoomName,
    x: request.x,
    y: request.y
  };
}

The request is disabled before the call so a thrown exception or later module cannot repeat an irreversible action. A rejected request stays disabled for human review. Only OK creates the pending operation record.

Verify the launcher signature

function verifyNukerState(pending) {
  if (!pending) return { status: 'no-pending-launch' };
  if (Game.time <= pending.submittedAt) {
    return { status: 'wait-for-next-tick' };
  }

  const nuker = Game.getObjectById(pending.nukerId);
  if (!nuker) return { status: 'nuker-not-visible' };

  const energy =
    nuker.store.getUsedCapacity(RESOURCE_ENERGY);
  const ghodium =
    nuker.store.getUsedCapacity(RESOURCE_GHODIUM);

  const localSignature =
    nuker.cooldown > 0
    && energy === 0
    && ghodium === 0;

  return {
    status: localSignature
      ? 'launcher-signature-observed'
      : 'accepted-launch-signature-mismatch',
    nukerId: nuker.id,
    cooldown: nuker.cooldown,
    energy,
    ghodium,
    expectedCooldown:
      pending.expectedCooldown
  };
}

The official engine sets an absolute cooldown time internally; the API exposes remaining cooldown. Check for a positive cooldown rather than requiring a copied value at every observation tick. The zero-resource signature is local proof for this Nuker, but it does not replace optional target evidence.

Match the target Nuke when visible

function verifyTargetNuke(pending) {
  const room = Game.rooms[pending.targetRoomName];
  if (!room) {
    return { status: 'target-evidence-unavailable' };
  }

  const matches = room.find(FIND_NUKES).filter(nuke =>
    nuke.pos.x === pending.x
    && nuke.pos.y === pending.y
    && nuke.launchRoomName
      === pending.launchRoomName
  );

  if (matches.length === 0) {
    return { status: 'target-nuke-not-observed' };
  }
  if (matches.length > 1) {
    return {
      status: 'target-nuke-ambiguous',
      count: matches.length
    };
  }

  return {
    status: 'target-nuke-observed',
    nukeId: matches[0].id,
    launchRoomName:
      matches[0].launchRoomName,
    timeToLand: matches[0].timeToLand,
    expectedLandTime:
      pending.expectedLandTime
  };
}

Coordinates alone are not enough because several players can launch at the same tile. Match the saved launching room as well. timeToLand is current remaining time; expectedLandTime is the submitted absolute planning value and should be reported separately.

Keep incomplete evidence visible

StatusMeaningResponse
confirmation-mismatchThe approved launcher or target changedRequire a new review
launch-rejectedThe API did not accept the irreversible actionKeep the request disabled and retain the return code
accepted-launch-signature-mismatchThe saved Nuker lacks the expected local statePreserve the discrepancy
target-evidence-unavailableThe target room is not visibleReport local evidence only
target-nuke-not-observedVision exists but no exact Nuke matchesDo not substitute another Nuke at the tile
target-nuke-ambiguousMore than one exact launcher-and-position match existsInspect the room objects directly

Production integration boundary

Keep one irreversible-operations queue, disable each request before the API call, and archive accepted records without mutating their target fields. Do not automate target selection, diplomacy, damage prediction or launch timing from this guide. Console execution, protected-area behavior, live Nuke observation and genuine screenshots remain pending.

Official documentation

Review the official Screeps API for StructureNuker.launchNuke(), RoomPosition, FIND_NUKES, Nuke.launchRoomName, Nuke.timeToLand, NUKE_RANGE, capacities, cooldown, landing time and return codes before adapting the examples.

SOURCE AND SCOPE

Review the source, evidence, or next system

This English guide keeps the technical scope and verification boundaries of its Chinese source. The verification record shows which checks were completed and which runtime observations are still pending.