core/sym.ts

import { Color } from "./color.ts";

/**
 * An immutable visual representation of a piece on the board.
 *
 * Boards are marked as either "outside" (sunlit, natural colors) or
 * "underground" (dark, roguelike terminal palette). The symbol carries
 * separate color/background pairs for each mode.
 *
 * Symbols are layered: terrain → items → effects → agent. The top-most
 * non-null color and background values win for each cell.
 */
export class Sym {
  static of(entity: string, color: Color, bg?: Color | null, outsideColor?: Color | null, outsideBg?: Color | null): Sym {
    if (arguments.length === 2) {
      return new Sym(entity, color, null, color, null);
    } else if (arguments.length === 3) {
      return new Sym(entity, color, bg ?? null, color, bg ?? null);
    } else {
      return new Sym(entity, color, bg ?? null, outsideColor ?? null, outsideBg ?? null);
    }
  }

  entity: string;
  color: Color | null;
  background: Color | null;
  outsideColor: Color | null;
  outsideBackground: Color | null;
  constructor(entity: string, color: Color, background: Color | null, outsideColor: Color | null, outsideBackground: Color | null) {
    this.entity = entity;
    this.color = color;
    this.background = background;
    this.outsideColor = outsideColor;
    this.outsideBackground = outsideBackground;
  }
  /** Foreground Color for the given lighting mode. */
  getColor(outside: boolean): Color | null {
    return outside ? this.outsideColor : this.color;
  }
  /** Background Color for the given lighting mode. */
  getBackground(outside: boolean): Color | null {
    return outside ? this.outsideBackground : this.background;
  }
  toString(): string {
    return `${this.color} ${this.entity}`;
  }
}