Use this guide when
Use this page when Memory already contains a target reference and the current tick must decide whether that reference is usable. Target restoration should answer one question: what can be proven about this saved reference now? It should not also select a replacement, move a Creep, or delete task state.
Use the Memory guide when the first problem is deciding what data may be stored across ticks.
Store enough context to explain a null result
function saveStaticTarget(target, kind, assignmentVersion) {
if (
!target
|| typeof target.id !== 'string'
|| !target.pos
|| typeof kind !== 'string'
|| !Number.isInteger(assignmentVersion)
) {
return null;
}
return {
id: target.id,
roomName: target.pos.roomName,
kind,
assignmentVersion,
selectedAt: Game.time
};
}
The API needs only the ID. The room name, kind, assignment version, and selection tick are project metadata. They make validation and diagnostics possible without serializing the live object.
A stored room name is most reliable for static targets such as Sources, Structures, and Construction Sites. A moving Creep can leave that room, so its lifecycle usually needs a name-based or movement-aware policy.
Return explicit restoration states
| Status | What is known | Safe default |
|---|---|---|
invalid-record | The saved data does not match the project schema. | Quarantine or clear this owned record. |
wrong-kind | Another task schema is being read. | Do not reinterpret it silently. |
ready | A current visible object passed the expected validator. | Return it to task logic. |
wrong-type | An object was found, but it is not the expected target type. | Clear or migrate the owned record. |
vision-unavailable | No object was returned and the recorded room is not visible. | Keep the reference until vision policy decides. |
missing-visible-room | No object was returned while the recorded room is visible. | Invalidate a static-target reference. |
missing-without-room-context | No object was returned and the record cannot explain visibility. | Require an explicit project policy. |
Resolve first, then interpret null
function resolveSavedTarget(record, expectedKind, isExpectedObject) {
if (
!record
|| typeof record !== 'object'
|| typeof record.id !== 'string'
|| record.id.length === 0
) {
return {
status: 'invalid-record',
target: null
};
}
if (record.kind !== expectedKind) {
return {
status: 'wrong-kind',
target: null
};
}
const target = Game.getObjectById(record.id);
if (target !== null) {
return isExpectedObject(target)
? { status: 'ready', target }
: { status: 'wrong-type', target: null };
}
if (
typeof record.roomName !== 'string'
|| record.roomName.length === 0
) {
return {
status: 'missing-without-room-context',
target: null
};
}
return Game.rooms[record.roomName]
? {
status: 'missing-visible-room',
target: null
}
: {
status: 'vision-unavailable',
target: null
};
}
The object lookup happens before the visibility interpretation. This allows a moving object that is currently visible somewhere else to be returned instead of being rejected solely because an older recorded room is not visible.
Validate the object required by this task
function isSource(target) {
return Boolean(
target
&& typeof target.id === 'string'
&& target.pos
&& Number.isFinite(target.energy)
&& Number.isFinite(target.energyCapacity)
&& Number.isInteger(target.ticksToRegeneration)
);
}
This guard checks the fields used by a Source task. A Structure task should validate structureType; a Construction Site task should validate its progress fields. Do not accept any object merely because the ID resolved.
Keep cleanup and reselection in the caller
function getAssignedSource(creep) {
const result = resolveSavedTarget(
creep.memory.target,
'source',
isSource
);
if (result.status === 'ready') {
return result;
}
if (result.status === 'vision-unavailable') {
return result;
}
if (
result.status === 'invalid-record'
|| result.status === 'wrong-kind'
|| result.status === 'wrong-type'
|| result.status === 'missing-visible-room'
) {
delete creep.memory.target;
}
return result;
}
The resolver reports evidence; the caller owns mutation. This separation prevents a generic helper from selecting a new Source, deleting a remote assignment, or changing role state without the scheduler's consent.
Do not confuse target identity with temporary state
An empty Source still exists. A full Container still exists. A damaged Structure still exists. Resource amount, cooldown, ownership, reservation, and task suitability belong to business rules after identity restoration.
For example, a fixed miner can keep an empty Source assignment and wait for regeneration, while a dynamic harvester may ask the room scheduler for another active Source. Neither policy changes what Game.getObjectById() proved.
Use the identifier that matches the object lifecycle
| Target | Durable reference | Extra context |
|---|---|---|
| Source, Structure, Construction Site | id | Room name, kind, assignment version |
| Creep | Usually name | Role, assignment identity, expected owner |
| Flag | name | Expected room and configuration version |
| Room | roomName | Intel timestamp and visibility state |
| Position | roomName, x, y | Purpose and version |
Verify each branch across real ticks
Capture one valid local target, one remote target without vision, one static target removed while its room is visible, one wrong-kind record, and one wrong-type record. Record only the status and the saved metadata needed to reproduce the branch. This revision contains static review and syntax checks; it does not contain a fabricated remote-vision transcript.
Choose another guide when
Use the dead-Creep Memory guide when a Creep name no longer exists. Use the global-cache guide when IDs are derived acceleration data rather than durable task assignments. Use the RoomVisual guide to draw the resolver status without changing it.