extremely claude-assisted go game based on atproto! working on cleaning up and giving a more unique design, still has a bit of a slop vibe to it.
1/**
2 * Simple SGF parser for extracting moves from SGF files
3 */
4
5export interface SgfMove {
6 color: 'black' | 'white';
7 x: number;
8 y: number;
9}
10
11export interface SgfData {
12 boardSize: number;
13 moves: SgfMove[];
14}
15
16/**
17 * Parse SGF content and extract board size and moves
18 */
19export function parseSgf(sgfContent: string): SgfData {
20 const moves: SgfMove[] = [];
21 let boardSize = 19; // default
22
23 // Extract board size
24 const sizeMatch = sgfContent.match(/SZ\[(\d+)\]/);
25 if (sizeMatch) {
26 boardSize = parseInt(sizeMatch[1], 10);
27 }
28
29 // Extract moves - pattern like ;B[dd] or ;W[ed]
30 const movePattern = /;([BW])\[([a-z]{0,2})\]/g;
31 let match;
32
33 while ((match = movePattern.exec(sgfContent)) !== null) {
34 const color = match[1] === 'B' ? 'black' : 'white';
35 const coords = match[2];
36
37 // Empty brackets mean pass
38 if (!coords) {
39 continue;
40 }
41
42 // Convert SGF coordinates (aa = top-left) to 0-based x,y
43 const x = coords.charCodeAt(0) - 97; // 'a' = 0
44 const y = coords.charCodeAt(1) - 97;
45
46 moves.push({ color, x, y });
47 }
48
49 return { boardSize, moves };
50}
51
52/**
53 * Load and parse an SGF file from a URL
54 */
55export async function loadSgf(url: string): Promise<SgfData> {
56 const response = await fetch(url);
57 const content = await response.text();
58 return parseSgf(content);
59}