mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2024-11-23 11:31:33 +01:00
CuckooChessEngine: Moved unit test code to a separate project, so that
it is not included in DroidFish.
This commit is contained in:
parent
d436b8567e
commit
c3f34dc9de
|
@ -2,7 +2,6 @@
|
|||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="test"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
|
|
@ -1,149 +0,0 @@
|
|||
/*
|
||||
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 static org.junit.Assert.*;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class BitBoardTest {
|
||||
public BitBoardTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
/** Test of kingAttacks, of class BitBoard. */
|
||||
@Test
|
||||
public void testKingAttacks() throws ChessParseError {
|
||||
System.out.println("kingAttacks");
|
||||
assertEquals(5, Long.bitCount(BitBoard.kingAttacks[TextIO.getSquare("g1")]));
|
||||
assertEquals(3, Long.bitCount(BitBoard.kingAttacks[TextIO.getSquare("h1")]));
|
||||
assertEquals(3, Long.bitCount(BitBoard.kingAttacks[TextIO.getSquare("a1")]));
|
||||
assertEquals(5, Long.bitCount(BitBoard.kingAttacks[TextIO.getSquare("a2")]));
|
||||
assertEquals(3, Long.bitCount(BitBoard.kingAttacks[TextIO.getSquare("h8")]));
|
||||
assertEquals(5, Long.bitCount(BitBoard.kingAttacks[TextIO.getSquare("a6")]));
|
||||
assertEquals(8, Long.bitCount(BitBoard.kingAttacks[TextIO.getSquare("b2")]));
|
||||
}
|
||||
|
||||
/** Test of knightAttacks, of class BitBoard. */
|
||||
@Test
|
||||
public void testKnightAttacks() throws ChessParseError {
|
||||
System.out.println("knightAttacks");
|
||||
assertEquals(3, Long.bitCount(BitBoard.knightAttacks[TextIO.getSquare("g1")]));
|
||||
assertEquals(2, Long.bitCount(BitBoard.knightAttacks[TextIO.getSquare("a1")]));
|
||||
assertEquals(2, Long.bitCount(BitBoard.knightAttacks[TextIO.getSquare("h1")]));
|
||||
assertEquals(4, Long.bitCount(BitBoard.knightAttacks[TextIO.getSquare("h6")]));
|
||||
assertEquals(4, Long.bitCount(BitBoard.knightAttacks[TextIO.getSquare("b7")]));
|
||||
assertEquals(8, Long.bitCount(BitBoard.knightAttacks[TextIO.getSquare("c6")]));
|
||||
assertEquals((1L<<TextIO.getSquare("e2")) |
|
||||
(1L<<TextIO.getSquare("f3")) |
|
||||
(1L<<TextIO.getSquare("h3")),
|
||||
BitBoard.knightAttacks[TextIO.getSquare("g1")]);
|
||||
}
|
||||
|
||||
/** Test of squaresBetween[][], of class BitBoard. */
|
||||
@Test
|
||||
public void testSquaresBetween() throws ChessParseError {
|
||||
System.out.println("squaresBetween");
|
||||
// Tests that the set of nonzero elements is correct
|
||||
for (int sq1 = 0; sq1 < 64; sq1++) {
|
||||
for (int sq2 = 0; sq2 < 64; sq2++) {
|
||||
int d = BitBoard.getDirection(sq1, sq2);
|
||||
if (d == 0) {
|
||||
assertEquals(0, BitBoard.squaresBetween[sq1][sq2]);
|
||||
} else {
|
||||
int dx = Position.getX(sq1) - Position.getX(sq2);
|
||||
int dy = Position.getY(sq1) - Position.getY(sq2);
|
||||
if (Math.abs(dx * dy) == 2) { // Knight direction
|
||||
assertEquals(0, BitBoard.squaresBetween[sq1][sq2]);
|
||||
} else {
|
||||
if ((Math.abs(dx) > 1) || (Math.abs(dy) > 1)) {
|
||||
assertTrue(BitBoard.squaresBetween[sq1][sq2] != 0);
|
||||
} else {
|
||||
assertEquals(0, BitBoard.squaresBetween[sq1][sq2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(0x0040201008040200L, BitBoard.squaresBetween[0][63]);
|
||||
assertEquals(0x000000001C000000L, BitBoard.squaresBetween[TextIO.getSquare("b4")][TextIO.getSquare("f4")]);
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is a piece type that can move from "from" to "to", return the
|
||||
* corresponding direction, 8*dy+dx.
|
||||
*/
|
||||
private static final int computeDirection(int from, int to) {
|
||||
int dx = Position.getX(to) - Position.getX(from);
|
||||
int dy = Position.getY(to) - Position.getY(from);
|
||||
if (dx == 0) { // Vertical rook direction
|
||||
if (dy == 0) return 0;
|
||||
return (dy > 0) ? 8 : -8;
|
||||
}
|
||||
if (dy == 0) // Horizontal rook direction
|
||||
return (dx > 0) ? 1 : -1;
|
||||
if (Math.abs(dx) == Math.abs(dy)) // Bishop direction
|
||||
return ((dy > 0) ? 8 : -8) + (dx > 0 ? 1 : -1);
|
||||
if (Math.abs(dx * dy) == 2) // Knight direction
|
||||
return dy * 8 + dx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDirection() {
|
||||
System.out.println("getDirection");
|
||||
for (int from = 0; from < 64; from++) {
|
||||
for (int to = 0; to < 64; to++) {
|
||||
assertEquals(computeDirection(from, to), BitBoard.getDirection(from, to));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final int computeDistance(int from, int to) {
|
||||
int dx = Position.getX(to) - Position.getX(from);
|
||||
int dy = Position.getY(to) - Position.getY(from);
|
||||
return Math.max(Math.abs(dx), Math.abs(dy));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDistance() {
|
||||
for (int from = 0; from < 64; from++)
|
||||
for (int to = 0; to < 64; to++)
|
||||
assertEquals(computeDistance(from, to), BitBoard.getDistance(from, to));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrailingZeros() {
|
||||
System.out.println("trailingZeros");
|
||||
for (int i = 0; i < 64; i++) {
|
||||
long mask = 1L << i;
|
||||
assertEquals(i, BitBoard.numberOfTrailingZeros(mask));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
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 org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author petero
|
||||
*/
|
||||
public class BookTest {
|
||||
|
||||
public BookTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getBookMove method, of class Book.
|
||||
*/
|
||||
@Test
|
||||
public void testGetBookMove() throws ChessParseError {
|
||||
System.out.println("getBookMove");
|
||||
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||
Book book = new Book(true);
|
||||
Move move = book.getBookMove(pos);
|
||||
checkValid(pos, move);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getAllBookMoves method, of class Book.
|
||||
*/
|
||||
@Test
|
||||
public void testGetAllBookMoves() throws ChessParseError {
|
||||
System.out.println("getAllBookMoves");
|
||||
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||
Book book = new Book(true);
|
||||
String moveListString = book.getAllBookMoves(pos);
|
||||
String[] strMoves = moveListString.split("\\([0-9]*\\) ");
|
||||
assertTrue(strMoves.length > 1);
|
||||
for (String strMove : strMoves) {
|
||||
Move m = TextIO.stringToMove(pos, strMove);
|
||||
checkValid(pos, m);
|
||||
}
|
||||
}
|
||||
|
||||
/** Check that move is a legal move in position pos. */
|
||||
private void checkValid(Position pos, Move move) {
|
||||
assertTrue(move != null);
|
||||
MoveGen.MoveList moveList = new MoveGen().pseudoLegalMoves(pos);
|
||||
MoveGen.removeIllegal(pos, moveList);
|
||||
boolean contains = false;
|
||||
for (int mi = 0; mi < moveList.size; mi++)
|
||||
if (moveList.m[mi].equals(move)) {
|
||||
contains = true;
|
||||
break;
|
||||
}
|
||||
assertTrue(contains);
|
||||
}
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
/*
|
||||
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 org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author petero
|
||||
*/
|
||||
public class ComputerPlayerTest {
|
||||
|
||||
public ComputerPlayerTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getCommand method, of class ComputerPlayer.
|
||||
*/
|
||||
@Test
|
||||
public void testGetCommand() throws ChessParseError {
|
||||
System.out.println("getCommand");
|
||||
ArrayList<Position> nullHist = new ArrayList<Position>();
|
||||
|
||||
Position pos = TextIO.readFEN("7k/5Q2/p5K1/8/8/8/8/8 b - - 99 80");
|
||||
ComputerPlayer cp = new ComputerPlayer();
|
||||
cp.maxDepth = 1;
|
||||
cp.maxTimeMillis = -1;
|
||||
cp.verbose = false;
|
||||
String result = cp.getCommand(pos, false, nullHist);
|
||||
assertEquals("a5", result); // Only one legal move
|
||||
|
||||
pos = TextIO.readFEN("7k/5Q2/p5K1/8/8/8/8/8 b - - 100 80");
|
||||
result = cp.getCommand(pos, false, nullHist);
|
||||
assertEquals("draw 50", result); // Should claim draw without making a move
|
||||
|
||||
pos = TextIO.readFEN("3k4/1R6/R7/8/8/8/8/1K6 w - - 100 80");
|
||||
result = cp.getCommand(pos, false, nullHist);
|
||||
assertEquals("Ra8#", result); // Can claim draw, but should not
|
||||
|
||||
pos = TextIO.readFEN("8/1R5k/R7/8/8/8/B7/1K6 b - - 99 80");
|
||||
result = cp.getCommand(pos, false, nullHist);
|
||||
assertEquals("draw 50 Kh8", result); // Should claim draw by 50-move rule
|
||||
|
||||
// Only one possible move. Should realize that draw claim is possible, but very bad
|
||||
pos = TextIO.readFEN("6Nk/8/5K1R/q7/q7/q7/8/8 b - - 100 80");
|
||||
result = cp.getCommand(pos, false, nullHist);
|
||||
assertEquals("Kxg8", result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of draw by repetition, of class ComputerPlayer.
|
||||
*/
|
||||
@Test
|
||||
public void testDrawRep() throws ChessParseError {
|
||||
System.out.println("drawRep");
|
||||
Game game = new Game(new HumanPlayer(), new HumanPlayer());
|
||||
ComputerPlayer cp = new ComputerPlayer();
|
||||
cp.maxDepth = 3;
|
||||
cp.maxTimeMillis = -1;
|
||||
cp.verbose = false;
|
||||
game.processString("setpos 7k/5RR1/8/8/8/8/q3q3/2K5 w - - 0 1");
|
||||
game.processString("Rh7");
|
||||
game.processString("Kg8");
|
||||
game.processString("Rhg7");
|
||||
String result = cp.getCommand(new Position(game.pos), false, game.getHistory());
|
||||
assertEquals("Kh8", result); // Not valid to claim draw here
|
||||
game.processString("Kh8");
|
||||
game.processString("Rh7");
|
||||
game.processString("Kg8");
|
||||
game.processString("Rhg7");
|
||||
result = cp.getCommand(new Position(game.pos), false, game.getHistory());
|
||||
assertEquals("draw rep Kh8", result); // Can't win, but can claim draw.
|
||||
|
||||
game.processString("setpos 7k/R7/1R6/8/8/8/8/K7 w - - 0 1");
|
||||
game.processString("Ra8");
|
||||
game.processString("Kh7");
|
||||
result = cp.getCommand(new Position(game.pos), false, game.getHistory());
|
||||
assertEquals("Ra7+", result); // Ra7 is mate-in-two
|
||||
game.processString("Ra7");
|
||||
game.processString("Kh8");
|
||||
game.processString("Ra8");
|
||||
game.processString("Kh7");
|
||||
result = cp.getCommand(new Position(game.pos), false, game.getHistory());
|
||||
assertTrue(!result.equals("Ra7+")); // Ra7 now leads to a draw by repetition
|
||||
}
|
||||
}
|
|
@ -1,530 +0,0 @@
|
|||
/*
|
||||
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 org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author petero
|
||||
*/
|
||||
public class EvaluateTest {
|
||||
|
||||
public EvaluateTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of evalPos method, of class Evaluate.
|
||||
*/
|
||||
@Test
|
||||
public void testEvalPos() throws ChessParseError {
|
||||
System.out.println("evalPos");
|
||||
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||
UndoInfo ui = new UndoInfo();
|
||||
pos.makeMove(TextIO.stringToMove(pos, "e4"), ui);
|
||||
pos.makeMove(TextIO.stringToMove(pos, "e5"), ui);
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Nf3"), ui);
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Nc6"), ui);
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Bb5"), ui);
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Nge7"), ui);
|
||||
assertTrue(moveScore(pos, "O-O") > 0); // Castling is good
|
||||
assertTrue(moveScore(pos, "Ke2") < 0); // Losing right to castle is bad
|
||||
assertTrue(moveScore(pos, "Kf1") < 0);
|
||||
assertTrue(moveScore(pos, "Rg1") < 0);
|
||||
assertTrue(moveScore(pos, "Rf1") < 0);
|
||||
|
||||
pos = TextIO.readFEN("8/8/8/1r3k2/4pP2/4P3/8/4K2R w K - 0 1");
|
||||
assertEquals(true, pos.h1Castle());
|
||||
int cs1 = evalWhite(pos);
|
||||
pos.setCastleMask(pos.getCastleMask() & ~(1 << Position.H1_CASTLE));
|
||||
assertEquals(false, pos.h1Castle());
|
||||
int cs2 = evalWhite(pos);
|
||||
assertTrue(cs2 >= cs1); // No bonus for useless castle right
|
||||
|
||||
// Test rook open file bonus
|
||||
pos = TextIO.readFEN("r4rk1/1pp1qppp/3b1n2/4p3/2B1P1b1/1QN2N2/PP3PPP/R3R1K1 w - - 0 1");
|
||||
int ms1 = moveScore(pos, "Red1");
|
||||
int ms2 = moveScore(pos, "Rec1");
|
||||
int ms3 = moveScore(pos, "Rac1");
|
||||
int ms4 = moveScore(pos, "Rad1");
|
||||
assertTrue(ms1 > 0); // Good to have rook on open file
|
||||
assertTrue(ms2 > 0); // Good to have rook on half-open file
|
||||
assertTrue(ms1 > ms2); // Open file better than half-open file
|
||||
assertTrue(ms3 > 0);
|
||||
assertTrue(ms4 > 0);
|
||||
assertTrue(ms4 > ms1);
|
||||
assertTrue(ms3 > ms2);
|
||||
|
||||
pos = TextIO.readFEN("r3kb1r/p3pp1p/bpPq1np1/4N3/2pP4/2N1PQ2/P1PB1PPP/R3K2R b KQkq - 0 12");
|
||||
assertTrue(moveScore(pos, "O-O-O") > 0); // Black long castle is bad for black
|
||||
pos.makeMove(TextIO.stringToMove(pos, "O-O-O"), ui);
|
||||
assertTrue(moveScore(pos, "O-O") > 0); // White short castle is good for white
|
||||
|
||||
pos = TextIO.readFEN("8/3k4/2p5/1pp5/1P1P4/3K4/8/8 w - - 0 1");
|
||||
int sc1 = moveScore(pos, "bxc5");
|
||||
int sc2 = moveScore(pos, "dxc5");
|
||||
assertTrue(sc1 < sc2); // Don't give opponent a passed pawn.
|
||||
|
||||
pos = TextIO.readFEN("8/pp1bk3/8/8/8/8/PPPBK3/8 w - - 0 1");
|
||||
sc1 = evalWhite(pos);
|
||||
pos.setPiece(Position.getSquare(3, 1), Piece.EMPTY);
|
||||
pos.setPiece(Position.getSquare(3, 0), Piece.WBISHOP);
|
||||
sc2 = evalWhite(pos);
|
||||
assertTrue(sc2 > sc1); // Easier to win if bishops on same color
|
||||
|
||||
// Test bishop mobility
|
||||
pos = TextIO.readFEN("r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3");
|
||||
sc1 = moveScore(pos, "Bd3");
|
||||
sc2 = moveScore(pos, "Bc4");
|
||||
assertTrue(sc2 > sc1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of pieceSquareEval method, of class Evaluate.
|
||||
*/
|
||||
@Test
|
||||
public void testPieceSquareEval() throws ChessParseError {
|
||||
System.out.println("pieceSquareEval");
|
||||
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||
int score = evalWhite(pos);
|
||||
assertEquals(0, score); // Should be zero, by symmetry
|
||||
UndoInfo ui = new UndoInfo();
|
||||
pos.makeMove(TextIO.stringToMove(pos, "e4"), ui);
|
||||
score = evalWhite(pos);
|
||||
assertTrue(score > 0); // Centralizing a pawn is a good thing
|
||||
pos.makeMove(TextIO.stringToMove(pos, "e5"), ui);
|
||||
score = evalWhite(pos);
|
||||
assertEquals(0, score); // Should be zero, by symmetry
|
||||
assertTrue(moveScore(pos, "Nf3") > 0); // Developing knight is good
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Nf3"), ui);
|
||||
assertTrue(moveScore(pos, "Nc6") < 0); // Developing knight is good
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Nc6"), ui);
|
||||
assertTrue(moveScore(pos, "Bb5") > 0); // Developing bishop is good
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Bb5"), ui);
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Nge7"), ui);
|
||||
assertTrue(moveScore(pos, "Qe2") > 0); // Queen away from edge is good
|
||||
score = evalWhite(pos);
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Bxc6"), ui);
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Nxc6"), ui);
|
||||
int score2 = evalWhite(pos);
|
||||
assertTrue(score2 < score); // Bishop worth more than knight in this case
|
||||
|
||||
pos = TextIO.readFEN("5k2/4nppp/p1n5/1pp1p3/4P3/2P1BN2/PP3PPP/3R2K1 w - - 0 1");
|
||||
assertTrue(moveScore(pos, "Rd7") > 0); // Rook on 7:th rank is good
|
||||
assertTrue(moveScore(pos, "Rd8") <= 0); // Rook on 8:th rank not particularly good
|
||||
pos.setPiece(TextIO.getSquare("a1"), Piece.WROOK);
|
||||
assertTrue(moveScore(pos, "Rac1") > 0); // Rook on c-f files considered good
|
||||
|
||||
pos = TextIO.readFEN("r4rk1/pppRRppp/1q4b1/n7/8/2N3B1/PPP1QPPP/6K1 w - - 0 1");
|
||||
score = evalWhite(pos);
|
||||
assertTrue(score > 100); // Two rooks on 7:th rank is very good
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of tradeBonus method, of class Evaluate.
|
||||
*/
|
||||
@Test
|
||||
public void testTradeBonus() throws ChessParseError {
|
||||
System.out.println("tradeBonus");
|
||||
String fen = "8/5k2/6r1/2p1p3/3p4/2P2N2/3PPP2/4K1R1 w - - 0 1";
|
||||
Position pos = TextIO.readFEN(fen);
|
||||
int score1 = evalWhite(pos);
|
||||
UndoInfo ui = new UndoInfo();
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Rxg6"), ui);
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Kxg6"), ui);
|
||||
int score2 = evalWhite(pos);
|
||||
assertTrue(score2 > score1); // White ahead, trading pieces is good
|
||||
|
||||
pos = TextIO.readFEN(fen);
|
||||
pos.makeMove(TextIO.stringToMove(pos, "cxd4"), ui);
|
||||
pos.makeMove(TextIO.stringToMove(pos, "cxd4"), ui);
|
||||
score2 = evalWhite(pos);
|
||||
assertTrue(score2 < score1); // White ahead, trading pawns is bad
|
||||
|
||||
pos = TextIO.readFEN("8/8/1b2b3/4kp2/5N2/4NKP1/6B1/8 w - - 0 62");
|
||||
score1 = evalWhite(pos);
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Nxe6"), ui);
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Kxe6"), ui);
|
||||
score2 = evalWhite(pos);
|
||||
assertTrue(score2 > score1); // White ahead, trading pieces is good
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of material method, of class Evaluate.
|
||||
*/
|
||||
@Test
|
||||
public void testMaterial() throws ChessParseError {
|
||||
System.out.println("material");
|
||||
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||
assertEquals(0, Evaluate.material(pos));
|
||||
|
||||
final int pV = Evaluate.pV;
|
||||
final int qV = Evaluate.qV;
|
||||
assertTrue(pV != 0);
|
||||
assertTrue(qV != 0);
|
||||
assertTrue(qV > pV);
|
||||
|
||||
UndoInfo ui = new UndoInfo();
|
||||
pos.makeMove(TextIO.stringToMove(pos, "e4"), ui);
|
||||
assertEquals(0, Evaluate.material(pos));
|
||||
pos.makeMove(TextIO.stringToMove(pos, "d5"), ui);
|
||||
assertEquals(0, Evaluate.material(pos));
|
||||
pos.makeMove(TextIO.stringToMove(pos, "exd5"), ui);
|
||||
assertEquals(pV, Evaluate.material(pos));
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Qxd5"), ui);
|
||||
assertEquals(0, Evaluate.material(pos));
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Nc3"), ui);
|
||||
assertEquals(0, Evaluate.material(pos));
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Qxd2"), ui);
|
||||
assertEquals(-pV, Evaluate.material(pos));
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Qxd2"), ui);
|
||||
assertEquals(-pV+qV, Evaluate.material(pos));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of kingSafety method, of class Evaluate.
|
||||
*/
|
||||
@Test
|
||||
public void testKingSafety() throws ChessParseError {
|
||||
System.out.println("kingSafety");
|
||||
Position pos = TextIO.readFEN("r3kb1r/p1p1pppp/b2q1n2/4N3/3P4/2N1PQ2/P2B1PPP/R3R1K1 w kq - 0 1");
|
||||
int s1 = evalWhite(pos);
|
||||
pos.setPiece(TextIO.getSquare("g7"), Piece.EMPTY);
|
||||
pos.setPiece(TextIO.getSquare("b7"), Piece.BPAWN);
|
||||
int s2 = evalWhite(pos);
|
||||
assertTrue(s2 < s1); // Half-open g-file is bad for white
|
||||
|
||||
// Trapping rook with own king is bad
|
||||
pos = TextIO.readFEN("rnbqk1nr/pppp1ppp/8/8/1bBpP3/8/PPP2PPP/RNBQK1NR w KQkq - 2 4");
|
||||
s1 = evalWhite(pos);
|
||||
pos.setPiece(TextIO.getSquare("e1"), Piece.EMPTY);
|
||||
pos.setPiece(TextIO.getSquare("f1"), Piece.WKING);
|
||||
s2 = evalWhite(pos);
|
||||
assertTrue(s2 < s1);
|
||||
|
||||
pos = TextIO.readFEN("rnbqk1nr/pppp1ppp/8/8/1bBpPB2/8/PPP1QPPP/RN1K2NR w kq - 0 1");
|
||||
s1 = evalWhite(pos);
|
||||
pos.setPiece(TextIO.getSquare("d1"), Piece.EMPTY);
|
||||
pos.setPiece(TextIO.getSquare("c1"), Piece.WKING);
|
||||
s2 = evalWhite(pos);
|
||||
assertTrue(s2 < s1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of endGameEval method, of class Evaluate.
|
||||
*/
|
||||
@Test
|
||||
public void testEndGameEval() throws ChessParseError {
|
||||
System.out.println("endGameEval");
|
||||
Position pos = new Position();
|
||||
pos.setPiece(Position.getSquare(4, 1), Piece.WKING);
|
||||
pos.setPiece(Position.getSquare(4, 6), Piece.BKING);
|
||||
int score = evalWhite(pos);
|
||||
assertEquals(0, score);
|
||||
|
||||
pos.setPiece(Position.getSquare(3, 1), Piece.WBISHOP);
|
||||
score = evalWhite(pos);
|
||||
assertTrue(Math.abs(score) < 50); // Insufficient material to mate
|
||||
|
||||
pos.setPiece(Position.getSquare(3, 1), Piece.WKNIGHT);
|
||||
score = evalWhite(pos);
|
||||
assertTrue(Math.abs(score) < 50); // Insufficient material to mate
|
||||
|
||||
pos.setPiece(Position.getSquare(3, 1), Piece.WROOK);
|
||||
score = evalWhite(pos);
|
||||
final int rV = Evaluate.rV;
|
||||
assertTrue(Math.abs(score) > rV + 100); // Enough material to force mate
|
||||
|
||||
pos.setPiece(Position.getSquare(3, 6), Piece.BBISHOP);
|
||||
score = evalWhite(pos);
|
||||
final int bV = Evaluate.bV;
|
||||
assertTrue(score >= 0);
|
||||
assertTrue(score < rV - bV); // Insufficient excess material to mate
|
||||
|
||||
pos.setPiece(Position.getSquare(5, 6), Piece.BROOK);
|
||||
score = evalWhite(pos);
|
||||
assertTrue(score <= 0);
|
||||
assertTrue(-score < bV);
|
||||
|
||||
pos.setPiece(Position.getSquare(2, 6), Piece.BBISHOP);
|
||||
score = evalWhite(pos);
|
||||
assertTrue(-score > bV * 2 + 100);
|
||||
|
||||
// KRPKN is win for white
|
||||
pos = TextIO.readFEN("8/3bk3/8/8/8/3P4/3RK3/8 w - - 0 1");
|
||||
score = evalWhite(pos);
|
||||
final int pV = Evaluate.pV;
|
||||
assertTrue(score > rV + pV - bV - 100);
|
||||
|
||||
// KNNK is a draw
|
||||
pos = TextIO.readFEN("8/8/4k3/8/8/3NK3/3N4/8 w - - 0 1");
|
||||
score = evalWhite(pos);
|
||||
assertTrue(Math.abs(score) < 50);
|
||||
|
||||
final int nV = Evaluate.nV;
|
||||
pos = TextIO.readFEN("8/8/8/4k3/N6N/P2K4/8/8 b - - 0 66");
|
||||
score = evalWhite(pos);
|
||||
assertTrue(score > nV * 2);
|
||||
|
||||
pos = TextIO.readFEN("8/8/3k4/8/8/3NK3/2B5/8 b - - 0 1");
|
||||
score = evalWhite(pos);
|
||||
assertTrue(score > bV + nV + 150); // KBNK is won, should have a bonus
|
||||
score = moveScore(pos, "Kc6");
|
||||
assertTrue(score > 0); // Black king going into wrong corner, good for white
|
||||
score = moveScore(pos, "Ke6");
|
||||
assertTrue(score < 0); // Black king going away from wrong corner, good for black
|
||||
|
||||
// KRN vs KR is generally drawn
|
||||
pos = TextIO.readFEN("rk/p/8/8/8/8/NKR/8 w - - 0 1");
|
||||
score = evalWhite(pos);
|
||||
assertTrue(score < nV - 2 * pV);
|
||||
|
||||
// KRKB, defending king should prefer corner that bishop cannot attack
|
||||
pos = TextIO.readFEN("6B1/8/8/8/8/2k5/4r3/2K5 w - - 0 93");
|
||||
score = evalWhite(pos);
|
||||
assertTrue(score >= -pV);
|
||||
score = moveScore(pos, "Kd1");
|
||||
assertTrue(score < 0);
|
||||
score = moveScore(pos, "Kb1");
|
||||
assertTrue(score > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of endGameEval method, of class Evaluate.
|
||||
*/
|
||||
@Test
|
||||
public void testPassedPawns() throws ChessParseError {
|
||||
System.out.println("passedPawns");
|
||||
Position pos = TextIO.readFEN("8/8/8/P3k/8/8/p/K w");
|
||||
int score = evalWhite(pos);
|
||||
assertTrue(score > 300); // Unstoppable passed pawn
|
||||
pos.whiteMove = false;
|
||||
score = evalWhite(pos);
|
||||
assertTrue(score <= 0); // Not unstoppable
|
||||
|
||||
pos = TextIO.readFEN("4R3/8/8/3K4/8/4pk2/8/8 w - - 0 1");
|
||||
score = evalWhite(pos);
|
||||
pos.setPiece(TextIO.getSquare("d5"), Piece.EMPTY);
|
||||
pos.setPiece(TextIO.getSquare("d4"), Piece.WKING);
|
||||
int score2 = evalWhite(pos);
|
||||
assertTrue(score2 > score); // King closer to passed pawn promotion square
|
||||
|
||||
// Connected passed pawn test. Disabled because it didn't help in tests
|
||||
// pos = TextIO.readFEN("4k3/8/8/4P3/3P1K2/8/8/8 w - - 0 1");
|
||||
// score = evalWhite(pos);
|
||||
// pos.setPiece(TextIO.getSquare("d4"), Piece.EMPTY);
|
||||
// pos.setPiece(TextIO.getSquare("d5"), Piece.WPAWN);
|
||||
// score2 = evalWhite(pos);
|
||||
// assertTrue(score2 > score); // Advancing passed pawn is good
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of endGameEval method, of class Evaluate.
|
||||
*/
|
||||
@Test
|
||||
public void testBishAndRookPawns() throws ChessParseError {
|
||||
System.out.println("bishAndRookPawns");
|
||||
final int pV = Evaluate.pV;
|
||||
final int bV = Evaluate.bV;
|
||||
final int winScore = pV + bV;
|
||||
final int drawish = (pV + bV) / 20;
|
||||
Position pos = TextIO.readFEN("k7/8/8/8/2B5/2K5/P7/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) > winScore);
|
||||
|
||||
pos = TextIO.readFEN("k7/8/8/8/3B4/2K5/P7/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) < drawish);
|
||||
|
||||
pos = TextIO.readFEN("8/2k5/8/8/3B4/2K5/P7/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) > winScore);
|
||||
|
||||
pos = TextIO.readFEN("8/2k5/8/8/3B4/2K4P/8/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) > winScore);
|
||||
|
||||
pos = TextIO.readFEN("8/2k5/8/8/4B3/2K4P/8/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) > winScore);
|
||||
|
||||
pos = TextIO.readFEN("8/6k1/8/8/4B3/2K4P/8/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) < drawish);
|
||||
|
||||
pos = TextIO.readFEN("8/6k1/8/8/4B3/2K4P/7P/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) < drawish);
|
||||
|
||||
pos = TextIO.readFEN("8/6k1/8/8/2B1B3/2K4P/7P/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) < drawish);
|
||||
|
||||
pos = TextIO.readFEN("8/6k1/8/2B5/4B3/2K4P/7P/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) > winScore);
|
||||
|
||||
pos = TextIO.readFEN("8/6k1/8/8/4B3/2K4P/P7/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) > winScore);
|
||||
|
||||
pos = TextIO.readFEN("8/6k1/8/8/4B3/2K3PP/8/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) > winScore);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrappedBishop() throws ChessParseError {
|
||||
Position pos = TextIO.readFEN("r2q1rk1/ppp2ppp/3p1n2/8/3P4/1P1Q1NP1/b1P2PBP/2KR3R w - - 0 1");
|
||||
assertTrue(evalWhite(pos) > 0); // Black has trapped bishop
|
||||
|
||||
pos = TextIO.readFEN("r2q2k1/pp1b1p1p/2p2np1/3p4/3P4/1BNQ2P1/PPPB1P1b/2KR4 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) > 0); // Black has trapped bishop
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of endGameEval method, of class Evaluate.
|
||||
*/
|
||||
@Test
|
||||
public void testKQKP() throws ChessParseError {
|
||||
System.out.println("KQKP");
|
||||
final int pV = Evaluate.pV;
|
||||
final int qV = Evaluate.qV;
|
||||
final int winScore = qV - pV - 200;
|
||||
final int drawish = (pV + qV) / 20;
|
||||
|
||||
// Pawn on a2
|
||||
Position pos = TextIO.readFEN("8/8/1K6/8/8/Q7/p7/1k6 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) < drawish);
|
||||
pos = TextIO.readFEN("8/8/8/1K6/8/Q7/p7/1k6 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) > winScore);
|
||||
pos = TextIO.readFEN("3Q4/8/8/8/K7/8/1kp5/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) > winScore);
|
||||
pos = TextIO.readFEN("8/8/8/8/8/1Q6/p3K3/k7 b - - 0 1");
|
||||
assertTrue(evalWhite(pos) < drawish);
|
||||
|
||||
// Pawn on c2
|
||||
pos = TextIO.readFEN("3Q4/8/8/8/3K4/8/1kp5/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) < drawish);
|
||||
pos = TextIO.readFEN("3Q4/8/8/8/8/4K3/1kp5/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) > winScore);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKRKP() throws ChessParseError {
|
||||
System.out.println("KRKP");
|
||||
final int pV = Evaluate.pV;
|
||||
final int rV = Evaluate.rV;
|
||||
final int winScore = rV - pV;
|
||||
final int drawish = (pV + rV) / 20;
|
||||
Position pos = TextIO.readFEN("6R1/8/8/8/5K2/2kp4/8/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) > winScore);
|
||||
pos.whiteMove = !pos.whiteMove;
|
||||
assertTrue(evalWhite(pos) < drawish);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCantWin() throws ChessParseError {
|
||||
Position pos = TextIO.readFEN("8/8/8/3k4/3p4/3K4/4N3/8 w - - 0 1");
|
||||
int score1 = evalWhite(pos);
|
||||
assertTrue(score1 < 0);
|
||||
UndoInfo ui = new UndoInfo();
|
||||
pos.makeMove(TextIO.stringToMove(pos, "Nxd4"), ui);
|
||||
int score2 = evalWhite(pos);
|
||||
assertTrue(score2 <= 0);
|
||||
assertTrue(score2 > score1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPawnRace() throws ChessParseError {
|
||||
final int pV = Evaluate.pV;
|
||||
final int winScore = 400;
|
||||
final int drawish = 100;
|
||||
Position pos = TextIO.readFEN("8/8/K7/1P3p2/8/6k1/8/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) > winScore);
|
||||
pos = TextIO.readFEN("8/8/K7/1P3p2/8/6k1/8/8 b - - 0 1");
|
||||
assertTrue(evalWhite(pos) > winScore);
|
||||
|
||||
pos = TextIO.readFEN("8/8/K7/1P3p2/6k1/8/8/8 b - - 0 1");
|
||||
assertTrue(Math.abs(evalWhite(pos)) < drawish);
|
||||
pos = TextIO.readFEN("8/8/K7/1P6/5pk1/8/8/8 b - - 0 1");
|
||||
assertTrue(evalWhite(pos) < -winScore);
|
||||
pos = TextIO.readFEN("8/K7/8/1P6/5pk1/8/8/8 b - - 0 1");
|
||||
assertTrue(Math.abs(evalWhite(pos)) < drawish);
|
||||
pos = TextIO.readFEN("8/K7/8/8/1PP2p1k/8/8/8 w - - 0 1");
|
||||
assertTrue(evalWhite(pos) < drawish + pV);
|
||||
assertTrue(evalWhite(pos) > 0);
|
||||
pos = TextIO.readFEN("8/K7/8/8/1PP2p1k/8/8/8 b - - 0 1");
|
||||
assertTrue(evalWhite(pos) < -winScore + pV);
|
||||
}
|
||||
|
||||
/** Return static evaluation score for white, regardless of whose turn it is to move. */
|
||||
final static int evalWhite(Position pos) {
|
||||
Evaluate eval = new Evaluate();
|
||||
int ret = eval.evalPos(pos);
|
||||
Position symPos = swapColors(pos);
|
||||
int symScore = eval.evalPos(symPos);
|
||||
assertEquals(ret, symScore);
|
||||
if (!pos.whiteMove) {
|
||||
ret = -ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
final static Position swapColors(Position pos) {
|
||||
Position sym = new Position();
|
||||
sym.whiteMove = !pos.whiteMove;
|
||||
for (int x = 0; x < 8; x++) {
|
||||
for (int y = 0; y < 8; y++) {
|
||||
int p = pos.getPiece(Position.getSquare(x, y));
|
||||
p = Piece.isWhite(p) ? Piece.makeBlack(p) : Piece.makeWhite(p);
|
||||
sym.setPiece(Position.getSquare(x, 7-y), p);
|
||||
}
|
||||
}
|
||||
|
||||
int castleMask = 0;
|
||||
if (pos.a1Castle()) castleMask |= 1 << Position.A8_CASTLE;
|
||||
if (pos.h1Castle()) castleMask |= 1 << Position.H8_CASTLE;
|
||||
if (pos.a8Castle()) castleMask |= 1 << Position.A1_CASTLE;
|
||||
if (pos.h8Castle()) castleMask |= 1 << Position.H1_CASTLE;
|
||||
sym.setCastleMask(castleMask);
|
||||
|
||||
if (pos.getEpSquare() >= 0) {
|
||||
int x = Position.getX(pos.getEpSquare());
|
||||
int y = Position.getY(pos.getEpSquare());
|
||||
sym.setEpSquare(Position.getSquare(x, 7-y));
|
||||
}
|
||||
|
||||
sym.halfMoveClock = pos.halfMoveClock;
|
||||
sym.fullMoveCounter = pos.fullMoveCounter;
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
/** Compute change in eval score for white after making "moveStr" in position "pos". */
|
||||
private final int moveScore(Position pos, String moveStr) {
|
||||
int score1 = evalWhite(pos);
|
||||
Position tmpPos = new Position(pos);
|
||||
UndoInfo ui = new UndoInfo();
|
||||
tmpPos.makeMove(TextIO.stringToMove(tmpPos, moveStr), ui);
|
||||
int score2 = evalWhite(tmpPos);
|
||||
// System.out.printf("move:%s s1:%d s2:%d\n", moveStr, score1, score2);
|
||||
return score2 - score1;
|
||||
}
|
||||
}
|
|
@ -1,441 +0,0 @@
|
|||
/*
|
||||
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 org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author petero
|
||||
*/
|
||||
public class GameTest {
|
||||
|
||||
public GameTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of haveDrawOffer method, of class Game.
|
||||
*/
|
||||
@Test
|
||||
public void testHaveDrawOffer() {
|
||||
System.out.println("haveDrawOffer");
|
||||
Game game = new Game(new HumanPlayer(), new HumanPlayer());
|
||||
assertEquals(false, game.haveDrawOffer());
|
||||
|
||||
boolean res = game.processString("e4");
|
||||
assertEquals(true, res);
|
||||
assertEquals(false, game.haveDrawOffer());
|
||||
|
||||
res = game.processString("draw offer e5");
|
||||
assertEquals(true, res);
|
||||
assertEquals(true, game.haveDrawOffer());
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Draw offer does not imply draw
|
||||
assertEquals(Piece.BPAWN, game.pos.getPiece(Position.getSquare(4, 4))); // e5 move made
|
||||
|
||||
res = game.processString("draw offer Nf3");
|
||||
assertEquals(true, res);
|
||||
assertEquals(true, game.haveDrawOffer());
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Draw offer does not imply draw
|
||||
assertEquals(Piece.WKNIGHT, game.pos.getPiece(Position.getSquare(5, 2))); // Nf3 move made
|
||||
|
||||
res = game.processString("Nc6");
|
||||
assertEquals(true, res);
|
||||
assertEquals(false, game.haveDrawOffer());
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
assertEquals(Piece.BKNIGHT, game.pos.getPiece(Position.getSquare(2, 5))); // Nc6 move made
|
||||
|
||||
res = game.processString("draw offer Bb5");
|
||||
assertEquals(true, res);
|
||||
assertEquals(true, game.haveDrawOffer());
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
assertEquals(Piece.WBISHOP, game.pos.getPiece(Position.getSquare(1, 4))); // Bb5 move made
|
||||
|
||||
res = game.processString("draw accept");
|
||||
assertEquals(true, res);
|
||||
assertEquals(Game.GameState.DRAW_AGREE, game.getGameState()); // Draw by agreement
|
||||
|
||||
res = game.processString("undo");
|
||||
assertEquals(true, res);
|
||||
assertEquals(Piece.EMPTY, game.pos.getPiece(Position.getSquare(1, 4))); // Bb5 move undone
|
||||
assertEquals(false, game.haveDrawOffer());
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
res = game.processString("undo");
|
||||
assertEquals(true, res);
|
||||
assertEquals(Piece.EMPTY, game.pos.getPiece(Position.getSquare(2, 5))); // Nc6 move undone
|
||||
assertEquals(true, game.haveDrawOffer());
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
|
||||
res = game.processString("redo");
|
||||
assertEquals(true, res);
|
||||
assertEquals(Piece.BKNIGHT, game.pos.getPiece(Position.getSquare(2, 5))); // Nc6 move redone
|
||||
assertEquals(false, game.haveDrawOffer());
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
res = game.processString("redo");
|
||||
assertEquals(true, res);
|
||||
assertEquals(Piece.WBISHOP, game.pos.getPiece(Position.getSquare(1, 4))); // Bb5 move redone
|
||||
assertEquals(true, game.haveDrawOffer());
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
res = game.processString("redo");
|
||||
assertEquals(true, res);
|
||||
assertEquals(true, game.haveDrawOffer());
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Can't redo draw accept
|
||||
|
||||
// Test draw offer in connection with invalid move
|
||||
res = game.processString("new");
|
||||
assertEquals(true, res);
|
||||
assertEquals(false, game.haveDrawOffer());
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
|
||||
res = game.processString("draw offer e5");
|
||||
assertEquals(true, res);
|
||||
assertEquals(TextIO.startPosFEN, TextIO.toFEN(game.pos)); // Move invalid, not executed
|
||||
res = game.processString("e4");
|
||||
assertEquals(true, res);
|
||||
assertEquals(true, game.haveDrawOffer()); // Previous draw offer still valid
|
||||
assertEquals(Piece.WPAWN, game.pos.getPiece(Position.getSquare(4, 3))); // e4 move made
|
||||
|
||||
// Undo/redo shall clear "pendingDrawOffer".
|
||||
game.processString("new");
|
||||
game.processString("e4");
|
||||
game.processString("draw offer e4"); // Invalid black move
|
||||
assertEquals(true, game.pendingDrawOffer);
|
||||
game.processString("undo");
|
||||
game.processString("redo");
|
||||
game.processString("e5");
|
||||
assertEquals(true,game.pos.whiteMove);
|
||||
assertEquals(false, game.haveDrawOffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of draw by 50 move rule, of class Game.
|
||||
*/
|
||||
@Test
|
||||
public void testDraw50() {
|
||||
System.out.println("draw50");
|
||||
Game game = new Game(new HumanPlayer(), new HumanPlayer());
|
||||
assertEquals(false, game.haveDrawOffer());
|
||||
boolean res = game.processString("draw 50");
|
||||
assertEquals(true, res);
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Draw claim invalid
|
||||
res = game.processString("e4");
|
||||
assertEquals(true, game.haveDrawOffer()); // Invalid claim converted to draw offer
|
||||
|
||||
String cmd = "setpos 8/4k3/8/P7/8/8/8/1N2K2R w K - 99 83";
|
||||
res = game.processString(cmd);
|
||||
assertEquals(true, res);
|
||||
res = game.processString("draw 50");
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Draw claim invalid
|
||||
|
||||
game.processString(cmd);
|
||||
game.processString("draw 50 Nc3");
|
||||
assertEquals(Game.GameState.DRAW_50, game.getGameState()); // Draw claim valid
|
||||
assertEquals("Game over, draw by 50 move rule! [Nc3]", game.getGameStateString());
|
||||
|
||||
game.processString(cmd);
|
||||
game.processString("draw 50 a6");
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Pawn move resets counter
|
||||
assertEquals(Piece.WPAWN, game.pos.getPiece(Position.getSquare(0, 5))); // Move a6 made
|
||||
|
||||
game.processString(cmd);
|
||||
game.processString("draw 50 O-O");
|
||||
assertEquals(Game.GameState.DRAW_50, game.getGameState()); // Castling doesn't reset counter
|
||||
|
||||
game.processString(cmd);
|
||||
game.processString("draw 50 Kf2");
|
||||
assertEquals(Game.GameState.DRAW_50, game.getGameState()); // Loss of castling right doesn't reset counter
|
||||
|
||||
game.processString(cmd);
|
||||
game.processString("draw 50 Ke3");
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Ke3 is invalid
|
||||
assertEquals(true,game.pos.whiteMove);
|
||||
game.processString("a6");
|
||||
assertEquals(true, game.haveDrawOffer()); // Previous invalid claim converted to offer
|
||||
game.processString("draw 50");
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState()); // 50 move counter reset.
|
||||
res = game.processString("draw accept");
|
||||
assertEquals(true, res);
|
||||
assertEquals(Game.GameState.DRAW_AGREE, game.getGameState()); // Can accept previous implicit offer
|
||||
|
||||
cmd = "setpos 3k4/R7/3K4/8/8/8/8/8 w - - 99 78";
|
||||
game.processString(cmd);
|
||||
game.processString("Ra8");
|
||||
assertEquals(Game.GameState.WHITE_MATE, game.getGameState());
|
||||
game.processString("draw 50");
|
||||
assertEquals(Game.GameState.WHITE_MATE, game.getGameState()); // Can't claim draw when game over
|
||||
assertEquals(Game.GameState.ALIVE, game.drawState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of draw by repetition, of class Game.
|
||||
*/
|
||||
@Test
|
||||
public void testDrawRep() {
|
||||
System.out.println("drawRep");
|
||||
Game game = new Game(new HumanPlayer(), new HumanPlayer());
|
||||
assertEquals(false, game.haveDrawOffer());
|
||||
game.processString("Nc3");
|
||||
game.processString("Nc6");
|
||||
game.processString("Nb1");
|
||||
game.processString("Nb8");
|
||||
game.processString("Nf3");
|
||||
game.processString("Nf6");
|
||||
game.processString("Ng1");
|
||||
assertEquals(false, game.haveDrawOffer());
|
||||
game.processString("draw rep");
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Claim not valid, one more move needed
|
||||
game.processString("draw rep Nc6");
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState()); // Claim not valid, wrong move claimed
|
||||
assertEquals(Piece.BKNIGHT, game.pos.getPiece(Position.getSquare(2, 5))); // Move Nc6 made
|
||||
assertEquals(true, game.haveDrawOffer());
|
||||
game.processString("undo");
|
||||
assertEquals(false, game.haveDrawOffer());
|
||||
assertEquals(Piece.EMPTY, game.pos.getPiece(Position.getSquare(2, 5)));
|
||||
game.processString("draw rep Ng8");
|
||||
assertEquals(Game.GameState.DRAW_REP, game.getGameState());
|
||||
assertEquals(Piece.EMPTY, game.pos.getPiece(Position.getSquare(6, 7))); // Ng8 not played
|
||||
|
||||
// Test draw by repetition when a "potential ep square but not real ep square" position is present.
|
||||
game.processString("new");
|
||||
game.processString("e4"); // e3 is not a real epSquare here
|
||||
game.processString("Nf6");
|
||||
game.processString("Nf3");
|
||||
game.processString("Ng8");
|
||||
game.processString("Ng1");
|
||||
game.processString("Nf6");
|
||||
game.processString("Nf3");
|
||||
game.processString("Ng8");
|
||||
game.processString("draw rep Ng1");
|
||||
assertEquals(Game.GameState.DRAW_REP, game.getGameState());
|
||||
|
||||
// Now check the case when e3 *is* an epSquare
|
||||
game.processString("new");
|
||||
game.processString("Nf3");
|
||||
game.processString("d5");
|
||||
game.processString("Ng1");
|
||||
game.processString("d4");
|
||||
game.processString("e4"); // Here e3 is a real epSquare
|
||||
game.processString("Nf6");
|
||||
game.processString("Nf3");
|
||||
game.processString("Ng8");
|
||||
game.processString("Ng1");
|
||||
game.processString("Nf6");
|
||||
game.processString("Nf3");
|
||||
game.processString("Ng8");
|
||||
game.processString("draw rep Ng1");
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
|
||||
// EP capture not valid because it would leave the king in check. Therefore
|
||||
// the position has been repeated three times at the end of the move sequence.
|
||||
game.processString("setpos 4k2n/8/8/8/4p3/8/3P4/3KR2N w - - 0 1");
|
||||
game.processString("d4");
|
||||
game.processString("Ng6");
|
||||
game.processString("Ng3");
|
||||
game.processString("Nh8");
|
||||
game.processString("Nh1");
|
||||
game.processString("Ng6");
|
||||
game.processString("Ng3");
|
||||
game.processString("Nh8");
|
||||
game.processString("draw rep Nh1");
|
||||
assertEquals(Game.GameState.DRAW_REP, game.getGameState());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of resign command, of class Game.
|
||||
*/
|
||||
@Test
|
||||
public void testResign() {
|
||||
System.out.println("resign");
|
||||
Game game = new Game(new HumanPlayer(), new HumanPlayer());
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
game.processString("f3");
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
game.processString("resign");
|
||||
assertEquals(Game.GameState.RESIGN_BLACK, game.getGameState());
|
||||
game.processString("undo");
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
game.processString("f3");
|
||||
game.processString("e5");
|
||||
game.processString("resign");
|
||||
assertEquals(Game.GameState.RESIGN_WHITE, game.getGameState());
|
||||
game.processString("undo");
|
||||
game.processString("e5");
|
||||
game.processString("g4");
|
||||
game.processString("Qh4");
|
||||
assertEquals(Game.GameState.BLACK_MATE, game.getGameState());
|
||||
game.processString("resign");
|
||||
assertEquals(Game.GameState.BLACK_MATE, game.getGameState()); // Can't resign after game over
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of processString method, of class Game.
|
||||
*/
|
||||
@Test
|
||||
public void testProcessString() throws ChessParseError {
|
||||
System.out.println("processString");
|
||||
Game game = new Game(new HumanPlayer(), new HumanPlayer());
|
||||
assertEquals(TextIO.startPosFEN, TextIO.toFEN(game.pos));
|
||||
boolean res = game.processString("Nf3");
|
||||
assertEquals(true, res);
|
||||
assertEquals(1, game.pos.halfMoveClock);
|
||||
assertEquals(1, game.pos.fullMoveCounter);
|
||||
res = game.processString("d5");
|
||||
assertEquals(true, res);
|
||||
assertEquals(0, game.pos.halfMoveClock);
|
||||
assertEquals(2, game.pos.fullMoveCounter);
|
||||
|
||||
res = game.processString("undo");
|
||||
assertEquals(true, res);
|
||||
assertEquals(1, game.pos.halfMoveClock);
|
||||
assertEquals(1, game.pos.fullMoveCounter);
|
||||
res = game.processString("undo");
|
||||
assertEquals(true, res);
|
||||
assertEquals(TextIO.startPosFEN, TextIO.toFEN(game.pos));
|
||||
res = game.processString("undo");
|
||||
assertEquals(true, res);
|
||||
assertEquals(TextIO.startPosFEN, TextIO.toFEN(game.pos));
|
||||
|
||||
res = game.processString("redo");
|
||||
assertEquals(true, res);
|
||||
assertEquals(1, game.pos.halfMoveClock);
|
||||
assertEquals(1, game.pos.fullMoveCounter);
|
||||
res = game.processString("redo");
|
||||
assertEquals(true, res);
|
||||
assertEquals(0, game.pos.halfMoveClock);
|
||||
assertEquals(2, game.pos.fullMoveCounter);
|
||||
res = game.processString("redo");
|
||||
assertEquals(true, res);
|
||||
assertEquals(0, game.pos.halfMoveClock);
|
||||
assertEquals(2, game.pos.fullMoveCounter);
|
||||
|
||||
res = game.processString("new");
|
||||
assertEquals(true, res);
|
||||
assertEquals(TextIO.startPosFEN, TextIO.toFEN(game.pos));
|
||||
|
||||
String fen = "8/8/8/4k3/8/8/2p5/5K2 b - - 47 68";
|
||||
Position pos = TextIO.readFEN(fen);
|
||||
res = game.processString("setpos " + fen);
|
||||
assertEquals(true, res);
|
||||
assertEquals(pos, game.pos);
|
||||
|
||||
res = game.processString("junk");
|
||||
assertEquals(false, res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getGameState method, of class Game.
|
||||
*/
|
||||
@Test
|
||||
public void testGetGameState() {
|
||||
System.out.println("getGameState");
|
||||
Game game = new Game(new HumanPlayer(), new HumanPlayer());
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
game.processString("f3");
|
||||
game.processString("e5");
|
||||
game.processString("g4");
|
||||
game.processString("Qh4");
|
||||
assertEquals(Game.GameState.BLACK_MATE, game.getGameState());
|
||||
|
||||
game.processString("setpos 5k2/5P2/5K2/8/8/8/8/8 b - - 0 1");
|
||||
assertEquals(Game.GameState.BLACK_STALEMATE, game.getGameState());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of insufficientMaterial method, of class Game.
|
||||
*/
|
||||
@Test
|
||||
public void testInsufficientMaterial() {
|
||||
System.out.println("insufficientMaterial");
|
||||
Game game = new Game(new HumanPlayer(), new HumanPlayer());
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
game.processString("setpos 4k3/8/8/8/8/8/8/4K3 w - - 0 1");
|
||||
assertEquals(Game.GameState.DRAW_NO_MATE, game.getGameState());
|
||||
final int a1 = Position.getSquare(0, 0);
|
||||
game.pos.setPiece(a1, Piece.WROOK);
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
game.pos.setPiece(a1, Piece.BQUEEN);
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
game.pos.setPiece(a1, Piece.WPAWN);
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
game.pos.setPiece(a1, Piece.BKNIGHT);
|
||||
assertEquals(Game.GameState.DRAW_NO_MATE, game.getGameState());
|
||||
game.pos.setPiece(a1, Piece.WBISHOP);
|
||||
assertEquals(Game.GameState.DRAW_NO_MATE, game.getGameState());
|
||||
|
||||
final int c1 = Position.getSquare(2, 0);
|
||||
game.pos.setPiece(c1, Piece.WKNIGHT);
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
game.pos.setPiece(c1, Piece.BBISHOP);
|
||||
assertEquals(Game.GameState.DRAW_NO_MATE, game.getGameState());
|
||||
game.pos.setPiece(c1, Piece.WBISHOP);
|
||||
assertEquals(Game.GameState.DRAW_NO_MATE, game.getGameState());
|
||||
|
||||
final int b2 = Position.getSquare(1, 1);
|
||||
game.pos.setPiece(b2, Piece.WBISHOP);
|
||||
assertEquals(Game.GameState.DRAW_NO_MATE, game.getGameState());
|
||||
game.pos.setPiece(b2, Piece.BBISHOP);
|
||||
assertEquals(Game.GameState.DRAW_NO_MATE, game.getGameState());
|
||||
|
||||
final int b3 = Position.getSquare(1, 2);
|
||||
game.pos.setPiece(b3, Piece.WBISHOP);
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
|
||||
// Can't force mate with KNNK, but still not an automatic draw.
|
||||
game.processString("setpos 8/8/8/8/8/8/8/K3nnk1 w - - 0 1");
|
||||
assertEquals(Game.GameState.ALIVE, game.getGameState());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of perfT method, of class Game.
|
||||
*/
|
||||
@Test
|
||||
public void testPerfT() {
|
||||
System.out.println("perfT");
|
||||
Game game = new Game(new HumanPlayer(), new HumanPlayer());
|
||||
game.processString("new");
|
||||
doTestPerfT(game.pos, 5, new long[]{20,400,8902,197281,4865609,119060324,3195901860L,84998978956L});
|
||||
|
||||
game.processString("setpos 8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - -");
|
||||
doTestPerfT(game.pos, 5, new long[]{14, 191, 2812, 43238, 674624, 11030083, 178633661});
|
||||
|
||||
game.processString("setpos r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq -");
|
||||
doTestPerfT(game.pos, 4, new long[]{48,2039,97862,4085603,193690690});
|
||||
}
|
||||
|
||||
private void doTestPerfT(Position pos, int maxDepth, long[] expectedNodeCounts) {
|
||||
for (int d = 1; d <= maxDepth; d++) {
|
||||
MoveGen moveGen = new MoveGen();
|
||||
long t0 = System.nanoTime();
|
||||
long nodes = Game.perfT(moveGen, pos, d);
|
||||
long t1 = System.nanoTime();
|
||||
System.out.printf("perft(%d) = %d, t=%.6fs\n", d, nodes, (t1 - t0)*1e-9);
|
||||
assertEquals(expectedNodeCounts[d-1], nodes);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
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 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 HistoryTest {
|
||||
|
||||
public HistoryTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getHistScore method, of class History.
|
||||
*/
|
||||
@Test
|
||||
public void testGetHistScore() throws ChessParseError {
|
||||
System.out.println("getHistScore");
|
||||
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||
History hs = new History();
|
||||
Move m1 = TextIO.stringToMove(pos, "e4");
|
||||
Move m2 = TextIO.stringToMove(pos, "d4");
|
||||
assertEquals(0, hs.getHistScore(pos, m1));
|
||||
|
||||
hs.addSuccess(pos, m1, 1);
|
||||
assertEquals(1 * 49 / 1, hs.getHistScore(pos, m1));
|
||||
assertEquals(0, hs.getHistScore(pos, m2));
|
||||
|
||||
hs.addSuccess(pos, m1, 1);
|
||||
assertEquals(1 * 49 / 1, hs.getHistScore(pos, m1));
|
||||
assertEquals(0, hs.getHistScore(pos, m2));
|
||||
|
||||
hs.addFail(pos, m1, 1);
|
||||
assertEquals(2 * 49 / 3, hs.getHistScore(pos, m1));
|
||||
assertEquals(0, hs.getHistScore(pos, m2));
|
||||
|
||||
hs.addFail(pos, m1, 1);
|
||||
assertEquals(2 * 49 / 4, hs.getHistScore(pos, m1));
|
||||
assertEquals(0, hs.getHistScore(pos, m2));
|
||||
|
||||
hs.addSuccess(pos, m2, 1);
|
||||
assertEquals(2 * 49 / 4, hs.getHistScore(pos, m1));
|
||||
assertEquals(1 * 49 / 1, hs.getHistScore(pos, m2));
|
||||
}
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
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 org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author petero
|
||||
*/
|
||||
public class KillerTableTest {
|
||||
|
||||
public KillerTableTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of addKiller method, of class KillerTable.
|
||||
*/
|
||||
@Test
|
||||
public void testAddKiller() {
|
||||
System.out.println("addKiller");
|
||||
KillerTable kt = new KillerTable();
|
||||
Move m = new Move(TextIO.getSquare("b1"), TextIO.getSquare("b5"), Piece.EMPTY);
|
||||
kt.addKiller(3, m);
|
||||
kt.addKiller(7, m);
|
||||
kt.addKiller(3, m);
|
||||
kt.addKiller(3, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getKillerScore method, of class KillerTable.
|
||||
*/
|
||||
@Test
|
||||
public void testGetKillerScore() {
|
||||
System.out.println("getKillerScore");
|
||||
KillerTable kt = new KillerTable();
|
||||
Move m1 = new Move(TextIO.getSquare("b1"), TextIO.getSquare("b5"), Piece.EMPTY);
|
||||
Move m2 = new Move(TextIO.getSquare("c1"), TextIO.getSquare("d2"), Piece.EMPTY);
|
||||
Move m3 = new Move(TextIO.getSquare("e1"), TextIO.getSquare("g1"), Piece.EMPTY);
|
||||
kt.addKiller(0, m1);
|
||||
assertEquals(4, kt.getKillerScore(0, m1));
|
||||
assertEquals(0, kt.getKillerScore(0, m2));
|
||||
assertEquals(0, kt.getKillerScore(0, new Move(m2)));
|
||||
kt.addKiller(0, m1);
|
||||
assertEquals(4, kt.getKillerScore(0, m1));
|
||||
kt.addKiller(0, m2);
|
||||
assertEquals(4, kt.getKillerScore(0, m2));
|
||||
assertEquals(4, kt.getKillerScore(0, new Move(m2))); // Must compare by value
|
||||
assertEquals(3, kt.getKillerScore(0, m1));
|
||||
kt.addKiller(0, new Move(m2));
|
||||
assertEquals(4, kt.getKillerScore(0, m2));
|
||||
assertEquals(3, kt.getKillerScore(0, m1));
|
||||
assertEquals(0, kt.getKillerScore(0, m3));
|
||||
kt.addKiller(0, m3);
|
||||
assertEquals(0, kt.getKillerScore(0, m1));
|
||||
assertEquals(3, kt.getKillerScore(0, m2));
|
||||
assertEquals(4, kt.getKillerScore(0, m3));
|
||||
|
||||
assertEquals(0, kt.getKillerScore(1, m3));
|
||||
assertEquals(2, kt.getKillerScore(2, m3));
|
||||
assertEquals(0, kt.getKillerScore(3, m3));
|
||||
assertEquals(0, kt.getKillerScore(4, m3));
|
||||
|
||||
kt.addKiller(2, m2);
|
||||
assertEquals(4, kt.getKillerScore(2, m2));
|
||||
assertEquals(3, kt.getKillerScore(0, m2));
|
||||
}
|
||||
}
|
|
@ -1,542 +0,0 @@
|
|||
/*
|
||||
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.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author petero
|
||||
*/
|
||||
public class MoveGenTest {
|
||||
|
||||
public MoveGenTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of pseudoLegalMoves method, of class MoveGen.
|
||||
*/
|
||||
@Test
|
||||
public void testPseudoLegalMoves() throws ChessParseError {
|
||||
System.out.println("pseudoLegalMoves");
|
||||
String fen = "8/3k4/8/2n2pP1/1P6/1NB5/2QP4/R3K2R w KQ f6 0 2";
|
||||
Position pos = TextIO.readFEN(fen);
|
||||
assertEquals(fen, TextIO.toFEN(pos));
|
||||
List<String> strMoves = getMoveList(pos, false);
|
||||
assertTrue(strMoves.contains("a1d1"));
|
||||
assertTrue(!strMoves.contains("a1e1"));
|
||||
assertTrue(!strMoves.contains("a1f1"));
|
||||
assertTrue(strMoves.contains("a1a7"));
|
||||
assertTrue(strMoves.contains("e1f2"));
|
||||
assertTrue(!strMoves.contains("e1g3"));
|
||||
assertTrue(strMoves.contains("c3f6"));
|
||||
assertTrue(!strMoves.contains("b3d2"));
|
||||
|
||||
// Test castling
|
||||
assertTrue(strMoves.contains("e1g1"));
|
||||
assertTrue(strMoves.contains("e1c1"));
|
||||
assertEquals(49, strMoves.size());
|
||||
|
||||
pos.setPiece(Position.getSquare(4,3), Piece.BROOK);
|
||||
strMoves = getMoveList(pos, false);
|
||||
assertTrue(!strMoves.contains("e1g1")); // In check, no castling possible
|
||||
assertTrue(!strMoves.contains("e1c1"));
|
||||
|
||||
pos.setPiece(Position.getSquare(4, 3), Piece.EMPTY);
|
||||
pos.setPiece(Position.getSquare(5, 3), Piece.BROOK);
|
||||
strMoves = getMoveList(pos, false);
|
||||
assertTrue(!strMoves.contains("e1g1")); // f1 attacked, short castle not possible
|
||||
assertTrue(strMoves.contains("e1c1"));
|
||||
|
||||
pos.setPiece(Position.getSquare(5, 3), Piece.EMPTY);
|
||||
pos.setPiece(Position.getSquare(6, 3), Piece.BBISHOP);
|
||||
strMoves = getMoveList(pos, false);
|
||||
assertTrue(strMoves.contains("e1g1")); // d1 attacked, long castle not possible
|
||||
assertTrue(!strMoves.contains("e1c1"));
|
||||
|
||||
pos.setPiece(Position.getSquare(6, 3), Piece.EMPTY);
|
||||
pos.setCastleMask(1 << Position.A1_CASTLE);
|
||||
strMoves = getMoveList(pos, false);
|
||||
assertTrue(!strMoves.contains("e1g1")); // short castle right has been lost
|
||||
assertTrue(strMoves.contains("e1c1"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of pseudoLegalMoves method, of class MoveGen. Pawn moves.
|
||||
*/
|
||||
@Test
|
||||
public void testPawnMoves() throws ChessParseError {
|
||||
System.out.println("pawnMoves");
|
||||
String fen = "1r2k3/P1pppp1p/8/1pP3p1/1nPp2P1/n4p1P/1P2PP2/4KBNR w K b6 0 1";
|
||||
Position pos = TextIO.readFEN(fen);
|
||||
assertEquals(fen, TextIO.toFEN(pos));
|
||||
List<String> strMoves = getMoveList(pos, false);
|
||||
assertTrue(strMoves.contains("c5b6")); // En passant capture
|
||||
assertTrue(strMoves.contains("a7a8q")); // promotion
|
||||
assertTrue(strMoves.contains("a7a8n")); // under promotion
|
||||
assertTrue(strMoves.contains("a7b8r")); // capture promotion
|
||||
assertTrue(strMoves.contains("b2b3")); // pawn single move
|
||||
assertTrue(strMoves.contains("b2a3")); // pawn capture to the left
|
||||
assertTrue(strMoves.contains("e2e4")); // pawn double move
|
||||
assertTrue(strMoves.contains("e2f3")); // pawn capture to the right
|
||||
assertEquals(22, strMoves.size());
|
||||
|
||||
pos.setEpSquare(-1);
|
||||
strMoves = getMoveList(pos, false);
|
||||
assertEquals(21, strMoves.size()); // No ep, one less move possible
|
||||
|
||||
// Check black pawn moves
|
||||
pos.setWhiteMove(false);
|
||||
strMoves = getMoveList(pos, false);
|
||||
assertTrue(strMoves.contains("f3e2"));
|
||||
assertTrue(strMoves.contains("d4d3"));
|
||||
assertTrue(strMoves.contains("e7e6"));
|
||||
assertTrue(strMoves.contains("e7e5"));
|
||||
assertEquals(28, strMoves.size());
|
||||
|
||||
// Check black pawn promotion
|
||||
pos.setPiece(Position.getSquare(0,1), Piece.BPAWN);
|
||||
strMoves = getMoveList(pos, false);
|
||||
assertTrue(strMoves.contains("a2a1q"));
|
||||
assertTrue(strMoves.contains("a2a1r"));
|
||||
assertTrue(strMoves.contains("a2a1n"));
|
||||
assertTrue(strMoves.contains("a2a1b"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of inCheck method, of class MoveGen.
|
||||
*/
|
||||
@Test
|
||||
public void testInCheck() {
|
||||
System.out.println("inCheck");
|
||||
Position pos = new Position();
|
||||
pos.setPiece(Position.getSquare(4,2), Piece.WKING);
|
||||
pos.setPiece(Position.getSquare(4,7), Piece.BKING);
|
||||
assertEquals(false, MoveGen.inCheck(pos));
|
||||
|
||||
pos.setPiece(Position.getSquare(3,3), Piece.BQUEEN);
|
||||
assertEquals(true, MoveGen.inCheck(pos));
|
||||
pos.setPiece(Position.getSquare(3,3), Piece.BROOK);
|
||||
assertEquals(false, MoveGen.inCheck(pos));
|
||||
pos.setPiece(Position.getSquare(3,3), Piece.BPAWN);
|
||||
assertEquals(true, MoveGen.inCheck(pos));
|
||||
|
||||
pos.setPiece(Position.getSquare(3,3), Piece.EMPTY);
|
||||
pos.setPiece(Position.getSquare(5,3), Piece.WQUEEN);
|
||||
assertEquals(false, MoveGen.inCheck(pos));
|
||||
|
||||
pos.setPiece(Position.getSquare(4, 6), Piece.BROOK);
|
||||
assertEquals(true, MoveGen.inCheck(pos));
|
||||
pos.setPiece(Position.getSquare(4, 4), Piece.WPAWN);
|
||||
assertEquals(false, MoveGen.inCheck(pos));
|
||||
|
||||
pos.setPiece(Position.getSquare(2, 3), Piece.BKNIGHT);
|
||||
assertEquals(true, MoveGen.inCheck(pos));
|
||||
|
||||
pos.setPiece(Position.getSquare(2, 3), Piece.EMPTY);
|
||||
pos.setPiece(Position.getSquare(0, 4), Piece.BKNIGHT);
|
||||
assertEquals(false, MoveGen.inCheck(pos));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of givesCheck method, of class MoveGen.
|
||||
*/
|
||||
@Test
|
||||
public void testGivesCheck() throws ChessParseError {
|
||||
System.out.println("givesCheck");
|
||||
Position pos = new Position();
|
||||
UndoInfo ui = new UndoInfo();
|
||||
pos.setPiece(TextIO.getSquare("e3"), Piece.WKING);
|
||||
pos.setPiece(TextIO.getSquare("e8"), Piece.BKING);
|
||||
pos.setPiece(TextIO.getSquare("c2"), Piece.WROOK);
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Rc8")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Rc6")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Rc7")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Re2")));
|
||||
|
||||
pos.setPiece(TextIO.getSquare("c2"), Piece.EMPTY);
|
||||
pos.setPiece(TextIO.getSquare("e2"), Piece.WROOK);
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Kd3")));
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Kd4")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Ke4")));
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Kf2")));
|
||||
|
||||
pos.setPiece(TextIO.getSquare("e4"), Piece.WBISHOP);
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Bd5")));
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Bc6")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Kd3")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Re1")));
|
||||
|
||||
pos = TextIO.readFEN("4k3/3p4/8/8/4B3/2K5/4R3/8 w - - 0 1");
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Bc6")));
|
||||
pos = TextIO.readFEN("4k3/8/5K2/8/6N1/8/8/8 w - - 0 1");
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Ke6")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, new Move(TextIO.getSquare("f6"),
|
||||
TextIO.getSquare("e7"),
|
||||
Piece.EMPTY)));
|
||||
|
||||
pos = TextIO.readFEN("8/2k5/8/4N3/8/2K3B1/8/8 w - - 0 1");
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Nf7")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Kc4")));
|
||||
pos.setPiece(TextIO.getSquare("g3"), Piece.WROOK);
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Nf7")));
|
||||
pos.setPiece(TextIO.getSquare("g3"), Piece.WQUEEN);
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Nf7")));
|
||||
pos.setPiece(TextIO.getSquare("g3"), Piece.WKNIGHT);
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Nf7")));
|
||||
pos.setPiece(TextIO.getSquare("g3"), Piece.WPAWN);
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Nf7")));
|
||||
pos.setPiece(TextIO.getSquare("c3"), Piece.EMPTY);
|
||||
pos.setPiece(TextIO.getSquare("g3"), Piece.WKING);
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Nf7")));
|
||||
|
||||
pos = TextIO.readFEN("8/2k5/3p4/4N3/8/2K3B1/8/8 w - - 0 1");
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Nf7")));
|
||||
|
||||
pos = TextIO.readFEN("8/2k5/8/4N3/8/6q1/2K5/8 w - - 0 1");
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Nf7")));
|
||||
pos = TextIO.readFEN("8/2k5/8/4N3/8/8/2K5/8 w - - 0 1");
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "Nf7")));
|
||||
pos = TextIO.readFEN("2nk4/3P4/8/8/3R4/8/2K5/8 w - - 0 1");
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "dxc8N")));
|
||||
|
||||
pos = TextIO.readFEN("8/2k5/2p5/1P1P4/8/2K5/8/8 w - - 0 1");
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "dxc6")));
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "d6")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "bxc6")));
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "b6")));
|
||||
|
||||
pos = TextIO.readFEN("8/8/R1PkP2R/8/8/2K5/8/8 w - - 0 1");
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "c7")));
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "e7")));
|
||||
|
||||
// Test pawn promotion
|
||||
pos = TextIO.readFEN("8/1P6/2kP4/8/8/2K5/8/8 w - - 0 1");
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "d7")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "b8Q")));
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "b8N")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "b8R")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "b8B")));
|
||||
|
||||
pos = TextIO.readFEN("8/2P1P3/2k5/8/8/2K5/8/8 w - - 0 1");
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "e8Q")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "e8N")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "e8R")));
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "e8B")));
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "c8Q")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "c8N")));
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "c8R")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "c8B")));
|
||||
|
||||
// Test castling
|
||||
pos = TextIO.readFEN("8/8/8/8/5k2/8/8/R3K2R w KQ - 0 1");
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "O-O")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "O-O-O")));
|
||||
pos = TextIO.readFEN("8/8/8/8/6k1/8/8/R3K2R w KQ - 0 1");
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "O-O")));
|
||||
pos = TextIO.readFEN("8/8/8/8/3k4/8/8/R3K2R w KQ - 0 1");
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "O-O")));
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "O-O-O")));
|
||||
pos = TextIO.readFEN("8/8/8/8/5k2/8/5P2/R3K2R w KQ - 0 1");
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "O-O")));
|
||||
pos = TextIO.readFEN("8/8/8/8/8/8/8/R3K2k w Q - 0 1");
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "O-O-O")));
|
||||
pos = TextIO.readFEN("8/8/8/8/8/8/8/2k1K2R w K - 0 1");
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "O-O")));
|
||||
pos.setPiece(TextIO.getSquare("d1"), Piece.WKNIGHT);
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "O-O")));
|
||||
|
||||
// Test en passant
|
||||
pos = TextIO.readFEN("8/1kp5/8/3P4/8/8/8/4K3 b - - 0 1");
|
||||
pos.makeMove(TextIO.stringToMove(pos, "c5"), ui);
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "dxc6")));
|
||||
|
||||
pos = TextIO.readFEN("3k4/2p5/8/3P4/8/8/3R4/4K3 b - - 0 1");
|
||||
pos.makeMove(TextIO.stringToMove(pos, "c5"), ui);
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "dxc6")));
|
||||
|
||||
pos = TextIO.readFEN("5k2/2p5/8/3P4/8/B7/8/4K3 b - - 0 1");
|
||||
pos.makeMove(TextIO.stringToMove(pos, "c5"), ui);
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "dxc6")));
|
||||
|
||||
pos = TextIO.readFEN("5k2/2p5/8/3P4/1P6/B7/8/4K3 b - - 0 1");
|
||||
pos.makeMove(TextIO.stringToMove(pos, "c5"), ui);
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "dxc6")));
|
||||
|
||||
pos = TextIO.readFEN("8/2p5/8/R2P1k2/8/8/8/4K3 b - - 0 1");
|
||||
pos.makeMove(TextIO.stringToMove(pos, "c5"), ui);
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "dxc6")));
|
||||
|
||||
// Black pawn moves
|
||||
pos = TextIO.readFEN("8/2p5/8/R4k2/1K6/8/8/8 b - - 0 1");
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "c5")));
|
||||
pos = TextIO.readFEN("8/2p5/8/R4k2/2K5/8/8/8 b - - 0 1");
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "c5")));
|
||||
pos = TextIO.readFEN("8/2p5/8/R4k2/3K4/8/8/8 b - - 0 1");
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "c5")));
|
||||
|
||||
// Black castling
|
||||
pos = TextIO.readFEN("r3k2r/8/8/5K2/8/8/8/8 b kq - 0 1");
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "O-O")));
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "O-O-O")));
|
||||
pos = TextIO.readFEN("r3k2r/8/8/6K1/8/8/8/8 b kq - 0 1");
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "O-O")));
|
||||
pos = TextIO.readFEN("r3k2r/8/8/2K5/8/8/8/8 b kq - 0 1");
|
||||
assertTrue(!MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "O-O-O")));
|
||||
pos = TextIO.readFEN("r3k2r/8/8/3K4/8/8/8/8 b kq - 0 1");
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "O-O-O")));
|
||||
|
||||
// Black en passant
|
||||
pos = TextIO.readFEN("8/8/4k3/8/4p3/8/5PK1/8 w - - 0 1");
|
||||
pos.makeMove(TextIO.stringToMove(pos, "f4"), ui);
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "exf3")));
|
||||
|
||||
pos = TextIO.readFEN("8/8/4k3/8/K3p1r1/8/5P2/8 w - - 0 1");
|
||||
pos.makeMove(TextIO.stringToMove(pos, "f4"), ui);
|
||||
assertTrue(MoveGen.givesCheck(pos, TextIO.stringToMove(pos, "exf3")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of removeIllegal method, of class MoveGen.
|
||||
*/
|
||||
@Test
|
||||
public void testRemoveIllegal() throws ChessParseError {
|
||||
System.out.println("removeIllegal");
|
||||
Position pos = TextIO.readFEN("8/3k4/8/2n1rpP1/1P6/1NB5/2QP4/R3K2R w KQ f6 0 1");
|
||||
List<String> strMoves = getMoveList(pos, true);
|
||||
assertTrue(strMoves.contains("c2e4"));
|
||||
assertTrue(strMoves.contains("c3e5"));
|
||||
assertTrue(strMoves.contains("e1d1"));
|
||||
assertTrue(strMoves.contains("e1f1"));
|
||||
assertTrue(strMoves.contains("e1f2"));
|
||||
assertEquals(5, strMoves.size());
|
||||
|
||||
pos = TextIO.readFEN("4k3/8/8/2KPp1r1/8/8/8/8 w - e6 0 2");
|
||||
strMoves = getMoveList(pos, true);
|
||||
assertTrue(!strMoves.contains("d5e6"));
|
||||
assertEquals(7, strMoves.size());
|
||||
|
||||
pos = TextIO.readFEN("8/6p1/4p3/2k1Pp1B/4KP1p/6rP/8/8 w - f6 0 55");
|
||||
strMoves = getMoveList(pos, true);
|
||||
assertTrue(strMoves.contains("e5f6"));
|
||||
assertEquals(1, strMoves.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that if king capture is possible, only a king capture move is returned in the move list.
|
||||
*/
|
||||
@Test
|
||||
public void testKingCapture() throws ChessParseError {
|
||||
System.out.println("kingCapture");
|
||||
Position pos = TextIO.readFEN("8/4k3/8/8/8/8/8/4RK2 b - - 0 1");
|
||||
pos.setWhiteMove(true);
|
||||
List<String> strMoves = getMoveList(pos, false);
|
||||
assertEquals(1, strMoves.size());
|
||||
assertEquals("e1e7", strMoves.get(0));
|
||||
|
||||
pos.setPiece(Position.getSquare(0, 2), Piece.WBISHOP);
|
||||
pos.setPiece(Position.getSquare(4, 1), Piece.WPAWN);
|
||||
strMoves = getMoveList(pos, false);
|
||||
assertEquals(1, strMoves.size());
|
||||
assertEquals("a3e7", strMoves.get(0));
|
||||
|
||||
pos.setPiece(Position.getSquare(1, 3), Piece.WPAWN);
|
||||
pos.setPiece(Position.getSquare(5, 5), Piece.WPAWN);
|
||||
strMoves = getMoveList(pos, false);
|
||||
assertEquals(1, strMoves.size());
|
||||
assertEquals("f6e7", strMoves.get(0));
|
||||
}
|
||||
|
||||
/** Test that captureList and captureAndcheckList are generated correctly. */
|
||||
@Test
|
||||
public void testCaptureList() throws ChessParseError {
|
||||
System.out.println("captureList");
|
||||
Position pos = TextIO.readFEN("rnbqkbnr/ppp2ppp/3p1p2/R7/4N3/8/PPPPQPPP/2B1KB1R w Kkq - 0 1");
|
||||
getMoveList(pos, false);
|
||||
|
||||
pos = TextIO.readFEN("rnb1kbn1/ppp1qppp/5p2/4p3/3N3r/3P4/PPP2PPP/R1BQKB1R b KQq - 0 1");
|
||||
getMoveList(pos, false);
|
||||
|
||||
pos = TextIO.readFEN("rnb1k1n1/ppp1qppp/5p2/b3p3/1r1N4/3P4/PPP2PPP/R1BQKB1R b KQq - 0 1");
|
||||
getMoveList(pos, false);
|
||||
|
||||
pos = TextIO.readFEN("8/8/8/8/3k4/8/4P3/4K3 w - - 0 1");
|
||||
getMoveList(pos, false);
|
||||
|
||||
pos = TextIO.readFEN("8/8/8/3k4/8/8/4P3/4K3 w - - 0 1");
|
||||
getMoveList(pos, false);
|
||||
|
||||
pos = TextIO.readFEN("8/8/8/3k4/4p3/8/3KP3/8 b - - 0 1");
|
||||
getMoveList(pos, false);
|
||||
|
||||
pos = TextIO.readFEN("3k4/r2p2K1/8/8/8/8/8/8 b - - 0 1");
|
||||
getMoveList(pos, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckEvasions() throws ChessParseError {
|
||||
System.out.println("checkEvasions");
|
||||
Position pos = TextIO.readFEN("n7/8/8/7k/5pP1/5K2/8/8 b - g3 0 1");
|
||||
getMoveList(pos, false);
|
||||
|
||||
pos = TextIO.readFEN("rn1qkbnr/pppB1ppp/3p4/4p3/4P3/5N2/PPPP1PPP/RNBQK2R b KQkq - 0 1");
|
||||
getMoveList(pos, false);
|
||||
|
||||
// King captures must be included in check evasions
|
||||
pos = TextIO.readFEN("r1bq2r1/pp3pbk/2p1p1P1/8/3P4/2PB1N2/PP3PPR/2KR4 b - - 0 1");
|
||||
UndoInfo ui = new UndoInfo();
|
||||
pos.makeMove(TextIO.uciStringToMove("g7h6"), ui);
|
||||
getMoveList(pos, false);
|
||||
List<String> evList = getCheckEvasions(pos, false);
|
||||
assertTrue(evList.contains("g6h7"));
|
||||
|
||||
pos = TextIO.readFEN("1R6/1brk2p1/2P1p2p/p3Pp2/P7/6P1/1P4P1/2R3K1 b - - 0 1");
|
||||
getMoveList(pos, false);
|
||||
evList = getCheckEvasions(pos, false);
|
||||
assertTrue(evList.contains("b7c6"));
|
||||
}
|
||||
|
||||
private List<String> getMoveList(Position pos, boolean onlyLegal) {
|
||||
Position swap = EvaluateTest.swapColors(pos);
|
||||
List<String> swapList = getMoveList0(swap, onlyLegal);
|
||||
List<String> ret = getMoveList0(pos, onlyLegal);
|
||||
assertEquals(swapList.size(), ret.size());
|
||||
return ret;
|
||||
}
|
||||
|
||||
private List<String> getMoveList0(Position pos, boolean onlyLegal) {
|
||||
MoveGen moveGen = new MoveGen();
|
||||
MoveGen.MoveList moves = moveGen.pseudoLegalMoves(pos);
|
||||
if (onlyLegal)
|
||||
MoveGen.removeIllegal(pos, moves);
|
||||
ArrayList<String> strMoves = new ArrayList<String>();
|
||||
for (int mi = 0; mi < moves.size; mi++) {
|
||||
Move m = moves.m[mi];
|
||||
String mStr = TextIO.moveToUCIString(m);
|
||||
strMoves.add(mStr);
|
||||
}
|
||||
|
||||
List<String> capList1 = getCaptureList(pos, false, onlyLegal);
|
||||
assertTrue(strMoves.containsAll(capList1));
|
||||
|
||||
List<String> capList2 = getCaptureList(pos, true, onlyLegal);
|
||||
assertTrue(strMoves.containsAll(capList2));
|
||||
|
||||
List<String> evList = getCheckEvasions(pos, onlyLegal);
|
||||
if (evList != null)
|
||||
assertTrue(strMoves.containsAll(evList));
|
||||
UndoInfo ui = new UndoInfo();
|
||||
for (String sm : strMoves) {
|
||||
Move m = TextIO.uciStringToMove(sm);
|
||||
if (m != null) {
|
||||
pos.makeMove(m, ui);
|
||||
boolean invalid = MoveGen.canTakeKing(pos);
|
||||
pos.unMakeMove(m, ui);
|
||||
if (invalid) m = null;
|
||||
}
|
||||
if (m == null) // Move was illegal (but pseudo-legal)
|
||||
continue;
|
||||
boolean qProm = false; // Promotion types considered in qsearch
|
||||
switch (m.promoteTo) {
|
||||
case Piece.WQUEEN: case Piece.BQUEEN:
|
||||
case Piece.WKNIGHT: case Piece.BKNIGHT:
|
||||
case Piece.EMPTY:
|
||||
qProm = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!MoveGen.canTakeKing(pos) && MoveGen.givesCheck(pos, m)) {
|
||||
if (qProm)
|
||||
assertTrue(capList2.contains(sm));
|
||||
} else {
|
||||
switch (m.promoteTo) {
|
||||
case Piece.WQUEEN: case Piece.BQUEEN:
|
||||
case Piece.WKNIGHT: case Piece.BKNIGHT:
|
||||
assertTrue(capList1.contains(sm)); // All queen/knight promotions
|
||||
assertTrue(capList2.contains(sm)); // All queen/knight promotions
|
||||
break;
|
||||
case Piece.EMPTY:
|
||||
break;
|
||||
default:
|
||||
assertTrue(!capList1.contains(sm)); // No rook/bishop promotions
|
||||
assertTrue(!capList2.contains(sm)); // No rook/bishop promotions
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pos.getPiece(m.to) != Piece.EMPTY) {
|
||||
if (qProm) {
|
||||
assertTrue(capList1.contains(sm));
|
||||
assertTrue(capList2.contains(sm));
|
||||
}
|
||||
}
|
||||
if (evList != null) {
|
||||
assertTrue(evList.contains(sm));
|
||||
}
|
||||
}
|
||||
|
||||
return strMoves;
|
||||
}
|
||||
|
||||
private List<String> getCaptureList(Position pos, boolean includeChecks, boolean onlyLegal) {
|
||||
MoveGen.MoveList moves;
|
||||
if (includeChecks) {
|
||||
moves = new MoveGen().pseudoLegalCapturesAndChecks(pos);
|
||||
} else {
|
||||
moves = new MoveGen().pseudoLegalCaptures(pos);
|
||||
}
|
||||
if (onlyLegal)
|
||||
MoveGen.removeIllegal(pos, moves);
|
||||
ArrayList<String> strMoves = new ArrayList<String>();
|
||||
for (int mi = 0; mi < moves.size; mi++) {
|
||||
Move m = moves.m[mi];
|
||||
String mStr = TextIO.moveToUCIString(m);
|
||||
strMoves.add(mStr);
|
||||
}
|
||||
return strMoves;
|
||||
}
|
||||
|
||||
private List<String> getCheckEvasions(Position pos, boolean onlyLegal) {
|
||||
if (!MoveGen.inCheck(pos))
|
||||
return null;
|
||||
MoveGen.MoveList moves = new MoveGen().checkEvasions(pos);
|
||||
if (onlyLegal)
|
||||
MoveGen.removeIllegal(pos, moves);
|
||||
ArrayList<String> strMoves = new ArrayList<String>();
|
||||
for (int mi = 0; mi < moves.size; mi++) {
|
||||
Move m = moves.m[mi];
|
||||
String mStr = TextIO.moveToUCIString(m);
|
||||
strMoves.add(mStr);
|
||||
}
|
||||
return strMoves;
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
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 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 MoveTest {
|
||||
|
||||
public MoveTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of move constructor, of class Move.
|
||||
*/
|
||||
@Test
|
||||
public void testMoveConstructor() {
|
||||
System.out.println("MoveTest");
|
||||
int f = Position.getSquare(4, 1);
|
||||
int t = Position.getSquare(4, 3);
|
||||
int p = Piece.WROOK;
|
||||
Move move = new Move(f, t, p);
|
||||
assertEquals(move.from, f);
|
||||
assertEquals(move.to,t);
|
||||
assertEquals(move.promoteTo, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of equals, of class Move.
|
||||
*/
|
||||
@Test
|
||||
public void testEquals() {
|
||||
System.out.println("equals");
|
||||
Move m1 = new Move(Position.getSquare(0, 6), Position.getSquare(1, 7), Piece.WROOK);
|
||||
Move m2 = new Move(Position.getSquare(0, 6), Position.getSquare(0, 7), Piece.WROOK);
|
||||
Move m3 = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WROOK);
|
||||
Move m4 = new Move(Position.getSquare(0, 6), Position.getSquare(1, 7), Piece.WKNIGHT);
|
||||
Move m5 = new Move(Position.getSquare(0, 6), Position.getSquare(1, 7), Piece.WROOK);
|
||||
assertTrue(!m1.equals(m2));
|
||||
assertTrue(!m1.equals(m3));
|
||||
assertTrue(!m1.equals(m4));
|
||||
assertTrue(m1.equals(m5));
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
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 org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author petero
|
||||
*/
|
||||
public class PieceTest {
|
||||
|
||||
public PieceTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of isWhite method, of class Piece.
|
||||
*/
|
||||
@Test
|
||||
public void testIsWhite() {
|
||||
System.out.println("isWhite");
|
||||
assertEquals(false, Piece.isWhite(Piece.BBISHOP));
|
||||
assertEquals(true , Piece.isWhite(Piece.WBISHOP));
|
||||
assertEquals(true , Piece.isWhite(Piece.WKING));
|
||||
assertEquals(false, Piece.isWhite(Piece.BKING));
|
||||
}
|
||||
}
|
|
@ -1,444 +0,0 @@
|
|||
/*
|
||||
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));
|
||||
}
|
||||
}
|
|
@ -1,473 +0,0 @@
|
|||
/*
|
||||
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 chess.Search.StopSearch;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author petero
|
||||
*/
|
||||
public class SearchTest {
|
||||
static final long[] nullHist = new long[200];
|
||||
static TranspositionTable tt = new TranspositionTable(19);
|
||||
static History ht = new History();
|
||||
|
||||
public SearchTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of negaScout method, of class Search.
|
||||
*/
|
||||
@Test
|
||||
public void testNegaScout() throws ChessParseError, StopSearch {
|
||||
System.out.println("negaScout");
|
||||
final int mate0 = Search.MATE0;
|
||||
|
||||
Position pos = TextIO.readFEN("3k4/8/3K2R1/8/8/8/8/8 w - - 0 1");
|
||||
Search sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
final int plyScale = Search.plyScale;
|
||||
int score = sc.negaScout(-mate0, mate0, 0, 2*plyScale, -1, MoveGen.inCheck(pos));
|
||||
assertEquals(mate0 - 2, score); // depth 2 is enough to find mate in 1
|
||||
int score2 = idSearch(sc, 2).score;
|
||||
assertEquals(score, score2);
|
||||
|
||||
pos = TextIO.readFEN("8/1P6/k7/2K5/8/8/8/8 w - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
score = sc.negaScout(-mate0, mate0, 0, 4*plyScale, -1, MoveGen.inCheck(pos));
|
||||
assertEquals(mate0 - 4, score); // depth 4 is enough to find mate in 2
|
||||
score2 = idSearch(sc, 4).score;
|
||||
assertEquals(score, score2);
|
||||
|
||||
pos = TextIO.readFEN("8/5P1k/5K2/8/8/8/8/8 w - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
score = sc.negaScout(-mate0, mate0, 0, 5*plyScale, -1, MoveGen.inCheck(pos));
|
||||
assertEquals(mate0 - 4, score); // must avoid stale-mate after f8Q
|
||||
score2 = idSearch(sc, 5).score;
|
||||
assertEquals(score, score2);
|
||||
|
||||
pos = TextIO.readFEN("4k3/8/3K1Q2/8/8/8/8/8 b - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
score = sc.negaScout(-mate0, mate0, 0, 2*plyScale, -1, MoveGen.inCheck(pos));
|
||||
assertEquals(0, score); // Position is stale-mate
|
||||
|
||||
pos = TextIO.readFEN("3kB3/8/1N1K4/8/8/8/8/8 w - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
score = sc.negaScout(-mate0, mate0, 0, 3*plyScale, -1, MoveGen.inCheck(pos));
|
||||
assertTrue(Math.abs(score) < 50); // Stale-mate trap
|
||||
score2 = idSearch(sc, 5).score;
|
||||
assertEquals(score, score2);
|
||||
|
||||
pos = TextIO.readFEN("8/8/2K5/3QP3/P6P/1q6/8/k7 w - - 31 51");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
Move bestM = idSearch(sc, 2);
|
||||
assertTrue(!TextIO.moveToString(pos, bestM, false).equals("Qxb3"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of draw by 50 move rule, of class Search.
|
||||
*/
|
||||
@Test
|
||||
public void testDraw50() throws ChessParseError, StopSearch {
|
||||
System.out.println("draw50");
|
||||
final int mate0 = Search.MATE0;
|
||||
final int mateInOne = mate0 - 2;
|
||||
final int matedInOne = -mate0 + 3;
|
||||
final int mateInTwo = mate0 - 4;
|
||||
final int mateInThree = mate0 - 6;
|
||||
|
||||
Position pos = TextIO.readFEN("8/1R2k3/R7/8/8/8/8/1K6 b - - 0 1");
|
||||
Search sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
sc.maxTimeMillis = -1;
|
||||
final int plyScale = Search.plyScale;
|
||||
int score = sc.negaScout(-mate0, mate0, 0, 2*plyScale, -1, MoveGen.inCheck(pos));
|
||||
assertEquals(matedInOne, score);
|
||||
|
||||
pos = TextIO.readFEN("8/1R2k3/R7/8/8/8/8/1K6 b - - 99 80");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
sc.maxTimeMillis = -1;
|
||||
score = sc.negaScout(-mate0, mate0, 0, 2*plyScale, -1, MoveGen.inCheck(pos));
|
||||
assertEquals(0, score); // Draw by 50-move rule
|
||||
|
||||
pos = TextIO.readFEN("8/1R2k3/R7/8/8/8/8/1K6 b - - 98 80");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
sc.maxTimeMillis = -1;
|
||||
score = sc.negaScout(-mate0, mate0, 0, 2*plyScale, -1, MoveGen.inCheck(pos));
|
||||
assertEquals(matedInOne, score); // No draw
|
||||
|
||||
pos = TextIO.readFEN("8/1R2k3/R7/8/8/8/8/1K6 b - - 99 80");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
sc.maxTimeMillis = -1;
|
||||
score = idSearch(sc, 3).score;
|
||||
assertEquals(0, score);
|
||||
|
||||
pos = TextIO.readFEN("3k4/1R6/R7/8/8/8/8/1K6 w - - 100 80");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
sc.maxTimeMillis = -1;
|
||||
score = idSearch(sc, 2).score;
|
||||
assertEquals(mateInOne, score); // Black forgot to claim draw. Now it's too late.
|
||||
|
||||
pos = TextIO.readFEN("8/7k/1R6/R7/8/7P/8/1K6 w - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
sc.maxTimeMillis = -1;
|
||||
score = idSearch(sc, 3).score;
|
||||
assertEquals(mateInTwo, score);
|
||||
|
||||
pos = TextIO.readFEN("8/7k/1R6/R7/8/7P/8/1K6 w - - 98 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
sc.maxTimeMillis = -1;
|
||||
score = idSearch(sc, 6).score;
|
||||
assertEquals(mateInThree, score); // Need an extra pawn move to avoid 50-move rule
|
||||
|
||||
pos = TextIO.readFEN("8/7k/1R6/R7/8/7P/8/1K6 w - - 125 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
sc.maxTimeMillis = -1;
|
||||
score = idSearch(sc, 6).score;
|
||||
assertEquals(mateInThree, score); // Need an extra pawn move to avoid 50-move rule
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of draw by repetition rule, of class Search.
|
||||
*/
|
||||
@Test
|
||||
public void testDrawRep() throws ChessParseError, StopSearch {
|
||||
System.out.println("drawRep");
|
||||
final int mate0 = Search.MATE0;
|
||||
Position pos = TextIO.readFEN("7k/5RR1/8/8/8/8/q3q3/2K5 w - - 0 1");
|
||||
Search sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
sc.maxTimeMillis = -1;
|
||||
final int plyScale = Search.plyScale;
|
||||
int score = sc.negaScout(-mate0, mate0, 0, 3*plyScale, -1, MoveGen.inCheck(pos));
|
||||
assertEquals(0, score);
|
||||
|
||||
pos = TextIO.readFEN("7k/5RR1/8/8/8/8/q3q3/2K5 w - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
sc.maxTimeMillis = -1;
|
||||
score = idSearch(sc, 3).score;
|
||||
assertEquals(0, score);
|
||||
|
||||
pos = TextIO.readFEN("7k/5RR1/8/8/8/8/1q3q2/3K4 w - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
sc.maxTimeMillis = -1;
|
||||
score = idSearch(sc, 4).score;
|
||||
assertTrue(score < 0);
|
||||
|
||||
pos = TextIO.readFEN("7k/5RR1/8/8/8/8/1q3q2/3K4 w - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
sc.maxTimeMillis = -1;
|
||||
score = sc.negaScout(-mate0, mate0, 0, 3*plyScale, -1, MoveGen.inCheck(pos));
|
||||
assertTrue(score < 0);
|
||||
|
||||
pos = TextIO.readFEN("qn6/qn4k1/pp3R2/5R2/8/8/8/K7 w - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
sc.maxTimeMillis = -1;
|
||||
score = idSearch(sc, 7).score;
|
||||
assertEquals(0, score); // Draw, black can not escape from perpetual checks
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of hash table, of class Search.
|
||||
*/
|
||||
@Test
|
||||
public void testHashing() throws ChessParseError {
|
||||
System.out.println("hashing");
|
||||
Position pos = TextIO.readFEN("/k/3p/p2P1p/P2P1P///K/ w - -"); // Fine #70
|
||||
Search sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
Move bestM = idSearch(sc, 28);
|
||||
assertEquals(TextIO.stringToMove(pos, "Kb1"), new Move(bestM));
|
||||
}
|
||||
|
||||
/**
|
||||
* Late move pruning must not be used in mate search.
|
||||
*/
|
||||
@Test
|
||||
public void testLMP() throws ChessParseError {
|
||||
Position pos = TextIO.readFEN("2r2rk1/6p1/p3pq1p/1p1b1p2/3P1n2/PP3N2/3N1PPP/1Q2RR1K b"); // WAC 174
|
||||
Search sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
Move bestM = idSearch(sc, 2);
|
||||
assertTrue(bestM.score < Search.MATE0 / 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckEvasion() throws ChessParseError {
|
||||
System.out.println("check evasion");
|
||||
Position pos = TextIO.readFEN("6r1/R5PK/2p5/1k6/8/8/p7/8 b - - 0 62");
|
||||
Search sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
Move bestM = idSearch(sc, 3);
|
||||
assertTrue(bestM.score < 0);
|
||||
|
||||
pos = TextIO.readFEN("r1bq2rk/pp3pbp/2p1p1pQ/7P/3P4/2PB1N2/PP3PPR/2KR4 w - -"); // WAC 004
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
bestM = idSearch(sc, 1);
|
||||
assertEquals(Search.MATE0 - 4, bestM.score);
|
||||
assertEquals(TextIO.stringToMove(pos, "Qxh7+"), new Move(bestM));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStalemateTrap() throws ChessParseError {
|
||||
System.out.println("stalemate trap");
|
||||
Position pos = TextIO.readFEN("7k/1P3R1P/6r1/5K2/8/8/6R1/8 b - - 98 194");
|
||||
Search sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
Move bestM = idSearch(sc, 3);
|
||||
assertEquals(0, bestM.score);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKQKRNullMove() throws ChessParseError {
|
||||
System.out.println("kqkrNullMove");
|
||||
Position pos = TextIO.readFEN("7K/6R1/5k2/3q4/8/8/8/8 b - - 0 1");
|
||||
Search sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
Move bestM = idSearch(sc, 10);
|
||||
assertEquals(Search.MATE0-18, bestM.score);
|
||||
}
|
||||
|
||||
private Move idSearch(Search sc, int maxDepth) {
|
||||
MoveGen.MoveList moves = new MoveGen().pseudoLegalMoves(sc.pos);
|
||||
MoveGen.removeIllegal(sc.pos, moves);
|
||||
sc.scoreMoveList(moves, 0);
|
||||
sc.timeLimit(-1, -1);
|
||||
Move bestM = sc.iterativeDeepening(moves, maxDepth, -1, false);
|
||||
return bestM;
|
||||
}
|
||||
|
||||
/** Compute SEE(m) and assure that signSEE and negSEE give matching results. */
|
||||
private int getSEE(Search sc, Move m) {
|
||||
int see = sc.SEE(m);
|
||||
boolean neg = sc.negSEE(m);
|
||||
assertEquals(neg, see < 0);
|
||||
int sign = sc.signSEE(m);
|
||||
if (sign > 0)
|
||||
assertTrue(see > 0);
|
||||
else if (sign == 0)
|
||||
assertEquals(0, see);
|
||||
else
|
||||
assertTrue(see < 0);
|
||||
return see;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of SEE method, of class Search.
|
||||
*/
|
||||
@Test
|
||||
public void testSEE() throws ChessParseError {
|
||||
System.out.println("SEE");
|
||||
final int pV = Evaluate.pV;
|
||||
final int nV = Evaluate.nV;
|
||||
final int bV = Evaluate.bV;
|
||||
final int rV = Evaluate.rV;
|
||||
|
||||
// Basic tests
|
||||
Position pos = TextIO.readFEN("r2qk2r/ppp2ppp/1bnp1nb1/1N2p3/3PP3/1PP2N2/1P3PPP/R1BQRBK1 w kq - 0 1");
|
||||
Search sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
assertEquals(0, getSEE(sc, TextIO.stringToMove(pos, "dxe5")));
|
||||
assertEquals(pV - nV, getSEE(sc, TextIO.stringToMove(pos, "Nxe5")));
|
||||
assertEquals(pV - rV, getSEE(sc, TextIO.stringToMove(pos, "Rxa7")));
|
||||
assertEquals(pV - nV, getSEE(sc, TextIO.stringToMove(pos, "Nxa7")));
|
||||
assertEquals(pV - nV, getSEE(sc, TextIO.stringToMove(pos, "Nxd6")));
|
||||
assertEquals(0, getSEE(sc, TextIO.stringToMove(pos, "d5")));
|
||||
assertEquals(-bV, getSEE(sc, TextIO.stringToMove(pos, "Bf4")));
|
||||
assertEquals(-bV, getSEE(sc, TextIO.stringToMove(pos, "Bh6")));
|
||||
assertEquals(-rV, getSEE(sc, TextIO.stringToMove(pos, "Ra5")));
|
||||
assertEquals(-rV, getSEE(sc, TextIO.stringToMove(pos, "Ra6")));
|
||||
|
||||
pos.setWhiteMove(false);
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
assertTrue(nV <= bV); // Assumed by following test
|
||||
assertEquals(pV - nV, getSEE(sc, TextIO.stringToMove(pos, "Nxd4")));
|
||||
assertEquals(pV - bV, getSEE(sc, TextIO.stringToMove(pos, "Bxd4")));
|
||||
assertEquals(0, getSEE(sc, TextIO.stringToMove(pos, "exd4")));
|
||||
assertEquals(pV, getSEE(sc, TextIO.stringToMove(pos, "Nxe4")));
|
||||
assertEquals(pV, getSEE(sc, TextIO.stringToMove(pos, "Bxe4")));
|
||||
assertEquals(0, getSEE(sc, TextIO.stringToMove(pos, "d5")));
|
||||
assertEquals(-nV, getSEE(sc, TextIO.stringToMove(pos, "Nd5")));
|
||||
assertEquals(0, getSEE(sc, TextIO.stringToMove(pos, "a6")));
|
||||
|
||||
// Test X-ray attacks
|
||||
pos = TextIO.readFEN("3r2k1/pp1q1ppp/1bnr1nb1/1Np1p3/1P1PP3/2P1BN2/1Q1R1PPP/3R1BK1 b - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
// 1 1 1 1 3 3 3 3 3 5 5 9 5 5
|
||||
// 0 1 0 1 0 3 0 3 0 5 0 9 0 5
|
||||
assertEquals(0, getSEE(sc, TextIO.stringToMove(pos, "exd4")));
|
||||
// 1 3 1 1 3 1 3 3 5 5 5 9 9
|
||||
//-1 2 1 0 3 0 3 0 5 0 5 0 9
|
||||
assertEquals(2 * pV - nV, getSEE(sc, TextIO.stringToMove(pos, "Nxd4")));
|
||||
|
||||
pos.setPiece(TextIO.getSquare("b2"), Piece.EMPTY); // Remove white queen
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
// 1 1 1 1 3 3 3 3 3 5 5 9 5
|
||||
// 0 1 0 1 0 3 0 3 0 4 1 4 5
|
||||
assertEquals(0, getSEE(sc, TextIO.stringToMove(pos, "exd4")));
|
||||
assertEquals(pV, getSEE(sc, TextIO.stringToMove(pos, "cxb4")));
|
||||
|
||||
pos.setPiece(TextIO.getSquare("b5"), Piece.EMPTY); // Remove white knight
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
// 1 1 1 1 3 3 3 3 5 5 5
|
||||
// 1 0 1 0 3 0 3 0 5 0 5
|
||||
assertEquals(pV, getSEE(sc, TextIO.stringToMove(pos, "exd4")));
|
||||
|
||||
pos.setPiece(TextIO.getSquare("b2"), Piece.WQUEEN); // Restore white queen
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
// 1 1 1 1 3 3 3 3 5 5 5 9 9
|
||||
// 1 0 1 0 3 0 3 0 5 0 5 0 9
|
||||
assertEquals(pV, getSEE(sc, TextIO.stringToMove(pos, "exd4")));
|
||||
|
||||
pos.setPiece(TextIO.getSquare("b6"), Piece.EMPTY); // Remove black bishop
|
||||
pos.setPiece(TextIO.getSquare("c6"), Piece.EMPTY); // Remove black knight
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
assertEquals(-pV, getSEE(sc, TextIO.stringToMove(pos, "a5")));
|
||||
|
||||
// Test EP capture
|
||||
pos = TextIO.readFEN("2b3k1/1p3ppp/8/pP6/8/2PB4/5PPP/6K1 w - a6 0 2");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
// 1 1 1 3
|
||||
// 0 1 0 3
|
||||
assertEquals(0, getSEE(sc, TextIO.stringToMove(pos, "bxa6")));
|
||||
|
||||
pos.setPiece(TextIO.getSquare("b7"), Piece.EMPTY); // Remove black pawn
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
// 1 1 3
|
||||
// 1 0 3
|
||||
assertEquals(pV, getSEE(sc, TextIO.stringToMove(pos, "bxa6")));
|
||||
|
||||
|
||||
// Test king capture
|
||||
pos = TextIO.readFEN("8/8/8/4k3/r3P3/4K3/8/4R3 b - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
// 1 5 99
|
||||
// 1 0 99
|
||||
assertEquals(pV, getSEE(sc, TextIO.stringToMove(pos, "Rxe4+")));
|
||||
|
||||
pos = TextIO.readFEN("8/8/8/4k3/r3P1R1/4K3/8/8 b - - 0 1");
|
||||
final int kV = Evaluate.kV;
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
// 1 5 5 99
|
||||
//-4 5 0 99
|
||||
assertEquals(pV - rV, getSEE(sc, TextIO.stringToMove(pos, "Rxe4+")));
|
||||
// 1 99
|
||||
//-98 99
|
||||
assertEquals(pV - kV, getSEE(sc, new Move(TextIO.getSquare("e5"), TextIO.getSquare("e4"), Piece.EMPTY)));
|
||||
|
||||
pos = TextIO.readFEN("8/8/4k3/8/r3P3/4K3/8/8 b - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
assertEquals(pV - rV, getSEE(sc, TextIO.stringToMove(pos, "Rxe4+")));
|
||||
|
||||
// Test king too far away
|
||||
pos = TextIO.readFEN("8/8/4k3/8/r3P3/8/4K3/8 b - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
assertEquals(pV, getSEE(sc, TextIO.stringToMove(pos, "Rxe4+")));
|
||||
|
||||
pos = TextIO.readFEN("8/3k4/8/8/r1K5/8/8/2R5 w - - 0 1");
|
||||
pos.setWhiteMove(false);
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
assertEquals(kV, getSEE(sc, new Move(TextIO.getSquare("a4"), TextIO.getSquare("c4"), Piece.EMPTY)));
|
||||
|
||||
|
||||
// Test blocking pieces
|
||||
pos = TextIO.readFEN("r7/p2k4/8/r7/P7/8/4K3/R7 b - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
assertEquals(pV - rV, getSEE(sc, TextIO.stringToMove(pos, "Rxa4"))); // Ra8 doesn't help
|
||||
|
||||
pos.setPiece(TextIO.getSquare("a7"), Piece.BBISHOP);
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
assertEquals(pV - rV, getSEE(sc, TextIO.stringToMove(pos, "Rxa4"))); // Ra8 doesn't help
|
||||
|
||||
pos.setPiece(TextIO.getSquare("a7"), Piece.BPAWN);
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
assertEquals(pV - rV, getSEE(sc, TextIO.stringToMove(pos, "Rxa4"))); // Ra8 doesn't help
|
||||
|
||||
pos.setPiece(TextIO.getSquare("a7"), Piece.BQUEEN);
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
assertEquals(pV, getSEE(sc, TextIO.stringToMove(pos, "Rxa4"))); // Ra8 does help
|
||||
|
||||
pos = TextIO.readFEN("8/3k4/R7/r7/P7/8/4K3/8 b - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
assertEquals(pV - rV, getSEE(sc, TextIO.stringToMove(pos, "Rxa4")));
|
||||
|
||||
pos = TextIO.readFEN("Q7/q6k/R7/r7/P7/8/4K3/8 b - - 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
assertEquals(pV - rV, getSEE(sc, TextIO.stringToMove(pos, "Rxa4")));
|
||||
|
||||
pos = TextIO.readFEN("8/3k4/5R2/8/4pP2/8/8/3K4 b - f3 0 1");
|
||||
sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
int score1 = EvaluateTest.evalWhite(sc.pos);
|
||||
long h1 = sc.pos.zobristHash();
|
||||
assertEquals(0, getSEE(sc, TextIO.stringToMove(pos, "exf3")));
|
||||
int score2 = EvaluateTest.evalWhite(sc.pos);
|
||||
long h2 = sc.pos.zobristHash();
|
||||
assertEquals(score1, score2);
|
||||
assertEquals(h1, h2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of scoreMoveList method, of class Search.
|
||||
*/
|
||||
@Test
|
||||
public void testScoreMoveList() throws ChessParseError {
|
||||
System.out.println("SEEorder");
|
||||
Position pos = TextIO.readFEN("r2qk2r/ppp2ppp/1bnp1nb1/1N2p3/3PP3/1PP2N2/1P3PPP/R1BQRBK1 w kq - 0 1");
|
||||
Search sc = new Search(pos, nullHist, 0, tt, ht);
|
||||
MoveGen moveGen = new MoveGen();
|
||||
MoveGen.MoveList moves = moveGen.pseudoLegalMoves(pos);
|
||||
sc.scoreMoveList(moves, 0);
|
||||
for (int i = 0; i < moves.size; i++) {
|
||||
Search.selectBest(moves, i);
|
||||
if (i > 0) {
|
||||
int sc1 = moves.m[i - 1].score;
|
||||
int sc2 = moves.m[i].score;
|
||||
assertTrue(sc2 <= sc1);
|
||||
}
|
||||
}
|
||||
|
||||
moves = moveGen.pseudoLegalMoves(pos);
|
||||
moves.m[0].score = 17;
|
||||
moves.m[1].score = 666;
|
||||
moves.m[2].score = 4711;
|
||||
sc.scoreMoveList(moves, 0, 2);
|
||||
assertEquals(17, moves.m[0].score);
|
||||
assertEquals(666, moves.m[1].score);
|
||||
for (int i = 1; i < moves.size; i++) {
|
||||
Search.selectBest(moves, i);
|
||||
if (i > 1) {
|
||||
int sc1 = moves.m[i - 1].score;
|
||||
int sc2 = moves.m[i].score;
|
||||
assertTrue(sc2 <= sc1);
|
||||
}
|
||||
}
|
||||
|
||||
// The hashMove should be first in the list
|
||||
Move m = TextIO.stringToMove(pos, "Ra6");
|
||||
moves = moveGen.pseudoLegalMoves(pos);
|
||||
boolean res = Search.selectHashMove(moves, m);
|
||||
assertEquals(true, res);
|
||||
assertEquals(m, moves.m[0]);
|
||||
}
|
||||
}
|
|
@ -1,398 +0,0 @@
|
|||
/*
|
||||
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 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 TextIOTest {
|
||||
|
||||
public TextIOTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of readFEN method, of class TextIO.
|
||||
*/
|
||||
@Test
|
||||
public void testReadFEN() throws ChessParseError {
|
||||
System.out.println("readFEN");
|
||||
String fen = "rnbqk2r/1p3ppp/p7/1NpPp3/QPP1P1n1/P4N2/4KbPP/R1B2B1R b kq - 0 1";
|
||||
Position pos = TextIO.readFEN(fen);
|
||||
assertEquals(fen, TextIO.toFEN(pos));
|
||||
assertEquals(pos.getPiece(Position.getSquare(0, 3)), Piece.WQUEEN);
|
||||
assertEquals(pos.getPiece(Position.getSquare(4, 7)), Piece.BKING);
|
||||
assertEquals(pos.getPiece(Position.getSquare(4, 1)), Piece.WKING);
|
||||
assertEquals(pos.whiteMove, false);
|
||||
assertEquals(pos.a1Castle(), false);
|
||||
assertEquals(pos.h1Castle(), false);
|
||||
assertEquals(pos.a8Castle(), true);
|
||||
assertEquals(pos.h8Castle(), true);
|
||||
|
||||
fen = "8/3k4/8/5pP1/1P6/1NB5/2QP4/R3K2R w KQ f6 1 2";
|
||||
pos = TextIO.readFEN(fen);
|
||||
assertEquals(fen, TextIO.toFEN(pos));
|
||||
assertEquals(1, pos.halfMoveClock);
|
||||
assertEquals(2, pos.fullMoveCounter);
|
||||
|
||||
// Must have exactly one king
|
||||
boolean wasError = testFENParseError("8/8/8/8/8/8/8/kk1K4 w - - 0 1");
|
||||
assertEquals(true, wasError);
|
||||
|
||||
// Must not be possible to capture the king
|
||||
wasError = testFENParseError("8/8/8/8/8/8/8/k1RK4 w - - 0 1");
|
||||
assertEquals(true, wasError);
|
||||
|
||||
// Make sure bogus en passant square information is removed
|
||||
fen = "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1";
|
||||
pos = TextIO.readFEN(fen);
|
||||
assertEquals(-1, pos.getEpSquare());
|
||||
|
||||
// Test for too many rows (slashes)
|
||||
wasError = testFENParseError("8/8/8/8/4k3/8/8/8/KBN5 w - - 0 1");
|
||||
assertEquals(true, wasError);
|
||||
|
||||
// Test for too many columns
|
||||
wasError = testFENParseError("8K/8/8/8/4k3/8/8/8 w - - 0 1");
|
||||
assertEquals(true, wasError);
|
||||
|
||||
// Pawns must not be on first/last rank
|
||||
wasError = testFENParseError("kp6/8/8/8/8/8/8/K7 w - - 0 1");
|
||||
assertEquals(true, wasError);
|
||||
|
||||
wasError = testFENParseError("kr/pppp/8/8/8/8/8/KBR w");
|
||||
assertEquals(false, wasError); // OK not to specify castling flags and ep square
|
||||
|
||||
wasError = testFENParseError("k/8/8/8/8/8/8/K");
|
||||
assertEquals(true, wasError); // Error side to move not specified
|
||||
|
||||
wasError = testFENParseError("");
|
||||
assertEquals(true, wasError);
|
||||
|
||||
wasError = testFENParseError(" |");
|
||||
assertEquals(true, wasError);
|
||||
|
||||
wasError = testFENParseError("1B1B4/6k1/7r/7P/6q1/r7/q7/7K b - - acn 6; acs 0;");
|
||||
assertEquals(false, wasError); // Extra stuff after FEN string is allowed
|
||||
}
|
||||
|
||||
/** Tests if trying to parse a FEN string causes an error. */
|
||||
private boolean testFENParseError(String fen) {
|
||||
boolean wasError;
|
||||
wasError = false;
|
||||
try {
|
||||
TextIO.readFEN(fen);
|
||||
} catch (ChessParseError err) {
|
||||
wasError = true;
|
||||
}
|
||||
return wasError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of moveToString method, of class TextIO.
|
||||
*/
|
||||
@Test
|
||||
public void testMoveToString() throws ChessParseError {
|
||||
System.out.println("moveToString");
|
||||
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||
assertEquals(TextIO.startPosFEN, TextIO.toFEN(pos));
|
||||
Move move = new Move(Position.getSquare(4, 1), Position.getSquare(4, 3),
|
||||
Piece.EMPTY);
|
||||
boolean longForm = true;
|
||||
String result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("e2-e4", result);
|
||||
|
||||
move = new Move(Position.getSquare(6, 0), Position.getSquare(5, 2), Piece.EMPTY);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("Ng1-f3", result);
|
||||
|
||||
move = new Move(Position.getSquare(4, 7), Position.getSquare(2, 7),
|
||||
Piece.EMPTY);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("O-O-O", result);
|
||||
|
||||
String fen = "1r3k2/2P5/8/8/8/4K3/8/8 w - - 0 1";
|
||||
pos = TextIO.readFEN(fen);
|
||||
assertEquals(fen, TextIO.toFEN(pos));
|
||||
move = new Move(Position.getSquare(2,6), Position.getSquare(1,7), Piece.WROOK);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("c7xb8R+", result);
|
||||
|
||||
move = new Move(Position.getSquare(2,6), Position.getSquare(2,7), Piece.WKNIGHT);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("c7-c8N", result);
|
||||
|
||||
move = new Move(Position.getSquare(2,6), Position.getSquare(2,7), Piece.WQUEEN);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("c7-c8Q+", result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of moveToString method, of class TextIO, mate/stalemate tests.
|
||||
*/
|
||||
@Test
|
||||
public void testMoveToStringMate() throws ChessParseError {
|
||||
System.out.println("moveToStringMate");
|
||||
Position pos = TextIO.readFEN("3k4/1PR5/3N4/8/4K3/8/8/8 w - - 0 1");
|
||||
boolean longForm = true;
|
||||
|
||||
Move move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WROOK);
|
||||
String result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("b7-b8R+", result); // check
|
||||
|
||||
move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WQUEEN);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("b7-b8Q#", result); // check mate
|
||||
|
||||
move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WKNIGHT);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("b7-b8N", result);
|
||||
|
||||
move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WBISHOP);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("b7-b8B", result); // stalemate
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of moveToString method, of class TextIO, short form.
|
||||
*/
|
||||
@Test
|
||||
public void testMoveToStringShortForm() throws ChessParseError {
|
||||
System.out.println("moveToStringShortForm");
|
||||
String fen = "r4rk1/2pn3p/2q1q1n1/8/2q2p2/6R1/p4PPP/1R4K1 b - - 0 1";
|
||||
Position pos = TextIO.readFEN(fen);
|
||||
assertEquals(fen, TextIO.toFEN(pos));
|
||||
boolean longForm = false;
|
||||
|
||||
Move move = new Move(Position.getSquare(4,5), Position.getSquare(4,3), Piece.EMPTY);
|
||||
String result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("Qee4", result); // File disambiguation needed
|
||||
|
||||
move = new Move(Position.getSquare(2,5), Position.getSquare(4,3), Piece.EMPTY);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("Qc6e4", result); // Full disambiguation needed
|
||||
|
||||
move = new Move(Position.getSquare(2,3), Position.getSquare(4,3), Piece.EMPTY);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("Q4e4", result); // Row disambiguation needed
|
||||
|
||||
move = new Move(Position.getSquare(2,3), Position.getSquare(2,0), Piece.EMPTY);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("Qc1+", result); // No disambiguation needed
|
||||
|
||||
move = new Move(Position.getSquare(0,1), Position.getSquare(0,0), Piece.BQUEEN);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("a1Q", result); // Normal promotion
|
||||
|
||||
move = new Move(Position.getSquare(0,1), Position.getSquare(1,0), Piece.BQUEEN);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("axb1Q#", result); // Capture promotion and check mate
|
||||
|
||||
move = new Move(Position.getSquare(0,1), Position.getSquare(1,0), Piece.BKNIGHT);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("axb1N", result); // Capture promotion
|
||||
|
||||
move = new Move(Position.getSquare(3,6), Position.getSquare(4,4), Piece.EMPTY);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("Ne5", result); // Other knight pinned, no disambiguation needed
|
||||
|
||||
move = new Move(Position.getSquare(7,6), Position.getSquare(7,4), Piece.EMPTY);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("h5", result); // Regular pawn move
|
||||
|
||||
move = new Move(Position.getSquare(5,7), Position.getSquare(3,7), Piece.EMPTY);
|
||||
result = TextIO.moveToString(pos, move, longForm);
|
||||
assertEquals("Rfd8", result); // File disambiguation needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of stringToMove method, of class TextIO.
|
||||
*/
|
||||
@Test
|
||||
public void testStringToMove() throws ChessParseError {
|
||||
System.out.println("stringToMove");
|
||||
Position pos = TextIO.readFEN("r4rk1/2pn3p/2q1q1n1/8/2q2p2/6R1/p4PPP/1R4K1 b - - 0 1");
|
||||
|
||||
Move mNe5 = new Move(Position.getSquare(3, 6), Position.getSquare(4, 4), Piece.EMPTY);
|
||||
Move m = TextIO.stringToMove(pos, "Ne5");
|
||||
assertEquals(mNe5, m);
|
||||
m = TextIO.stringToMove(pos, "ne");
|
||||
assertEquals(mNe5, m);
|
||||
m = TextIO.stringToMove(pos, "N");
|
||||
assertEquals(null, m);
|
||||
|
||||
Move mQc6e4 = new Move(Position.getSquare(2, 5), Position.getSquare(4, 3), Piece.EMPTY);
|
||||
m = TextIO.stringToMove(pos, "Qc6-e4");
|
||||
assertEquals(mQc6e4, m);
|
||||
m = TextIO.stringToMove(pos, "Qc6e4");
|
||||
assertEquals(mQc6e4, m);
|
||||
m = TextIO.stringToMove(pos, "Qce4");
|
||||
assertEquals(null, m);
|
||||
m = TextIO.stringToMove(pos, "Q6e4");
|
||||
assertEquals(null, m);
|
||||
|
||||
Move maxb1Q = new Move(Position.getSquare(0, 1), Position.getSquare(1, 0), Piece.BQUEEN);
|
||||
m = TextIO.stringToMove(pos, "axb1Q");
|
||||
assertEquals(maxb1Q, m);
|
||||
m = TextIO.stringToMove(pos, "axb1Q#");
|
||||
assertEquals(maxb1Q, m);
|
||||
m = TextIO.stringToMove(pos, "axb1Q+");
|
||||
assertEquals(null, m);
|
||||
|
||||
Move mh5= new Move(Position.getSquare(7, 6), Position.getSquare(7, 4), Piece.EMPTY);
|
||||
m = TextIO.stringToMove(pos, "h5");
|
||||
assertEquals(mh5, m);
|
||||
m = TextIO.stringToMove(pos, "h7-h5");
|
||||
assertEquals(mh5, m);
|
||||
m = TextIO.stringToMove(pos, "h");
|
||||
assertEquals(null, m);
|
||||
|
||||
pos = TextIO.readFEN("r1b1k2r/1pqpppbp/p5pn/3BP3/8/2pP4/PPPBQPPP/R3K2R w KQkq - 0 12");
|
||||
m = TextIO.stringToMove(pos, "bxc3");
|
||||
assertEquals(TextIO.getSquare("b2"), m.from);
|
||||
m = TextIO.stringToMove(pos, "Bxc3");
|
||||
assertEquals(TextIO.getSquare("d2"), m.from);
|
||||
m = TextIO.stringToMove(pos, "bxc");
|
||||
assertEquals(TextIO.getSquare("b2"), m.from);
|
||||
m = TextIO.stringToMove(pos, "Bxc");
|
||||
assertEquals(TextIO.getSquare("d2"), m.from);
|
||||
|
||||
// Test castling. o-o is a substring of o-o-o, which could cause problems.
|
||||
pos = TextIO.readFEN("5k2/p1pQn3/1p2Bp1r/8/4P1pN/2N5/PPP2PPP/R3K2R w KQ - 0 16");
|
||||
Move kCastle = new Move(Position.getSquare(4,0), Position.getSquare(6,0), Piece.EMPTY);
|
||||
Move qCastle = new Move(Position.getSquare(4,0), Position.getSquare(2,0), Piece.EMPTY);
|
||||
m = TextIO.stringToMove(pos, "o");
|
||||
assertEquals(null, m);
|
||||
m = TextIO.stringToMove(pos, "o-o");
|
||||
assertEquals(kCastle, m);
|
||||
m = TextIO.stringToMove(pos, "O-O");
|
||||
assertEquals(kCastle, m);
|
||||
m = TextIO.stringToMove(pos, "o-o-o");
|
||||
assertEquals(qCastle, m);
|
||||
|
||||
// Test 'o-o+'
|
||||
pos.setPiece(Position.getSquare(5,1), Piece.EMPTY);
|
||||
pos.setPiece(Position.getSquare(5,5), Piece.EMPTY);
|
||||
m = TextIO.stringToMove(pos, "o");
|
||||
assertEquals(null, m);
|
||||
m = TextIO.stringToMove(pos, "o-o");
|
||||
assertEquals(kCastle, m);
|
||||
m = TextIO.stringToMove(pos, "o-o-o");
|
||||
assertEquals(qCastle, m);
|
||||
m = TextIO.stringToMove(pos, "o-o+");
|
||||
assertEquals(kCastle, m);
|
||||
|
||||
// Test d8=Q+ syntax
|
||||
pos = TextIO.readFEN("1r3r2/2kP2Rp/p1bN1p2/2p5/5P2/2P5/P5PP/3R2K1 w - -");
|
||||
m = TextIO.stringToMove(pos, "d8=Q+");
|
||||
Move m2 = TextIO.stringToMove(pos, "d8Q");
|
||||
assertEquals(m2, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getSquare method, of class TextIO.
|
||||
*/
|
||||
@Test
|
||||
public void testGetSquare() throws ChessParseError {
|
||||
System.out.println("getSquare");
|
||||
assertEquals(Position.getSquare(0, 0), TextIO.getSquare("a1"));
|
||||
assertEquals(Position.getSquare(1, 7), TextIO.getSquare("b8"));
|
||||
assertEquals(Position.getSquare(3, 3), TextIO.getSquare("d4"));
|
||||
assertEquals(Position.getSquare(4, 3), TextIO.getSquare("e4"));
|
||||
assertEquals(Position.getSquare(3, 1), TextIO.getSquare("d2"));
|
||||
assertEquals(Position.getSquare(7, 7), TextIO.getSquare("h8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of squareToString method, of class TextIO.
|
||||
*/
|
||||
@Test
|
||||
public void testSquareToString() {
|
||||
System.out.println("squareToString");
|
||||
assertEquals("a1", TextIO.squareToString(Position.getSquare(0, 0)));
|
||||
assertEquals("h6", TextIO.squareToString(Position.getSquare(7, 5)));
|
||||
assertEquals("e4", TextIO.squareToString(Position.getSquare(4, 3)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of asciiBoard method, of class TextIO.
|
||||
*/
|
||||
@Test
|
||||
public void testAsciiBoard() throws ChessParseError {
|
||||
System.out.println("asciiBoard");
|
||||
Position pos = TextIO.readFEN("r4rk1/2pn3p/2q1q1n1/8/2q2p2/6R1/p4PPP/1R4K1 b - - 0 1");
|
||||
String aBrd = TextIO.asciiBoard(pos);
|
||||
// System.out.print(aBrd);
|
||||
assertEquals(12, aBrd.length() - aBrd.replaceAll("\\*", "").length()); // 12 black pieces
|
||||
assertEquals(3, aBrd.length() - aBrd.replaceAll("\\*Q", " ").length()); // 3 black queens
|
||||
assertEquals(3, aBrd.length() - aBrd.replaceAll(" P", " ").length()); // 3 white pawns
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of uciStringToMove method, of class TextIO.
|
||||
*/
|
||||
@Test
|
||||
public void testUciStringToMove() throws ChessParseError {
|
||||
System.out.println("stringToMove");
|
||||
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||
Move m = TextIO.uciStringToMove("e2e4");
|
||||
assertEquals(TextIO.stringToMove(pos, "e4"), m);
|
||||
m = TextIO.uciStringToMove("e2e5");
|
||||
assertEquals(new Move(12, 12+8*3, Piece.EMPTY), m);
|
||||
|
||||
m = TextIO.uciStringToMove("e2e5q");
|
||||
assertEquals(null, m);
|
||||
|
||||
m = TextIO.uciStringToMove("e7e8q");
|
||||
assertEquals(Piece.WQUEEN, m.promoteTo);
|
||||
m = TextIO.uciStringToMove("e7e8r");
|
||||
assertEquals(Piece.WROOK, m.promoteTo);
|
||||
m = TextIO.uciStringToMove("e7e8b");
|
||||
assertEquals(Piece.WBISHOP, m.promoteTo);
|
||||
m = TextIO.uciStringToMove("e2e1n");
|
||||
assertEquals(Piece.BKNIGHT, m.promoteTo);
|
||||
m = TextIO.uciStringToMove("e7e8x");
|
||||
assertEquals(null, m); // Invalid promotion piece
|
||||
m = TextIO.uciStringToMove("i1i3");
|
||||
assertEquals(null, m); // Outside board
|
||||
}
|
||||
}
|
|
@ -1,162 +0,0 @@
|
|||
/*
|
||||
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 chess.TranspositionTable.TTEntry;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author petero
|
||||
*/
|
||||
public class TranspositionTableTest {
|
||||
|
||||
public TranspositionTableTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of TTEntry nested class, of class TranspositionTable.
|
||||
*/
|
||||
@Test
|
||||
public void testTTEntry() throws ChessParseError {
|
||||
System.out.println("TTEntry");
|
||||
final int mate0 = Search.MATE0;
|
||||
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||
Move move = TextIO.stringToMove(pos, "e4");
|
||||
|
||||
// Test "normal" (non-mate) score
|
||||
int score = 17;
|
||||
int ply = 3;
|
||||
TTEntry ent1 = new TTEntry();
|
||||
ent1.key = 1;
|
||||
ent1.setMove(move);
|
||||
ent1.setScore(score, ply);
|
||||
ent1.setDepth(3);
|
||||
ent1.generation = 0;
|
||||
ent1.type = TranspositionTable.TTEntry.T_EXACT;
|
||||
ent1.setHashSlot(0);
|
||||
Move tmpMove = new Move(0,0,0);
|
||||
ent1.getMove(tmpMove);
|
||||
assertEquals(move, tmpMove);
|
||||
assertEquals(score, ent1.getScore(ply));
|
||||
assertEquals(score, ent1.getScore(ply + 3)); // Non-mate score, should be ply-independent
|
||||
|
||||
// Test positive mate score
|
||||
TTEntry ent2 = new TTEntry();
|
||||
score = mate0 - 6;
|
||||
ply = 3;
|
||||
ent2.key = 3;
|
||||
move = new Move(8, 0, Piece.BQUEEN);
|
||||
ent2.setMove(move);
|
||||
ent2.setScore(score, ply);
|
||||
ent2.setDepth(99);
|
||||
ent2.generation = 0;
|
||||
ent2.type = TranspositionTable.TTEntry.T_EXACT;
|
||||
ent2.setHashSlot(0);
|
||||
ent2.getMove(tmpMove);
|
||||
assertEquals(move, tmpMove);
|
||||
assertEquals(score, ent2.getScore(ply));
|
||||
assertEquals(score + 2, ent2.getScore(ply - 2));
|
||||
|
||||
// Compare ent1 and ent2
|
||||
assertTrue(!ent1.betterThan(ent2, 0)); // More depth is good
|
||||
assertTrue(ent2.betterThan(ent1, 0));
|
||||
|
||||
ent2.generation = 1;
|
||||
assertTrue(!ent2.betterThan(ent1, 0)); // ent2 has wrong generation
|
||||
assertTrue(ent2.betterThan(ent1, 1)); // ent1 has wrong generation
|
||||
|
||||
ent2.generation = 0;
|
||||
ent1.setDepth(7); ent2.setDepth(7);
|
||||
ent1.type = TranspositionTable.TTEntry.T_GE;
|
||||
assertTrue(ent2.betterThan(ent1, 0));
|
||||
ent2.type = TranspositionTable.TTEntry.T_LE;
|
||||
assertTrue(!ent2.betterThan(ent1, 0)); // T_GE is equally good as T_LE
|
||||
assertTrue(!ent1.betterThan(ent2, 0));
|
||||
|
||||
// Test negative mate score
|
||||
TTEntry ent3 = new TTEntry();
|
||||
score = -mate0 + 5;
|
||||
ply = 3;
|
||||
ent3.key = 3;
|
||||
move = new Move(8, 0, Piece.BQUEEN);
|
||||
ent3.setMove(move);
|
||||
ent3.setScore(score, ply);
|
||||
ent3.setDepth(99);
|
||||
ent3.generation = 0;
|
||||
ent3.type = TranspositionTable.TTEntry.T_EXACT;
|
||||
ent3.setHashSlot(0);
|
||||
ent3.getMove(tmpMove);
|
||||
assertEquals(move, tmpMove);
|
||||
assertEquals(score, ent3.getScore(ply));
|
||||
assertEquals(score - 2, ent3.getScore(ply - 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of insert method, of class TranspositionTable.
|
||||
*/
|
||||
@Test
|
||||
public void testInsert() throws ChessParseError {
|
||||
System.out.println("insert");
|
||||
TranspositionTable tt = new TranspositionTable(16);
|
||||
Position pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||
String[] moves = {
|
||||
"e4", "e5", "Nf3", "Nc6", "Bb5", "a6", "Ba4", "b5", "Bb3", "Nf6", "O-O", "Be7", "Re1"
|
||||
};
|
||||
UndoInfo ui = new UndoInfo();
|
||||
for (int i = 0; i < moves.length; i++) {
|
||||
Move m = TextIO.stringToMove(pos, moves[i]);
|
||||
pos.makeMove(m, ui);
|
||||
int score = i * 17 + 3;
|
||||
m.score = score;
|
||||
int type = TranspositionTable.TTEntry.T_EXACT;
|
||||
int ply = i + 1;
|
||||
int depth = i * 2 + 5;
|
||||
tt.insert(pos.historyHash(), m, type, ply, depth, score * 2 + 3);
|
||||
}
|
||||
|
||||
pos = TextIO.readFEN(TextIO.startPosFEN);
|
||||
for (int i = 0; i < moves.length; i++) {
|
||||
Move m = TextIO.stringToMove(pos, moves[i]);
|
||||
pos.makeMove(m, ui);
|
||||
TranspositionTable.TTEntry ent = tt.probe(pos.historyHash());
|
||||
assertEquals(TranspositionTable.TTEntry.T_EXACT, ent.type);
|
||||
int score = i * 17 + 3;
|
||||
int ply = i + 1;
|
||||
int depth = i * 2 + 5;
|
||||
assertEquals(score, ent.getScore(ply));
|
||||
assertEquals(depth, ent.getDepth());
|
||||
assertEquals(score * 2 + 3, ent.evalScore);
|
||||
Move tmpMove = new Move(0,0,0);
|
||||
ent.getMove(tmpMove);
|
||||
assertEquals(m, tmpMove);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
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 guibase;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import chess.ChessParseError;
|
||||
import chess.Piece;
|
||||
import chess.TextIO;
|
||||
|
||||
public class ChessControllerTest {
|
||||
|
||||
@Test
|
||||
public final void testSetPGN() throws ChessParseError {
|
||||
ChessController ctrl = new ChessController(null);
|
||||
ctrl.newGame(true, 8, false);
|
||||
ctrl.setPGN("[FEN \"k/8/8/8/8/8/KP/8 w\"]\n");
|
||||
assertEquals(TextIO.getSquare("a2"), ctrl.game.pos.getKingSq(true));
|
||||
assertEquals(TextIO.getSquare("a8"), ctrl.game.pos.getKingSq(false));
|
||||
|
||||
ctrl.setPGN("1.e4 e5 2. Nf3!!! $6 (Nc3 (a3)) Nc6?? Bb5!!? a6?! * Ba4");
|
||||
assertEquals(Piece.BPAWN, ctrl.game.pos.getPiece(TextIO.getSquare("a6")));
|
||||
assertEquals(Piece.WBISHOP, ctrl.game.pos.getPiece(TextIO.getSquare("b5")));
|
||||
assertEquals(Piece.EMPTY, ctrl.game.pos.getPiece(TextIO.getSquare("a4")));
|
||||
|
||||
ctrl.setPGN("[FEN \"r1bq1rk1/pp3ppp/2n1pn2/6B1/1bBP4/2N2N2/PPQ2PPP/R3K2R w KQ - 1 10\"]\n");
|
||||
assertEquals(10, ctrl.game.pos.fullMoveCounter);
|
||||
}
|
||||
}
|
|
@ -139,7 +139,7 @@ import android.widget.Toast;
|
|||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
public class DroidFish extends Activity implements GUIInterface {
|
||||
// FIXME!!! book.txt (and test classes) should not be included in apk
|
||||
// FIXME!!! book.txt should not be included in apk
|
||||
|
||||
// FIXME!!! PGN view option: game continuation (for training)
|
||||
// FIXME!!! Remove invalid playerActions in PGN import (should be done in verifyChildren)
|
||||
|
|
Loading…
Reference in New Issue
Block a user