core/direction.js

/**
 * Direction constants and helpers.
 * Mirrors Direction.java exactly, including xDelta/yDelta and reverse lookup.
 */

class Direction {
  constructor(name, xDelta, yDelta, reverseName) {
    this.name = name;
    this.xDelta = xDelta;
    this.yDelta = yDelta;
    this._reverseName = reverseName;
    // Register by lowercase and capitalized name
    byName.set(name, this);
    byName.set(name[0] + name.slice(1), this);
  }

  /** Direction in the opposite direction. */
  get reverse() {
    return byName.get(this._reverseName);
  }

  isDiagonal() {
    return (
      this === NORTHEAST ||
      this === NORTHWEST ||
      this === SOUTHEAST ||
      this === SOUTHWEST
    );
  }
  isVertical() {
    return this === UP || this === DOWN;
  }
  isNorthSouth() {
    return this === NORTH || this === SOUTH;
  }
  isEastWest() {
    return this === EAST || this === WEST;
  }
  isNortherly() {
    return this === NORTHWEST || this === NORTH || this === NORTHEAST;
  }
  isSoutherly() {
    return this === SOUTHWEST || this === SOUTH || this === SOUTHEAST;
  }
  isWesterly() {
    return this === NORTHWEST || this === WEST || this === SOUTHWEST;
  }
  isEasterly() {
    return this === NORTHEAST || this === EAST || this === SOUTHEAST;
  }

  toString() {
    return this.name;
  }
}

const byName = new Map();

export const NO_DIRECTION = new Direction("none", 0, 0, "none");
export const NONE = new Direction("none", 0, 0, "none");
export const NORTH = new Direction("north", 0, -1, "south");
export const SOUTH = new Direction("south", 0, 1, "north");
export const EAST = new Direction("east", 1, 0, "west");
export const WEST = new Direction("west", -1, 0, "east");
export const NORTHWEST = new Direction("northwest", -1, -1, "southeast");
export const NORTHEAST = new Direction("northeast", 1, -1, "southwest");
export const SOUTHWEST = new Direction("southwest", -1, 1, "northeast");
export const SOUTHEAST = new Direction("southeast", 1, 1, "northwest");
export const UP = new Direction("up", 0, 0, "down");
export const DOWN = new Direction("down", 0, 0, "up");

/** Directions that can lead to adjacent boards (cardinal + vertical). */
export const MAP_DIRECTIONS = [NORTH, SOUTH, EAST, WEST, UP, DOWN];

/** Directions that lead to adjacent cells on the same board (8-directional). */
export const ADJ_DIRECTIONS = [
  NORTH,
  NORTHEAST,
  EAST,
  SOUTHEAST,
  SOUTH,
  SOUTHWEST,
  WEST,
  NORTHWEST,
];

/** Look up a Direction by name (case-insensitive). Returns null if not found. */
export function directionByName(name) {
  return byName.get(name) ?? null;
}