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

workbenchthis machine
Files 8c843521bbc603b656573701a58a86c57edd8cbc
68 lines · 2.7 KB · ~790 tok Raw History
1
import { expect, test } from "bun:test";
2
import {
3
  DEPTHS, HEIGHT, WIDTH, at, distance, floorAt, openCells, seesFrom,
4
  stepToward, visibleFrom, walkable, xy,
5
} from "./dungeon.ts";
6
7
test("a floor is the same floor every time it is asked for", () => {
8
  for (let depth = 1; depth <= DEPTHS; depth += 1)
9
    expect(floorAt(depth).tiles.join("")).toBe(floorAt(depth).tiles.join(""));
10
  expect(floorAt(1).tiles.join("")).not.toBe(floorAt(2).tiles.join(""));
11
});
12
13
test("every floor has rooms, an entrance, and a way on", () => {
14
  for (let depth = 1; depth <= DEPTHS; depth += 1) {
15
    const floor = floorAt(depth);
16
    expect(floor.rooms.length).toBeGreaterThanOrEqual(5);
17
    expect(openCells(floor).length).toBeGreaterThan(150);
18
    expect(floor.tiles[floor.entrance]).toBe("<");
19
    if (depth < DEPTHS) expect(floor.tiles[floor.descent as number]).toBe(">");
20
    else expect(floor.descent).toBeUndefined();
21
  }
22
});
23
24
test("the stair is reachable from the entrance", () => {
25
  // A floor you cannot cross is a floor nobody can finish. Flood fill.
26
  for (let depth = 1; depth < DEPTHS; depth += 1) {
27
    const floor = floorAt(depth);
28
    const seen = new Set<number>([floor.entrance]);
29
    const queue = [floor.entrance];
30
    while (queue.length > 0) {
31
      const cell = queue.shift() as number;
32
      const { x, y } = xy(cell);
33
      for (const [dx, dy] of [[0,-1],[0,1],[1,0],[-1,0]] as const) {
34
        const nx = x + dx;
35
        const ny = y + dy;
36
        if (nx < 0 || ny < 0 || nx >= WIDTH || ny >= HEIGHT) continue;
37
        const next = at(nx, ny);
38
        if (seen.has(next) || !walkable(floor.tiles[next])) continue;
39
        seen.add(next);
40
        queue.push(next);
41
      }
42
    }
43
    expect(seen.has(floor.descent as number)).toBe(true);
44
  }
45
});
46
47
test("a wall stops the light at the wall", () => {
48
  const floor = floorAt(1);
49
  const wall = floor.tiles.findIndex((t) => t === "#");
50
  const lit = visibleFrom(floor, floor.entrance);
51
  expect(lit).toContain(floor.entrance);
52
  // Nothing lit is further than the lantern reaches.
53
  for (const cell of lit) expect(distance(floor.entrance, cell)).toBeLessThanOrEqual(4);
54
  // And sight into solid rock stops: a cell behind a wall is not visible.
55
  const blocked = floor.tiles.findIndex(
56
    (t, i) => t === "." && !seesFrom(floor, floor.entrance, i) && distance(floor.entrance, i) <= 4,
57
  );
58
  if (blocked !== -1) expect(lit).not.toContain(blocked);
59
  expect(wall).toBeGreaterThan(-1);
60
});
61
62
test("a step toward something goes around the corner it cannot go through", () => {
63
  const floor = floorAt(1);
64
  const from = floor.entrance;
65
  const step = stepToward(floor, from, floor.descent as number);
66
  expect(walkable(floor.tiles[step])).toBe(true);
67
  expect(distance(step, from)).toBeLessThanOrEqual(1);
68
});
↑↓ navigate ↵ open esc close
↑↓ navigate ↵ open esc close

Keyboard shortcuts