RESOURCES · LAB BOOST WORKFLOW

How to Boost Creep Body Parts Safely in Screeps

Match a Lab mineral to BOOSTS, count eligible unboosted body parts, calculate LAB_BOOST_MINERAL and LAB_BOOST_ENERGY budgets, enforce range 1, ownership and activity, submit one reviewed boost request, and verify exact body-part changes afterward.

Verification statusChinese source article: Reviewed in full · Official docs: Checked — boostCreep(), BOOSTS, per-part mineral and Energy, range, bodyPartsCount, part order and return codes · Eligibility boundary: Only unboosted parts of the body type supported by the Lab mineral are counted

VERIFICATION

Evidence and test status

Chinese source article
Reviewed in full
Official docs
Checked — boostCreep(), BOOSTS, per-part mineral and Energy, range, bodyPartsCount, part order and return codes
Eligibility boundary
Only unboosted parts of the body type supported by the Lab mineral are counted
Execution boundary
OK means the boost was scheduled; body-part boost fields require later verification
JavaScript syntax
Passed
Offline boost review
Passed — Lab, Creep, mineral mapping, eligible parts, requested count, Store budgets and range states
Screeps Console test
Pending
Live boost, body-part order and Store delta test
Pending
Last verified
July 26, 2026

Quick answer

Recover one owned active Lab and one owned Creep in the same room, read the Lab mineral, find the supported body type through BOOSTS, count unboosted eligible parts, limit the requested count, require LAB_BOOST_MINERAL and LAB_BOOST_ENERGY per part, enforce range 1, disable the one-time request before lab.boostCreep(), then compare body-part boost fields and Lab Store afterward.

Map the Lab mineral through BOOSTS

function getBoostBodyType(mineralType) {
  if (typeof mineralType !== 'string') {
    return null;
  }

  for (const bodyType of BODYPARTS_ALL) {
    if (BOOSTS[bodyType]?.[mineralType]) {
      return bodyType;
    }
  }

  return null;
}

Do not infer the body type from the mineral name. Use the current official BOOSTS mapping.

Count eligible unboosted parts

function getEligibleBoostParts(creep, bodyType) {
  return creep.body
    .map((part, index) => ({ part, index }))
    .filter(({ part }) =>
      part.type === bodyType
      && part.hits > 0
      && !part.boost
    );
}

Damaged but active parts remain eligible when hits > 0. Already boosted parts must not be counted again.

Understand body-part application order

function getExpectedBoostIndexes(
  eligible,
  bodyType,
  count
) {
  const ordered = bodyType === TOUGH
    ? [...eligible]
    : [...eligible].reverse();

  return ordered
    .slice(0, count)
    .map(item => item.index);
}

This prediction helps verification when bodyPartsCount is lower than the total eligible count. The API's part-order rule matters for carefully ordered combat bodies.

Calculate mineral and Energy budgets

function calculateBoostBudget(partCount) {
  if (!Number.isInteger(partCount) || partCount <= 0) {
    return null;
  }

  return {
    mineral: partCount * LAB_BOOST_MINERAL,
    energy: partCount * LAB_BOOST_ENERGY
  };
}

The Lab must already contain the boost mineral and enough Energy. Resource hauling is a separate workflow.

Build a testable boost plan

function evaluateBoost(input) {
  const { lab, creep, requestedParts } = input;

  if (!lab || !creep) {
    return { ready: false, reason: 'object-missing' };
  }

  if (lab.room.name !== creep.room.name) {
    return { ready: false, reason: 'different-rooms' };
  }

  const mineralType = lab.mineralType;
  const bodyType = getBoostBodyType(mineralType);

  if (!mineralType || !bodyType) {
    return { ready: false, reason: 'boost-mineral-invalid' };
  }

  const eligible = getEligibleBoostParts(creep, bodyType);
  const count = requestedParts == null
    ? eligible.length
    : requestedParts;

  if (
    !Number.isInteger(count)
    || count <= 0
    || count > eligible.length
  ) {
    return {
      ready: false,
      reason: 'part-count-invalid',
      eligibleCount: eligible.length
    };
  }

  const budget = calculateBoostBudget(count);

  if (
    lab.store.getUsedCapacity(mineralType)
      < budget.mineral
    || lab.store.getUsedCapacity(RESOURCE_ENERGY)
      < budget.energy
  ) {
    return {
      ready: false,
      reason: 'resources-insufficient',
      mineralType,
      bodyType,
      ...budget
    };
  }

  if (!lab.pos.isNearTo(creep)) {
    return { ready: false, reason: 'creep-out-of-range' };
  }

  return {
    ready: true,
    reason: 'ready',
    mineralType,
    bodyType,
    partCount: count,
    expectedIndexes:
      getExpectedBoostIndexes(eligible, bodyType, count),
    ...budget
  };
}

Complete one-time boost example

State impact: this code may schedule one real boost and writes a request snapshot. It never retries automatically.

function getOwnedActiveLab(id) {
  const lab = typeof id === 'string'
    ? Game.getObjectById(id)
    : null;

  return lab
    && lab.structureType === STRUCTURE_LAB
    && lab.my === true
    && lab.isActive() === true
      ? lab
      : null;
}

module.exports.loop = function () {
  const request = Memory.labBoostRequest;

  if (!request || request.enabled !== true) {
    return;
  }

  const lab = getOwnedActiveLab(request.labId);
  const creep = typeof request.creepName === 'string'
    ? Game.creeps[request.creepName]
    : null;
  const ownedCreep = creep?.my === true
    && creep.spawning !== true
      ? creep
      : null;
  const plan = evaluateBoost({
    lab,
    creep: ownedCreep,
    requestedParts: request.bodyPartsCount
  });

  request.lastCheckedAt = Game.time;
  request.lastStatus = plan.reason;

  if (!plan.ready) {
    request.preview = {
      eligibleCount: plan.eligibleCount ?? null,
      mineral: plan.mineral ?? null,
      energy: plan.energy ?? null
    };
    return;
  }

  request.enabled = false;
  request.submittedAt = Game.time;
  request.snapshot = {
    labId: lab.id,
    creepName: ownedCreep.name,
    mineralType: plan.mineralType,
    bodyType: plan.bodyType,
    partCount: plan.partCount,
    expectedIndexes: plan.expectedIndexes,
    mineralBefore:
      lab.store.getUsedCapacity(plan.mineralType),
    energyBefore:
      lab.store.getUsedCapacity(RESOURCE_ENERGY),
    boostsBefore: ownedCreep.body.map(part =>
      part.boost ?? null
    )
  };

  const result = lab.boostCreep(
    ownedCreep,
    plan.partCount
  );

  request.result = result;
  request.resultAt = Game.time;
  request.status = result === OK
    ? 'accepted-pending-verification'
    : 'failed-review-required';
};

Verify body and Store changes

function verifyBoost(request) {
  const snapshot = request?.snapshot;
  const creep = snapshot
    ? Game.creeps[snapshot.creepName]
    : null;

  if (!snapshot || !creep) {
    return { verified: false, reason: 'snapshot-or-creep-missing' };
  }

  const changedIndexes = creep.body
    .map((part, index) => ({
      index,
      before: snapshot.boostsBefore[index],
      after: part.boost ?? null
    }))
    .filter(item => item.before !== item.after)
    .map(item => item.index);

  return {
    verified:
      request.result === OK
      && changedIndexes.length === snapshot.partCount,
    changedIndexes,
    expectedIndexes: snapshot.expectedIndexes
  };
}

The Creep may die or leave visibility before verification. Keep the request snapshot and treat that as an unavailable outcome, not automatic success.

Handle return codes

CodeMeaning
OKBoost scheduled
ERR_NOT_ENOUGH_RESOURCESMineral or Energy insufficient
ERR_INVALID_TARGETCreep cannot be boosted by this Lab mineral
ERR_NOT_IN_RANGECreep is not adjacent
ERR_INVALID_ARGSRequested body-part count is invalid
ERR_RCL_NOT_ENOUGHLab is inactive at the current RCL

Debugging checklist

  • Recover one owned active Lab and one owned Creep.
  • Require the same room and range 1.
  • Map the mineral through BOOSTS.
  • Count only active unboosted eligible parts.
  • Validate the requested count.
  • Calculate per-part mineral and Energy.
  • Predict part order for limited boosts.
  • Disable before the call.
  • Save body and Store snapshots.
  • Verify exact changed indexes later.

Scope and next steps

This guide does not implement boost queues, Lab mineral loading, body design, combat deployment, unboosting, or multi-Lab assignment. Continue with Factory commodity production.

Frequently asked questions

Can already boosted parts be boosted again?

No. Count only unboosted eligible parts.

Can bodyPartsCount exceed eligible parts?

No. Reject that request before calling.

Why predict indexes?

Limited boosts follow a documented body-order rule and can affect combat body behavior.

Should a failed boost retry every tick?

No. Require a new reviewed request.

Official documentation

SOURCE AND SCOPE

Review the source, evidence, or next system

This English guide is rewritten for a focused search intent while preserving the technical scope and verification boundaries of its Chinese source. Live-room evidence is claimed only when the verification record says it exists.