mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2024-12-02 16:32:59 +01:00
445 lines
18 KiB
Java
445 lines
18 KiB
Java
/*
|
|
CuckooChess - A java chess program.
|
|
Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package chess;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import org.junit.After;
|
|
import org.junit.AfterClass;
|
|
import org.junit.Before;
|
|
import org.junit.BeforeClass;
|
|
import org.junit.Test;
|
|
import static org.junit.Assert.*;
|
|
|
|
/**
|
|
*
|
|
* @author petero
|
|
*/
|
|
public class PositionTest {
|
|
|
|
public PositionTest() {
|
|
}
|
|
|
|
@BeforeClass
|
|
public static void setUpClass() throws Exception {
|
|
}
|
|
|
|
@AfterClass
|
|
public static void tearDownClass() throws Exception {
|
|
}
|
|
|
|
@Before
|
|
public void setUp() {
|
|
}
|
|
|
|
@After
|
|
public void tearDown() {
|
|
}
|
|
|
|
/**
|
|
* Test of getPiece method, of class Position.
|
|
*/
|
|
@Test
|
|
public void testGetPiece() throws ChessParseError {
|
|
System.out.println("getPiece");
|
|
Position pos = new Position();
|
|
int result = pos.getPiece(0);
|
|
assertEquals(result, Piece.EMPTY);
|
|
|
|
pos = TextIO.readFEN(TextIO.startPosFEN);
|
|
result = pos.getPiece(0);
|
|
assertEquals(result, Piece.WROOK);
|
|
for (int x = 0; x < 8; x++) {
|
|
for (int y = 0; y < 2; y++) {
|
|
int p1 = pos.getPiece(Position.getSquare(x, y));
|
|
int p2 = pos.getPiece(Position.getSquare(x, 7-y));
|
|
int bwDiff = Piece.BPAWN - Piece.WPAWN;
|
|
assertEquals(p2, p1 + bwDiff);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test of getIndex method, of class Position.
|
|
*/
|
|
@Test
|
|
public void testGetIndex() {
|
|
System.out.println("getIndex");
|
|
for (int x = 0; x < 8; x++) {
|
|
for (int y = 0; y < 8; y++) {
|
|
int sq = Position.getSquare(x, y);
|
|
int x2 = Position.getX(sq);
|
|
int y2 = Position.getY(sq);
|
|
assertEquals(x, x2);
|
|
assertEquals(y, y2);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test of setPiece method, of class Position.
|
|
*/
|
|
@Test
|
|
public void testSetPiece() {
|
|
System.out.println("setPiece");
|
|
Position instance = new Position();
|
|
assertEquals(Piece.EMPTY, instance.getPiece(Position.getSquare(0, 0)));
|
|
instance.setPiece(Position.getSquare(3, 4), Piece.WKING);
|
|
assertEquals(Piece.WKING, instance.getPiece(Position.getSquare(3, 4)));
|
|
}
|
|
|
|
/**
|
|
* Test of makeMove method, of class Position.
|
|
*/
|
|
@Test
|
|
public void testMakeMove() throws ChessParseError {
|
|
System.out.println("makeMove");
|
|
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
|
Position origPos = new Position(pos);
|
|
assertTrue(pos.equals(origPos));
|
|
Move move = new Move(Position.getSquare(4,1), Position.getSquare(4,3), Piece.EMPTY);
|
|
UndoInfo ui = new UndoInfo();
|
|
pos.makeMove(move, ui);
|
|
assertEquals(pos.whiteMove, false);
|
|
assertEquals(-1, pos.getEpSquare());
|
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(4,1)));
|
|
assertEquals(Piece.WPAWN, pos.getPiece(Position.getSquare(4,3)));
|
|
assertTrue(!pos.equals(origPos));
|
|
int castleMask = (1 << Position.A1_CASTLE) |
|
|
(1 << Position.H1_CASTLE) |
|
|
(1 << Position.A8_CASTLE) |
|
|
(1 << Position.H8_CASTLE);
|
|
assertEquals(castleMask,pos.getCastleMask());
|
|
pos.unMakeMove(move, ui);
|
|
assertEquals(pos.whiteMove, true);
|
|
assertEquals(Piece.WPAWN, pos.getPiece(Position.getSquare(4,1)));
|
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(4,3)));
|
|
assertTrue(pos.equals(origPos));
|
|
|
|
String fen = "r1bqk2r/2ppbppp/p1n2n2/1pP1p3/B3P3/5N2/PP1P1PPP/RNBQK2R w KQkq b6 0 2";
|
|
pos = TextIO.readFEN(fen);
|
|
assertEquals(fen, TextIO.toFEN(pos));
|
|
origPos = new Position(pos);
|
|
assertEquals(Position.getSquare(1,5), pos.getEpSquare());
|
|
|
|
// Test capture
|
|
move = new Move(Position.getSquare(0, 3), Position.getSquare(1,4), Piece.EMPTY);
|
|
pos.makeMove(move, ui);
|
|
assertEquals(-1, pos.getEpSquare());
|
|
assertEquals(Piece.WBISHOP, pos.getPiece(Position.getSquare(1,4)));
|
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(0,3)));
|
|
pos.unMakeMove(move, ui);
|
|
assertTrue(pos.equals(origPos));
|
|
|
|
// Test castling
|
|
move = new Move(Position.getSquare(4, 0), Position.getSquare(6,0), Piece.EMPTY);
|
|
pos.makeMove(move, ui);
|
|
assertEquals(Piece.WROOK, pos.getPiece(Position.getSquare(5,0)));
|
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(7,0)));
|
|
castleMask = (1 << Position.A8_CASTLE) |
|
|
(1 << Position.H8_CASTLE);
|
|
assertEquals(castleMask,pos.getCastleMask());
|
|
assertEquals(-1, pos.getEpSquare());
|
|
pos.unMakeMove(move, ui);
|
|
assertTrue(pos.equals(origPos));
|
|
|
|
// Test castling rights (king move)
|
|
move = new Move(Position.getSquare(4, 0), Position.getSquare(4,1), Piece.EMPTY);
|
|
pos.makeMove(move, ui);
|
|
castleMask = (1 << Position.A8_CASTLE) |
|
|
(1 << Position.H8_CASTLE);
|
|
assertEquals(castleMask,pos.getCastleMask());
|
|
assertEquals(-1, pos.getEpSquare());
|
|
pos.unMakeMove(move, ui);
|
|
assertTrue(pos.equals(origPos));
|
|
|
|
// Test castling rights (rook move)
|
|
move = new Move(Position.getSquare(7, 0), Position.getSquare(6,0), Piece.EMPTY);
|
|
pos.makeMove(move, ui);
|
|
castleMask = (1 << Position.A1_CASTLE) |
|
|
(1 << Position.A8_CASTLE) |
|
|
(1 << Position.H8_CASTLE);
|
|
assertEquals(castleMask,pos.getCastleMask());
|
|
assertEquals(-1, pos.getEpSquare());
|
|
pos.unMakeMove(move, ui);
|
|
assertTrue(pos.equals(origPos));
|
|
|
|
// Test en passant
|
|
move = new Move(Position.getSquare(2, 4), Position.getSquare(1,5), Piece.EMPTY);
|
|
pos.makeMove(move, ui);
|
|
assertEquals(Piece.WPAWN, pos.getPiece(Position.getSquare(1,5)));
|
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(2,4)));
|
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(1,4)));
|
|
pos.unMakeMove(move, ui);
|
|
assertTrue(pos.equals(origPos));
|
|
|
|
// Test castling rights loss when rook captured
|
|
pos.setPiece(Position.getSquare(6,2), Piece.BKNIGHT);
|
|
pos.setWhiteMove(false);
|
|
Position origPos2 = new Position(pos);
|
|
move = new Move(Position.getSquare(6,2), Position.getSquare(7,0), Piece.EMPTY);
|
|
pos.makeMove(move, ui);
|
|
castleMask = (1 << Position.A1_CASTLE) |
|
|
(1 << Position.A8_CASTLE) |
|
|
(1 << Position.H8_CASTLE);
|
|
assertEquals(castleMask,pos.getCastleMask());
|
|
assertEquals(-1, pos.getEpSquare());
|
|
pos.unMakeMove(move, ui);
|
|
assertTrue(pos.equals(origPos2));
|
|
}
|
|
|
|
@Test
|
|
public void testCastleMask() throws ChessParseError {
|
|
System.out.println("castleMask");
|
|
Position pos = TextIO.readFEN("rnbqk1nr/pppp1ppp/8/4p3/4P3/2N2N2/PPPP1bPP/R1BQKB1R w KQkq - 0 1");
|
|
UndoInfo ui = new UndoInfo();
|
|
Move m = TextIO.stringToMove(pos, "Kxf2");
|
|
pos.makeMove(m, ui);
|
|
int castleMask = (1 << Position.A8_CASTLE) |
|
|
(1 << Position.H8_CASTLE);
|
|
assertEquals(castleMask, pos.getCastleMask());
|
|
}
|
|
|
|
/**
|
|
* Test of makeMove method, of class Position.
|
|
*/
|
|
@Test
|
|
public void testPromotion() throws ChessParseError {
|
|
System.out.println("promotion");
|
|
String fen = "r1bqk2r/1Pppbppp/p1n2n2/2P1p3/B3P3/5N2/Pp1P1PPP/R1BQK2R w KQkq - 0 1";
|
|
Position pos = TextIO.readFEN(fen);
|
|
assertEquals(fen, TextIO.toFEN(pos));
|
|
Position origPos = new Position(pos);
|
|
assertEquals(origPos, pos);
|
|
|
|
Move move = new Move(Position.getSquare(1, 6), Position.getSquare(0,7), Piece.WQUEEN);
|
|
UndoInfo ui = new UndoInfo();
|
|
pos.makeMove(move, ui);
|
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(1,6)));
|
|
assertEquals(Piece.WQUEEN, pos.getPiece(Position.getSquare(0,7)));
|
|
pos.unMakeMove(move, ui);
|
|
assertEquals(origPos, pos);
|
|
|
|
move = new Move(Position.getSquare(1, 6), Position.getSquare(1,7), Piece.WKNIGHT);
|
|
ui = new UndoInfo();
|
|
pos.makeMove(move, ui);
|
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(1,6)));
|
|
assertEquals(Piece.WKNIGHT, pos.getPiece(Position.getSquare(1,7)));
|
|
pos.unMakeMove(move, ui);
|
|
assertEquals(origPos, pos);
|
|
|
|
pos.setWhiteMove(false);
|
|
origPos = new Position(pos);
|
|
|
|
move = new Move(Position.getSquare(1, 1), Position.getSquare(2, 0), Piece.BROOK);
|
|
ui = new UndoInfo();
|
|
pos.makeMove(move, ui);
|
|
assertEquals(Piece.EMPTY, pos.getPiece(Position.getSquare(1,1)));
|
|
assertEquals(Piece.BROOK, pos.getPiece(Position.getSquare(2,0)));
|
|
pos.unMakeMove(move, ui);
|
|
assertEquals(origPos, pos);
|
|
}
|
|
|
|
/**
|
|
* Test move counters, of class Position.
|
|
*/
|
|
@Test
|
|
public void testMoveCounters() throws ChessParseError {
|
|
System.out.println("moveCounters");
|
|
String fen = "r1bqk2r/2ppbppp/p1n2n2/1pP1p3/B3P3/5N2/PP1P1PPP/RNBQK2R w KQkq b6 0 7";
|
|
Position pos = TextIO.readFEN(fen);
|
|
|
|
Move move = TextIO.stringToMove(pos, "Nc3");
|
|
UndoInfo ui = new UndoInfo();
|
|
pos.makeMove(move, ui);
|
|
assertEquals(1, pos.halfMoveClock);
|
|
assertEquals(7, pos.fullMoveCounter);
|
|
pos.unMakeMove(move, ui);
|
|
|
|
move = TextIO.stringToMove(pos, "O-O");
|
|
pos.makeMove(move, ui);
|
|
assertEquals(1, pos.halfMoveClock); // Castling does not reset 50 move counter
|
|
assertEquals(7, pos.fullMoveCounter);
|
|
pos.unMakeMove(move, ui);
|
|
|
|
move = TextIO.stringToMove(pos, "a3");
|
|
pos.makeMove(move, ui);
|
|
assertEquals(0, pos.halfMoveClock); // Pawn move resets 50 move counter
|
|
assertEquals(7, pos.fullMoveCounter);
|
|
pos.unMakeMove(move, ui);
|
|
|
|
move = TextIO.stringToMove(pos, "Nxe5");
|
|
pos.makeMove(move, ui);
|
|
assertEquals(0, pos.halfMoveClock); // Capture move resets 50 move counter
|
|
assertEquals(7, pos.fullMoveCounter);
|
|
pos.unMakeMove(move, ui);
|
|
|
|
move = TextIO.stringToMove(pos, "cxb6");
|
|
pos.makeMove(move, ui);
|
|
assertEquals(0, pos.halfMoveClock); // EP capture move resets 50 move counter
|
|
assertEquals(7, pos.fullMoveCounter);
|
|
pos.unMakeMove(move, ui);
|
|
|
|
move = TextIO.stringToMove(pos, "Kf1");
|
|
pos.makeMove(move, ui);
|
|
assertEquals(1, pos.halfMoveClock); // Loss of castling rights does not reset 50 move counter
|
|
assertEquals(7, pos.fullMoveCounter);
|
|
pos.unMakeMove(move, ui);
|
|
|
|
Move firstMove = TextIO.stringToMove(pos, "Nc3");
|
|
UndoInfo firstUi = new UndoInfo();
|
|
pos.makeMove(move, firstUi);
|
|
move = TextIO.stringToMove(pos, "O-O");
|
|
pos.makeMove(move, ui);
|
|
assertEquals(2, pos.halfMoveClock);
|
|
assertEquals(8, pos.fullMoveCounter); // Black move increases fullMoveCounter
|
|
pos.unMakeMove(move, ui);
|
|
pos.unMakeMove(firstMove, firstUi);
|
|
|
|
fen = "8/8/8/4k3/8/8/2p5/5K2 b - - 47 68";
|
|
pos = TextIO.readFEN(fen);
|
|
move = TextIO.stringToMove(pos, "c1Q");
|
|
pos.makeMove(move, ui);
|
|
assertEquals(0, pos.halfMoveClock); // Pawn promotion resets 50 move counter
|
|
assertEquals(69, pos.fullMoveCounter);
|
|
}
|
|
|
|
/**
|
|
* Test of drawRuleEquals, of class Position.
|
|
*/
|
|
@Test
|
|
public void testDrawRuleEquals() throws ChessParseError {
|
|
System.out.println("drawRuleEquals");
|
|
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
|
Position origPos = new Position(pos);
|
|
UndoInfo ui = new UndoInfo();
|
|
pos.makeMove(TextIO.stringToMove(pos, "Nf3"), ui);
|
|
assertEquals(false, pos.drawRuleEquals(origPos));
|
|
pos.makeMove(TextIO.stringToMove(pos, "Nf6"), ui);
|
|
assertEquals(false, pos.drawRuleEquals(origPos));
|
|
pos.makeMove(TextIO.stringToMove(pos, "Ng1"), ui);
|
|
assertEquals(false, pos.drawRuleEquals(origPos));
|
|
pos.makeMove(TextIO.stringToMove(pos, "Ng8"), ui);
|
|
assertEquals(true, pos.drawRuleEquals(origPos));
|
|
assertEquals(false, pos.equals(origPos)); // Move counters have changed
|
|
|
|
String fen = "r1bqkb1r/pppp1ppp/2n2n2/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R w KQkq - 0 1";
|
|
pos = TextIO.readFEN(fen);
|
|
origPos = new Position(pos);
|
|
pos.makeMove(TextIO.stringToMove(pos, "Ke2"), ui);
|
|
assertEquals(false, pos.drawRuleEquals(origPos));
|
|
pos.makeMove(TextIO.stringToMove(pos, "Be7"), ui);
|
|
assertEquals(false, pos.drawRuleEquals(origPos));
|
|
pos.makeMove(TextIO.stringToMove(pos, "Ke1"), ui);
|
|
assertEquals(false, pos.drawRuleEquals(origPos));
|
|
pos.makeMove(TextIO.stringToMove(pos, "Bf8"), ui);
|
|
assertEquals(false, pos.drawRuleEquals(origPos)); // Not equal, castling rights lost
|
|
|
|
pos = TextIO.readFEN(TextIO.startPosFEN);
|
|
pos.makeMove(TextIO.stringToMove(pos, "c4"), ui);
|
|
pos.makeMove(TextIO.stringToMove(pos, "a6"), ui);
|
|
pos.makeMove(TextIO.stringToMove(pos, "c5"), ui);
|
|
pos.makeMove(TextIO.stringToMove(pos, "b5"), ui);
|
|
assertEquals(Position.getSquare(1, 5), pos.getEpSquare());
|
|
origPos = new Position(pos);
|
|
pos.makeMove(TextIO.stringToMove(pos, "Nc3"), ui);
|
|
pos.makeMove(TextIO.stringToMove(pos, "Nc6"), ui);
|
|
pos.makeMove(TextIO.stringToMove(pos, "Nb1"), ui);
|
|
pos.makeMove(TextIO.stringToMove(pos, "Nb8"), ui);
|
|
assertEquals(false, pos.drawRuleEquals(origPos)); // Not equal, en passant rights lost
|
|
}
|
|
|
|
/**
|
|
* Test of hashCode method, of class Position.
|
|
*/
|
|
@Test
|
|
public void testHashCode() throws ChessParseError {
|
|
System.out.println("hashCode");
|
|
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
|
long h1 = pos.zobristHash();
|
|
assertEquals(h1, pos.computeZobristHash());
|
|
UndoInfo ui = new UndoInfo();
|
|
Move move = TextIO.stringToMove(pos, "e4");
|
|
pos.makeMove(move, ui);
|
|
assertTrue(h1 != pos.zobristHash());
|
|
pos.unMakeMove(move, ui);
|
|
assertTrue(h1 == pos.zobristHash());
|
|
|
|
pos.setWhiteMove(!pos.whiteMove);
|
|
long h4 = pos.zobristHash();
|
|
assertEquals(h4, pos.computeZobristHash());
|
|
assertTrue(h1 != pos.zobristHash());
|
|
pos.setWhiteMove(!pos.whiteMove);
|
|
assertTrue(h1 == pos.zobristHash());
|
|
|
|
pos.setCastleMask(0);
|
|
assertTrue(h1 != pos.zobristHash());
|
|
|
|
pos = TextIO.readFEN("rnbqkbnr/pppp1ppp/8/2P1p3/8/8/PP1PPPPP/RNBQKBNR b KQkq - 0 1");
|
|
h1 = pos.zobristHash();
|
|
assertEquals(h1, pos.computeZobristHash());
|
|
|
|
String[] moves = {
|
|
"b5", "Nc3", "Nf6", "Nb1", "Ng8", "Nc3", "Nf6", "Nb1", "Ng8", "Nc3", "d5",
|
|
"cxd6", "Qxd6", "h4", "Be6", "h5", "Nc6", "h6", "o-o-o", "hxg7", "Nf6", "gxh8Q", "Be7"
|
|
};
|
|
List<UndoInfo> uiList = new ArrayList<UndoInfo>();
|
|
List<Long> hashList = new ArrayList<Long>();
|
|
List<Move> moveList = new ArrayList<Move>();
|
|
for (int i = 0; i < moves.length; i++) {
|
|
uiList.add(new UndoInfo());
|
|
Move m = TextIO.stringToMove(pos, moves[i]);
|
|
moveList.add(m);
|
|
pos.makeMove(m, uiList.get(i));
|
|
long h = pos.zobristHash();
|
|
assertEquals(h, pos.computeZobristHash());
|
|
hashList.add(h);
|
|
}
|
|
assertTrue(!hashList.get(0).equals(hashList.get(4)));
|
|
assertTrue(hashList.get(4).equals(hashList.get(8)));
|
|
for (int i = moves.length - 1; i >= 0; i--) {
|
|
pos.unMakeMove(moveList.get(i), uiList.get(i));
|
|
long h = pos.zobristHash();
|
|
assertEquals(h, pos.computeZobristHash());
|
|
assertEquals(h, i > 0 ? hashList.get(i - 1) : h1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test of getKingSq method, of class Position.
|
|
*/
|
|
@Test
|
|
public void testGetKingSq() throws ChessParseError {
|
|
System.out.println("getKingSq");
|
|
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
|
assertEquals(TextIO.getSquare("e1"), pos.getKingSq(true));
|
|
assertEquals(TextIO.getSquare("e8"), pos.getKingSq(false));
|
|
pos = TextIO.readFEN("r1bq1bnr/ppppkppp/2n5/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R w KQ - 0 4");
|
|
assertEquals(TextIO.getSquare("e1"), pos.getKingSq(true));
|
|
assertEquals(TextIO.getSquare("e7"), pos.getKingSq(false));
|
|
UndoInfo ui = new UndoInfo();
|
|
pos.makeMove(TextIO.stringToMove(pos, "o-o"), ui);
|
|
assertEquals(TextIO.getSquare("g1"), pos.getKingSq(true));
|
|
assertEquals(TextIO.getSquare("e7"), pos.getKingSq(false));
|
|
pos.makeMove(TextIO.stringToMove(pos, "Kd6"), ui);
|
|
assertEquals(TextIO.getSquare("g1"), pos.getKingSq(true));
|
|
assertEquals(TextIO.getSquare("d6"), pos.getKingSq(false));
|
|
}
|
|
}
|