From 36832733b66acd468e018f508dd166206135a01a Mon Sep 17 00:00:00 2001 From: CyB3RC0nN0R Date: Wed, 24 Jul 2019 17:52:42 +0200 Subject: [PATCH] Added en passant availability logging and FEN string export --- src/dev/kske/chess/board/Board.java | 6 +-- src/dev/kske/chess/board/Log.java | 11 ++++- src/dev/kske/chess/board/Move.java | 6 +-- src/dev/kske/chess/board/Position.java | 8 +++- src/dev/kske/chess/game/UCIPlayer.java | 2 +- test/dev/kske/chess/test/PositionTest.java | 52 ++++++++++++++++++++++ 6 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 test/dev/kske/chess/test/PositionTest.java diff --git a/src/dev/kske/chess/board/Board.java b/src/dev/kske/chess/board/Board.java index f99b2c9..b8da2ba 100644 --- a/src/dev/kske/chess/board/Board.java +++ b/src/dev/kske/chess/board/Board.java @@ -458,11 +458,11 @@ public class Board implements Cloneable { if (castlingSb.length() == 0) sb.append("-"); sb.append(castlingSb); - // TODO: en passant availability - sb.append(" -"); - final LoggedMove lastMove = log.getLast(); + // En passant availabillity + sb.append(" " + (lastMove == null || lastMove.enPassant == null ? "-" : lastMove.enPassant.toSAN())); + // Halfmove clock sb.append(" " + String.valueOf(lastMove == null ? 0 : lastMove.halfmoveClock)); diff --git a/src/dev/kske/chess/board/Log.java b/src/dev/kske/chess/board/Log.java index 22d8bf2..6211983 100644 --- a/src/dev/kske/chess/board/Log.java +++ b/src/dev/kske/chess/board/Log.java @@ -22,6 +22,11 @@ public class Log implements Cloneable { } public void add(Move move, Piece capturedPiece, boolean pawnMove) { + // En passant availability + Position enPassant = null; + if (pawnMove && move.yDist == 2) enPassant = new Position(move.pos.x, move.pos.y + move.ySign); + + // Fullmove counter and halfmove clock int fullmoveCounter, halfmoveClock; if (moves.isEmpty()) { fullmoveCounter = 1; @@ -32,7 +37,7 @@ public class Log implements Cloneable { halfmoveClock = capturedPiece != null || pawnMove ? 0 : getLast().halfmoveClock + 1; } activeColor = activeColor.opposite(); - moves.add(new LoggedMove(move, capturedPiece, fullmoveCounter, halfmoveClock)); + moves.add(new LoggedMove(move, capturedPiece, enPassant, fullmoveCounter, halfmoveClock)); } public LoggedMove getLast() { return moves.isEmpty() ? null : moves.get(moves.size() - 1); } @@ -63,11 +68,13 @@ public class Log implements Cloneable { public final Move move; public final Piece capturedPiece; + public final Position enPassant; public final int fullmoveCounter, halfmoveClock; - public LoggedMove(Move move, Piece capturedPiece, int fullmoveCounter, int halfmoveClock) { + public LoggedMove(Move move, Piece capturedPiece, Position enPassant, int fullmoveCounter, int halfmoveClock) { this.move = move; this.capturedPiece = capturedPiece; + this.enPassant = enPassant; this.fullmoveCounter = fullmoveCounter; this.halfmoveClock = halfmoveClock; } diff --git a/src/dev/kske/chess/board/Move.java b/src/dev/kske/chess/board/Move.java index eafb9b9..06d7ba9 100644 --- a/src/dev/kske/chess/board/Move.java +++ b/src/dev/kske/chess/board/Move.java @@ -30,9 +30,9 @@ public class Move { this(new Position(xPos, yPos), new Position(xDest, yDest)); } - public static Move fromAlgebraicNotation(String move) { - return new Move(Position.fromAlgebraicNotation(move.substring(0, 2)), - Position.fromAlgebraicNotation(move.substring(2))); + public static Move fromSAN(String move) { + return new Move(Position.fromSAN(move.substring(0, 2)), + Position.fromSAN(move.substring(2))); } public boolean isHorizontal() { return yDist == 0; } diff --git a/src/dev/kske/chess/board/Position.java b/src/dev/kske/chess/board/Position.java index 69bb03b..ac9638d 100644 --- a/src/dev/kske/chess/board/Position.java +++ b/src/dev/kske/chess/board/Position.java @@ -15,8 +15,12 @@ public class Position { this.y = y; } - public static Position fromAlgebraicNotation(String pos) { - return new Position(pos.charAt(0) - 97, 7 - (Character.getNumericValue(pos.charAt(1)) - 1)); + public static Position fromSAN(String pos) { + return new Position(pos.charAt(0) - 97, 8 - Character.getNumericValue(pos.charAt(1))); + } + + public String toSAN() { + return String.valueOf((char) (x + 97)) + String.valueOf(8 - y); } @Override diff --git a/src/dev/kske/chess/game/UCIPlayer.java b/src/dev/kske/chess/game/UCIPlayer.java index 0af08b2..edf1a56 100644 --- a/src/dev/kske/chess/game/UCIPlayer.java +++ b/src/dev/kske/chess/game/UCIPlayer.java @@ -74,7 +74,7 @@ public class UCIPlayer extends Player implements UCIListener { @Override public void onBestMove(String move) { - Move moveObj = Move.fromAlgebraicNotation(move); + Move moveObj = Move.fromSAN(move); game.onMove(this, moveObj); } diff --git a/test/dev/kske/chess/test/PositionTest.java b/test/dev/kske/chess/test/PositionTest.java new file mode 100644 index 0000000..c98c2ba --- /dev/null +++ b/test/dev/kske/chess/test/PositionTest.java @@ -0,0 +1,52 @@ +package dev.kske.chess.test; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.IntStream; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import dev.kske.chess.board.Position; + +/** + * Project: Chess
+ * File: PositionTest.java
+ * Created: 24.07.2019
+ * Author: Kai S. K. Engelbart + */ +class PositionTest { + + List positions; + List sans; + + /** + * @throws java.lang.Exception + */ + @BeforeEach + void setUp() throws Exception { + positions = Arrays.asList(new Position(0, 0), new Position(7, 7), new Position(0, 7), new Position(7, 0)); + sans = Arrays.asList("a8", "h1", "a1", "h8"); + } + + /** + * Test method for + * {@link dev.kske.chess.board.Position#fromSAN(java.lang.String)}. + */ + @Test + void testFromSAN() { + IntStream.range(0, positions.size()) + .forEach(i -> assertEquals(positions.get(i), Position.fromSAN(sans.get(i)))); + } + + /** + * Test method for {@link dev.kske.chess.board.Position#toSAN()}. + */ + @Test + void testToSAN() { + IntStream.range(0, positions.size()).forEach(i -> assertEquals(sans.get(i), positions.get(i).toSAN())); + } + +}