feat(engine): coordinate notation and JSON save/load
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { toCoordinate, serialize, deserialize } from './notation';
|
||||||
|
import type { HistoryEntry } from './types';
|
||||||
|
|
||||||
|
describe('notation', () => {
|
||||||
|
it('renders a move as a coordinate token', () => {
|
||||||
|
expect(toCoordinate({ from: 'e2', to: 'e4' })).toBe('e2e4');
|
||||||
|
expect(toCoordinate({ from: 'e7', to: 'e8', promotion: 'q' })).toBe('e7e8q');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('round-trips a game through serialize/deserialize', () => {
|
||||||
|
const history: HistoryEntry[] = [
|
||||||
|
{ player: 'N', from: 'e2', to: 'e4' },
|
||||||
|
{ player: 'S', from: 'e2', to: 'e4' },
|
||||||
|
];
|
||||||
|
const restored = deserialize(serialize(history));
|
||||||
|
expect(restored).toEqual(history);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects a file that is not a duplicate-chess save', () => {
|
||||||
|
expect(() => deserialize('{"variant":"chess","version":1,"moves":[]}')).toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import type { SyncMove, HistoryEntry } from './types';
|
||||||
|
|
||||||
|
/** Coordinate notation, e.g. "e2e4" or "e7e8q". */
|
||||||
|
export function toCoordinate(move: SyncMove): string {
|
||||||
|
return `${move.from}${move.to}${move.promotion ?? ''}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SavedGame {
|
||||||
|
variant: 'duplicate-chess';
|
||||||
|
version: 1;
|
||||||
|
moves: HistoryEntry[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function serialize(history: HistoryEntry[]): string {
|
||||||
|
const data: SavedGame = { variant: 'duplicate-chess', version: 1, moves: history };
|
||||||
|
return JSON.stringify(data, null, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deserialize(json: string): HistoryEntry[] {
|
||||||
|
const data = JSON.parse(json) as Partial<SavedGame>;
|
||||||
|
if (data.variant !== 'duplicate-chess' || !Array.isArray(data.moves)) {
|
||||||
|
throw new Error('Not a duplicate-chess save file');
|
||||||
|
}
|
||||||
|
return data.moves;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user