Skip to content
import type { ClassId } from "./heroes.ts";
export {
  criticalChance,
  levelUpCost,
  maxEnergy,
  maxVigor,
  progressionPoints,
  SKILLS,
} from "./progression.ts";
import strikeArt from "../assets/icons/ffffff/transparent/1x1/lorc/broadsword.svg";
import defendArt from "../assets/icons/ffffff/transparent/1x1/lorc/riot-shield.svg";
import shieldBashArt from "../assets/icons/ffffff/transparent/1x1/delapouite/shield-bash.svg";
import bulwarkArt from "../assets/icons/ffffff/transparent/1x1/lorc/bordered-shield.svg";
import riposteArt from "../assets/icons/ffffff/transparent/1x1/lorc/shield-reflect.svg";
import sentinelOathArt from "../assets/icons/ffffff/transparent/1x1/lorc/winged-shield.svg";
import hexBoltArt from "../assets/icons/ffffff/transparent/1x1/lorc/magic-swirl.svg";
import creepingDreadArt from "../assets/icons/ffffff/transparent/1x1/lorc/poison-gas.svg";
import siphonArt from "../assets/icons/ffffff/transparent/1x1/lorc/life-tap.svg";
import moonRitualArt from "../assets/icons/ffffff/transparent/1x1/lorc/moon-claws.svg";
import backstabArt from "../assets/icons/ffffff/transparent/1x1/lorc/backstab.svg";
import vanishArt from "../assets/icons/ffffff/transparent/1x1/lorc/cloak-dagger.svg";
import fanOfKnivesArt from "../assets/icons/ffffff/transparent/1x1/lorc/all-for-one.svg";
import gildedFlourishArt from "../assets/icons/ffffff/transparent/1x1/lorc/sword-spin.svg";
import maidenArt from "../assets/icons/ffffff/transparent/1x1/delapouite/viking-shield.svg";
import witchArt from "../assets/icons/ffffff/transparent/1x1/delapouite/woman-elf-face.svg";
import assassinArt from "../assets/icons/ffffff/transparent/1x1/darkzaitzev/hooded-assassin.svg";
import brassSentinelArt from "../assets/icons/ffffff/transparent/1x1/lorc/robot-golem.svg";
import clockworkDivaArt from "../assets/icons/ffffff/transparent/1x1/lorc/sing.svg";
import gildedThugArt from "../assets/icons/ffffff/transparent/1x1/lorc/mailed-fist.svg";
import moonHagArt from "../assets/icons/ffffff/transparent/1x1/cathelineau/witch-face.svg";
import obsidianMatronArt from "../assets/icons/ffffff/transparent/1x1/lorc/reaper-scythe.svg";
import sunburstSovereignArt from "../assets/icons/ffffff/transparent/1x1/lorc/queen-crown.svg";
import velvetFencerArt from "../assets/icons/ffffff/transparent/1x1/cathelineau/swordwoman.svg";

export type { ClassId };

export const CLASSES: Record<
  ClassId,
  {
    id: ClassId;
    name: string;
    title: string;
    art: string;
    maxHp: number;
    energy: number;
    handSize: number;
    blurb: string;
    signature: string[];
  }
> = {
  maiden: {
    id: "maiden",
    name: "Shield Maiden",
    title: "The Immovable Protector",
    art: maidenArt,
    maxHp: 80,
    energy: 3,
    handSize: 5,
    blurb:
      "A living bulwark of ivory and brass. She turns the storm aside and answers it in kind.",
    signature: ["shield_bash", "bulwark", "riposte"],
  },
  witch: {
    id: "witch",
    name: "Witch",
    title: "Weaver of Hexes",
    art: witchArt,
    maxHp: 64,
    energy: 3,
    handSize: 5,
    blurb:
      "She does not strike — she lingers. Curses bloom slowly, then all at once.",
    signature: ["hex_bolt", "creeping_dread", "siphon"],
  },
  assassin: {
    id: "assassin",
    name: "Assassin",
    title: "Whisper of the Blade",
    art: assassinArt,
    maxHp: 58,
    energy: 3,
    handSize: 5,
    blurb:
      "Seen once, in the moment the knife is already sheathed. Burst, vanish, repeat.",
    signature: ["backstab", "vanish", "fan_of_knives"],
  },
};

export interface CardEffect {
  damage?: number;
  hits?: number;
  block?: number;
  heal?: number;
  draw?: number;
  energyGain?: number;
  poison?: number;
  weak?: number;
  strength?: number;
  evade?: number;
  retaliate?: number;
  anima?: number;
  aoe?: boolean;
}

export interface CardDef {
  id: string;
  name: string;
  art: string;
  klass: ClassId | "any";
  type: "physical" | "defense" | "poison" | "arcane";
  cost: number;
  text: string;
  effects: CardEffect;
  rare?: boolean;
}

export const CARDS: Record<string, CardDef> = {
  strike: {
    id: "strike",
    name: "Strike",
    art: strikeArt,
    klass: "any",
    type: "physical",
    cost: 1,
    text: "Deal 6 damage.",
    effects: { damage: 6 },
  },
  defend: {
    id: "defend",
    name: "Defend",
    art: defendArt,
    klass: "any",
    type: "defense",
    cost: 1,
    text: "Gain 5 block.",
    effects: { block: 5 },
  },
  shield_bash: {
    id: "shield_bash",
    name: "Shield Bash",
    art: shieldBashArt,
    klass: "maiden",
    type: "physical",
    cost: 1,
    text: "Deal 4 damage. Gain 4 block.",
    effects: { damage: 4, block: 4 },
  },
  bulwark: {
    id: "bulwark",
    name: "Bulwark",
    art: bulwarkArt,
    klass: "maiden",
    type: "defense",
    cost: 2,
    text: "Gain 12 block. Gain 1 strength.",
    effects: { block: 12, strength: 1 },
  },
  riposte: {
    id: "riposte",
    name: "Riposte",
    art: riposteArt,
    klass: "maiden",
    type: "defense",
    cost: 1,
    text: "Gain 5 block. Deal 4 damage to any attacker this turn.",
    effects: { block: 5, retaliate: 4 },
    rare: true,
  },
  sentinel_oath: {
    id: "sentinel_oath",
    name: "Sentinel's Oath",
    art: sentinelOathArt,
    klass: "maiden",
    type: "defense",
    cost: 1,
    text: "Gain 7 block. Draw 1 card.",
    effects: { block: 7, draw: 1 },
  },
  hex_bolt: {
    id: "hex_bolt",
    name: "Hex Bolt",
    art: hexBoltArt,
    klass: "witch",
    type: "poison",
    cost: 1,
    text: "Deal 3 damage. Apply 3 poison.",
    effects: { damage: 3, poison: 3 },
  },
  creeping_dread: {
    id: "creeping_dread",
    name: "Creeping Dread",
    art: creepingDreadArt,
    klass: "witch",
    type: "poison",
    cost: 1,
    text: "Apply 4 poison. Apply 1 weak.",
    effects: { poison: 4, weak: 1 },
  },
  siphon: {
    id: "siphon",
    name: "Siphon",
    art: siphonArt,
    klass: "witch",
    type: "arcane",
    cost: 2,
    text: "Deal 8 damage. Heal 4.",
    effects: { damage: 8, heal: 4 },
  },
  moon_ritual: {
    id: "moon_ritual",
    name: "Moon Ritual",
    art: moonRitualArt,
    klass: "witch",
    type: "arcane",
    cost: 0,
    text: "Draw 1 card. Gain 1 anima.",
    effects: { draw: 1, anima: 2 },
    rare: true,
  },
  backstab: {
    id: "backstab",
    name: "Backstab",
    art: backstabArt,
    klass: "assassin",
    type: "physical",
    cost: 0,
    text: "Deal 9 damage. Exhausting speed — costs nothing, draws nothing.",
    effects: { damage: 9 },
  },
  vanish: {
    id: "vanish",
    name: "Vanish",
    art: vanishArt,
    klass: "assassin",
    type: "defense",
    cost: 1,
    text: "Gain 4 block. Evade the next 2 attacks.",
    effects: { block: 4, evade: 2 },
  },
  fan_of_knives: {
    id: "fan_of_knives",
    name: "Fan of Knives",
    art: fanOfKnivesArt,
    klass: "assassin",
    type: "physical",
    cost: 1,
    text: "Deal 3 damage twice to ALL enemies.",
    effects: { damage: 3, hits: 2, aoe: true },
  },
  gilded_flourish: {
    id: "gilded_flourish",
    name: "Gilded Flourish",
    art: gildedFlourishArt,
    klass: "assassin",
    type: "physical",
    cost: 1,
    text: "Deal 5 damage. Gain 1 strength.",
    effects: { damage: 5, strength: 1 },
    rare: true,
  },
};

export interface CardInstance {
  uid: number;
  def: CardDef;
  upgraded: boolean;
}

let uidCounter = 0;

export function makeCard(id: string): CardInstance | null {
  const def = CARDS[id];
  if (!def) return null;
  return { uid: ++uidCounter, def, upgraded: false };
}

const UPGRADE_MULT = 1.5;

function round(n: number): number {
  return Math.max(1, Math.round(n));
}

export function upgradeEffect(effects: CardEffect): CardEffect {
  const out: CardEffect = { ...effects };
  for (
    const key of [
      "damage",
      "block",
      "heal",
      "poison",
      "weak",
      "strength",
      "evade",
      "retaliate",
      "anima",
    ] as const
  ) {
    const value = out[key];
    if (typeof value === "number") {
      // deno-lint-ignore no-explicit-any
      out[key] = round(value * UPGRADE_MULT) as any;
    }
  }
  return out;
}

/** Starting deck per design: small, consistent, class-flavored. */
export function startingDeck(klass: ClassId): string[] {
  return [
    ...Array(4).fill("strike"),
    ...Array(4).fill("defend"),
    ...CLASSES[klass].signature.slice(0, 2),
  ];
}

// ---------------------------------------------------------------------------
// Enemies
// ---------------------------------------------------------------------------

export interface EnemyMoveDef {
  kind: "attack" | "block" | "buff" | "hex";
  damage?: number;
  hits?: number;
  block?: number;
  strength?: number;
  poison?: number;
  label: string;
}

export interface EnemyTemplate {
  name: string;
  art: string;
  hp: number;
  moves: EnemyMoveDef[];
}

export const ENEMY_TEMPLATES: Record<string, EnemyTemplate> = {
  gilded_thug: {
    name: "Gilded Thug",
    art: gildedThugArt,
    hp: 22,
    moves: [
      { kind: "attack", damage: 7, label: "Cudgel" },
      { kind: "attack", damage: 4, hits: 2, label: "Flurry" },
    ],
  },
  brass_sentinel: {
    name: "Brass Sentinel",
    art: brassSentinelArt,
    hp: 30,
    moves: [
      { kind: "block", block: 8, label: "Harden" },
      { kind: "attack", damage: 10, label: "Gavel Fist" },
    ],
  },
  moon_hag: {
    name: "Moon Hag",
    art: moonHagArt,
    hp: 20,
    moves: [
      { kind: "hex", poison: 4, label: "Bitter Draught" },
      { kind: "attack", damage: 6, label: "Claw" },
      { kind: "buff", strength: 2, label: "Work Up" },
    ],
  },
  velvet_fencer: {
    name: "Velvet Fencer",
    art: velvetFencerArt,
    hp: 24,
    moves: [
      { kind: "attack", damage: 5, hits: 3, label: "Triple Lunge" },
      { kind: "block", block: 6, label: "Parry Stance" },
    ],
  },
};

export const ELITE_TEMPLATES: EnemyTemplate[] = [
  {
    name: "Obsidian Matron",
    art: obsidianMatronArt,
    hp: 46,
    moves: [
      { kind: "attack", damage: 9, hits: 2, label: "Twin Scythes" },
      { kind: "hex", poison: 5, label: "Withering Gaze" },
      { kind: "block", block: 10, label: "Umbral Veil" },
    ],
  },
  {
    name: "Clockwork Diva",
    art: clockworkDivaArt,
    hp: 52,
    moves: [
      { kind: "block", block: 12, label: "Gilded Aria" },
      { kind: "attack", damage: 14, label: "Fortissimo" },
      { kind: "buff", strength: 3, label: "Crescendo" },
    ],
  },
];

export const BOSS_TEMPLATES: EnemyTemplate[] = [
  {
    name: "The Sunburst Sovereign",
    art: sunburstSovereignArt,
    hp: 90,
    moves: [
      { kind: "attack", damage: 12, hits: 2, label: "Radiant Verdict" },
      { kind: "block", block: 15, label: "Solar Court" },
      { kind: "hex", poison: 6, label: "Golden Rot" },
      { kind: "buff", strength: 3, label: "Coronation" },
    ],
  },
];

export function scaleHp(base: number, depth: number): number {
  return Math.round(base * (1 + 0.28 * depth));
}

export function scaleDamage(base: number, depth: number): number {
  return Math.round(base * (1 + 0.18 * depth));
}

// ---------------------------------------------------------------------------
// Dungeon map
// ---------------------------------------------------------------------------

export type NodeKind =
  | "fight"
  | "elite"
  | "treasure"
  | "rest"
  | "boss";

export interface MapNode {
  kind: NodeKind;
  done: boolean;
}

export const MAP_FLOORS = 6;