CONFIGURATION · FLAGS AND OBJECT REFERENCES

How to Use Flags as Reviewed Configuration Instead of Hidden Automation

Resolve exact Flag names from Game.flags, validate flag.memory fields, recover configured targets by ID before a deterministic local fallback, and report missing or stale configuration without mutating Flags.

Verification statusChinese source article: Reviewed in full · Official docs: Checked — Game.flags, Flag.name, Flag.pos, Flag.memory and Game.getObjectById() · Policy boundary: Required Flag names, mode values and fallback rules are project configuration

VERIFICATION

Evidence and test status

Chinese source article
Reviewed in full
Official docs
Checked — Game.flags, Flag.name, Flag.pos, Flag.memory and Game.getObjectById()
Policy boundary
Required Flag names, mode values and fallback rules are project configuration
Mutation boundary
The examples read Flags and write diagnostics only; they do not create, move, rename or remove Flags
JavaScript syntax
Passed
Offline configuration review
Passed — missing Flag, invalid mode, stale object ID, visible-room fallback and stable tie states
Screeps Console test
Pending
Live Flag rename, removal, invisible-room and object replacement test
Pending
Last verified
July 26, 2026

Quick answer

Define required Flag names in code, resolve each one directly from Game.flags[name], validate every custom flag.memory field, recover an optional target ID with Game.getObjectById(), and use only a narrow room-local fallback when the ID is missing or stale. Record configuration status separately. Do not choose the first Flag or mutate Flags as a side effect of reading configuration.

Use exact Flag names

const FLAG_CONFIG = {
  remoteMine: 'RemoteMine_W2N2',
  rally: 'Rally_W1N1'
};

function getNamedFlag(name) {
  return typeof name === 'string'
    ? Game.flags[name] || null
    : null;
}

Names are a project contract. Document them like role names and Memory schema fields.

Treat Flag memory as untrusted input

const ALLOWED_REMOTE_MODES = new Set([
  'observe',
  'harvest',
  'pause'
]);

function readRemoteFlagMemory(flag) {
  if (!flag) {
    return { valid: false, reason: 'flag-missing' };
  }

  const mode = flag.memory?.mode;
  const sourceId = flag.memory?.sourceId;

  if (!ALLOWED_REMOTE_MODES.has(mode)) {
    return { valid: false, reason: 'invalid-mode' };
  }

  if (
    sourceId !== undefined
    && typeof sourceId !== 'string'
  ) {
    return { valid: false, reason: 'invalid-source-id' };
  }

  return {
    valid: true,
    reason: 'valid',
    mode,
    sourceId: sourceId || null
  };
}

A misspelled value should fail closed rather than silently selecting another mission.

Prefer a configured object ID

function recoverConfiguredSource(sourceId) {
  if (typeof sourceId !== 'string') {
    return null;
  }

  const object = Game.getObjectById(sourceId);

  return object
    && object.energy !== undefined
    && object.energyCapacity !== undefined
    ? object
    : null;
}

Recover the current object each tick. An ID can become stale after a typo, object replacement or changed mission.

Use a narrow local fallback

function selectSourceNearFlag(flag) {
  if (!flag?.room) {
    return null;
  }

  return flag.room.find(FIND_SOURCES)
    .map(source => ({
      source,
      range: flag.pos.getRangeTo(source)
    }))
    .sort((left, right) =>
      left.range - right.range
      || left.source.id.localeCompare(right.source.id)
    )[0]?.source || null;
}

The fallback is limited to the visible Flag room and uses stable range and ID ordering. It does not rewrite the configured ID automatically.

Complete Flag configuration reader

function readRemoteMiningConfiguration() {
  const flagName = FLAG_CONFIG.remoteMine;
  const flag = getNamedFlag(flagName);
  const memory = readRemoteFlagMemory(flag);

  if (!flag || !memory.valid) {
    return {
      ready: false,
      reason: memory.reason,
      flagName
    };
  }

  if (memory.mode === 'pause') {
    return {
      ready: false,
      reason: 'mission-paused',
      flagName,
      roomName: flag.pos.roomName
    };
  }

  const configuredSource = recoverConfiguredSource(
    memory.sourceId
  );
  const fallbackSource = configuredSource
    ? null
    : selectSourceNearFlag(flag);
  const source = configuredSource || fallbackSource;

  if (!source) {
    return {
      ready: false,
      reason: flag.room
        ? 'source-not-found'
        : 'flag-room-not-visible',
      flagName,
      roomName: flag.pos.roomName,
      configuredSourceId: memory.sourceId
    };
  }

  return {
    ready: true,
    reason: 'ready',
    flagName,
    mode: memory.mode,
    roomName: flag.pos.roomName,
    x: flag.pos.x,
    y: flag.pos.y,
    sourceId: source.id,
    sourceSelection: configuredSource
      ? 'configured-id'
      : 'nearest-visible-fallback'
  };
}
function recordFlagConfigurationStatus(key, status) {
  Memory.configurationStatus ??= {};
  Memory.configurationStatus.flags ??= {};

  Memory.configurationStatus.flags[key] = {
    checkedAt: Game.time,
    ...status
  };
}
module.exports.loop = function () {
  const configuration = readRemoteMiningConfiguration();
  recordFlagConfigurationStatus('remoteMine', configuration);

  if (!configuration.ready || Game.time % 100 === 0) {
    console.log(JSON.stringify({
      type: 'flag-configuration-status',
      ...configuration
    }));
  }
};

Do not use the first Flag or Source

const unsafeFlag = Object.values(Game.flags)[0];
const unsafeSource = unsafeFlag?.room?.find(FIND_SOURCES)[0];

Object order is not a mission contract. Exact names and stable target selection prevent unrelated additions from changing behavior.

Report missing and stale configuration

function summarizeRequiredFlags(names) {
  return names.map(name => {
    const flag = Game.flags[name];

    return flag
      ? {
          name,
          present: true,
          roomName: flag.pos.roomName,
          x: flag.pos.x,
          y: flag.pos.y
        }
      : { name, present: false };
  });
}

Expose the exact missing name and stale ID instead of silently switching missions.

Debugging checklist

  • Document every required Flag name.
  • Resolve Flags by exact name.
  • Validate custom Flag memory.
  • Store object IDs, not live objects.
  • Recover IDs each tick.
  • Use a narrow deterministic fallback.
  • Do not select the first Flag or Source.
  • Do not mutate Flags while reading configuration.
  • Record missing and stale state.

Scope and next steps

This guide does not create, move, recolor or remove Flags, implement remote harvesting, coordinate invisible rooms or define diplomacy. Continue with module organization.

Frequently asked questions

Why allow a fallback?

It keeps visible-room configuration diagnosable when an ID is missing, while clearly marking that the configured identity was not used.

Should the fallback save the new Source ID?

Not automatically. Review the reason for the missing ID before changing persistent configuration.

Can Flag memory be shared across modules?

Yes, but one documented reader should validate it so different modules do not interpret the same fields differently.

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.