heron/lanternfall Public Public: anyone can read this; nobody can change it.

workbenchthis machine
Files e53b98b72d84ce5feeddbe32d2586ca5df139720
62 lines · 2.2 KB · ~637 tok Raw History
1
/**
2
 * Names and epitaphs, composed rather than typed. Nobody writes free text
3
 * into this dungeon: a delver's name comes from their hand, and the dead
4
 * speak in a fixed grammar. It keeps the world's voice consistent, and it
5
 * means a public game needs no moderation.
6
 */
7
8
const FIRST = [
9
  "Alder", "Bryn", "Coll", "Dunnock", "Eira", "Fen", "Gorse", "Hale",
10
  "Isolde", "Jarrow", "Kestrel", "Lirien", "Morrow", "Nix", "Orrin", "Pell",
11
  "Quill", "Rook", "Sable", "Thorn", "Ursel", "Vane", "Wren", "Yarrow",
12
];
13
const SECOND = [
14
  "Ashdown", "Barrowe", "Coldwater", "Dimmick", "Emberly", "Fallow",
15
  "Greaves", "Hollowell", "Ironsides", "Jessop", "Kindle", "Lampwright",
16
  "Mordaunt", "Nettles", "Oakes", "Pyre", "Quarles", "Rushbrook",
17
  "Stannard", "Tallow", "Underhill", "Vesper", "Wickham", "Yewtree",
18
];
19
20
function hash(text: string, salt = 0): number {
21
  let h = 2166136261 ^ salt;
22
  for (const ch of text) h = Math.imul(h ^ ch.charCodeAt(0), 16777619) >>> 0;
23
  return h >>> 0;
24
}
25
26
export function nameFor(hand: string, attempt: number): string {
27
  const h = hash(hand, attempt * 7919);
28
  return `${FIRST[h % FIRST.length]} ${SECOND[(h >>> 9) % SECOND.length]}`;
29
}
30
31
const ENDINGS = [
32
  "died with their lantern still lit",
33
  "was cornered in a doorway",
34
  "bled out two steps from the stair",
35
  "went one room further",
36
  "did not hear it coming",
37
  "stopped to count their gold",
38
  "was found facing the wrong way",
39
  "ran out of floor",
40
];
41
42
const COUNSEL = [
43
  "beware the corridor",
44
  "try the far door",
45
  "seek the stair, not the gold",
46
  "do not follow the walls",
47
  "turn back at the rats",
48
  "the dark room is a trap",
49
  "rest before the descent",
50
  "carry less, climb sooner",
51
];
52
53
/** What the stone says. Deterministic in where and how the delver died. */
54
export function epitaphFor(name: string, depth: number, cell: number, turns: number): string {
55
  const h = hash(`${name}:${depth}:${cell}:${turns}`);
56
  const ending = ENDINGS[h % ENDINGS.length];
57
  const counsel = COUNSEL[(h >>> 11) % COUNSEL.length];
58
  return `${name} ${ending} on floor ${depth}. Traveller: ${counsel}.`;
59
}
60
61
export const ordinal = (n: number): string =>
62
  ["surface", "first", "second", "third", "fourth", "fifth"][n] ?? `floor ${n}`;
↑↓ navigate ↵ open esc close
↑↓ navigate ↵ open esc close

Keyboard shortcuts