mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2024-12-11 20:30:54 +01:00
462 lines
19 KiB
Java
462 lines
19 KiB
Java
/*
|
|
CuckooChess - A java chess program.
|
|
Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package chess;
|
|
|
|
import 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);
|
|
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
score = sc.negaScout(-mate0, mate0, 0, 3*plyScale, -1, MoveGen.inCheck(pos));
|
|
assertTrue(Math.abs(score) < 50); // Stale-mate trap
|
|
score2 = idSearch(sc, 9).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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
sc.maxTimeMillis = -1;
|
|
score = idSearch(sc, 3).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);
|
|
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);
|
|
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);
|
|
Move bestM = idSearch(sc, 28);
|
|
assertEquals(TextIO.stringToMove(pos, "Kb1"), new Move(bestM));
|
|
}
|
|
|
|
@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);
|
|
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);
|
|
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);
|
|
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);
|
|
Move bestM = idSearch(sc, 9);
|
|
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);
|
|
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);
|
|
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);
|
|
// 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);
|
|
// 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);
|
|
// 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);
|
|
// 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);
|
|
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);
|
|
// 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);
|
|
// 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);
|
|
// 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);
|
|
// 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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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]);
|
|
}
|
|
}
|