v0.14.0 web replay UI, My games, CLI replay

This commit is contained in:
lixen committed 2026-10-19 18:07:41 -04:00
1 parent 87dcb3e550
commit a999177f0c
37 files changed
+4058 -1803

No files matched your search

+50
View File
@@ -0,0 +1,50 @@
package display
import (
"fmt"
"strings"
)
// BoardFromFEN renders a FEN's piece placement in the server's ASCII board
// format (files on the first and last lines, ranks at both ends of a row,
// "." for an empty square), so RenderBoard colors it the same way.
func BoardFromFEN(fen string) (string, error) {
fields := strings.Fields(fen)
if len(fields) == 0 {
return "", fmt.Errorf("empty FEN")
}
rows := strings.Split(fields[0], "/")
if len(rows) != 8 {
return "", fmt.Errorf("FEN has %d ranks, want 8", len(rows))
}
var b strings.Builder
b.WriteString(" a b c d e f g h\n")
for i, row := range rows {
rank := byte('8' - i)
b.WriteByte(rank)
b.WriteByte(' ')
files := 0
for _, c := range row {
switch {
case c >= '1' && c <= '8':
for n := 0; n < int(c-'0'); n++ {
b.WriteString(". ")
}
files += int(c - '0')
case strings.ContainsRune("pnbrqkPNBRQK", c):
b.WriteRune(c)
b.WriteByte(' ')
files++
default:
return "", fmt.Errorf("invalid FEN character %q", c)
}
}
if files != 8 {
return "", fmt.Errorf("rank %c has %d files, want 8", rank, files)
}
b.WriteByte(rank)
b.WriteByte('\n')
}
b.WriteString(" a b c d e f g h")
return b.String(), nil
}
+28
View File
@@ -0,0 +1,28 @@
package display
import "testing"
func TestBoardFromFEN(t *testing.T) {
got, err := BoardFromFEN("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1")
if err != nil {
t.Fatal(err)
}
want := " a b c d e f g h\n" +
"8 r n b q k b n r 8\n" +
"7 p p p p p p p p 7\n" +
"6 . . . . . . . . 6\n" +
"5 . . . . . . . . 5\n" +
"4 . . . . P . . . 4\n" +
"3 . . . . . . . . 3\n" +
"2 P P P P . P P P 2\n" +
"1 R N B Q K B N R 1\n" +
" a b c d e f g h"
if got != want {
t.Errorf("board:\n%s\nwant:\n%s", got, want)
}
for _, bad := range []string{"", "8/8/8/8/8/8/8 w - - 0 1", "9/8/8/8/8/8/8/8 w - - 0 1", "x7/8/8/8/8/8/8/8 w - - 0 1"} {
if _, err := BoardFromFEN(bad); err == nil {
t.Errorf("BoardFromFEN(%q) accepted", bad)
}
}
}