Back to Wizard Duel
SOURCE / PINNED RELEASE

Made of little things.

Wizard Duel

Release
48b4ed933a32…
Author-recorded commit
3ed8fcbbf62c…
License
LICENSE
Author’s source reference
nostr://npub1ny7l44q0au5xkv3mjgt6zks5f0e2ydefslq4nhh2ve2xypgc2mqqat8qx2/wss%3A%2F%2Fgit.napplet.soy%2F/n-86005d75eb4

Archive hash verified: 4196bfb69e536a86…. The source-to-build association is the author’s claim; it has not been independently rebuilt.

src/game/familiars.ts
// Familiars: little magic pets a wizard can summon with a secret rune combo.
// Each one floats behind its wizard for a while and does one special thing.
// A wizard can have up to MAX_FAMILIARS at once; summoning more sends the oldest away.

import type { Wizard } from './game.js';
import type { Spell } from './spells.js';
import { sfx } from './sound.js';

export type FamiliarKind = 'fairy' | 'imp' | 'owl';

export const MAX_FAMILIARS = 3;
/** How many seconds a familiar stays before it poofs away. */
export const FAMILIAR_LIFE = 12;

export interface FamiliarInfo {
  name: string;
  /** What the familiar says when it arrives. */
  hello: string;
  /** 7×7 pixel sprite, facing right. Letters pick colours from `palette`. */
  sprite: string[];
  palette: Record<string, string>;
  /** Seconds between uses of its special power (0 = no repeating power). */
  every: number;
}

export const FAMILIARS: Record<FamiliarKind, FamiliarInfo> = {
  // Heals its wizard a little every couple of seconds.
  fairy: {
    name: 'Healing Fairy',
    hello: 'TWINKLE!',
    sprite: ['w.....w', 'ww.a.ww', 'wwaaaww', '.waEaw.', '..aaa..', '...a...', '..a.a..'],
    palette: { w: '#c8f4ff', a: '#ff9cf5', E: '#120a1f' },
    every: 2,
  },
  // Spits a tiny fire spark at the other wizard.
  imp: {
    name: 'Fire Imp',
    hello: 'HEHEHE!',
    sprite: ['r.....r', 'rr...rr', '.rrrrr.', '.ryryr.', '.rrrrr.', '..rrr..', '.r...r.'],
    palette: { r: '#e0402a', y: '#ffd23f' },
    every: 3,
  },
  // Catches the next enemy spell that would hit its wizard, then flies off.
  owl: {
    name: 'Guard Owl',
    hello: 'HOOT!',
    sprite: ['b.....b', 'bbbbbbb', 'bwwbwwb', 'bwEbEwb', 'bbbybbb', '.bcccb.', '..y.y..'],
    palette: { b: '#8a5a2b', w: '#fff4e0', E: '#120a1f', y: '#ffb000', c: '#d9a066' },
    every: 0,
  },
};

export interface Familiar {
  kind: FamiliarKind;
  owner: Wizard;
  x: number;
  y: number;
  /** Seconds left before it poofs away. */
  life: number;
  /** Seconds until it next uses its special power. */
  timer: number;
}

/** Not a castable spell: the little fire spark a Fire Imp spits. */
export const FIRE_SPARK: Spell = {
  id: 'firespark', name: 'Fire Spark', hitText: 'OUCH!', len: 0,
  colors: ['#ff7a1a', '#ffd23f'], icon: 'spark', speed: 150, damage: 2,
  sound: sfx.fire,
};