core/flags.js

/**
 * Bitmask flag constants for pieces, terrain, items, and agents.
 * Mirrors Flags.java exactly.
 */

export const PLAYER = 1 << 0;
export const TRAVERSABLE = 1 << 1;
/** Thrown items can fly over this terrain. */
export const PENETRABLE = 1 << 2;
export const ETHEREAL = 1 << 3;
export const AQUATIC = (1 << 4) | PENETRABLE | ETHEREAL;
export const LAVITIC = (1 << 5) | PENETRABLE | ETHEREAL;
export const FLIER = 1 << 6;
/** This piece should not be available in the map editor. */
export const NOT_EDITABLE = 1 << 7;
export const AMMUNITION = 1 << 8;
export const WEAPON = 1 << 9;
export const MELEE_WEAPON = (1 << 10) | WEAPON;
export const RANGED_WEAPON = (1 << 11) | WEAPON;
export const CARNIVORE = 1 << 12;
export const ORGANIC = 1 << 13;
export const PUSHABLE = 1 << 14;
export const FIRE_RESISTANT = 1 << 15;
export const WATER_RESISTANT = 1 << 16;
export const THEFT_RESISTANT = 1 << 17;
export const POISON_RESISTANT = 1 << 18;
export const PARALYSIS_RESISTANT = 1 << 19;
export const POISONED = 1 << 20;
export const TURNED_TO_STONE = 1 << 21;
export const PARALYZED = 1 << 22;
export const DETECT_HIDDEN = 1 << 23;
export const STONING_RESISTANT = 1 << 24;
export const WEAK = 1 << 25;
export const AMMO_ENLIVENER = 1 << 26;
export const MEAT = 1 << 27;
export const HIDES_ITEMS = 1 << 28;
export const REQUIRES_AMMO = 1 << 29;
export const TRANSIENT = 1 << 30;
export const VERTICAL = 1 << 31;

// Player-visible flag labels (shown in the status flags display)
const LABELS = new Map([
  [DETECT_HIDDEN, "Detect Hidden"],
  [FIRE_RESISTANT, "Fire Resistant"],
  [POISONED, "Poisoned"],
  [PARALYSIS_RESISTANT, "Paralysis Resistant"],
  [PARALYZED, "Paralyzed"],
  [POISON_RESISTANT, "Poison Resistant"],
  [STONING_RESISTANT, "Resistant to Stoning"],
  [THEFT_RESISTANT, "Theft Resistant"],
  [TURNED_TO_STONE, "Turned to Stone"],
  [WATER_RESISTANT, "Water Resistant"],
  [WEAK, "Weak"],
]);

/** True if `flag` is set in `flags`. */
export function is(flag, flags) {
  return (flags & flag) === flag;
}

/** True if `flag` is NOT set in `flags`. */
export function not(flag, flags) {
  return (flags & flag) !== flag;
}

/**
 * Return a comma-separated string of visible flag labels for a given flags value.
 * Returns an empty string if no visible flags are set.
 */
export function description(flags) {
  const parts = [];
  for (const [flag, label] of LABELS) {
    if (is(flag, flags)) parts.push(label);
  }
  return parts.join(", ");
}

/** Look up a flag constant by its display label. Returns -1 if not found. */
export function getFlag(label) {
  for (const [flag, l] of LABELS) {
    if (l === label) return flag;
  }
  return -1;
}