explodorama / files / test / padTarget.test.ts
padTarget.test.ts
| 1 | import { describe, expect, it } from 'vitest' |
| 2 | import { board } from './helpers' |
| 3 | import { aimStart, explainableTiles, firstTarget, jumpTarget } from '../src/ui/padTarget' |
| 4 | |
| 5 | describe('firstTarget', () => { |
| 6 | it('is null for no tiles', () => { |
| 7 | expect(firstTarget([], { x: 5, y: 5 })).toBeNull() |
| 8 | }) |
| 9 | it('is the nearest tile to the player', () => { |
| 10 | expect(firstTarget([{ x: 9, y: 5 }, { x: 5, y: 7 }, { x: 4, y: 5 }], { x: 5, y: 5 })).toEqual({ x: 4, y: 5 }) |
| 11 | }) |
| 12 | it('breaks a tie by the smaller y, then the smaller x', () => { |
| 13 | const around = [{ x: 6, y: 5 }, { x: 5, y: 6 }, { x: 4, y: 5 }, { x: 5, y: 4 }] |
| 14 | expect(firstTarget(around, { x: 5, y: 5 })).toEqual({ x: 5, y: 4 }) |
| 15 | expect(firstTarget(around.slice(0, 3), { x: 5, y: 5 })).toEqual({ x: 4, y: 5 }) |
| 16 | }) |
| 17 | }) |
| 18 | |
| 19 | describe('jumpTarget', () => { |
| 20 | // The four neighbours of (5, 5); the board's y grows down, so up is the smaller y. |
| 21 | const tiles = [{ x: 5, y: 4 }, { x: 6, y: 5 }, { x: 5, y: 6 }, { x: 4, y: 5 }] |
| 22 | it('goes the way pressed', () => { |
| 23 | expect(jumpTarget(tiles, tiles[0]!, 0, 1)).toEqual({ x: 5, y: 6 }) |
| 24 | expect(jumpTarget(tiles, tiles[1]!, -1, 0)).toEqual({ x: 4, y: 5 }) |
| 25 | expect(jumpTarget(tiles, tiles[3]!, 1, -1)).toEqual({ x: 5, y: 4 }) |
| 26 | }) |
| 27 | it('stays put when nothing lies that way (nothing wraps)', () => { |
| 28 | expect(jumpTarget(tiles, tiles[0]!, 0, -1)).toEqual({ x: 5, y: 4 }) |
| 29 | expect(jumpTarget(tiles, tiles[1]!, 1, 0)).toEqual({ x: 6, y: 5 }) |
| 30 | }) |
| 31 | it('prefers the tile straight along over a nearer one a row off', () => { |
| 32 | const row = [{ x: 0, y: 0 }, { x: 1, y: 2 }, { x: 3, y: 0 }] |
| 33 | expect(jumpTarget(row, row[0]!, 1, 0)).toEqual({ x: 3, y: 0 }) |
| 34 | }) |
| 35 | it('falls back to the nearest tile if the current one is not in the list', () => { |
| 36 | expect(jumpTarget(tiles, { x: 5, y: 5 }, 1, 0)).toEqual({ x: 5, y: 4 }) |
| 37 | }) |
| 38 | }) |
| 39 | |
| 40 | describe('explainableTiles', () => { |
| 41 | it('lists what "What is that?" explains, nearest the player first, without plain pillars or the outer wall', () => { |
| 42 | const s = board(` |
| 43 | ####### |
| 44 | #P.+.B# |
| 45 | #.#...# |
| 46 | #.$..3# |
| 47 | #######`) |
| 48 | const tiles = explainableTiles(s) |
| 49 | // The crate, the blob, the coin and the bomb; no wall of any kind, no empty floor, and not the player. |
| 50 | const key = tiles.map((t) => `${t.x},${t.y}`) |
| 51 | expect(key).toContain('3,1') |
| 52 | expect(key).toContain('5,1') |
| 53 | expect(key).toContain('2,3') |
| 54 | expect(key).toContain('5,3') |
| 55 | expect(key).toHaveLength(4) |
| 56 | // Nearest first: the coin (2,3) is 2.2 away, the crate (3,1) is 2 away. |
| 57 | expect(key[0]).toBe('3,1') |
| 58 | }) |
| 59 | }) |
| 60 | |
| 61 | describe('Q82: pillars and walls are in the aim', () => { |
| 62 | const s = board(` |
| 63 | ####### |
| 64 | #P.+.B# |
| 65 | #.#...# |
| 66 | #######`) |
| 67 | it('with `plain` the pillar and the outer wall can be aimed at; the aim still starts on something else', () => { |
| 68 | const all = explainableTiles(s, true).map((t) => `${t.x},${t.y}`) |
| 69 | expect(all).toContain('2,2') |
| 70 | expect(all).toContain('0,0') |
| 71 | expect(all.length).toBeGreaterThan(explainableTiles(s).length) |
| 72 | // The nearest tile is a wall, but the start is the crate. |
| 73 | expect(aimStart(s, explainableTiles(s, true))).toEqual({ x: 3, y: 1 }) |
| 74 | }) |
| 75 | it('a d-pad press from the crate reaches the pillar below it and the wall above it', () => { |
| 76 | const tiles = explainableTiles(s, true) |
| 77 | expect(jumpTarget(tiles, { x: 3, y: 1 }, 0, -1)).toEqual({ x: 3, y: 0 }) |
| 78 | expect(jumpTarget(tiles, { x: 3, y: 1 }, -1, 1)).toEqual({ x: 2, y: 2 }) |
| 79 | }) |
| 80 | }) |
| 81 | |
| 82 | describe('Q86: the aim can rest on yourself', () => { |
| 83 | const s = board(` |
| 84 | ####### |
| 85 | #P.+.B# |
| 86 | #######`) |
| 87 | it('the full list has the player, the old list and the start do not', () => { |
| 88 | expect(explainableTiles(s, true).some((t) => t.x === 1 && t.y === 1)).toBe(true) |
| 89 | expect(explainableTiles(s).some((t) => t.x === 1 && t.y === 1)).toBe(false) |
| 90 | expect(aimStart(s, explainableTiles(s, true))).toEqual({ x: 3, y: 1 }) |
| 91 | }) |
| 92 | it('a d-pad press from the crate goes back to the player', () => { |
| 93 | expect(jumpTarget(explainableTiles(s, true), { x: 3, y: 1 }, -1, 0)).toEqual({ x: 1, y: 1 }) |
| 94 | }) |
| 95 | }) |