droidfish/CuckooChessEngine/test/chess/PositionTest.java
2011-11-12 19:43:53 +00:00

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));
}
}