JavaScript
// Board points with coords (normalized 0..1) and adjacency list
const points = {
A1: {x:0, y:0, adj:['D1','A4']},
D1: {x:0.5, y:0, adj:['A1','G1','D2']},
G1: {x:1, y:0, adj:['D1','G4']},
B2: {x:0.166, y:0.166, adj:['D2','B4']},
D2: {x:0.5, y:0.166, adj:['B2','F2','D1','D3']},
F2: {x:0.833, y:0.166, adj:['D2','F4']},
C3: {x:0.333, y:0.333, adj:['D3','C4']},
D3: {x:0.5, y:0.333, adj:['C3','E3','D2']},
E3: {x:0.666, y:0.333, adj:['D3','E4']},
A4: {x:0, y:0.5, adj:['A1','B4','A7']},
B4: {x:0.166, y:0.5, adj:['A4','B2','C4','B6']},
C4: {x:0.333, y:0.5, adj:['C3','B4','E4','C6']},
E4: {x:0.666, y:0.5, adj:['E3','C4','F4','E6']},
F4: {x:0.833, y:0.5, adj:['F2','E4','F6','G4']},
G4: {x:1, y:0.5, adj:['G1','F4','G7']},
C6: {x:0.333, y:0.666, adj:['C4','D6']},
D6: {x:0.5, y:0.666, adj:['C6','F6','D7']},
F6: {x:0.833, y:0.666, adj:['D6','F4']},
B6: {x:0.166, y:0.833, adj:['B4','D7']},
D7: {x:0.5, y:0.833, adj:['B6','D6','G7']},
G7: {x:1, y:0.833, adj:['D7','G4']},
A7: {x:0, y:1, adj:['A4','D7']},
};
// Predefined mills (sets of 3)
const mills = [
['A1','D1','G1'],
['B2','D2','F2'],
['C3','D3','E3'],
['A4','B4','C4'],
['E4','F4','G4'],
['C6','D6','E6'], // note E6 missing from points; fix: E6 isn't defined - adjust according to standard: actually mills include C6-D6-E6 and B6-D7-G7? Wait. We'll derive dynamically
['A7','D7','G7'],
['A1','A4','A7'],
['B2','B4','B6'],
['C3','C4','C6'],
['D1','D2','D3'],
['E3','E4','E6'],
['F2','F4','F6'],
['G1','G4','G7'],
['G7','D7','A7'],
];
// Correction: define missing E6 and F6 etc? The earlier structure had E6 implicit; we should add them
// Let's add E6 to points and adjust adjacency for C6, E6, F6 etc to match standard board.
points.E6 = {x:0.666, y:0.666, adj:['E4','D6','F6']};
points.F6.adj = ['D6','F4','E6'];
points.C6.adj = ['C4','D6'];
points.D6.adj = ['C6','F6','D7'];
points.D7.adj = ['B6','D6','G7'];
points.B6.adj =...