core/piece.js

import { is, not } from "./flags.js";
import { NONE } from "./color.js";

/**
 * Base class for all board pieces (Terrain, Item, Agent, Effect).
 * All pieces are immutable — their state is set at construction and never changes.
 * The Registry ensures that identical pieces are the same object instance.
 */
export class Piece {
  /**
   * @param {string} name       - Display name shown to the player
   * @param {number} flags      - Bitmask of Flags constants
   * @param {string} color      - CSS color string (use Color.NONE for no color)
   * @param {Symbol} symbol - Visual representation
   */
  constructor(name, flags, color, symbol) {
    if (!name) {
      throw new Error("name is required");
    }
    if (arguments.length === 3) {
      if (!color) {
        throw new Error("symbol is required");
      }
      // name, flag, symbol
      this.name = name;
      this.flags = flags;
      this.color = NONE;
      this.symbol = color; // actually symbol
    } else if (arguments.length === 2) {
      if (!flags) {
        throw new Error("symbol is required");
      }
      // name, symbol
      this.name = name;
      this.flags = 0;
      this.color = NONE;
      this.symbol = flags; // actually symbol
    } else {
      if (!symbol) {
        throw new Error("symbol is required");
      }
      this.name = name;
      this.flags = flags;
      this.color = color;
      this.symbol = symbol;
    }
  }

  /** True if this piece has the given flag set. */
  is(flag) {
    return is(flag, this.flags);
  }

  /** True if this piece does NOT have the given flag set. */
  not(flag) {
    return not(flag, this.flags);
  }
}