Skip to content

Instantly share code, notes, and snippets.

@tors42
Created January 28, 2024 14:21
Show Gist options
  • Save tors42/cf46f273493742d0960011b3d4429208 to your computer and use it in GitHub Desktop.
Save tors42/cf46f273493742d0960011b3d4429208 to your computer and use it in GitHub Desktop.
Annotate PGNs from input.pgn, with FEN of each move as PGN Tags and PGN Move comments - using JShell (Java)
Path inputFile = Path.of("input.pgn");
if (! Files.exists(inputFile)) {
System.out.println("Couldn't find input file " + inputFile);
return -1;
}
if (! Files.exists(Path.of("chariot.jar"))) {
Files.write(Path.of("chariot.jar"), URI.create(
"https://repo1.maven.org/maven2/io/github/tors42/chariot/0.0.82/chariot-0.0.82.jar"
).toURL().openStream().readAllBytes());
}
/env --class-path chariot.jar
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
import chariot.model.Pgn;
import chariot.model.Pgn.*;
import chariot.util.Board;
String annotate(List<Pgn> pgns, UnaryOperator<Pgn> annotationStrategy) {
return pgns.stream()
.map(annotationStrategy)
.map(Pgn::toString)
.collect(Collectors.joining("\n\n"));
}
class Strategy {
// Add PGN tags with FENs for each move
static Pgn fensAsTags(Pgn pgn) {
List<String> plies = pgn.moveListSAN();
Stream<Tag> annotatedTags = IntStream.range(1, plies.size()+1)
.mapToObj(ply -> Tag.of(
"FenAtPly"+ply,
Board.fromStandardPosition()
.play(String.join(" ", plies.subList(0, ply)))
.toFEN().split(" ")[0]));
return Pgn.of(Stream.concat(pgn.tags().stream(), annotatedTags).toList(), pgn.moves());
}
// Add PGN move comments with FENs for each move
static Pgn fensAsComments(Pgn pgn) {
Deque<Board> boards = new ArrayDeque<>();
boards.push(Board.fromStandardPosition());
List<String> annotatedMoves = pgn.moveList().stream()
.mapMulti((Move move, Consumer<Move> mapper) -> {
mapper.accept(move);
if (move instanceof San san) {
boards.push(boards.peek().play(san.san()));
mapper.accept(new Pgn.Comment(boards.peek().toFEN().split(" ")[0]));
}
})
.map(Move::render)
.toList();
return Pgn.of(pgn.tags(), String.join(" ", annotatedMoves));
}
}
List<Pgn> pgns = Pgn.readFromFile(inputFile);
System.out.println("Found " + pgns.size() + " games from " + inputFile);
var tag = Path.of("tag-annotated-games.pgn");
var comment = Path.of("comment-annotated-games.pgn");
Files.writeString(tag, annotate(pgns, Strategy::fensAsTags));
Files.writeString(comment, annotate(pgns, Strategy::fensAsComments));
System.out.println("Wrote " + tag);
System.out.println("Wrote " + comment);
/exit
[Event "Test Event 1"]
[Site "https://github.com/tors42/chariot"]
[White "Player 1"]
[Black "Player 2"]
[Result "0-1"]
1. d4 {rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR} c6 {rnbqkbnr/pp1ppppp/2p5/8/3P4/8/PPP1PPPP/RNBQKBNR} 2. c4 {rnbqkbnr/pp1ppppp/2p5/8/2PP4/8/PP2PPPP/RNBQKBNR} g6 {rnbqkbnr/pp1ppp1p/2p3p1/8/2PP4/8/PP2PPPP/RNBQKBNR} 0-1
[Event "Test Event 2"]
[Site "https://github.com/tors42/chariot"]
[White "Player 1"]
[Black "Player 2"]
[Result "0-1"]
1. d4 {rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR} e6 {rnbqkbnr/pppp1ppp/4p3/8/3P4/8/PPP1PPPP/RNBQKBNR} 2. Nf3 {rnbqkbnr/pppp1ppp/4p3/8/3P4/5N2/PPP1PPPP/RNBQKB1R} 0-1
[Event "Test Event 3"]
[Site "https://github.com/tors42/chariot"]
[White "Player 1"]
[Black "Player 2"]
[Result "1-0"]
1. e4 {rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR} c6 {rnbqkbnr/pp1ppppp/2p5/8/4P3/8/PPPP1PPP/RNBQKBNR} 2. f4 {rnbqkbnr/pp1ppppp/2p5/8/4PP2/8/PPPP2PP/RNBQKBNR} 1-0
[Event "Test Event 1"]
[Site "https://github.com/tors42/chariot"]
[White "Player 1"]
[Black "Player 2"]
[Result "0-1"]
1. d4 c6 2. c4 g6 0-1
[Event "Test Event 2"]
[Site "https://github.com/tors42/chariot"]
[White "Player 1"]
[Black "Player 2"]
[Result "0-1"]
1. d4 e6 2. Nf3 0-1
[Event "Test Event 3"]
[Site "https://github.com/tors42/chariot"]
[White "Player 1"]
[Black "Player 2"]
[Result "1-0"]
1. e4 c6 2. f4 1-0
[Event "Test Event 1"]
[Site "https://github.com/tors42/chariot"]
[White "Player 1"]
[Black "Player 2"]
[Result "0-1"]
[FenAtPly1 "rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR"]
[FenAtPly2 "rnbqkbnr/pp1ppppp/2p5/8/3P4/8/PPP1PPPP/RNBQKBNR"]
[FenAtPly3 "rnbqkbnr/pp1ppppp/2p5/8/2PP4/8/PP2PPPP/RNBQKBNR"]
[FenAtPly4 "rnbqkbnr/pp1ppp1p/2p3p1/8/2PP4/8/PP2PPPP/RNBQKBNR"]
1. d4 c6 2. c4 g6 0-1
[Event "Test Event 2"]
[Site "https://github.com/tors42/chariot"]
[White "Player 1"]
[Black "Player 2"]
[Result "0-1"]
[FenAtPly1 "rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR"]
[FenAtPly2 "rnbqkbnr/pppp1ppp/4p3/8/3P4/8/PPP1PPPP/RNBQKBNR"]
[FenAtPly3 "rnbqkbnr/pppp1ppp/4p3/8/3P4/5N2/PPP1PPPP/RNBQKB1R"]
1. d4 e6 2. Nf3 0-1
[Event "Test Event 3"]
[Site "https://github.com/tors42/chariot"]
[White "Player 1"]
[Black "Player 2"]
[Result "1-0"]
[FenAtPly1 "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR"]
[FenAtPly2 "rnbqkbnr/pp1ppppp/2p5/8/4P3/8/PPPP1PPP/RNBQKBNR"]
[FenAtPly3 "rnbqkbnr/pp1ppppp/2p5/8/4PP2/8/PPPP2PP/RNBQKBNR"]
1. e4 c6 2. f4 1-0
@tors42
Copy link
Author

tors42 commented Jan 28, 2024

Needs at least Java 17. ( Latest Java can be downloaded from https://jdk.java.net/21/ )

Example,

$ jshell annotate.jsh 
Found 3 games from input.pgn
Wrote tag-annotated-games.pgn
Wrote comment-annotated-games.pgn

See example input and output pgn files above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment