import assert from 'node:assert/strict'; import { test } from 'node:test'; import { HexBoard } from '../src/board'; import { Game } from '../src/game'; import { PointerInput } from '../src/input'; import type { HexCellDef } from '../src/types'; const c = (id: string, q: number, r: number, clue?: number): HexCellDef => ({ id, q, r, clue }); const level13 = () => HexBoard.fromCells([c('a', 0, 0, 1), c('b', 1, 0), c('c', 0, 1), c('d', 1, 1, 4)], [['a', 'b']]); function setup() { const b = level13(); const g = new Game(b); const input = new PointerInput(g); const id = (s: string) => b.cellById(s).index; return { b, g, input, id }; } test('按下起点、滑到邻格追加、滑回撤销、松手保留', () => { const { g, input, id } = setup(); assert.equal(input.down(id('a'))[0].type, 'step'); assert.ok(input.isDrawing); assert.equal(input.move(id('c'))[0].type, 'step'); assert.deepEqual(input.move(id('c')), [], '同一格不重复触发'); assert.equal(input.move(id('a'))[0].type, 'unstep'); assert.equal(g.path.length, 1); input.move(id('c')); input.up(); assert.equal(g.status, 'idle'); assert.equal(g.path.length, 2); }); test('滑向有墙的邻格 → wallHit 一次,路径不变', () => { const { g, input, id } = setup(); input.down(id('a')); const ev = input.move(id('b')); assert.equal(ev.length, 1); assert.equal(ev[0].type, 'wallHit'); assert.deepEqual(input.move(id('b')), [], '停在同一格不重复报'); assert.equal(g.path.length, 1); // 指针逻辑上仍在末端:继续滑到 c 可追加 assert.equal(input.move(id('c'))[0].type, 'step'); }); test('点末端继续、点前一格撤销、点旁边空格追加、点墙外邻格报撞墙', () => { const { g, input, id } = setup(); input.down(id('a')); input.move(id('c')); input.up(); assert.equal(input.down(id('c')).length, 0); assert.ok(input.isDrawing); input.up(); assert.equal(input.down(id('a'))[0].type, 'unstep'); assert.equal(g.path.length, 1); input.up(); assert.equal(input.down(id('c'))[0].type, 'step', '点着走'); input.up(); // 路径 a,c;c 的邻居 b 无墙 → 追加;再从 b 去 a 已走 → 忽略 assert.equal(input.down(id('b'))[0].type, 'step'); input.up(); // 从 a 起手时点 b:撞墙反馈 input.cancel(); g.apply({ type: 'reset' }); input.down(id('a')); input.up(); assert.equal(input.down(id('b'))[0].type, 'wallHit'); }); test('非法起手与空白按下', () => { const { input, id } = setup(); assert.equal(input.down(id('b'))[0].type, 'rejectStart'); assert.ok(!input.isDrawing); assert.deepEqual(input.down(-1), []); assert.deepEqual(input.move(id('a')), [], '没在画,move 无效'); }); test('过关后手势失效', () => { const { g, input, id } = setup(); input.down(id('a')); input.move(id('c')); input.move(id('b')); const ev = input.move(id('d')); assert.ok(ev.some((e) => e.type === 'cleared')); assert.ok(!input.isDrawing); assert.equal(g.isCleared, true); assert.deepEqual(input.down(id('d')), []); });