MOVEMENT · ROOMPOSITION DISTANCE

Which Screeps RoomPosition Distance Method Should You Use?

CURATED PATH

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

Movement

Recommended next steps

Apply range checks to ERR_NOT_IN_RANGEPractical useSelect a Source by reachable pathTarget selectionMove from range math to PathFinder.search()Advanced pathfinding
Verification statusChinese source article: Reviewed in full · Official docs: Checked — RoomPosition range, equality, adjacency and closest-target methods · Room boundary: Same-room linear comparison is separated from cross-room routing

VERIFICATION

Evidence and test status

Chinese source article
Reviewed in full
Official docs
Checked — RoomPosition range, equality, adjacency and closest-target methods
Room boundary
Same-room linear comparison is separated from cross-room routing
Semantic boundary
isNearTo() includes the same tile because it equals inRangeTo(target, 1)
JavaScript syntax
Passed
Offline relation review
Passed — equal, adjacent, diagonal, range 3, cross-room and target-selection states
Live path and target-selection test
Pending
Official engine source
Checked August 16, 2026 — getRangeTo(), inRangeTo(), isNearTo(), isEqualTo(), getDirectionTo(), findInRange(), and findClosestByRange()
Cross-room boundary
Verified in source — object/RoomPosition getRangeTo() returns Infinity across rooms while getDirectionTo() computes a world-space direction
Overload boundary
Reviewed — object/RoomPosition targets preserve room identity; local x/y overloads do not encode another room
Screeps Console test
Pending — no live cross-room RoomPosition transcript is claimed
Live path comparison
Pending — no measured route/path comparison is claimed
Last editorial review
August 16, 2026

Quick answer

Use RoomPosition range methods to answer a coordinate question and path methods to answer a travel question. getRangeTo(), inRangeTo(), isNearTo(), isEqualTo(), findClosestByRange(), and findInRange() do not prove that terrain and structures permit a route. findClosestByPath(), findPathTo(), PathFinder.search(), and moveTo() involve pathfinding.

Linear range and path distance

QuestionUse
Can the action run now?Linear range
Are two coordinates equal or adjacent?Equality or range
Which target is geometrically closest?Closest by range
Which target has the shortest usable route?Closest by path
Which rooms should a Creep cross?Map-level routing

In an eight-direction grid, diagonal displacement counts by the larger coordinate difference. From (10,10) to (13,12), the linear range is 3.

getRangeTo() and inRangeTo()

const range = creep.pos.getRangeTo(target);

if (creep.pos.inRangeTo(target, 3)) {
  // A documented range-3 action may run.
}

getRangeTo() returns a finite Chebyshev range only when the target resolves to the same room. In the current official engine, a target with a different roomName returns Infinity. inRangeTo() includes an explicit room-name equality test, so a different-room target returns false for ordinary finite ranges. Those are useful API signals; they are not path length.

function getSameRoomRange(from, to) {
  if (
    !from
    || !to
    || from.roomName !== to.roomName
  ) {
    return null;
  }

  return Math.max(
    Math.abs(from.x - to.x),
    Math.abs(from.y - to.y)
  );
}

Cross-room RoomPosition methods do not all behave the same way

Method with a RoomPosition/object targetDifferent roomWhat the result means
getRangeTo(target)InfinityThere is no same-room linear range. It is not a travel-distance estimate.
inRangeTo(target, n)falseThe target cannot satisfy a same-room action-range test.
isNearTo(target)falseThe positions are not near in the same room.
isEqualTo(target)falseRoom identity is part of equality for a RoomPosition target.
getDirectionTo(target)Direction 1–8The current engine converts room coordinates into world-space displacement and returns a direction, not a route.

This difference matters in diagnostics. A cross-room Infinity from getRangeTo() is expected API behavior, while a finite path length must come from a routing/pathfinding workflow. Also prefer the RoomPosition/object overload when room identity matters: the two-number overload contains only local x and y and cannot encode another room name.

function describePositionApiBoundary(from, to) {
  if (!from || !to) {
    return { status: 'position-missing' };
  }

  return {
    status: from.roomName === to.roomName
      ? 'same-room'
      : 'different-room',
    range: from.getRangeTo(to),
    withinThree: from.inRangeTo(to, 3),
    near: from.isNearTo(to),
    equal: from.isEqualTo(to),
    direction: from.getDirectionTo(to)
  };
}

The returned direction is geometric guidance only. It does not prove that an exit exists in that direction, that a room-level route exists, or that a Creep can traverse the intervening tiles.

isNearTo() and isEqualTo()

const withinOne = creep.pos.isNearTo(target);
const sameTile = creep.pos.isEqualTo(target);
const strictlyAdjacent = withinOne && !sameTile;

The official API defines isNearTo(target) as the same test as inRangeTo(target, 1). That includes range 0. Game objects such as a Creep and a solid Structure usually cannot occupy the same tile, but pure RoomPosition comparisons can.

Closest by range or path

const linearTarget = creep.pos.findClosestByRange(
  FIND_HOSTILE_CREEPS
);

const reachableSource = creep.pos.findClosestByPath(
  FIND_SOURCES_ACTIVE
);
MethodTerrain and blockersTypical use
findClosestByRange()NoTower target, quick shortlist, geometry
findClosestByPath()YesA Creep must travel to one candidate

Both return null when no matching candidate is found. Path-based selection can also return null when candidates exist but no path is available under the supplied options.

Filter candidates with findInRange()

const hostiles = tower.pos.findInRange(
  FIND_HOSTILE_CREEPS,
  10
);

This returns every candidate inside the linear range. It is useful before sorting by hits, role, threat, or another rule. It does not test reachability.

Do not compare local coordinates across rooms

if (from.roomName !== to.roomName) {
  return {
    comparable: false,
    reason: 'different-rooms'
  };
}

Every room reuses local coordinates 0–49. Two positions at (25,25) in different rooms are not the same world location. Do not manually subtract their local coordinates. The API already makes that boundary visible: getRangeTo() returns Infinity and finite inRangeTo() tests fail across rooms. Use Game.map.findRoute(), Game.map.getRoomLinearDistance() when room-count distance is actually the intended metric, PathFinder, or moveTo() for the corresponding cross-room question.

Complete same-room relation helper

function describePositionRelation(
  from,
  to,
  requiredRange
) {
  if (
    !from
    || !to
    || from.roomName !== to.roomName
    || !Number.isInteger(requiredRange)
    || requiredRange < 0
  ) {
    return {
      comparable: false,
      sameTile: false,
      withinOne: false,
      strictlyAdjacent: false,
      inRequiredRange: false,
      range: null
    };
  }

  const range = Math.max(
    Math.abs(from.x - to.x),
    Math.abs(from.y - to.y)
  );

  return {
    comparable: true,
    sameTile: range === 0,
    withinOne: range <= 1,
    strictlyAdjacent: range === 1,
    inRequiredRange: range <= requiredRange,
    range
  };
}

This pure function verifies coordinate semantics. It does not inspect terrain, structures, Creeps, or path callbacks.

Use the required action range

State impact: this example may submit one movement order. It does not write Memory.

const ACTION_RANGE = {
  harvest: 1,
  withdraw: 1,
  transfer: 1,
  pickup: 1,
  build: 3,
  repair: 3,
  upgrade: 3
};

function prepareForAction(creep, target, action) {
  if (!creep || !target?.pos) {
    return {
      status: 'object-invalid'
    };
  }

  const requiredRange = ACTION_RANGE[action];

  if (!Number.isInteger(requiredRange)) {
    return {
      status: 'action-range-unknown'
    };
  }

  if (
    creep.pos.roomName === target.pos.roomName
    && creep.pos.inRangeTo(target, requiredRange)
  ) {
    return {
      status: 'action-range-ready',
      requiredRange,
      range: creep.pos.getRangeTo(target)
    };
  }

  const moveResult = creep.moveTo(target, {
    range: requiredRange,
    reusePath: 10
  });

  return {
    status: moveResult === OK
      ? 'move-submitted'
      : 'move-failed',
    requiredRange,
    moveResult
  };
}

Do not force every action to range 1. Build, repair, and Controller upgrade work at range 3. The range option tells pathfinding where it may stop; it does not change the action's API.

Range does not prove reachability

Two coordinates can have range 2 while a wall, hostile Rampart, Structure, room edge, CostMatrix rule, or traffic pattern prevents direct travel. Range answers “how far apart are the coordinates?” Pathfinding answers “how can this Creep travel under these rules?”

Likewise, a Controller at range 3 is ready for upgrading even when the shortest route to that position would have required many earlier steps. Action range and path length are different measurements.

Debugging checklist

  • Expect getRangeTo() to return Infinity for an object or RoomPosition in another room.
  • Expect finite inRangeTo() and object-target isNearTo() checks to fail across rooms.
  • Do not reinterpret getDirectionTo() across rooms as route reachability.
  • Check roomName before manual same-room range logic.
  • Use isEqualTo() for exact coordinates.
  • Remember that isNearTo() includes range 0.
  • Use inRangeTo() for action readiness.
  • Use findClosestByRange() only when linear proximity is intended.
  • Use findClosestByPath() when a Creep must travel.
  • Handle null from both closest-target methods.
  • Do not use pathfinding merely to check an already-satisfied action range.
  • Do not use range as proof of reachability.

Scope and next steps

This guide does not compare PathFinder heuristics, CPU cost across large candidate sets, multi-room linear distance, portals, traffic reservations, or route caching. Continue with cross-room route planning.

Frequently asked questions

Does getRangeTo() consider obstacles?

No. It is a linear coordinate measurement.

Does isNearTo() mean exactly one tile away?

No. It means range is at most 1. Exclude isEqualTo() for strict adjacency.

Which closest method should a moving Creep use?

Use path-based selection when route length and reachability matter.

Can local x and y compare different rooms?

No. Check room names and use map or path routing.

Official documentation

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.