feat(shared): pure phantom-model helpers (seed positions, deserialize)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,3 +2,4 @@ export * from './types.js';
|
||||
export * from './moderator.js';
|
||||
export * from './protocol.js';
|
||||
export * from './geometric.js';
|
||||
export * from './phantoms.js';
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { FILES, isSquare, type Color, type Piece, type PieceType, type Square } from './types.js';
|
||||
|
||||
const BACK_RANK: PieceType[] = ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'];
|
||||
const COLORS: Color[] = ['w', 'b'];
|
||||
const TYPES: PieceType[] = ['p', 'n', 'b', 'r', 'q', 'k'];
|
||||
|
||||
/**
|
||||
* The standard starting position for one colour, as a square→piece map.
|
||||
* Used to seed the phantom opponent-model layer with the opponent's army.
|
||||
*/
|
||||
export function opponentStartPosition(opponentColor: Color): Partial<Record<Square, Piece>> {
|
||||
const backRank = opponentColor === 'w' ? '1' : '8';
|
||||
const pawnRank = opponentColor === 'w' ? '2' : '7';
|
||||
const out: Partial<Record<Square, Piece>> = {};
|
||||
FILES.forEach((file, i) => {
|
||||
out[`${file}${backRank}` as Square] = { color: opponentColor, type: BACK_RANK[i]! };
|
||||
out[`${file}${pawnRank}` as Square] = { color: opponentColor, type: 'p' };
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a persisted phantom map (from localStorage). Tolerant: returns {} on
|
||||
* any structural failure and silently drops individual invalid entries.
|
||||
*/
|
||||
export function deserializePhantoms(raw: string | null): Partial<Record<Square, Piece>> {
|
||||
if (!raw) return {};
|
||||
let parsed: unknown;
|
||||
try { parsed = JSON.parse(raw); } catch { return {}; }
|
||||
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) return {};
|
||||
const out: Partial<Record<Square, Piece>> = {};
|
||||
for (const [k, v] of Object.entries(parsed as Record<string, unknown>)) {
|
||||
if (!isSquare(k)) continue;
|
||||
if (typeof v !== 'object' || v === null) continue;
|
||||
const { color, type } = v as { color?: unknown; type?: unknown };
|
||||
if (!COLORS.includes(color as Color)) continue;
|
||||
if (!TYPES.includes(type as PieceType)) continue;
|
||||
out[k] = { color: color as Color, type: type as PieceType };
|
||||
}
|
||||
return out;
|
||||
}
|
||||
Reference in New Issue
Block a user